deps: update v8 to 4.3.61.21
[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 <iomanip>
6 #include <sstream>
7
8 #include "src/v8.h"
9
10 #include "src/accessors.h"
11 #include "src/allocation-site-scopes.h"
12 #include "src/api.h"
13 #include "src/arguments.h"
14 #include "src/base/bits.h"
15 #include "src/bootstrapper.h"
16 #include "src/code-stubs.h"
17 #include "src/codegen.h"
18 #include "src/compiler.h"
19 #include "src/cpu-profiler.h"
20 #include "src/date.h"
21 #include "src/debug.h"
22 #include "src/deoptimizer.h"
23 #include "src/elements.h"
24 #include "src/execution.h"
25 #include "src/field-index-inl.h"
26 #include "src/field-index.h"
27 #include "src/full-codegen.h"
28 #include "src/heap/mark-compact.h"
29 #include "src/heap/objects-visiting-inl.h"
30 #include "src/hydrogen.h"
31 #include "src/ic/ic.h"
32 #include "src/isolate-inl.h"
33 #include "src/log.h"
34 #include "src/lookup.h"
35 #include "src/macro-assembler.h"
36 #include "src/objects-inl.h"
37 #include "src/prototype.h"
38 #include "src/safepoint-table.h"
39 #include "src/string-search.h"
40 #include "src/string-stream.h"
41 #include "src/utils.h"
42
43 #ifdef ENABLE_DISASSEMBLER
44 #include "src/disasm.h"
45 #include "src/disassembler.h"
46 #endif
47
48 namespace v8 {
49 namespace internal {
50
51 Handle<HeapType> Object::OptimalType(Isolate* isolate,
52                                      Representation representation) {
53   if (representation.IsNone()) return HeapType::None(isolate);
54   if (FLAG_track_field_types) {
55     if (representation.IsHeapObject() && IsHeapObject()) {
56       // We can track only JavaScript objects with stable maps.
57       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
58       if (map->is_stable() &&
59           map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
60           map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
61         return HeapType::Class(map, isolate);
62       }
63     }
64   }
65   return HeapType::Any(isolate);
66 }
67
68
69 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
70                                          Handle<Object> object,
71                                          Handle<Context> native_context) {
72   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
73   Handle<JSFunction> constructor;
74   if (object->IsNumber()) {
75     constructor = handle(native_context->number_function(), isolate);
76   } else if (object->IsBoolean()) {
77     constructor = handle(native_context->boolean_function(), isolate);
78   } else if (object->IsString()) {
79     constructor = handle(native_context->string_function(), isolate);
80   } else if (object->IsSymbol()) {
81     constructor = handle(native_context->symbol_function(), isolate);
82   } else {
83     return MaybeHandle<JSReceiver>();
84   }
85   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
86   Handle<JSValue>::cast(result)->set_value(*object);
87   return result;
88 }
89
90
91 bool Object::BooleanValue() {
92   if (IsBoolean()) return IsTrue();
93   if (IsSmi()) return Smi::cast(this)->value() != 0;
94   if (IsUndefined() || IsNull()) return false;
95   if (IsUndetectableObject()) return false;   // Undetectable object is false.
96   if (IsString()) return String::cast(this)->length() != 0;
97   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
98   return true;
99 }
100
101
102 bool Object::IsCallable() const {
103   const Object* fun = this;
104   while (fun->IsJSFunctionProxy()) {
105     fun = JSFunctionProxy::cast(fun)->call_trap();
106   }
107   return fun->IsJSFunction() ||
108          (fun->IsHeapObject() &&
109           HeapObject::cast(fun)->map()->has_instance_call_handler());
110 }
111
112
113 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
114   for (; it->IsFound(); it->Next()) {
115     switch (it->state()) {
116       case LookupIterator::NOT_FOUND:
117       case LookupIterator::TRANSITION:
118         UNREACHABLE();
119       case LookupIterator::JSPROXY:
120         return JSProxy::GetPropertyWithHandler(it->GetHolder<JSProxy>(),
121                                                it->GetReceiver(), it->name());
122       case LookupIterator::INTERCEPTOR: {
123         MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithInterceptor(
124             it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
125         if (!maybe_result.is_null()) return maybe_result;
126         if (it->isolate()->has_pending_exception()) return maybe_result;
127         break;
128       }
129       case LookupIterator::ACCESS_CHECK:
130         if (it->HasAccess()) break;
131         return JSObject::GetPropertyWithFailedAccessCheck(it);
132       case LookupIterator::ACCESSOR:
133         return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
134                                        it->GetHolder<JSObject>(),
135                                        it->GetAccessors());
136       case LookupIterator::INTEGER_INDEXED_EXOTIC:
137         return it->factory()->undefined_value();
138       case LookupIterator::DATA:
139         return it->GetDataValue();
140     }
141   }
142   return it->factory()->undefined_value();
143 }
144
145
146 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
147                                          Handle<Name> key) {
148   LookupIterator it(object, key,
149                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
150   return GetDataProperty(&it);
151 }
152
153
154 Handle<Object> JSObject::GetDataProperty(LookupIterator* it) {
155   for (; it->IsFound(); it->Next()) {
156     switch (it->state()) {
157       case LookupIterator::INTERCEPTOR:
158       case LookupIterator::NOT_FOUND:
159       case LookupIterator::TRANSITION:
160         UNREACHABLE();
161       case LookupIterator::ACCESS_CHECK:
162         if (it->HasAccess()) continue;
163       // Fall through.
164       case LookupIterator::JSPROXY:
165         it->NotFound();
166         return it->isolate()->factory()->undefined_value();
167       case LookupIterator::ACCESSOR:
168         // TODO(verwaest): For now this doesn't call into
169         // ExecutableAccessorInfo, since clients don't need it. Update once
170         // relevant.
171         it->NotFound();
172         return it->isolate()->factory()->undefined_value();
173       case LookupIterator::INTEGER_INDEXED_EXOTIC:
174         return it->isolate()->factory()->undefined_value();
175       case LookupIterator::DATA:
176         return it->GetDataValue();
177     }
178   }
179   return it->isolate()->factory()->undefined_value();
180 }
181
182
183 bool Object::ToInt32(int32_t* value) {
184   if (IsSmi()) {
185     *value = Smi::cast(this)->value();
186     return true;
187   }
188   if (IsHeapNumber()) {
189     double num = HeapNumber::cast(this)->value();
190     if (FastI2D(FastD2I(num)) == num) {
191       *value = FastD2I(num);
192       return true;
193     }
194   }
195   return false;
196 }
197
198
199 bool Object::ToUint32(uint32_t* value) {
200   if (IsSmi()) {
201     int num = Smi::cast(this)->value();
202     if (num >= 0) {
203       *value = static_cast<uint32_t>(num);
204       return true;
205     }
206   }
207   if (IsHeapNumber()) {
208     double num = HeapNumber::cast(this)->value();
209     if (num >= 0 && FastUI2D(FastD2UI(num)) == num) {
210       *value = FastD2UI(num);
211       return true;
212     }
213   }
214   return false;
215 }
216
217
218 bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
219   if (!object->IsHeapObject()) return false;
220   return IsTemplateFor(HeapObject::cast(object)->map());
221 }
222
223
224 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
225   // There is a constraint on the object; check.
226   if (!map->IsJSObjectMap()) return false;
227   // Fetch the constructor function of the object.
228   Object* cons_obj = map->GetConstructor();
229   if (!cons_obj->IsJSFunction()) return false;
230   JSFunction* fun = JSFunction::cast(cons_obj);
231   // Iterate through the chain of inheriting function templates to
232   // see if the required one occurs.
233   for (Object* type = fun->shared()->function_data();
234        type->IsFunctionTemplateInfo();
235        type = FunctionTemplateInfo::cast(type)->parent_template()) {
236     if (type == this) return true;
237   }
238   // Didn't find the required type in the inheritance chain.
239   return false;
240 }
241
242
243 // TODO(dcarney): CallOptimization duplicates this logic, merge.
244 Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate,
245                                                     Object* receiver) {
246   // API calls are only supported with JSObject receivers.
247   if (!receiver->IsJSObject()) return isolate->heap()->null_value();
248   Object* recv_type = this->signature();
249   // No signature, return holder.
250   if (recv_type->IsUndefined()) return receiver;
251   FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
252   // Check the receiver.
253   for (PrototypeIterator iter(isolate, receiver,
254                               PrototypeIterator::START_AT_RECEIVER);
255        !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
256     if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent();
257   }
258   return isolate->heap()->null_value();
259 }
260
261
262 Handle<FixedArray> JSObject::EnsureWritableFastElements(
263     Handle<JSObject> object) {
264   DCHECK(object->HasFastSmiOrObjectElements());
265   Isolate* isolate = object->GetIsolate();
266   Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
267   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
268   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
269       elems, isolate->factory()->fixed_array_map());
270   object->set_elements(*writable_elems);
271   isolate->counters()->cow_arrays_converted()->Increment();
272   return writable_elems;
273 }
274
275
276 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
277                                                     Handle<Object> receiver,
278                                                     Handle<Name> name) {
279   Isolate* isolate = proxy->GetIsolate();
280
281   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
282   if (name->IsSymbol()) return isolate->factory()->undefined_value();
283
284   Handle<Object> args[] = { receiver, name };
285   return CallTrap(
286       proxy, "get",  isolate->derived_get_trap(), arraysize(args), args);
287 }
288
289
290 MaybeHandle<Object> Object::GetPropertyWithAccessor(Handle<Object> receiver,
291                                                     Handle<Name> name,
292                                                     Handle<JSObject> holder,
293                                                     Handle<Object> structure) {
294   Isolate* isolate = name->GetIsolate();
295   DCHECK(!structure->IsForeign());
296   // api style callbacks.
297   if (structure->IsAccessorInfo()) {
298     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
299     if (!info->IsCompatibleReceiver(*receiver)) {
300       Handle<Object> args[] = {name, receiver};
301       THROW_NEW_ERROR(isolate,
302                       NewTypeError("incompatible_method_receiver",
303                                    HandleVector(args, arraysize(args))),
304                       Object);
305     }
306
307     Handle<ExecutableAccessorInfo> data =
308         Handle<ExecutableAccessorInfo>::cast(structure);
309     v8::AccessorNameGetterCallback call_fun =
310         v8::ToCData<v8::AccessorNameGetterCallback>(data->getter());
311     if (call_fun == NULL) return isolate->factory()->undefined_value();
312
313     LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
314     PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
315     v8::Handle<v8::Value> result =
316         args.Call(call_fun, v8::Utils::ToLocal(name));
317     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
318     if (result.IsEmpty()) {
319       return isolate->factory()->undefined_value();
320     }
321     Handle<Object> return_value = v8::Utils::OpenHandle(*result);
322     return_value->VerifyApiCallResultType();
323     // Rebox handle before return.
324     return handle(*return_value, isolate);
325   }
326
327   // __defineGetter__ callback
328   Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
329                         isolate);
330   if (getter->IsSpecFunction()) {
331     // TODO(rossberg): nicer would be to cast to some JSCallable here...
332     return Object::GetPropertyWithDefinedGetter(
333         receiver, Handle<JSReceiver>::cast(getter));
334   }
335   // Getter is not a function.
336   return isolate->factory()->undefined_value();
337 }
338
339
340 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
341                                            Handle<AccessorInfo> info,
342                                            Handle<Map> map) {
343   if (!info->HasExpectedReceiverType()) return true;
344   if (!map->IsJSObjectMap()) return false;
345   return FunctionTemplateInfo::cast(info->expected_receiver_type())
346       ->IsTemplateFor(*map);
347 }
348
349
350 MaybeHandle<Object> Object::SetPropertyWithAccessor(
351     Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
352     Handle<JSObject> holder, Handle<Object> structure,
353     LanguageMode language_mode) {
354   Isolate* isolate = name->GetIsolate();
355
356   // We should never get here to initialize a const with the hole
357   // value since a const declaration would conflict with the setter.
358   DCHECK(!structure->IsForeign());
359   if (structure->IsExecutableAccessorInfo()) {
360     // Don't call executable accessor setters with non-JSObject receivers.
361     if (!receiver->IsJSObject()) return value;
362     // api style callbacks
363     ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure);
364     if (!info->IsCompatibleReceiver(*receiver)) {
365       Handle<Object> args[] = {name, receiver};
366       THROW_NEW_ERROR(isolate,
367                       NewTypeError("incompatible_method_receiver",
368                                    HandleVector(args, arraysize(args))),
369                       Object);
370     }
371     Object* call_obj = info->setter();
372     v8::AccessorNameSetterCallback call_fun =
373         v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
374     if (call_fun == NULL) return value;
375     LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
376     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
377     args.Call(call_fun,
378               v8::Utils::ToLocal(name),
379               v8::Utils::ToLocal(value));
380     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
381     return value;
382   }
383
384   if (structure->IsAccessorPair()) {
385     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
386     if (setter->IsSpecFunction()) {
387       // TODO(rossberg): nicer would be to cast to some JSCallable here...
388       return SetPropertyWithDefinedSetter(
389           receiver, Handle<JSReceiver>::cast(setter), value);
390     } else {
391       if (is_sloppy(language_mode)) return value;
392       Handle<Object> args[] = {name, holder};
393       THROW_NEW_ERROR(isolate,
394                       NewTypeError("no_setter_in_callback",
395                                    HandleVector(args, arraysize(args))),
396                       Object);
397     }
398   }
399
400   UNREACHABLE();
401   return MaybeHandle<Object>();
402 }
403
404
405 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
406     Handle<Object> receiver,
407     Handle<JSReceiver> getter) {
408   Isolate* isolate = getter->GetIsolate();
409   Debug* debug = isolate->debug();
410   // Handle stepping into a getter if step into is active.
411   // TODO(rossberg): should this apply to getters that are function proxies?
412   if (debug->is_active()) {
413     debug->HandleStepIn(getter, Handle<Object>::null(), 0, false);
414   }
415
416   return Execution::Call(isolate, getter, receiver, 0, NULL, true);
417 }
418
419
420 MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
421     Handle<Object> receiver,
422     Handle<JSReceiver> setter,
423     Handle<Object> value) {
424   Isolate* isolate = setter->GetIsolate();
425
426   Debug* debug = isolate->debug();
427   // Handle stepping into a setter if step into is active.
428   // TODO(rossberg): should this apply to getters that are function proxies?
429   if (debug->is_active()) {
430     debug->HandleStepIn(setter, Handle<Object>::null(), 0, false);
431   }
432
433   Handle<Object> argv[] = { value };
434   RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver,
435                                                arraysize(argv), argv, true),
436                       Object);
437   return value;
438 }
439
440
441 static bool FindAllCanReadHolder(LookupIterator* it) {
442   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
443   // which have already been checked.
444   DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
445          it->state() == LookupIterator::INTERCEPTOR);
446   for (it->Next(); it->IsFound(); it->Next()) {
447     if (it->state() == LookupIterator::ACCESSOR) {
448       auto accessors = it->GetAccessors();
449       if (accessors->IsAccessorInfo()) {
450         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
451       }
452     } else if (it->state() == LookupIterator::INTERCEPTOR) {
453       auto holder = it->GetHolder<JSObject>();
454       if (holder->GetNamedInterceptor()->all_can_read()) return true;
455     }
456   }
457   return false;
458 }
459
460
461 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
462     LookupIterator* it) {
463   Handle<JSObject> checked = it->GetHolder<JSObject>();
464   while (FindAllCanReadHolder(it)) {
465     if (it->state() == LookupIterator::ACCESSOR) {
466       return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
467                                      it->GetHolder<JSObject>(),
468                                      it->GetAccessors());
469     }
470     DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
471     auto receiver = Handle<JSObject>::cast(it->GetReceiver());
472     auto result = GetPropertyWithInterceptor(it->GetHolder<JSObject>(),
473                                              receiver, it->name());
474     if (it->isolate()->has_scheduled_exception()) break;
475     if (!result.is_null()) return result;
476   }
477   it->isolate()->ReportFailedAccessCheck(checked);
478   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
479   return it->factory()->undefined_value();
480 }
481
482
483 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
484     LookupIterator* it) {
485   Handle<JSObject> checked = it->GetHolder<JSObject>();
486   while (FindAllCanReadHolder(it)) {
487     if (it->state() == LookupIterator::ACCESSOR) {
488       return Just(it->property_details().attributes());
489     }
490     DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
491     auto result = GetPropertyAttributesWithInterceptor(
492         it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
493     if (it->isolate()->has_scheduled_exception()) break;
494     if (result.IsJust() && result.FromJust() != ABSENT) return result;
495   }
496   it->isolate()->ReportFailedAccessCheck(checked);
497   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
498                                       Nothing<PropertyAttributes>());
499   return Just(ABSENT);
500 }
501
502
503 static bool FindAllCanWriteHolder(LookupIterator* it) {
504   for (; it->IsFound(); it->Next()) {
505     if (it->state() == LookupIterator::ACCESSOR) {
506       Handle<Object> accessors = it->GetAccessors();
507       if (accessors->IsAccessorInfo()) {
508         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
509       }
510     }
511   }
512   return false;
513 }
514
515
516 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
517     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
518   Handle<JSObject> checked = it->GetHolder<JSObject>();
519   if (FindAllCanWriteHolder(it)) {
520     return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
521                                    it->GetHolder<JSObject>(),
522                                    it->GetAccessors(), language_mode);
523   }
524
525   it->isolate()->ReportFailedAccessCheck(checked);
526   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
527   return value;
528 }
529
530
531 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
532                                      Handle<Name> name,
533                                      Handle<Object> value,
534                                      PropertyDetails details) {
535   DCHECK(!object->HasFastProperties());
536   Handle<NameDictionary> property_dictionary(object->property_dictionary());
537
538   if (!name->IsUniqueName()) {
539     name = object->GetIsolate()->factory()->InternalizeString(
540         Handle<String>::cast(name));
541   }
542
543   int entry = property_dictionary->FindEntry(name);
544   if (entry == NameDictionary::kNotFound) {
545     if (object->IsGlobalObject()) {
546       auto cell = object->GetIsolate()->factory()->NewPropertyCell();
547       cell->set_value(*value);
548       auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
549                                             : PropertyCellType::kConstant;
550       details = details.set_cell_type(cell_type);
551       value = cell;
552     }
553     property_dictionary =
554         NameDictionary::Add(property_dictionary, name, value, details);
555     object->set_properties(*property_dictionary);
556     return;
557   }
558
559   if (object->IsGlobalObject()) {
560     PropertyCell::UpdateCell(property_dictionary, entry, value, details);
561     return;
562   }
563
564   PropertyDetails original_details = property_dictionary->DetailsAt(entry);
565   int enumeration_index = original_details.dictionary_index();
566   DCHECK(enumeration_index > 0);
567   details = details.set_index(enumeration_index);
568   property_dictionary->SetEntry(entry, name, value, details);
569 }
570
571
572 static MaybeHandle<JSObject> FindIndexedAllCanReadHolder(
573     Isolate* isolate, Handle<JSObject> js_object,
574     PrototypeIterator::WhereToStart where_to_start) {
575   for (PrototypeIterator iter(isolate, js_object, where_to_start);
576        !iter.IsAtEnd(); iter.Advance()) {
577     auto curr = PrototypeIterator::GetCurrent(iter);
578     if (!curr->IsJSObject()) break;
579     auto obj = Handle<JSObject>::cast(curr);
580     if (!obj->HasIndexedInterceptor()) continue;
581     if (obj->GetIndexedInterceptor()->all_can_read()) return obj;
582   }
583   return MaybeHandle<JSObject>();
584 }
585
586
587 MaybeHandle<Object> JSObject::GetElementWithFailedAccessCheck(
588     Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
589     uint32_t index) {
590   Handle<JSObject> holder = object;
591   PrototypeIterator::WhereToStart where_to_start =
592       PrototypeIterator::START_AT_RECEIVER;
593   while (true) {
594     auto all_can_read_holder =
595         FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
596     if (!all_can_read_holder.ToHandle(&holder)) break;
597     auto result =
598         JSObject::GetElementWithInterceptor(holder, receiver, index, false);
599     if (isolate->has_scheduled_exception()) break;
600     if (!result.is_null()) return result;
601     where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
602   }
603   isolate->ReportFailedAccessCheck(object);
604   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
605   return isolate->factory()->undefined_value();
606 }
607
608
609 Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck(
610     Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
611     uint32_t index) {
612   Handle<JSObject> holder = object;
613   PrototypeIterator::WhereToStart where_to_start =
614       PrototypeIterator::START_AT_RECEIVER;
615   while (true) {
616     auto all_can_read_holder =
617         FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
618     if (!all_can_read_holder.ToHandle(&holder)) break;
619     auto result =
620         JSObject::GetElementAttributeFromInterceptor(holder, receiver, index);
621     if (isolate->has_scheduled_exception()) break;
622     if (result.IsJust() && result.FromJust() != ABSENT) return result;
623     where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
624   }
625   isolate->ReportFailedAccessCheck(object);
626   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
627   return Just(ABSENT);
628 }
629
630
631 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
632                                                    Handle<Object> object,
633                                                    Handle<Object> receiver,
634                                                    uint32_t index) {
635   if (object->IsUndefined()) {
636     // TODO(verwaest): Why is this check here?
637     UNREACHABLE();
638     return isolate->factory()->undefined_value();
639   }
640
641   // Iterate up the prototype chain until an element is found or the null
642   // prototype is encountered.
643   for (PrototypeIterator iter(isolate, object,
644                               object->IsJSProxy() || object->IsJSObject()
645                                   ? PrototypeIterator::START_AT_RECEIVER
646                                   : PrototypeIterator::START_AT_PROTOTYPE);
647        !iter.IsAtEnd(); iter.Advance()) {
648     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
649       return JSProxy::GetElementWithHandler(
650           Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
651           index);
652     }
653
654     // Inline the case for JSObjects. Doing so significantly improves the
655     // performance of fetching elements where checking the prototype chain is
656     // necessary.
657     Handle<JSObject> js_object =
658         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
659
660     // Check access rights if needed.
661     if (js_object->IsAccessCheckNeeded()) {
662       if (!isolate->MayAccess(js_object)) {
663         return JSObject::GetElementWithFailedAccessCheck(isolate, js_object,
664                                                          receiver, index);
665       }
666     }
667
668     if (js_object->HasIndexedInterceptor()) {
669       return JSObject::GetElementWithInterceptor(js_object, receiver, index,
670                                                  true);
671     }
672
673     if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
674       Handle<Object> result;
675       ASSIGN_RETURN_ON_EXCEPTION(
676           isolate, result,
677           js_object->GetElementsAccessor()->Get(receiver, js_object, index),
678           Object);
679       if (!result->IsTheHole()) return result;
680     }
681   }
682
683   return isolate->factory()->undefined_value();
684 }
685
686
687 MaybeHandle<Object> Object::SetElementWithReceiver(
688     Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
689     uint32_t index, Handle<Object> value, LanguageMode language_mode) {
690   // Iterate up the prototype chain until an element is found or the null
691   // prototype is encountered.
692   bool done = false;
693   for (PrototypeIterator iter(isolate, object,
694                               object->IsJSProxy() || object->IsJSObject()
695                                   ? PrototypeIterator::START_AT_RECEIVER
696                                   : PrototypeIterator::START_AT_PROTOTYPE);
697        !iter.IsAtEnd() && !done; iter.Advance()) {
698     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
699       // TODO(dslomov): implement.
700       isolate->ThrowIllegalOperation();
701       return MaybeHandle<Object>();
702     }
703
704     Handle<JSObject> js_object =
705         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
706
707     // Check access rights if needed.
708     if (js_object->IsAccessCheckNeeded()) {
709       if (!isolate->MayAccess(js_object)) {
710         isolate->ReportFailedAccessCheck(js_object);
711         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
712         return isolate->factory()->undefined_value();
713       }
714     }
715
716     if (js_object->HasIndexedInterceptor()) {
717       Maybe<PropertyAttributes> from_interceptor =
718           JSObject::GetElementAttributeFromInterceptor(js_object, receiver,
719                                                        index);
720       if (!from_interceptor.IsJust()) return MaybeHandle<Object>();
721       if ((from_interceptor.FromJust() & READ_ONLY) != 0) {
722         return WriteToReadOnlyElement(isolate, receiver, index, value,
723                                       language_mode);
724       }
725       done = from_interceptor.FromJust() != ABSENT;
726     }
727
728     if (!done &&
729         js_object->elements() != isolate->heap()->empty_fixed_array()) {
730       ElementsAccessor* accessor = js_object->GetElementsAccessor();
731       PropertyAttributes attrs = accessor->GetAttributes(js_object, index);
732       if ((attrs & READ_ONLY) != 0) {
733         return WriteToReadOnlyElement(isolate, receiver, index, value,
734                                       language_mode);
735       }
736       Handle<AccessorPair> pair;
737       if (accessor->GetAccessorPair(js_object, index).ToHandle(&pair)) {
738         return JSObject::SetElementWithCallback(receiver, pair, index, value,
739                                                 js_object, language_mode);
740       } else {
741         done = attrs != ABSENT;
742       }
743     }
744   }
745
746   if (!receiver->IsJSObject()) {
747     return WriteToReadOnlyElement(isolate, receiver, index, value,
748                                   language_mode);
749   }
750   Handle<JSObject> target = Handle<JSObject>::cast(receiver);
751   ElementsAccessor* accessor = target->GetElementsAccessor();
752   PropertyAttributes attrs = accessor->GetAttributes(target, index);
753   if (attrs == ABSENT) {
754     return JSObject::SetElement(target, index, value, NONE, language_mode,
755                                 false);
756   }
757   return JSObject::SetElement(target, index, value, attrs, language_mode, false,
758                               DEFINE_PROPERTY);
759 }
760
761
762 Map* Object::GetRootMap(Isolate* isolate) {
763   DisallowHeapAllocation no_alloc;
764   if (IsSmi()) {
765     Context* context = isolate->context()->native_context();
766     return context->number_function()->initial_map();
767   }
768
769   HeapObject* heap_object = HeapObject::cast(this);
770
771   // The object is either a number, a string, a boolean,
772   // a real JS object, or a Harmony proxy.
773   if (heap_object->IsJSReceiver()) {
774     return heap_object->map();
775   }
776   Context* context = isolate->context()->native_context();
777
778   if (heap_object->IsHeapNumber()) {
779     return context->number_function()->initial_map();
780   }
781   if (heap_object->IsString()) {
782     return context->string_function()->initial_map();
783   }
784   if (heap_object->IsSymbol()) {
785     return context->symbol_function()->initial_map();
786   }
787   if (heap_object->IsBoolean()) {
788     return context->boolean_function()->initial_map();
789   }
790   return isolate->heap()->null_value()->map();
791 }
792
793
794 Object* Object::GetHash() {
795   // The object is either a number, a name, an odd-ball,
796   // a real JS object, or a Harmony proxy.
797   if (IsSmi()) {
798     int num = Smi::cast(this)->value();
799     uint32_t hash = ComputeLongHash(double_to_uint64(static_cast<double>(num)));
800     return Smi::FromInt(hash & Smi::kMaxValue);
801   }
802   if (IsHeapNumber()) {
803     double num = HeapNumber::cast(this)->value();
804     if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
805     if (i::IsMinusZero(num)) num = 0;
806     uint32_t hash = ComputeLongHash(double_to_uint64(num));
807     return Smi::FromInt(hash & Smi::kMaxValue);
808   }
809   if (IsName()) {
810     uint32_t hash = Name::cast(this)->Hash();
811     return Smi::FromInt(hash);
812   }
813   if (IsOddball()) {
814     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
815     return Smi::FromInt(hash);
816   }
817
818   DCHECK(IsJSReceiver());
819   return JSReceiver::cast(this)->GetIdentityHash();
820 }
821
822
823 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
824   Handle<Object> hash(object->GetHash(), isolate);
825   if (hash->IsSmi()) return Handle<Smi>::cast(hash);
826
827   DCHECK(object->IsJSReceiver());
828   return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
829 }
830
831
832 bool Object::SameValue(Object* other) {
833   if (other == this) return true;
834
835   // The object is either a number, a name, an odd-ball,
836   // a real JS object, or a Harmony proxy.
837   if (IsNumber() && other->IsNumber()) {
838     double this_value = Number();
839     double other_value = other->Number();
840     bool equal = this_value == other_value;
841     // SameValue(NaN, NaN) is true.
842     if (!equal) return std::isnan(this_value) && std::isnan(other_value);
843     // SameValue(0.0, -0.0) is false.
844     return (this_value != 0) || ((1 / this_value) == (1 / other_value));
845   }
846   if (IsString() && other->IsString()) {
847     return String::cast(this)->Equals(String::cast(other));
848   }
849   return false;
850 }
851
852
853 bool Object::SameValueZero(Object* other) {
854   if (other == this) return true;
855
856   // The object is either a number, a name, an odd-ball,
857   // a real JS object, or a Harmony proxy.
858   if (IsNumber() && other->IsNumber()) {
859     double this_value = Number();
860     double other_value = other->Number();
861     // +0 == -0 is true
862     return this_value == other_value
863         || (std::isnan(this_value) && std::isnan(other_value));
864   }
865   if (IsString() && other->IsString()) {
866     return String::cast(this)->Equals(String::cast(other));
867   }
868   return false;
869 }
870
871
872 void Object::ShortPrint(FILE* out) {
873   OFStream os(out);
874   os << Brief(this);
875 }
876
877
878 void Object::ShortPrint(StringStream* accumulator) {
879   std::ostringstream os;
880   os << Brief(this);
881   accumulator->Add(os.str().c_str());
882 }
883
884
885 void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
886
887
888 std::ostream& operator<<(std::ostream& os, const Brief& v) {
889   if (v.value->IsSmi()) {
890     Smi::cast(v.value)->SmiPrint(os);
891   } else {
892     // TODO(svenpanne) Const-correct HeapObjectShortPrint!
893     HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
894     obj->HeapObjectShortPrint(os);
895   }
896   return os;
897 }
898
899
900 void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
901   os << value();
902 }
903
904
905 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
906 // English?  Returns false for non-ASCII or words that don't start with
907 // a capital letter.  The a/an rule follows pronunciation in English.
908 // We don't use the BBC's overcorrect "an historic occasion" though if
909 // you speak a dialect you may well say "an 'istoric occasion".
910 static bool AnWord(String* str) {
911   if (str->length() == 0) return false;  // A nothing.
912   int c0 = str->Get(0);
913   int c1 = str->length() > 1 ? str->Get(1) : 0;
914   if (c0 == 'U') {
915     if (c1 > 'Z') {
916       return true;  // An Umpire, but a UTF8String, a U.
917     }
918   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
919     return true;    // An Ape, an ABCBook.
920   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
921            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
922             c0 == 'S' || c0 == 'X')) {
923     return true;    // An MP3File, an M.
924   }
925   return false;
926 }
927
928
929 Handle<String> String::SlowFlatten(Handle<ConsString> cons,
930                                    PretenureFlag pretenure) {
931   DCHECK(AllowHeapAllocation::IsAllowed());
932   DCHECK(cons->second()->length() != 0);
933   Isolate* isolate = cons->GetIsolate();
934   int length = cons->length();
935   PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
936                                                             : TENURED;
937   Handle<SeqString> result;
938   if (cons->IsOneByteRepresentation()) {
939     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
940         length, tenure).ToHandleChecked();
941     DisallowHeapAllocation no_gc;
942     WriteToFlat(*cons, flat->GetChars(), 0, length);
943     result = flat;
944   } else {
945     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
946         length, tenure).ToHandleChecked();
947     DisallowHeapAllocation no_gc;
948     WriteToFlat(*cons, flat->GetChars(), 0, length);
949     result = flat;
950   }
951   cons->set_first(*result);
952   cons->set_second(isolate->heap()->empty_string());
953   DCHECK(result->IsFlat());
954   return result;
955 }
956
957
958
959 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
960   // Externalizing twice leaks the external resource, so it's
961   // prohibited by the API.
962   DCHECK(!this->IsExternalString());
963 #ifdef ENABLE_SLOW_DCHECKS
964   if (FLAG_enable_slow_asserts) {
965     // Assert that the resource and the string are equivalent.
966     DCHECK(static_cast<size_t>(this->length()) == resource->length());
967     ScopedVector<uc16> smart_chars(this->length());
968     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
969     DCHECK(memcmp(smart_chars.start(),
970                   resource->data(),
971                   resource->length() * sizeof(smart_chars[0])) == 0);
972   }
973 #endif  // DEBUG
974   int size = this->Size();  // Byte size of the original string.
975   // Abort if size does not allow in-place conversion.
976   if (size < ExternalString::kShortSize) return false;
977   Heap* heap = GetHeap();
978   bool is_one_byte = this->IsOneByteRepresentation();
979   bool is_internalized = this->IsInternalizedString();
980
981   // Morph the string to an external string by replacing the map and
982   // reinitializing the fields.  This won't work if the space the existing
983   // string occupies is too small for a regular  external string.
984   // Instead, we resort to a short external string instead, omitting
985   // the field caching the address of the backing store.  When we encounter
986   // short external strings in generated code, we need to bailout to runtime.
987   Map* new_map;
988   if (size < ExternalString::kSize) {
989     new_map = is_internalized
990         ? (is_one_byte
991            ? heap->short_external_internalized_string_with_one_byte_data_map()
992            : heap->short_external_internalized_string_map())
993         : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
994                        : heap->short_external_string_map());
995   } else {
996     new_map = is_internalized
997         ? (is_one_byte
998            ? heap->external_internalized_string_with_one_byte_data_map()
999            : heap->external_internalized_string_map())
1000         : (is_one_byte ? heap->external_string_with_one_byte_data_map()
1001                        : heap->external_string_map());
1002   }
1003
1004   // Byte size of the external String object.
1005   int new_size = this->SizeFromMap(new_map);
1006   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1007
1008   // We are storing the new map using release store after creating a filler for
1009   // the left-over space to avoid races with the sweeper thread.
1010   this->synchronized_set_map(new_map);
1011
1012   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
1013   self->set_resource(resource);
1014   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1015
1016   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1017   return true;
1018 }
1019
1020
1021 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
1022   // Externalizing twice leaks the external resource, so it's
1023   // prohibited by the API.
1024   DCHECK(!this->IsExternalString());
1025 #ifdef ENABLE_SLOW_DCHECKS
1026   if (FLAG_enable_slow_asserts) {
1027     // Assert that the resource and the string are equivalent.
1028     DCHECK(static_cast<size_t>(this->length()) == resource->length());
1029     if (this->IsTwoByteRepresentation()) {
1030       ScopedVector<uint16_t> smart_chars(this->length());
1031       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1032       DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
1033     }
1034     ScopedVector<char> smart_chars(this->length());
1035     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1036     DCHECK(memcmp(smart_chars.start(),
1037                   resource->data(),
1038                   resource->length() * sizeof(smart_chars[0])) == 0);
1039   }
1040 #endif  // DEBUG
1041   int size = this->Size();  // Byte size of the original string.
1042   // Abort if size does not allow in-place conversion.
1043   if (size < ExternalString::kShortSize) return false;
1044   Heap* heap = GetHeap();
1045   bool is_internalized = this->IsInternalizedString();
1046
1047   // Morph the string to an external string by replacing the map and
1048   // reinitializing the fields.  This won't work if the space the existing
1049   // string occupies is too small for a regular  external string.
1050   // Instead, we resort to a short external string instead, omitting
1051   // the field caching the address of the backing store.  When we encounter
1052   // short external strings in generated code, we need to bailout to runtime.
1053   Map* new_map;
1054   if (size < ExternalString::kSize) {
1055     new_map = is_internalized
1056                   ? heap->short_external_one_byte_internalized_string_map()
1057                   : heap->short_external_one_byte_string_map();
1058   } else {
1059     new_map = is_internalized
1060                   ? heap->external_one_byte_internalized_string_map()
1061                   : heap->external_one_byte_string_map();
1062   }
1063
1064   // Byte size of the external String object.
1065   int new_size = this->SizeFromMap(new_map);
1066   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1067
1068   // We are storing the new map using release store after creating a filler for
1069   // the left-over space to avoid races with the sweeper thread.
1070   this->synchronized_set_map(new_map);
1071
1072   ExternalOneByteString* self = ExternalOneByteString::cast(this);
1073   self->set_resource(resource);
1074   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1075
1076   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1077   return true;
1078 }
1079
1080
1081 void String::StringShortPrint(StringStream* accumulator) {
1082   int len = length();
1083   if (len > kMaxShortPrintLength) {
1084     accumulator->Add("<Very long string[%u]>", len);
1085     return;
1086   }
1087
1088   if (!LooksValid()) {
1089     accumulator->Add("<Invalid String>");
1090     return;
1091   }
1092
1093   StringCharacterStream stream(this);
1094
1095   bool truncated = false;
1096   if (len > kMaxShortPrintLength) {
1097     len = kMaxShortPrintLength;
1098     truncated = true;
1099   }
1100   bool one_byte = true;
1101   for (int i = 0; i < len; i++) {
1102     uint16_t c = stream.GetNext();
1103
1104     if (c < 32 || c >= 127) {
1105       one_byte = false;
1106     }
1107   }
1108   stream.Reset(this);
1109   if (one_byte) {
1110     accumulator->Add("<String[%u]: ", length());
1111     for (int i = 0; i < len; i++) {
1112       accumulator->Put(static_cast<char>(stream.GetNext()));
1113     }
1114     accumulator->Put('>');
1115   } else {
1116     // Backslash indicates that the string contains control
1117     // characters and that backslashes are therefore escaped.
1118     accumulator->Add("<String[%u]\\: ", length());
1119     for (int i = 0; i < len; i++) {
1120       uint16_t c = stream.GetNext();
1121       if (c == '\n') {
1122         accumulator->Add("\\n");
1123       } else if (c == '\r') {
1124         accumulator->Add("\\r");
1125       } else if (c == '\\') {
1126         accumulator->Add("\\\\");
1127       } else if (c < 32 || c > 126) {
1128         accumulator->Add("\\x%02x", c);
1129       } else {
1130         accumulator->Put(static_cast<char>(c));
1131       }
1132     }
1133     if (truncated) {
1134       accumulator->Put('.');
1135       accumulator->Put('.');
1136       accumulator->Put('.');
1137     }
1138     accumulator->Put('>');
1139   }
1140   return;
1141 }
1142
1143
1144 void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
1145   if (end < 0) end = length();
1146   StringCharacterStream stream(this, start);
1147   for (int i = start; i < end && stream.HasMore(); i++) {
1148     os << AsUC16(stream.GetNext());
1149   }
1150 }
1151
1152
1153 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1154   switch (map()->instance_type()) {
1155     case JS_ARRAY_TYPE: {
1156       double length = JSArray::cast(this)->length()->IsUndefined()
1157           ? 0
1158           : JSArray::cast(this)->length()->Number();
1159       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1160       break;
1161     }
1162     case JS_WEAK_MAP_TYPE: {
1163       accumulator->Add("<JS WeakMap>");
1164       break;
1165     }
1166     case JS_WEAK_SET_TYPE: {
1167       accumulator->Add("<JS WeakSet>");
1168       break;
1169     }
1170     case JS_REGEXP_TYPE: {
1171       accumulator->Add("<JS RegExp>");
1172       break;
1173     }
1174     case JS_FUNCTION_TYPE: {
1175       JSFunction* function = JSFunction::cast(this);
1176       Object* fun_name = function->shared()->DebugName();
1177       bool printed = false;
1178       if (fun_name->IsString()) {
1179         String* str = String::cast(fun_name);
1180         if (str->length() > 0) {
1181           accumulator->Add("<JS Function ");
1182           accumulator->Put(str);
1183           printed = true;
1184         }
1185       }
1186       if (!printed) {
1187         accumulator->Add("<JS Function");
1188       }
1189       accumulator->Add(" (SharedFunctionInfo %p)",
1190                        reinterpret_cast<void*>(function->shared()));
1191       accumulator->Put('>');
1192       break;
1193     }
1194     case JS_GENERATOR_OBJECT_TYPE: {
1195       accumulator->Add("<JS Generator>");
1196       break;
1197     }
1198     case JS_MODULE_TYPE: {
1199       accumulator->Add("<JS Module>");
1200       break;
1201     }
1202     // All other JSObjects are rather similar to each other (JSObject,
1203     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1204     default: {
1205       Map* map_of_this = map();
1206       Heap* heap = GetHeap();
1207       Object* constructor = map_of_this->GetConstructor();
1208       bool printed = false;
1209       if (constructor->IsHeapObject() &&
1210           !heap->Contains(HeapObject::cast(constructor))) {
1211         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1212       } else {
1213         bool global_object = IsJSGlobalProxy();
1214         if (constructor->IsJSFunction()) {
1215           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1216             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1217           } else {
1218             Object* constructor_name =
1219                 JSFunction::cast(constructor)->shared()->name();
1220             if (constructor_name->IsString()) {
1221               String* str = String::cast(constructor_name);
1222               if (str->length() > 0) {
1223                 bool vowel = AnWord(str);
1224                 accumulator->Add("<%sa%s ",
1225                        global_object ? "Global Object: " : "",
1226                        vowel ? "n" : "");
1227                 accumulator->Put(str);
1228                 accumulator->Add(" with %smap %p",
1229                     map_of_this->is_deprecated() ? "deprecated " : "",
1230                     map_of_this);
1231                 printed = true;
1232               }
1233             }
1234           }
1235         }
1236         if (!printed) {
1237           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1238         }
1239       }
1240       if (IsJSValue()) {
1241         accumulator->Add(" value = ");
1242         JSValue::cast(this)->value()->ShortPrint(accumulator);
1243       }
1244       accumulator->Put('>');
1245       break;
1246     }
1247   }
1248 }
1249
1250
1251 void JSObject::PrintElementsTransition(
1252     FILE* file, Handle<JSObject> object,
1253     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
1254     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
1255   if (from_kind != to_kind) {
1256     OFStream os(file);
1257     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
1258        << ElementsKindToString(to_kind) << "] in ";
1259     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
1260     PrintF(file, " for ");
1261     object->ShortPrint(file);
1262     PrintF(file, " from ");
1263     from_elements->ShortPrint(file);
1264     PrintF(file, " to ");
1265     to_elements->ShortPrint(file);
1266     PrintF(file, "\n");
1267   }
1268 }
1269
1270
1271 void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
1272                                PropertyAttributes attributes) {
1273   OFStream os(file);
1274   os << "[reconfiguring ";
1275   constructor_name()->PrintOn(file);
1276   os << "] ";
1277   Name* name = instance_descriptors()->GetKey(modify_index);
1278   if (name->IsString()) {
1279     String::cast(name)->PrintOn(file);
1280   } else {
1281     os << "{symbol " << static_cast<void*>(name) << "}";
1282   }
1283   os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
1284   os << attributes << " [";
1285   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1286   os << "]\n";
1287 }
1288
1289
1290 void Map::PrintGeneralization(FILE* file,
1291                               const char* reason,
1292                               int modify_index,
1293                               int split,
1294                               int descriptors,
1295                               bool constant_to_field,
1296                               Representation old_representation,
1297                               Representation new_representation,
1298                               HeapType* old_field_type,
1299                               HeapType* new_field_type) {
1300   OFStream os(file);
1301   os << "[generalizing ";
1302   constructor_name()->PrintOn(file);
1303   os << "] ";
1304   Name* name = instance_descriptors()->GetKey(modify_index);
1305   if (name->IsString()) {
1306     String::cast(name)->PrintOn(file);
1307   } else {
1308     os << "{symbol " << static_cast<void*>(name) << "}";
1309   }
1310   os << ":";
1311   if (constant_to_field) {
1312     os << "c";
1313   } else {
1314     os << old_representation.Mnemonic() << "{";
1315     old_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1316     os << "}";
1317   }
1318   os << "->" << new_representation.Mnemonic() << "{";
1319   new_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1320   os << "} (";
1321   if (strlen(reason) > 0) {
1322     os << reason;
1323   } else {
1324     os << "+" << (descriptors - split) << " maps";
1325   }
1326   os << ") [";
1327   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1328   os << "]\n";
1329 }
1330
1331
1332 void JSObject::PrintInstanceMigration(FILE* file,
1333                                       Map* original_map,
1334                                       Map* new_map) {
1335   PrintF(file, "[migrating ");
1336   map()->constructor_name()->PrintOn(file);
1337   PrintF(file, "] ");
1338   DescriptorArray* o = original_map->instance_descriptors();
1339   DescriptorArray* n = new_map->instance_descriptors();
1340   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
1341     Representation o_r = o->GetDetails(i).representation();
1342     Representation n_r = n->GetDetails(i).representation();
1343     if (!o_r.Equals(n_r)) {
1344       String::cast(o->GetKey(i))->PrintOn(file);
1345       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
1346     } else if (o->GetDetails(i).type() == DATA_CONSTANT &&
1347                n->GetDetails(i).type() == DATA) {
1348       Name* name = o->GetKey(i);
1349       if (name->IsString()) {
1350         String::cast(name)->PrintOn(file);
1351       } else {
1352         PrintF(file, "{symbol %p}", static_cast<void*>(name));
1353       }
1354       PrintF(file, " ");
1355     }
1356   }
1357   PrintF(file, "\n");
1358 }
1359
1360
1361 void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
1362   Heap* heap = GetHeap();
1363   if (!heap->Contains(this)) {
1364     os << "!!!INVALID POINTER!!!";
1365     return;
1366   }
1367   if (!heap->Contains(map())) {
1368     os << "!!!INVALID MAP!!!";
1369     return;
1370   }
1371
1372   os << this << " ";
1373
1374   if (IsString()) {
1375     HeapStringAllocator allocator;
1376     StringStream accumulator(&allocator);
1377     String::cast(this)->StringShortPrint(&accumulator);
1378     os << accumulator.ToCString().get();
1379     return;
1380   }
1381   if (IsJSObject()) {
1382     HeapStringAllocator allocator;
1383     StringStream accumulator(&allocator);
1384     JSObject::cast(this)->JSObjectShortPrint(&accumulator);
1385     os << accumulator.ToCString().get();
1386     return;
1387   }
1388   switch (map()->instance_type()) {
1389     case MAP_TYPE:
1390       os << "<Map(elements=" << Map::cast(this)->elements_kind() << ")>";
1391       break;
1392     case FIXED_ARRAY_TYPE:
1393       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
1394       break;
1395     case FIXED_DOUBLE_ARRAY_TYPE:
1396       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
1397          << "]>";
1398       break;
1399     case BYTE_ARRAY_TYPE:
1400       os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
1401       break;
1402     case FREE_SPACE_TYPE:
1403       os << "<FreeSpace[" << FreeSpace::cast(this)->Size() << "]>";
1404       break;
1405 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
1406   case EXTERNAL_##TYPE##_ARRAY_TYPE:                                          \
1407     os << "<External" #Type "Array["                                          \
1408        << External##Type##Array::cast(this)->length() << "]>";                \
1409     break;                                                                    \
1410   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
1411     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
1412        << "]>";                                                               \
1413     break;
1414
1415     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1416 #undef TYPED_ARRAY_SHORT_PRINT
1417
1418     case SHARED_FUNCTION_INFO_TYPE: {
1419       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
1420       SmartArrayPointer<char> debug_name =
1421           shared->DebugName()->ToCString();
1422       if (debug_name[0] != 0) {
1423         os << "<SharedFunctionInfo " << debug_name.get() << ">";
1424       } else {
1425         os << "<SharedFunctionInfo>";
1426       }
1427       break;
1428     }
1429     case JS_MESSAGE_OBJECT_TYPE:
1430       os << "<JSMessageObject>";
1431       break;
1432 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1433   case NAME##_TYPE:                        \
1434     os << "<" #Name ">";                   \
1435     break;
1436   STRUCT_LIST(MAKE_STRUCT_CASE)
1437 #undef MAKE_STRUCT_CASE
1438     case CODE_TYPE: {
1439       Code* code = Code::cast(this);
1440       os << "<Code: " << Code::Kind2String(code->kind()) << ">";
1441       break;
1442     }
1443     case ODDBALL_TYPE: {
1444       if (IsUndefined()) {
1445         os << "<undefined>";
1446       } else if (IsTheHole()) {
1447         os << "<the hole>";
1448       } else if (IsNull()) {
1449         os << "<null>";
1450       } else if (IsTrue()) {
1451         os << "<true>";
1452       } else if (IsFalse()) {
1453         os << "<false>";
1454       } else {
1455         os << "<Odd Oddball>";
1456       }
1457       break;
1458     }
1459     case SYMBOL_TYPE: {
1460       Symbol* symbol = Symbol::cast(this);
1461       symbol->SymbolShortPrint(os);
1462       break;
1463     }
1464     case HEAP_NUMBER_TYPE: {
1465       os << "<Number: ";
1466       HeapNumber::cast(this)->HeapNumberPrint(os);
1467       os << ">";
1468       break;
1469     }
1470     case MUTABLE_HEAP_NUMBER_TYPE: {
1471       os << "<MutableNumber: ";
1472       HeapNumber::cast(this)->HeapNumberPrint(os);
1473       os << '>';
1474       break;
1475     }
1476     case JS_PROXY_TYPE:
1477       os << "<JSProxy>";
1478       break;
1479     case JS_FUNCTION_PROXY_TYPE:
1480       os << "<JSFunctionProxy>";
1481       break;
1482     case FOREIGN_TYPE:
1483       os << "<Foreign>";
1484       break;
1485     case CELL_TYPE: {
1486       os << "Cell for ";
1487       HeapStringAllocator allocator;
1488       StringStream accumulator(&allocator);
1489       Cell::cast(this)->value()->ShortPrint(&accumulator);
1490       os << accumulator.ToCString().get();
1491       break;
1492     }
1493     case PROPERTY_CELL_TYPE: {
1494       os << "PropertyCell for ";
1495       HeapStringAllocator allocator;
1496       StringStream accumulator(&allocator);
1497       PropertyCell::cast(this)->value()->ShortPrint(&accumulator);
1498       os << accumulator.ToCString().get();
1499       break;
1500     }
1501     case WEAK_CELL_TYPE: {
1502       os << "WeakCell for ";
1503       HeapStringAllocator allocator;
1504       StringStream accumulator(&allocator);
1505       WeakCell::cast(this)->value()->ShortPrint(&accumulator);
1506       os << accumulator.ToCString().get();
1507       break;
1508     }
1509     default:
1510       os << "<Other heap object (" << map()->instance_type() << ")>";
1511       break;
1512   }
1513 }
1514
1515
1516 void HeapObject::Iterate(ObjectVisitor* v) {
1517   // Handle header
1518   IteratePointer(v, kMapOffset);
1519   // Handle object body
1520   Map* m = map();
1521   IterateBody(m->instance_type(), SizeFromMap(m), v);
1522 }
1523
1524
1525 void HeapObject::IterateBody(InstanceType type, int object_size,
1526                              ObjectVisitor* v) {
1527   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1528   // During GC, the map pointer field is encoded.
1529   if (type < FIRST_NONSTRING_TYPE) {
1530     switch (type & kStringRepresentationMask) {
1531       case kSeqStringTag:
1532         break;
1533       case kConsStringTag:
1534         ConsString::BodyDescriptor::IterateBody(this, v);
1535         break;
1536       case kSlicedStringTag:
1537         SlicedString::BodyDescriptor::IterateBody(this, v);
1538         break;
1539       case kExternalStringTag:
1540         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1541           reinterpret_cast<ExternalOneByteString*>(this)
1542               ->ExternalOneByteStringIterateBody(v);
1543         } else {
1544           reinterpret_cast<ExternalTwoByteString*>(this)->
1545               ExternalTwoByteStringIterateBody(v);
1546         }
1547         break;
1548     }
1549     return;
1550   }
1551
1552   switch (type) {
1553     case FIXED_ARRAY_TYPE:
1554       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1555       break;
1556     case CONSTANT_POOL_ARRAY_TYPE:
1557       reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v);
1558       break;
1559     case FIXED_DOUBLE_ARRAY_TYPE:
1560       break;
1561     case JS_OBJECT_TYPE:
1562     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1563     case JS_GENERATOR_OBJECT_TYPE:
1564     case JS_MODULE_TYPE:
1565     case JS_VALUE_TYPE:
1566     case JS_DATE_TYPE:
1567     case JS_ARRAY_TYPE:
1568     case JS_ARRAY_BUFFER_TYPE:
1569     case JS_TYPED_ARRAY_TYPE:
1570     case JS_DATA_VIEW_TYPE:
1571     case JS_SET_TYPE:
1572     case JS_MAP_TYPE:
1573     case JS_SET_ITERATOR_TYPE:
1574     case JS_MAP_ITERATOR_TYPE:
1575     case JS_WEAK_MAP_TYPE:
1576     case JS_WEAK_SET_TYPE:
1577     case JS_REGEXP_TYPE:
1578     case JS_GLOBAL_PROXY_TYPE:
1579     case JS_GLOBAL_OBJECT_TYPE:
1580     case JS_BUILTINS_OBJECT_TYPE:
1581     case JS_MESSAGE_OBJECT_TYPE:
1582       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1583       break;
1584     case JS_FUNCTION_TYPE:
1585       reinterpret_cast<JSFunction*>(this)
1586           ->JSFunctionIterateBody(object_size, v);
1587       break;
1588     case ODDBALL_TYPE:
1589       Oddball::BodyDescriptor::IterateBody(this, v);
1590       break;
1591     case JS_PROXY_TYPE:
1592       JSProxy::BodyDescriptor::IterateBody(this, v);
1593       break;
1594     case JS_FUNCTION_PROXY_TYPE:
1595       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1596       break;
1597     case FOREIGN_TYPE:
1598       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1599       break;
1600     case MAP_TYPE:
1601       Map::BodyDescriptor::IterateBody(this, v);
1602       break;
1603     case CODE_TYPE:
1604       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1605       break;
1606     case CELL_TYPE:
1607       Cell::BodyDescriptor::IterateBody(this, v);
1608       break;
1609     case PROPERTY_CELL_TYPE:
1610       PropertyCell::BodyDescriptor::IterateBody(this, v);
1611       break;
1612     case WEAK_CELL_TYPE:
1613       WeakCell::BodyDescriptor::IterateBody(this, v);
1614       break;
1615     case SYMBOL_TYPE:
1616       Symbol::BodyDescriptor::IterateBody(this, v);
1617       break;
1618
1619     case HEAP_NUMBER_TYPE:
1620     case MUTABLE_HEAP_NUMBER_TYPE:
1621     case FILLER_TYPE:
1622     case BYTE_ARRAY_TYPE:
1623     case FREE_SPACE_TYPE:
1624       break;
1625
1626 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
1627     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
1628     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
1629       break;
1630
1631     TYPED_ARRAYS(TYPED_ARRAY_CASE)
1632 #undef TYPED_ARRAY_CASE
1633
1634     case SHARED_FUNCTION_INFO_TYPE: {
1635       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1636       break;
1637     }
1638
1639 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1640         case NAME##_TYPE:
1641       STRUCT_LIST(MAKE_STRUCT_CASE)
1642 #undef MAKE_STRUCT_CASE
1643       if (type == ALLOCATION_SITE_TYPE) {
1644         AllocationSite::BodyDescriptor::IterateBody(this, v);
1645       } else {
1646         StructBodyDescriptor::IterateBody(this, object_size, v);
1647       }
1648       break;
1649     default:
1650       PrintF("Unknown type: %d\n", type);
1651       UNREACHABLE();
1652   }
1653 }
1654
1655
1656 bool HeapNumber::HeapNumberBooleanValue() {
1657   return DoubleToBoolean(value());
1658 }
1659
1660
1661 void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
1662   os << value();
1663 }
1664
1665
1666 String* JSReceiver::class_name() {
1667   if (IsJSFunction() || IsJSFunctionProxy()) {
1668     return GetHeap()->Function_string();
1669   }
1670   Object* maybe_constructor = map()->GetConstructor();
1671   if (maybe_constructor->IsJSFunction()) {
1672     JSFunction* constructor = JSFunction::cast(maybe_constructor);
1673     return String::cast(constructor->shared()->instance_class_name());
1674   }
1675   // If the constructor is not present, return "Object".
1676   return GetHeap()->Object_string();
1677 }
1678
1679
1680 String* Map::constructor_name() {
1681   Object* maybe_constructor = GetConstructor();
1682   if (maybe_constructor->IsJSFunction()) {
1683     JSFunction* constructor = JSFunction::cast(maybe_constructor);
1684     String* name = String::cast(constructor->shared()->name());
1685     if (name->length() > 0) return name;
1686     String* inferred_name = constructor->shared()->inferred_name();
1687     if (inferred_name->length() > 0) return inferred_name;
1688     Object* proto = prototype();
1689     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1690   }
1691   // TODO(rossberg): what about proxies?
1692   // If the constructor is not present, return "Object".
1693   return GetHeap()->Object_string();
1694 }
1695
1696
1697 String* JSReceiver::constructor_name() {
1698   return map()->constructor_name();
1699 }
1700
1701
1702 static Handle<Object> WrapType(Handle<HeapType> type) {
1703   if (type->IsClass()) return Map::WeakCellForMap(type->AsClass()->Map());
1704   return type;
1705 }
1706
1707
1708 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
1709                                     Handle<Name> name,
1710                                     Handle<HeapType> type,
1711                                     PropertyAttributes attributes,
1712                                     Representation representation,
1713                                     TransitionFlag flag) {
1714   DCHECK(DescriptorArray::kNotFound ==
1715          map->instance_descriptors()->Search(
1716              *name, map->NumberOfOwnDescriptors()));
1717
1718   // Ensure the descriptor array does not get too big.
1719   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1720     return MaybeHandle<Map>();
1721   }
1722
1723   Isolate* isolate = map->GetIsolate();
1724
1725   // Compute the new index for new field.
1726   int index = map->NextFreePropertyIndex();
1727
1728   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1729     representation = Representation::Tagged();
1730     type = HeapType::Any(isolate);
1731   }
1732
1733   Handle<Object> wrapped_type(WrapType(type));
1734
1735   DataDescriptor new_field_desc(name, index, wrapped_type, attributes,
1736                                 representation);
1737   Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1738   int unused_property_fields = new_map->unused_property_fields() - 1;
1739   if (unused_property_fields < 0) {
1740     unused_property_fields += JSObject::kFieldsAdded;
1741   }
1742   new_map->set_unused_property_fields(unused_property_fields);
1743   return new_map;
1744 }
1745
1746
1747 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1748                                        Handle<Name> name,
1749                                        Handle<Object> constant,
1750                                        PropertyAttributes attributes,
1751                                        TransitionFlag flag) {
1752   // Ensure the descriptor array does not get too big.
1753   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1754     return MaybeHandle<Map>();
1755   }
1756
1757   // Allocate new instance descriptors with (name, constant) added.
1758   DataConstantDescriptor new_constant_desc(name, constant, attributes);
1759   return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1760 }
1761
1762
1763 void JSObject::AddSlowProperty(Handle<JSObject> object,
1764                                Handle<Name> name,
1765                                Handle<Object> value,
1766                                PropertyAttributes attributes) {
1767   DCHECK(!object->HasFastProperties());
1768   Isolate* isolate = object->GetIsolate();
1769   Handle<NameDictionary> dict(object->property_dictionary());
1770   PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid);
1771   if (object->IsGlobalObject()) {
1772     int entry = dict->FindEntry(name);
1773     // If there's a cell there, just invalidate and set the property.
1774     if (entry != NameDictionary::kNotFound) {
1775       PropertyCell::UpdateCell(dict, entry, value, details);
1776       // TODO(dcarney): move this to UpdateCell.
1777       // Need to adjust the details.
1778       int index = dict->NextEnumerationIndex();
1779       dict->SetNextEnumerationIndex(index + 1);
1780       details = dict->DetailsAt(entry).set_index(index);
1781       dict->DetailsAtPut(entry, details);
1782       return;
1783     }
1784     auto cell = isolate->factory()->NewPropertyCell();
1785     cell->set_value(*value);
1786     auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
1787                                           : PropertyCellType::kConstant;
1788     details = details.set_cell_type(cell_type);
1789     value = cell;
1790   }
1791   Handle<NameDictionary> result =
1792       NameDictionary::Add(dict, name, value, details);
1793   if (*dict != *result) object->set_properties(*result);
1794 }
1795
1796
1797 Context* JSObject::GetCreationContext() {
1798   Object* constructor = this->map()->GetConstructor();
1799   JSFunction* function;
1800   if (!constructor->IsJSFunction()) {
1801     // Functions have null as a constructor,
1802     // but any JSFunction knows its context immediately.
1803     function = JSFunction::cast(this);
1804   } else {
1805     function = JSFunction::cast(constructor);
1806   }
1807
1808   return function->context()->native_context();
1809 }
1810
1811
1812 MaybeHandle<Object> JSObject::EnqueueChangeRecord(Handle<JSObject> object,
1813                                                   const char* type_str,
1814                                                   Handle<Name> name,
1815                                                   Handle<Object> old_value) {
1816   DCHECK(!object->IsJSGlobalProxy());
1817   DCHECK(!object->IsJSGlobalObject());
1818   Isolate* isolate = object->GetIsolate();
1819   HandleScope scope(isolate);
1820   Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
1821   Handle<Object> args[] = { type, object, name, old_value };
1822   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
1823
1824   return Execution::Call(isolate,
1825                          Handle<JSFunction>(isolate->observers_notify_change()),
1826                          isolate->factory()->undefined_value(), argc, args);
1827 }
1828
1829
1830 const char* Representation::Mnemonic() const {
1831   switch (kind_) {
1832     case kNone: return "v";
1833     case kTagged: return "t";
1834     case kSmi: return "s";
1835     case kDouble: return "d";
1836     case kInteger32: return "i";
1837     case kHeapObject: return "h";
1838     case kExternal: return "x";
1839     default:
1840       UNREACHABLE();
1841       return NULL;
1842   }
1843 }
1844
1845
1846 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
1847                                  int target_inobject, int target_unused,
1848                                  int* old_number_of_fields) {
1849   // If fields were added (or removed), rewrite the instance.
1850   *old_number_of_fields = NumberOfFields();
1851   DCHECK(target_number_of_fields >= *old_number_of_fields);
1852   if (target_number_of_fields != *old_number_of_fields) return true;
1853
1854   // If smi descriptors were replaced by double descriptors, rewrite.
1855   DescriptorArray* old_desc = instance_descriptors();
1856   DescriptorArray* new_desc = target->instance_descriptors();
1857   int limit = NumberOfOwnDescriptors();
1858   for (int i = 0; i < limit; i++) {
1859     if (new_desc->GetDetails(i).representation().IsDouble() !=
1860         old_desc->GetDetails(i).representation().IsDouble()) {
1861       return true;
1862     }
1863   }
1864
1865   // If no fields were added, and no inobject properties were removed, setting
1866   // the map is sufficient.
1867   if (target_inobject == inobject_properties()) return false;
1868   // In-object slack tracking may have reduced the object size of the new map.
1869   // In that case, succeed if all existing fields were inobject, and they still
1870   // fit within the new inobject size.
1871   DCHECK(target_inobject < inobject_properties());
1872   if (target_number_of_fields <= target_inobject) {
1873     DCHECK(target_number_of_fields + target_unused == target_inobject);
1874     return false;
1875   }
1876   // Otherwise, properties will need to be moved to the backing store.
1877   return true;
1878 }
1879
1880
1881 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) {
1882   Isolate* isolate = parent->GetIsolate();
1883   Handle<Name> name = isolate->factory()->elements_transition_symbol();
1884   ConnectTransition(parent, child, name, SPECIAL_TRANSITION);
1885 }
1886
1887
1888 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
1889   if (object->map() == *new_map) return;
1890   if (object->HasFastProperties()) {
1891     if (!new_map->is_dictionary_map()) {
1892       Handle<Map> old_map(object->map());
1893       MigrateFastToFast(object, new_map);
1894       if (old_map->is_prototype_map()) {
1895         // Clear out the old descriptor array to avoid problems to sharing
1896         // the descriptor array without using an explicit.
1897         old_map->InitializeDescriptors(
1898             old_map->GetHeap()->empty_descriptor_array(),
1899             LayoutDescriptor::FastPointerLayout());
1900         // Ensure that no transition was inserted for prototype migrations.
1901         DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
1902                          old_map->raw_transitions()));
1903         DCHECK(new_map->GetBackPointer()->IsUndefined());
1904       }
1905     } else {
1906       MigrateFastToSlow(object, new_map, 0);
1907     }
1908   } else {
1909     // For slow-to-fast migrations JSObject::TransformToFastProperties()
1910     // must be used instead.
1911     CHECK(new_map->is_dictionary_map());
1912
1913     // Slow-to-slow migration is trivial.
1914     object->set_map(*new_map);
1915   }
1916 }
1917
1918
1919 // To migrate a fast instance to a fast map:
1920 // - First check whether the instance needs to be rewritten. If not, simply
1921 //   change the map.
1922 // - Otherwise, allocate a fixed array large enough to hold all fields, in
1923 //   addition to unused space.
1924 // - Copy all existing properties in, in the following order: backing store
1925 //   properties, unused fields, inobject properties.
1926 // - If all allocation succeeded, commit the state atomically:
1927 //   * Copy inobject properties from the backing store back into the object.
1928 //   * Trim the difference in instance size of the object. This also cleanly
1929 //     frees inobject properties that moved to the backing store.
1930 //   * If there are properties left in the backing store, trim of the space used
1931 //     to temporarily store the inobject properties.
1932 //   * If there are properties left in the backing store, install the backing
1933 //     store.
1934 void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
1935   Isolate* isolate = object->GetIsolate();
1936   Handle<Map> old_map(object->map());
1937   int old_number_of_fields;
1938   int number_of_fields = new_map->NumberOfFields();
1939   int inobject = new_map->inobject_properties();
1940   int unused = new_map->unused_property_fields();
1941
1942   // Nothing to do if no functions were converted to fields and no smis were
1943   // converted to doubles.
1944   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
1945                                        unused, &old_number_of_fields)) {
1946     object->synchronized_set_map(*new_map);
1947     return;
1948   }
1949
1950   int total_size = number_of_fields + unused;
1951   int external = total_size - inobject;
1952
1953   if (number_of_fields != old_number_of_fields &&
1954       new_map->GetBackPointer() == *old_map) {
1955     PropertyDetails details = new_map->GetLastDescriptorDetails();
1956
1957     if (old_map->unused_property_fields() > 0) {
1958       if (details.representation().IsDouble()) {
1959         FieldIndex index =
1960             FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
1961         if (new_map->IsUnboxedDoubleField(index)) {
1962           object->RawFastDoublePropertyAtPut(index, 0);
1963         } else {
1964           Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1965           object->RawFastPropertyAtPut(index, *value);
1966         }
1967       }
1968       object->synchronized_set_map(*new_map);
1969       return;
1970     }
1971
1972     DCHECK(number_of_fields == old_number_of_fields + 1);
1973     // This migration is a transition from a map that has run out of property
1974     // space. Therefore it could be done by extending the backing store.
1975     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
1976     Handle<FixedArray> new_storage =
1977         FixedArray::CopySize(old_storage, external);
1978
1979     // Properly initialize newly added property.
1980     Handle<Object> value;
1981     if (details.representation().IsDouble()) {
1982       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1983     } else {
1984       value = isolate->factory()->uninitialized_value();
1985     }
1986     DCHECK(details.type() == DATA);
1987     int target_index = details.field_index() - inobject;
1988     DCHECK(target_index >= 0);  // Must be a backing store index.
1989     new_storage->set(target_index, *value);
1990
1991     // From here on we cannot fail and we shouldn't GC anymore.
1992     DisallowHeapAllocation no_allocation;
1993
1994     // Set the new property value and do the map transition.
1995     object->set_properties(*new_storage);
1996     object->synchronized_set_map(*new_map);
1997     return;
1998   }
1999   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
2000
2001   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
2002   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
2003   int old_nof = old_map->NumberOfOwnDescriptors();
2004   int new_nof = new_map->NumberOfOwnDescriptors();
2005
2006   // This method only supports generalizing instances to at least the same
2007   // number of properties.
2008   DCHECK(old_nof <= new_nof);
2009
2010   for (int i = 0; i < old_nof; i++) {
2011     PropertyDetails details = new_descriptors->GetDetails(i);
2012     if (details.type() != DATA) continue;
2013     PropertyDetails old_details = old_descriptors->GetDetails(i);
2014     Representation old_representation = old_details.representation();
2015     Representation representation = details.representation();
2016     Handle<Object> value;
2017     if (old_details.type() == ACCESSOR_CONSTANT) {
2018       // In case of kAccessor -> kData property reconfiguration, the property
2019       // must already be prepared for data or certain type.
2020       DCHECK(!details.representation().IsNone());
2021       if (details.representation().IsDouble()) {
2022         value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2023       } else {
2024         value = isolate->factory()->uninitialized_value();
2025       }
2026     } else if (old_details.type() == DATA_CONSTANT) {
2027       value = handle(old_descriptors->GetValue(i), isolate);
2028       DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
2029     } else {
2030       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
2031       if (object->IsUnboxedDoubleField(index)) {
2032         double old = object->RawFastDoublePropertyAt(index);
2033         value = isolate->factory()->NewHeapNumber(
2034             old, representation.IsDouble() ? MUTABLE : IMMUTABLE);
2035
2036       } else {
2037         value = handle(object->RawFastPropertyAt(index), isolate);
2038         if (!old_representation.IsDouble() && representation.IsDouble()) {
2039           if (old_representation.IsNone()) {
2040             value = handle(Smi::FromInt(0), isolate);
2041           }
2042           value = Object::NewStorageFor(isolate, value, representation);
2043         } else if (old_representation.IsDouble() &&
2044                    !representation.IsDouble()) {
2045           value = Object::WrapForRead(isolate, value, old_representation);
2046         }
2047       }
2048     }
2049     DCHECK(!(representation.IsDouble() && value->IsSmi()));
2050     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2051     if (target_index < 0) target_index += total_size;
2052     array->set(target_index, *value);
2053   }
2054
2055   for (int i = old_nof; i < new_nof; i++) {
2056     PropertyDetails details = new_descriptors->GetDetails(i);
2057     if (details.type() != DATA) continue;
2058     Handle<Object> value;
2059     if (details.representation().IsDouble()) {
2060       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2061     } else {
2062       value = isolate->factory()->uninitialized_value();
2063     }
2064     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2065     if (target_index < 0) target_index += total_size;
2066     array->set(target_index, *value);
2067   }
2068
2069   // From here on we cannot fail and we shouldn't GC anymore.
2070   DisallowHeapAllocation no_allocation;
2071
2072   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2073   // avoid overwriting |one_pointer_filler_map|.
2074   int limit = Min(inobject, number_of_fields);
2075   for (int i = 0; i < limit; i++) {
2076     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
2077     Object* value = array->get(external + i);
2078     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
2079     // yet.
2080     if (new_map->IsUnboxedDoubleField(index)) {
2081       DCHECK(value->IsMutableHeapNumber());
2082       object->RawFastDoublePropertyAtPut(index,
2083                                          HeapNumber::cast(value)->value());
2084     } else {
2085       object->RawFastPropertyAtPut(index, value);
2086     }
2087   }
2088
2089   Heap* heap = isolate->heap();
2090
2091   // If there are properties in the new backing store, trim it to the correct
2092   // size and install the backing store into the object.
2093   if (external > 0) {
2094     heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, inobject);
2095     object->set_properties(*array);
2096   }
2097
2098   // Create filler object past the new instance size.
2099   int new_instance_size = new_map->instance_size();
2100   int instance_size_delta = old_map->instance_size() - new_instance_size;
2101   DCHECK(instance_size_delta >= 0);
2102
2103   if (instance_size_delta > 0) {
2104     Address address = object->address();
2105     heap->CreateFillerObjectAt(
2106         address + new_instance_size, instance_size_delta);
2107     heap->AdjustLiveBytes(address, -instance_size_delta, Heap::FROM_MUTATOR);
2108   }
2109
2110   // We are storing the new map using release store after creating a filler for
2111   // the left-over space to avoid races with the sweeper thread.
2112   object->synchronized_set_map(*new_map);
2113 }
2114
2115
2116 int Map::NumberOfFields() {
2117   DescriptorArray* descriptors = instance_descriptors();
2118   int result = 0;
2119   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2120     if (descriptors->GetDetails(i).location() == kField) result++;
2121   }
2122   return result;
2123 }
2124
2125
2126 Handle<Map> Map::CopyGeneralizeAllRepresentations(
2127     Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind,
2128     PropertyAttributes attributes, const char* reason) {
2129   Isolate* isolate = map->GetIsolate();
2130   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2131   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2132   Handle<DescriptorArray> descriptors =
2133       DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
2134
2135   for (int i = 0; i < number_of_own_descriptors; i++) {
2136     descriptors->SetRepresentation(i, Representation::Tagged());
2137     if (descriptors->GetDetails(i).type() == DATA) {
2138       descriptors->SetValue(i, HeapType::Any());
2139     }
2140   }
2141
2142   Handle<LayoutDescriptor> new_layout_descriptor(
2143       LayoutDescriptor::FastPointerLayout(), isolate);
2144   Handle<Map> new_map = CopyReplaceDescriptors(
2145       map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
2146       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
2147
2148   // Unless the instance is being migrated, ensure that modify_index is a field.
2149   if (modify_index >= 0) {
2150     PropertyDetails details = descriptors->GetDetails(modify_index);
2151     if (store_mode == FORCE_FIELD &&
2152         (details.type() != DATA || details.attributes() != attributes)) {
2153       int field_index = details.type() == DATA ? details.field_index()
2154                                                : new_map->NumberOfFields();
2155       DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
2156                        field_index, attributes, Representation::Tagged());
2157       descriptors->Replace(modify_index, &d);
2158       if (details.type() != DATA) {
2159         int unused_property_fields = new_map->unused_property_fields() - 1;
2160         if (unused_property_fields < 0) {
2161           unused_property_fields += JSObject::kFieldsAdded;
2162         }
2163         new_map->set_unused_property_fields(unused_property_fields);
2164       }
2165     } else {
2166       DCHECK(details.attributes() == attributes);
2167     }
2168
2169     if (FLAG_trace_generalization) {
2170       HeapType* field_type =
2171           (details.type() == DATA)
2172               ? map->instance_descriptors()->GetFieldType(modify_index)
2173               : NULL;
2174       map->PrintGeneralization(
2175           stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
2176           new_map->NumberOfOwnDescriptors(),
2177           details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
2178           details.representation(), Representation::Tagged(), field_type,
2179           HeapType::Any());
2180     }
2181   }
2182   return new_map;
2183 }
2184
2185
2186 void Map::DeprecateTransitionTree() {
2187   if (is_deprecated()) return;
2188   Object* transitions = raw_transitions();
2189   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
2190   for (int i = 0; i < num_transitions; ++i) {
2191     TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
2192   }
2193   deprecate();
2194   dependent_code()->DeoptimizeDependentCodeGroup(
2195       GetIsolate(), DependentCode::kTransitionGroup);
2196   NotifyLeafMapLayoutChange();
2197 }
2198
2199
2200 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
2201   if (obj1 == obj2) return true;  // Valid for both kData and kAccessor kinds.
2202   // TODO(ishell): compare AccessorPairs.
2203   return false;
2204 }
2205
2206
2207 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2208 // the current instance_descriptors to ensure proper sharing of descriptor
2209 // arrays.
2210 // Returns true if the transition target at given key was deprecated.
2211 bool Map::DeprecateTarget(PropertyKind kind, Name* key,
2212                           PropertyAttributes attributes,
2213                           DescriptorArray* new_descriptors,
2214                           LayoutDescriptor* new_layout_descriptor) {
2215   bool transition_target_deprecated = false;
2216   Map* maybe_transition =
2217       TransitionArray::SearchTransition(this, kind, key, attributes);
2218   if (maybe_transition != NULL) {
2219     maybe_transition->DeprecateTransitionTree();
2220     transition_target_deprecated = true;
2221   }
2222
2223   // Don't overwrite the empty descriptor array.
2224   if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated;
2225
2226   DescriptorArray* to_replace = instance_descriptors();
2227   Map* current = this;
2228   GetHeap()->incremental_marking()->RecordWrites(to_replace);
2229   while (current->instance_descriptors() == to_replace) {
2230     current->SetEnumLength(kInvalidEnumCacheSentinel);
2231     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
2232     Object* next = current->GetBackPointer();
2233     if (next->IsUndefined()) break;
2234     current = Map::cast(next);
2235   }
2236
2237   set_owns_descriptors(false);
2238   return transition_target_deprecated;
2239 }
2240
2241
2242 Map* Map::FindRootMap() {
2243   Map* result = this;
2244   while (true) {
2245     Object* back = result->GetBackPointer();
2246     if (back->IsUndefined()) return result;
2247     result = Map::cast(back);
2248   }
2249 }
2250
2251
2252 Map* Map::FindLastMatchMap(int verbatim,
2253                            int length,
2254                            DescriptorArray* descriptors) {
2255   DisallowHeapAllocation no_allocation;
2256
2257   // This can only be called on roots of transition trees.
2258   DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
2259
2260   Map* current = this;
2261
2262   for (int i = verbatim; i < length; i++) {
2263     Name* name = descriptors->GetKey(i);
2264     PropertyDetails details = descriptors->GetDetails(i);
2265     Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
2266                                                   details.attributes());
2267     if (next == NULL) break;
2268     DescriptorArray* next_descriptors = next->instance_descriptors();
2269
2270     PropertyDetails next_details = next_descriptors->GetDetails(i);
2271     DCHECK_EQ(details.kind(), next_details.kind());
2272     DCHECK_EQ(details.attributes(), next_details.attributes());
2273     if (details.location() != next_details.location()) break;
2274     if (!details.representation().Equals(next_details.representation())) break;
2275
2276     if (next_details.location() == kField) {
2277       HeapType* next_field_type = next_descriptors->GetFieldType(i);
2278       if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
2279         break;
2280       }
2281     } else {
2282       if (!EqualImmutableValues(descriptors->GetValue(i),
2283                                 next_descriptors->GetValue(i))) {
2284         break;
2285       }
2286     }
2287     current = next;
2288   }
2289   return current;
2290 }
2291
2292
2293 Map* Map::FindFieldOwner(int descriptor) {
2294   DisallowHeapAllocation no_allocation;
2295   DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
2296   Map* result = this;
2297   while (true) {
2298     Object* back = result->GetBackPointer();
2299     if (back->IsUndefined()) break;
2300     Map* parent = Map::cast(back);
2301     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
2302     result = parent;
2303   }
2304   return result;
2305 }
2306
2307
2308 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
2309                           Representation new_representation,
2310                           Handle<Object> new_wrapped_type) {
2311   DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
2312   DisallowHeapAllocation no_allocation;
2313   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
2314   if (details.type() != DATA) return;
2315   Object* transitions = raw_transitions();
2316   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
2317   for (int i = 0; i < num_transitions; ++i) {
2318     Map* target = TransitionArray::GetTarget(transitions, i);
2319     target->UpdateFieldType(descriptor, name, new_representation,
2320                             new_wrapped_type);
2321   }
2322   // It is allowed to change representation here only from None to something.
2323   DCHECK(details.representation().Equals(new_representation) ||
2324          details.representation().IsNone());
2325
2326   // Skip if already updated the shared descriptor.
2327   if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return;
2328   DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
2329                    new_wrapped_type, details.attributes(), new_representation);
2330   instance_descriptors()->Replace(descriptor, &d);
2331 }
2332
2333
2334 // static
2335 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
2336                                           Handle<HeapType> type2,
2337                                           Isolate* isolate) {
2338   if (type1->NowIs(type2)) return type2;
2339   if (type2->NowIs(type1)) return type1;
2340   return HeapType::Any(isolate);
2341 }
2342
2343
2344 // static
2345 void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
2346                               Representation new_representation,
2347                               Handle<HeapType> new_field_type) {
2348   Isolate* isolate = map->GetIsolate();
2349
2350   // Check if we actually need to generalize the field type at all.
2351   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2352   Representation old_representation =
2353       old_descriptors->GetDetails(modify_index).representation();
2354   Handle<HeapType> old_field_type(old_descriptors->GetFieldType(modify_index),
2355                                   isolate);
2356
2357   if (old_representation.Equals(new_representation) &&
2358       new_field_type->NowIs(old_field_type)) {
2359     DCHECK(Map::GeneralizeFieldType(old_field_type,
2360                                     new_field_type,
2361                                     isolate)->NowIs(old_field_type));
2362     return;
2363   }
2364
2365   // Determine the field owner.
2366   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
2367   Handle<DescriptorArray> descriptors(
2368       field_owner->instance_descriptors(), isolate);
2369   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
2370   bool old_field_type_was_cleared =
2371       old_field_type->Is(HeapType::None()) && old_representation.IsHeapObject();
2372
2373   // Determine the generalized new field type. Conservatively assume type Any
2374   // for cleared field types because the cleared type could have been a
2375   // deprecated map and there still could be live instances with a non-
2376   // deprecated version of the map.
2377   new_field_type =
2378       old_field_type_was_cleared
2379           ? HeapType::Any(isolate)
2380           : Map::GeneralizeFieldType(old_field_type, new_field_type, isolate);
2381
2382   PropertyDetails details = descriptors->GetDetails(modify_index);
2383   Handle<Name> name(descriptors->GetKey(modify_index));
2384
2385   Handle<Object> wrapped_type(WrapType(new_field_type));
2386   field_owner->UpdateFieldType(modify_index, name, new_representation,
2387                                wrapped_type);
2388   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
2389       isolate, DependentCode::kFieldTypeGroup);
2390
2391   if (FLAG_trace_generalization) {
2392     map->PrintGeneralization(
2393         stdout, "field type generalization",
2394         modify_index, map->NumberOfOwnDescriptors(),
2395         map->NumberOfOwnDescriptors(), false,
2396         details.representation(), details.representation(),
2397         *old_field_type, *new_field_type);
2398   }
2399 }
2400
2401
2402 static inline Handle<HeapType> GetFieldType(Isolate* isolate,
2403                                             Handle<DescriptorArray> descriptors,
2404                                             int descriptor,
2405                                             PropertyLocation location,
2406                                             Representation representation) {
2407 #ifdef DEBUG
2408   PropertyDetails details = descriptors->GetDetails(descriptor);
2409   DCHECK_EQ(kData, details.kind());
2410   DCHECK_EQ(details.location(), location);
2411 #endif
2412   if (location == kField) {
2413     return handle(descriptors->GetFieldType(descriptor), isolate);
2414   } else {
2415     return descriptors->GetValue(descriptor)
2416         ->OptimalType(isolate, representation);
2417   }
2418 }
2419
2420
2421 // Reconfigures property at |modify_index| with |new_kind|, |new_attributes|,
2422 // |store_mode| and/or |new_representation|/|new_field_type|.
2423 // If |modify_index| is negative then no properties are reconfigured but the
2424 // map is migrated to the up-to-date non-deprecated state.
2425 //
2426 // This method rewrites or completes the transition tree to reflect the new
2427 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
2428 // on every rewrite the new type is deduced by merging the current type with
2429 // any potential new (partial) version of the type in the transition tree.
2430 // To do this, on each rewrite:
2431 // - Search the root of the transition tree using FindRootMap.
2432 // - Find |target_map|, the newest matching version of this map using the
2433 //   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
2434 //   |modify_index| is considered to be of |new_kind| and having
2435 //   |new_attributes|) to walk the transition tree.
2436 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
2437 //   descriptor array of the |target_map|.
2438 // - Generalize the |modify_index| descriptor using |new_representation| and
2439 //   |new_field_type|.
2440 // - Walk the tree again starting from the root towards |target_map|. Stop at
2441 //   |split_map|, the first map who's descriptor array does not match the merged
2442 //   descriptor array.
2443 // - If |target_map| == |split_map|, |target_map| is in the expected state.
2444 //   Return it.
2445 // - Otherwise, invalidate the outdated transition target from |target_map|, and
2446 //   replace its transition tree with a new branch for the updated descriptors.
2447 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
2448                                      PropertyKind new_kind,
2449                                      PropertyAttributes new_attributes,
2450                                      Representation new_representation,
2451                                      Handle<HeapType> new_field_type,
2452                                      StoreMode store_mode) {
2453   DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
2454   DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
2455   Isolate* isolate = old_map->GetIsolate();
2456
2457   Handle<DescriptorArray> old_descriptors(
2458       old_map->instance_descriptors(), isolate);
2459   int old_nof = old_map->NumberOfOwnDescriptors();
2460
2461   // If it's just a representation generalization case (i.e. property kind and
2462   // attributes stays unchanged) it's fine to transition from None to anything
2463   // but double without any modification to the object, because the default
2464   // uninitialized value for representation None can be overwritten by both
2465   // smi and tagged values. Doubles, however, would require a box allocation.
2466   if (modify_index >= 0 && !new_representation.IsNone() &&
2467       !new_representation.IsDouble()) {
2468     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2469     Representation old_representation = old_details.representation();
2470
2471     if (old_representation.IsNone()) {
2472       DCHECK_EQ(new_kind, old_details.kind());
2473       DCHECK_EQ(new_attributes, old_details.attributes());
2474       DCHECK_EQ(DATA, old_details.type());
2475       if (FLAG_trace_generalization) {
2476         old_map->PrintGeneralization(
2477             stdout, "uninitialized field", modify_index,
2478             old_map->NumberOfOwnDescriptors(),
2479             old_map->NumberOfOwnDescriptors(), false, old_representation,
2480             new_representation, old_descriptors->GetFieldType(modify_index),
2481             *new_field_type);
2482       }
2483       Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
2484
2485       GeneralizeFieldType(field_owner, modify_index, new_representation,
2486                           new_field_type);
2487       DCHECK(old_descriptors->GetDetails(modify_index)
2488                  .representation()
2489                  .Equals(new_representation));
2490       DCHECK(
2491           old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
2492       return old_map;
2493     }
2494   }
2495
2496   // Check the state of the root map.
2497   Handle<Map> root_map(old_map->FindRootMap(), isolate);
2498   if (!old_map->EquivalentToForTransition(*root_map)) {
2499     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2500                                             new_kind, new_attributes,
2501                                             "GenAll_NotEquivalent");
2502   }
2503
2504   ElementsKind from_kind = root_map->elements_kind();
2505   ElementsKind to_kind = old_map->elements_kind();
2506   if (from_kind != to_kind &&
2507       !(IsTransitionableFastElementsKind(from_kind) &&
2508         IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
2509     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2510                                             new_kind, new_attributes,
2511                                             "GenAll_InvalidElementsTransition");
2512   }
2513   int root_nof = root_map->NumberOfOwnDescriptors();
2514   if (modify_index >= 0 && modify_index < root_nof) {
2515     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2516     if (old_details.kind() != new_kind ||
2517         old_details.attributes() != new_attributes) {
2518       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2519                                               new_kind, new_attributes,
2520                                               "GenAll_RootModification1");
2521     }
2522     if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
2523         (old_details.type() == DATA &&
2524          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
2525           !new_representation.fits_into(old_details.representation())))) {
2526       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2527                                               new_kind, new_attributes,
2528                                               "GenAll_RootModification2");
2529     }
2530   }
2531
2532   // From here on, use the map with correct elements kind as root map.
2533   if (from_kind != to_kind) {
2534     root_map = Map::AsElementsKind(root_map, to_kind);
2535   }
2536
2537   Handle<Map> target_map = root_map;
2538   for (int i = root_nof; i < old_nof; ++i) {
2539     PropertyDetails old_details = old_descriptors->GetDetails(i);
2540     PropertyKind next_kind;
2541     PropertyLocation next_location;
2542     PropertyAttributes next_attributes;
2543     Representation next_representation;
2544     bool property_kind_reconfiguration = false;
2545
2546     if (modify_index == i) {
2547       DCHECK_EQ(FORCE_FIELD, store_mode);
2548       property_kind_reconfiguration = old_details.kind() != new_kind;
2549
2550       next_kind = new_kind;
2551       next_location = kField;
2552       next_attributes = new_attributes;
2553       // If property kind is not reconfigured merge the result with
2554       // representation/field type from the old descriptor.
2555       next_representation = new_representation;
2556       if (!property_kind_reconfiguration) {
2557         next_representation =
2558             next_representation.generalize(old_details.representation());
2559       }
2560
2561     } else {
2562       next_kind = old_details.kind();
2563       next_location = old_details.location();
2564       next_attributes = old_details.attributes();
2565       next_representation = old_details.representation();
2566     }
2567     Map* transition = TransitionArray::SearchTransition(
2568         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
2569     if (transition == NULL) break;
2570     Handle<Map> tmp_map(transition, isolate);
2571
2572     Handle<DescriptorArray> tmp_descriptors = handle(
2573         tmp_map->instance_descriptors(), isolate);
2574
2575     // Check if target map is incompatible.
2576     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2577     DCHECK_EQ(next_kind, tmp_details.kind());
2578     DCHECK_EQ(next_attributes, tmp_details.attributes());
2579     if (next_kind == kAccessor &&
2580         !EqualImmutableValues(old_descriptors->GetValue(i),
2581                               tmp_descriptors->GetValue(i))) {
2582       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2583                                               new_kind, new_attributes,
2584                                               "GenAll_Incompatible");
2585     }
2586     if (next_location == kField && tmp_details.location() == kDescriptor) break;
2587
2588     Representation tmp_representation = tmp_details.representation();
2589     if (!next_representation.fits_into(tmp_representation)) break;
2590
2591     PropertyLocation old_location = old_details.location();
2592     PropertyLocation tmp_location = tmp_details.location();
2593     if (tmp_location == kField) {
2594       if (next_kind == kData) {
2595         Handle<HeapType> next_field_type;
2596         if (modify_index == i) {
2597           next_field_type = new_field_type;
2598           if (!property_kind_reconfiguration) {
2599             Handle<HeapType> old_field_type =
2600                 GetFieldType(isolate, old_descriptors, i,
2601                              old_details.location(), tmp_representation);
2602             next_field_type =
2603                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2604           }
2605         } else {
2606           Handle<HeapType> old_field_type =
2607               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2608                            tmp_representation);
2609           next_field_type = old_field_type;
2610         }
2611         GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
2612       }
2613     } else if (old_location == kField ||
2614                !EqualImmutableValues(old_descriptors->GetValue(i),
2615                                      tmp_descriptors->GetValue(i))) {
2616       break;
2617     }
2618     DCHECK(!tmp_map->is_deprecated());
2619     target_map = tmp_map;
2620   }
2621
2622   // Directly change the map if the target map is more general.
2623   Handle<DescriptorArray> target_descriptors(
2624       target_map->instance_descriptors(), isolate);
2625   int target_nof = target_map->NumberOfOwnDescriptors();
2626   if (target_nof == old_nof &&
2627       (store_mode != FORCE_FIELD ||
2628        (modify_index >= 0 &&
2629         target_descriptors->GetDetails(modify_index).location() == kField))) {
2630 #ifdef DEBUG
2631     if (modify_index >= 0) {
2632       PropertyDetails details = target_descriptors->GetDetails(modify_index);
2633       DCHECK_EQ(new_kind, details.kind());
2634       DCHECK_EQ(new_attributes, details.attributes());
2635       DCHECK(new_representation.fits_into(details.representation()));
2636       DCHECK(details.location() != kField ||
2637              new_field_type->NowIs(
2638                  target_descriptors->GetFieldType(modify_index)));
2639     }
2640 #endif
2641     return target_map;
2642   }
2643
2644   // Find the last compatible target map in the transition tree.
2645   for (int i = target_nof; i < old_nof; ++i) {
2646     PropertyDetails old_details = old_descriptors->GetDetails(i);
2647     PropertyKind next_kind;
2648     PropertyAttributes next_attributes;
2649     if (modify_index == i) {
2650       next_kind = new_kind;
2651       next_attributes = new_attributes;
2652     } else {
2653       next_kind = old_details.kind();
2654       next_attributes = old_details.attributes();
2655     }
2656     Map* transition = TransitionArray::SearchTransition(
2657         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
2658     if (transition == NULL) break;
2659     Handle<Map> tmp_map(transition, isolate);
2660     Handle<DescriptorArray> tmp_descriptors(
2661         tmp_map->instance_descriptors(), isolate);
2662
2663     // Check if target map is compatible.
2664 #ifdef DEBUG
2665     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2666     DCHECK_EQ(next_kind, tmp_details.kind());
2667     DCHECK_EQ(next_attributes, tmp_details.attributes());
2668 #endif
2669     if (next_kind == kAccessor &&
2670         !EqualImmutableValues(old_descriptors->GetValue(i),
2671                               tmp_descriptors->GetValue(i))) {
2672       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2673                                               new_kind, new_attributes,
2674                                               "GenAll_Incompatible");
2675     }
2676     DCHECK(!tmp_map->is_deprecated());
2677     target_map = tmp_map;
2678   }
2679   target_nof = target_map->NumberOfOwnDescriptors();
2680   target_descriptors = handle(target_map->instance_descriptors(), isolate);
2681
2682   // Allocate a new descriptor array large enough to hold the required
2683   // descriptors, with minimally the exact same size as the old descriptor
2684   // array.
2685   int new_slack = Max(
2686       old_nof, old_descriptors->number_of_descriptors()) - old_nof;
2687   Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
2688       isolate, old_nof, new_slack);
2689   DCHECK(new_descriptors->length() > target_descriptors->length() ||
2690          new_descriptors->NumberOfSlackDescriptors() > 0 ||
2691          new_descriptors->number_of_descriptors() ==
2692          old_descriptors->number_of_descriptors());
2693   DCHECK(new_descriptors->number_of_descriptors() == old_nof);
2694
2695   // 0 -> |root_nof|
2696   int current_offset = 0;
2697   for (int i = 0; i < root_nof; ++i) {
2698     PropertyDetails old_details = old_descriptors->GetDetails(i);
2699     if (old_details.location() == kField) {
2700       current_offset += old_details.field_width_in_words();
2701     }
2702     Descriptor d(handle(old_descriptors->GetKey(i), isolate),
2703                  handle(old_descriptors->GetValue(i), isolate),
2704                  old_details);
2705     new_descriptors->Set(i, &d);
2706   }
2707
2708   // |root_nof| -> |target_nof|
2709   for (int i = root_nof; i < target_nof; ++i) {
2710     Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
2711     PropertyDetails old_details = old_descriptors->GetDetails(i);
2712     PropertyDetails target_details = target_descriptors->GetDetails(i);
2713
2714     PropertyKind next_kind;
2715     PropertyAttributes next_attributes;
2716     PropertyLocation next_location;
2717     Representation next_representation;
2718     bool property_kind_reconfiguration = false;
2719
2720     if (modify_index == i) {
2721       DCHECK_EQ(FORCE_FIELD, store_mode);
2722       property_kind_reconfiguration = old_details.kind() != new_kind;
2723
2724       next_kind = new_kind;
2725       next_attributes = new_attributes;
2726       next_location = kField;
2727
2728       // Merge new representation/field type with ones from the target
2729       // descriptor. If property kind is not reconfigured merge the result with
2730       // representation/field type from the old descriptor.
2731       next_representation =
2732           new_representation.generalize(target_details.representation());
2733       if (!property_kind_reconfiguration) {
2734         next_representation =
2735             next_representation.generalize(old_details.representation());
2736       }
2737     } else {
2738       // Merge old_descriptor and target_descriptor entries.
2739       DCHECK_EQ(target_details.kind(), old_details.kind());
2740       next_kind = target_details.kind();
2741       next_attributes = target_details.attributes();
2742       next_location =
2743           old_details.location() == kField ||
2744                   target_details.location() == kField ||
2745                   !EqualImmutableValues(target_descriptors->GetValue(i),
2746                                         old_descriptors->GetValue(i))
2747               ? kField
2748               : kDescriptor;
2749
2750       next_representation = old_details.representation().generalize(
2751           target_details.representation());
2752     }
2753     DCHECK_EQ(next_kind, target_details.kind());
2754     DCHECK_EQ(next_attributes, target_details.attributes());
2755
2756     if (next_location == kField) {
2757       if (next_kind == kData) {
2758         Handle<HeapType> target_field_type =
2759             GetFieldType(isolate, target_descriptors, i,
2760                          target_details.location(), next_representation);
2761
2762         Handle<HeapType> next_field_type;
2763         if (modify_index == i) {
2764           next_field_type =
2765               GeneralizeFieldType(target_field_type, new_field_type, isolate);
2766           if (!property_kind_reconfiguration) {
2767             Handle<HeapType> old_field_type =
2768                 GetFieldType(isolate, old_descriptors, i,
2769                              old_details.location(), next_representation);
2770             next_field_type =
2771                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2772           }
2773         } else {
2774           Handle<HeapType> old_field_type =
2775               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2776                            next_representation);
2777           next_field_type =
2778               GeneralizeFieldType(target_field_type, old_field_type, isolate);
2779         }
2780         Handle<Object> wrapped_type(WrapType(next_field_type));
2781         DataDescriptor d(target_key, current_offset, wrapped_type,
2782                          next_attributes, next_representation);
2783         current_offset += d.GetDetails().field_width_in_words();
2784         new_descriptors->Set(i, &d);
2785       } else {
2786         UNIMPLEMENTED();  // TODO(ishell): implement.
2787       }
2788     } else {
2789       PropertyDetails details(next_attributes, next_kind, next_location,
2790                               next_representation);
2791       Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
2792                    details);
2793       new_descriptors->Set(i, &d);
2794     }
2795   }
2796
2797   // |target_nof| -> |old_nof|
2798   for (int i = target_nof; i < old_nof; ++i) {
2799     PropertyDetails old_details = old_descriptors->GetDetails(i);
2800     Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
2801
2802     // Merge old_descriptor entry and modified details together.
2803     PropertyKind next_kind;
2804     PropertyAttributes next_attributes;
2805     PropertyLocation next_location;
2806     Representation next_representation;
2807     bool property_kind_reconfiguration = false;
2808
2809     if (modify_index == i) {
2810       DCHECK_EQ(FORCE_FIELD, store_mode);
2811       // In case of property kind reconfiguration it is not necessary to
2812       // take into account representation/field type of the old descriptor.
2813       property_kind_reconfiguration = old_details.kind() != new_kind;
2814
2815       next_kind = new_kind;
2816       next_attributes = new_attributes;
2817       next_location = kField;
2818       next_representation = new_representation;
2819       if (!property_kind_reconfiguration) {
2820         next_representation =
2821             next_representation.generalize(old_details.representation());
2822       }
2823     } else {
2824       next_kind = old_details.kind();
2825       next_attributes = old_details.attributes();
2826       next_location = old_details.location();
2827       next_representation = old_details.representation();
2828     }
2829
2830     if (next_location == kField) {
2831       if (next_kind == kData) {
2832         Handle<HeapType> next_field_type;
2833         if (modify_index == i) {
2834           next_field_type = new_field_type;
2835           if (!property_kind_reconfiguration) {
2836             Handle<HeapType> old_field_type =
2837                 GetFieldType(isolate, old_descriptors, i,
2838                              old_details.location(), next_representation);
2839             next_field_type =
2840                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2841           }
2842         } else {
2843           Handle<HeapType> old_field_type =
2844               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2845                            next_representation);
2846           next_field_type = old_field_type;
2847         }
2848
2849         Handle<Object> wrapped_type(WrapType(next_field_type));
2850
2851         DataDescriptor d(old_key, current_offset, wrapped_type, next_attributes,
2852                          next_representation);
2853         current_offset += d.GetDetails().field_width_in_words();
2854         new_descriptors->Set(i, &d);
2855       } else {
2856         UNIMPLEMENTED();  // TODO(ishell): implement.
2857       }
2858     } else {
2859       PropertyDetails details(next_attributes, next_kind, next_location,
2860                               next_representation);
2861       Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
2862                    details);
2863       new_descriptors->Set(i, &d);
2864     }
2865   }
2866
2867   new_descriptors->Sort();
2868
2869   DCHECK(store_mode != FORCE_FIELD ||
2870          new_descriptors->GetDetails(modify_index).location() == kField);
2871
2872   Handle<Map> split_map(root_map->FindLastMatchMap(
2873           root_nof, old_nof, *new_descriptors), isolate);
2874   int split_nof = split_map->NumberOfOwnDescriptors();
2875   DCHECK_NE(old_nof, split_nof);
2876
2877   Handle<LayoutDescriptor> new_layout_descriptor =
2878       LayoutDescriptor::New(split_map, new_descriptors, old_nof);
2879
2880   PropertyKind split_kind;
2881   PropertyAttributes split_attributes;
2882   if (modify_index == split_nof) {
2883     split_kind = new_kind;
2884     split_attributes = new_attributes;
2885   } else {
2886     PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
2887     split_kind = split_prop_details.kind();
2888     split_attributes = split_prop_details.attributes();
2889   }
2890   bool transition_target_deprecated = split_map->DeprecateTarget(
2891       split_kind, old_descriptors->GetKey(split_nof), split_attributes,
2892       *new_descriptors, *new_layout_descriptor);
2893
2894   // If |transition_target_deprecated| is true then the transition array
2895   // already contains entry for given descriptor. This means that the transition
2896   // could be inserted regardless of whether transitions array is full or not.
2897   if (!transition_target_deprecated &&
2898       !TransitionArray::CanHaveMoreTransitions(split_map)) {
2899     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2900                                             new_kind, new_attributes,
2901                                             "GenAll_CantHaveMoreTransitions");
2902   }
2903
2904   if (FLAG_trace_generalization && modify_index >= 0) {
2905     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2906     PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
2907     Handle<HeapType> old_field_type =
2908         (old_details.type() == DATA)
2909             ? handle(old_descriptors->GetFieldType(modify_index), isolate)
2910             : HeapType::Constant(
2911                   handle(old_descriptors->GetValue(modify_index), isolate),
2912                   isolate);
2913     Handle<HeapType> new_field_type =
2914         (new_details.type() == DATA)
2915             ? handle(new_descriptors->GetFieldType(modify_index), isolate)
2916             : HeapType::Constant(
2917                   handle(new_descriptors->GetValue(modify_index), isolate),
2918                   isolate);
2919     old_map->PrintGeneralization(
2920         stdout, "", modify_index, split_nof, old_nof,
2921         old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
2922         old_details.representation(), new_details.representation(),
2923         *old_field_type, *new_field_type);
2924   }
2925
2926   // Add missing transitions.
2927   Handle<Map> new_map = split_map;
2928   for (int i = split_nof; i < old_nof; ++i) {
2929     new_map = CopyInstallDescriptors(new_map, i, new_descriptors,
2930                                      new_layout_descriptor);
2931   }
2932   new_map->set_owns_descriptors(true);
2933   return new_map;
2934 }
2935
2936
2937 // Generalize the representation of all DATA descriptors.
2938 Handle<Map> Map::GeneralizeAllFieldRepresentations(
2939     Handle<Map> map) {
2940   Handle<DescriptorArray> descriptors(map->instance_descriptors());
2941   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
2942     PropertyDetails details = descriptors->GetDetails(i);
2943     if (details.type() == DATA) {
2944       map = ReconfigureProperty(map, i, kData, details.attributes(),
2945                                 Representation::Tagged(),
2946                                 HeapType::Any(map->GetIsolate()), FORCE_FIELD);
2947     }
2948   }
2949   return map;
2950 }
2951
2952
2953 // static
2954 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
2955   DisallowHeapAllocation no_allocation;
2956   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
2957
2958   if (!old_map->is_deprecated()) return old_map;
2959
2960   // Check the state of the root map.
2961   Map* root_map = old_map->FindRootMap();
2962   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
2963   int root_nof = root_map->NumberOfOwnDescriptors();
2964
2965   int old_nof = old_map->NumberOfOwnDescriptors();
2966   DescriptorArray* old_descriptors = old_map->instance_descriptors();
2967
2968   Map* new_map = root_map;
2969   for (int i = root_nof; i < old_nof; ++i) {
2970     PropertyDetails old_details = old_descriptors->GetDetails(i);
2971     Map* transition = TransitionArray::SearchTransition(
2972         new_map, old_details.kind(), old_descriptors->GetKey(i),
2973         old_details.attributes());
2974     if (transition == NULL) return MaybeHandle<Map>();
2975     new_map = transition;
2976     DescriptorArray* new_descriptors = new_map->instance_descriptors();
2977
2978     PropertyDetails new_details = new_descriptors->GetDetails(i);
2979     DCHECK_EQ(old_details.kind(), new_details.kind());
2980     DCHECK_EQ(old_details.attributes(), new_details.attributes());
2981     if (!old_details.representation().fits_into(new_details.representation())) {
2982       return MaybeHandle<Map>();
2983     }
2984     switch (new_details.type()) {
2985       case DATA: {
2986         HeapType* new_type = new_descriptors->GetFieldType(i);
2987         PropertyType old_property_type = old_details.type();
2988         if (old_property_type == DATA) {
2989           HeapType* old_type = old_descriptors->GetFieldType(i);
2990           if (!old_type->NowIs(new_type)) {
2991             return MaybeHandle<Map>();
2992           }
2993         } else {
2994           DCHECK(old_property_type == DATA_CONSTANT);
2995           Object* old_value = old_descriptors->GetValue(i);
2996           if (!new_type->NowContains(old_value)) {
2997             return MaybeHandle<Map>();
2998           }
2999         }
3000         break;
3001       }
3002       case ACCESSOR: {
3003 #ifdef DEBUG
3004         HeapType* new_type = new_descriptors->GetFieldType(i);
3005         DCHECK(HeapType::Any()->Is(new_type));
3006 #endif
3007         break;
3008       }
3009
3010       case DATA_CONSTANT:
3011       case ACCESSOR_CONSTANT: {
3012         Object* old_value = old_descriptors->GetValue(i);
3013         Object* new_value = new_descriptors->GetValue(i);
3014         if (old_details.location() == kField || old_value != new_value) {
3015           return MaybeHandle<Map>();
3016         }
3017         break;
3018       }
3019     }
3020   }
3021   if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
3022   return handle(new_map);
3023 }
3024
3025
3026 // static
3027 Handle<Map> Map::Update(Handle<Map> map) {
3028   if (!map->is_deprecated()) return map;
3029   return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
3030                              HeapType::None(map->GetIsolate()),
3031                              ALLOW_IN_DESCRIPTOR);
3032 }
3033
3034
3035 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
3036                                                          Handle<Object> value) {
3037   Handle<Name> name = it->name();
3038   Handle<JSObject> holder = it->GetHolder<JSObject>();
3039   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
3040   if (interceptor->setter()->IsUndefined() ||
3041       (name->IsSymbol() && !interceptor->can_intercept_symbols())) {
3042     return MaybeHandle<Object>();
3043   }
3044
3045   LOG(it->isolate(),
3046       ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
3047   PropertyCallbackArguments args(it->isolate(), interceptor->data(), *holder,
3048                                  *holder);
3049   v8::GenericNamedPropertySetterCallback setter =
3050       v8::ToCData<v8::GenericNamedPropertySetterCallback>(
3051           interceptor->setter());
3052   v8::Handle<v8::Value> result =
3053       args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
3054   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
3055   if (!result.IsEmpty()) return value;
3056
3057   return MaybeHandle<Object>();
3058 }
3059
3060
3061 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
3062                                         Handle<Name> name, Handle<Object> value,
3063                                         LanguageMode language_mode,
3064                                         StoreFromKeyed store_mode) {
3065   LookupIterator it(object, name);
3066   return SetProperty(&it, value, language_mode, store_mode);
3067 }
3068
3069
3070 MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
3071                                                 Handle<Object> value,
3072                                                 LanguageMode language_mode,
3073                                                 StoreFromKeyed store_mode,
3074                                                 bool* found) {
3075   // Make sure that the top context does not change when doing callbacks or
3076   // interceptor calls.
3077   AssertNoContextChange ncc(it->isolate());
3078
3079   *found = true;
3080
3081   bool done = false;
3082   for (; it->IsFound(); it->Next()) {
3083     switch (it->state()) {
3084       case LookupIterator::NOT_FOUND:
3085         UNREACHABLE();
3086
3087       case LookupIterator::ACCESS_CHECK:
3088         // TODO(verwaest): Remove the distinction. This is mostly bogus since we
3089         // don't know whether we'll want to fetch attributes or call a setter
3090         // until we find the property.
3091         if (it->HasAccess()) break;
3092         return JSObject::SetPropertyWithFailedAccessCheck(it, value,
3093                                                           language_mode);
3094
3095       case LookupIterator::JSPROXY:
3096         if (it->HolderIsReceiverOrHiddenPrototype()) {
3097           return JSProxy::SetPropertyWithHandler(it->GetHolder<JSProxy>(),
3098                                                  it->GetReceiver(), it->name(),
3099                                                  value, language_mode);
3100         } else {
3101           // TODO(verwaest): Use the MaybeHandle to indicate result.
3102           bool has_result = false;
3103           MaybeHandle<Object> maybe_result =
3104               JSProxy::SetPropertyViaPrototypesWithHandler(
3105                   it->GetHolder<JSProxy>(), it->GetReceiver(), it->name(),
3106                   value, language_mode, &has_result);
3107           if (has_result) return maybe_result;
3108           done = true;
3109         }
3110         break;
3111
3112       case LookupIterator::INTERCEPTOR:
3113         if (it->HolderIsReceiverOrHiddenPrototype()) {
3114           MaybeHandle<Object> maybe_result =
3115               JSObject::SetPropertyWithInterceptor(it, value);
3116           if (!maybe_result.is_null()) return maybe_result;
3117           if (it->isolate()->has_pending_exception()) return maybe_result;
3118         } else {
3119           Maybe<PropertyAttributes> maybe_attributes =
3120               JSObject::GetPropertyAttributesWithInterceptor(
3121                   it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
3122           if (!maybe_attributes.IsJust()) return MaybeHandle<Object>();
3123           done = maybe_attributes.FromJust() != ABSENT;
3124           if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) {
3125             return WriteToReadOnlyProperty(it, value, language_mode);
3126           }
3127         }
3128         break;
3129
3130       case LookupIterator::ACCESSOR:
3131         if (it->property_details().IsReadOnly()) {
3132           return WriteToReadOnlyProperty(it, value, language_mode);
3133         }
3134         return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
3135                                        it->GetHolder<JSObject>(),
3136                                        it->GetAccessors(), language_mode);
3137
3138       case LookupIterator::INTEGER_INDEXED_EXOTIC:
3139         done = true;
3140         break;
3141
3142       case LookupIterator::DATA:
3143         if (it->property_details().IsReadOnly()) {
3144           return WriteToReadOnlyProperty(it, value, language_mode);
3145         }
3146         if (it->HolderIsReceiverOrHiddenPrototype()) {
3147           return SetDataProperty(it, value);
3148         }
3149         done = true;
3150         break;
3151
3152       case LookupIterator::TRANSITION:
3153         done = true;
3154         break;
3155     }
3156
3157     if (done) break;
3158   }
3159
3160   // If the receiver is the JSGlobalObject, the store was contextual. In case
3161   // the property did not exist yet on the global object itself, we have to
3162   // throw a reference error in strict mode.
3163   if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) {
3164     Handle<Object> args[] = {it->name()};
3165     THROW_NEW_ERROR(
3166         it->isolate(),
3167         NewReferenceError("not_defined", HandleVector(args, arraysize(args))),
3168         Object);
3169   }
3170
3171   *found = false;
3172   return MaybeHandle<Object>();
3173 }
3174
3175
3176 MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
3177                                         Handle<Object> value,
3178                                         LanguageMode language_mode,
3179                                         StoreFromKeyed store_mode) {
3180   bool found = false;
3181   MaybeHandle<Object> result =
3182       SetPropertyInternal(it, value, language_mode, store_mode, &found);
3183   if (found) return result;
3184   return AddDataProperty(it, value, NONE, language_mode, store_mode);
3185 }
3186
3187
3188 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
3189                                              Handle<Object> value,
3190                                              LanguageMode language_mode,
3191                                              StoreFromKeyed store_mode) {
3192   bool found = false;
3193   MaybeHandle<Object> result =
3194       SetPropertyInternal(it, value, language_mode, store_mode, &found);
3195   if (found) return result;
3196
3197   LookupIterator own_lookup(it->GetReceiver(), it->name(), LookupIterator::OWN);
3198
3199   switch (own_lookup.state()) {
3200     case LookupIterator::NOT_FOUND:
3201       return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
3202                                        store_mode);
3203
3204     case LookupIterator::INTEGER_INDEXED_EXOTIC:
3205       return result;
3206
3207     case LookupIterator::DATA: {
3208       PropertyDetails details = own_lookup.property_details();
3209       if (details.IsConfigurable() || !details.IsReadOnly()) {
3210         return JSObject::SetOwnPropertyIgnoreAttributes(
3211             Handle<JSObject>::cast(it->GetReceiver()), it->name(), value,
3212             details.attributes());
3213       }
3214       return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
3215     }
3216
3217     case LookupIterator::ACCESSOR: {
3218       PropertyDetails details = own_lookup.property_details();
3219       if (details.IsConfigurable()) {
3220         return JSObject::SetOwnPropertyIgnoreAttributes(
3221             Handle<JSObject>::cast(it->GetReceiver()), it->name(), value,
3222             details.attributes());
3223       }
3224
3225       return RedefineNonconfigurableProperty(it->isolate(), it->name(), value,
3226                                              language_mode);
3227     }
3228
3229     case LookupIterator::TRANSITION:
3230       UNREACHABLE();
3231       break;
3232
3233     case LookupIterator::INTERCEPTOR:
3234     case LookupIterator::JSPROXY:
3235     case LookupIterator::ACCESS_CHECK: {
3236       bool found = false;
3237       MaybeHandle<Object> result = SetPropertyInternal(
3238           &own_lookup, value, language_mode, store_mode, &found);
3239       if (found) return result;
3240       return SetDataProperty(&own_lookup, value);
3241     }
3242   }
3243
3244   UNREACHABLE();
3245   return MaybeHandle<Object>();
3246 }
3247
3248
3249 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3250     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
3251   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(), it->name(),
3252                                  value, language_mode);
3253 }
3254
3255
3256 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3257     Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
3258     Handle<Object> value, LanguageMode language_mode) {
3259   if (is_sloppy(language_mode)) return value;
3260   Handle<Object> args[] = {name, receiver};
3261   THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
3262                                         HandleVector(args, arraysize(args))),
3263                   Object);
3264 }
3265
3266
3267 MaybeHandle<Object> Object::WriteToReadOnlyElement(Isolate* isolate,
3268                                                    Handle<Object> receiver,
3269                                                    uint32_t index,
3270                                                    Handle<Object> value,
3271                                                    LanguageMode language_mode) {
3272   return WriteToReadOnlyProperty(isolate, receiver,
3273                                  isolate->factory()->NewNumberFromUint(index),
3274                                  value, language_mode);
3275 }
3276
3277
3278 MaybeHandle<Object> Object::RedefineNonconfigurableProperty(
3279     Isolate* isolate, Handle<Object> name, Handle<Object> value,
3280     LanguageMode language_mode) {
3281   if (is_sloppy(language_mode)) return value;
3282   Handle<Object> args[] = {name};
3283   THROW_NEW_ERROR(isolate, NewTypeError("redefine_disallowed",
3284                                         HandleVector(args, arraysize(args))),
3285                   Object);
3286 }
3287
3288
3289 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
3290                                             Handle<Object> value) {
3291   // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3292   // have own properties.
3293   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3294
3295   // Store on the holder which may be hidden behind the receiver.
3296   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
3297
3298   // Old value for the observation change record.
3299   // Fetch before transforming the object since the encoding may become
3300   // incompatible with what's cached in |it|.
3301   bool is_observed = receiver->map()->is_observed() &&
3302                      !it->isolate()->IsInternallyUsedPropertyName(it->name());
3303   MaybeHandle<Object> maybe_old;
3304   if (is_observed) maybe_old = it->GetDataValue();
3305
3306   // Possibly migrate to the most up-to-date map that will be able to store
3307   // |value| under it->name().
3308   it->PrepareForDataProperty(value);
3309
3310   // Write the property value.
3311   value = it->WriteDataValue(value);
3312
3313   // Send the change record if there are observers.
3314   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
3315     RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3316                                            receiver, "update", it->name(),
3317                                            maybe_old.ToHandleChecked()),
3318                         Object);
3319   }
3320
3321   return value;
3322 }
3323
3324
3325 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3326                                             Handle<Object> value,
3327                                             PropertyAttributes attributes,
3328                                             LanguageMode language_mode,
3329                                             StoreFromKeyed store_mode) {
3330   DCHECK(!it->GetReceiver()->IsJSProxy());
3331   if (!it->GetReceiver()->IsJSObject()) {
3332     // TODO(verwaest): Throw a TypeError with a more specific message.
3333     return WriteToReadOnlyProperty(it, value, language_mode);
3334   }
3335
3336   if (it->state() == LookupIterator::INTEGER_INDEXED_EXOTIC) return value;
3337
3338   Handle<JSObject> receiver = it->GetStoreTarget();
3339
3340   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3341   // instead. If the prototype is Null, the proxy is detached.
3342   if (receiver->IsJSGlobalProxy()) return value;
3343
3344   // Possibly migrate to the most up-to-date map that will be able to store
3345   // |value| under it->name() with |attributes|.
3346   it->PrepareTransitionToDataProperty(value, attributes, store_mode);
3347   if (it->state() != LookupIterator::TRANSITION) {
3348     if (is_sloppy(language_mode)) return value;
3349
3350     Handle<Object> args[] = {it->name()};
3351     THROW_NEW_ERROR(it->isolate(),
3352                     NewTypeError("object_not_extensible",
3353                                  HandleVector(args, arraysize(args))),
3354                     Object);
3355   }
3356   it->ApplyTransitionToDataProperty();
3357
3358   // TODO(verwaest): Encapsulate dictionary handling better.
3359   if (receiver->map()->is_dictionary_map()) {
3360     // TODO(verwaest): Probably should ensure this is done beforehand.
3361     it->InternalizeName();
3362     // TODO(dcarney): just populate TransitionPropertyCell here?
3363     JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3364   } else {
3365     // Write the property value.
3366     value = it->WriteDataValue(value);
3367   }
3368
3369   // Send the change record if there are observers.
3370   if (receiver->map()->is_observed() &&
3371       !it->isolate()->IsInternallyUsedPropertyName(it->name())) {
3372     RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3373                                            receiver, "add", it->name(),
3374                                            it->factory()->the_hole_value()),
3375                         Object);
3376   }
3377
3378   return value;
3379 }
3380
3381
3382 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3383     Handle<JSObject> object, uint32_t index, Handle<Object> value, bool* found,
3384     LanguageMode language_mode) {
3385   Isolate* isolate = object->GetIsolate();
3386   for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
3387        iter.Advance()) {
3388     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
3389       return JSProxy::SetPropertyViaPrototypesWithHandler(
3390           Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object,
3391           isolate->factory()->Uint32ToString(index),  // name
3392           value, language_mode, found);
3393     }
3394     Handle<JSObject> js_proto =
3395         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
3396
3397     if (js_proto->IsAccessCheckNeeded()) {
3398       if (!isolate->MayAccess(js_proto)) {
3399         *found = true;
3400         isolate->ReportFailedAccessCheck(js_proto);
3401         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3402         return MaybeHandle<Object>();
3403       }
3404     }
3405
3406     if (!js_proto->HasDictionaryElements()) {
3407       continue;
3408     }
3409
3410     Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
3411     int entry = dictionary->FindEntry(index);
3412     if (entry != SeededNumberDictionary::kNotFound) {
3413       PropertyDetails details = dictionary->DetailsAt(entry);
3414       if (details.type() == ACCESSOR_CONSTANT) {
3415         *found = true;
3416         Handle<Object> structure(dictionary->ValueAt(entry), isolate);
3417         return SetElementWithCallback(object, structure, index, value, js_proto,
3418                                       language_mode);
3419       }
3420     }
3421   }
3422   *found = false;
3423   return isolate->factory()->the_hole_value();
3424 }
3425
3426
3427 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3428   // Only supports adding slack to owned descriptors.
3429   DCHECK(map->owns_descriptors());
3430
3431   Handle<DescriptorArray> descriptors(map->instance_descriptors());
3432   int old_size = map->NumberOfOwnDescriptors();
3433   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3434
3435   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3436       descriptors, old_size, slack);
3437
3438   DisallowHeapAllocation no_allocation;
3439   // The descriptors are still the same, so keep the layout descriptor.
3440   LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
3441
3442   if (old_size == 0) {
3443     map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3444     return;
3445   }
3446
3447   // If the source descriptors had an enum cache we copy it. This ensures
3448   // that the maps to which we push the new descriptor array back can rely
3449   // on a cache always being available once it is set. If the map has more
3450   // enumerated descriptors than available in the original cache, the cache
3451   // will be lazily replaced by the extended cache when needed.
3452   if (descriptors->HasEnumCache()) {
3453     new_descriptors->CopyEnumCacheFrom(*descriptors);
3454   }
3455
3456   // Replace descriptors by new_descriptors in all maps that share it.
3457   map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
3458
3459   Map* walk_map;
3460   for (Object* current = map->GetBackPointer();
3461        !current->IsUndefined();
3462        current = walk_map->GetBackPointer()) {
3463     walk_map = Map::cast(current);
3464     if (walk_map->instance_descriptors() != *descriptors) break;
3465     walk_map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3466   }
3467
3468   map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3469 }
3470
3471
3472 template<class T>
3473 static int AppendUniqueCallbacks(NeanderArray* callbacks,
3474                                  Handle<typename T::Array> array,
3475                                  int valid_descriptors) {
3476   int nof_callbacks = callbacks->length();
3477
3478   Isolate* isolate = array->GetIsolate();
3479   // Ensure the keys are unique names before writing them into the
3480   // instance descriptor. Since it may cause a GC, it has to be done before we
3481   // temporarily put the heap in an invalid state while appending descriptors.
3482   for (int i = 0; i < nof_callbacks; ++i) {
3483     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3484     if (entry->name()->IsUniqueName()) continue;
3485     Handle<String> key =
3486         isolate->factory()->InternalizeString(
3487             Handle<String>(String::cast(entry->name())));
3488     entry->set_name(*key);
3489   }
3490
3491   // Fill in new callback descriptors.  Process the callbacks from
3492   // back to front so that the last callback with a given name takes
3493   // precedence over previously added callbacks with that name.
3494   for (int i = nof_callbacks - 1; i >= 0; i--) {
3495     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3496     Handle<Name> key(Name::cast(entry->name()));
3497     // Check if a descriptor with this name already exists before writing.
3498     if (!T::Contains(key, entry, valid_descriptors, array)) {
3499       T::Insert(key, entry, valid_descriptors, array);
3500       valid_descriptors++;
3501     }
3502   }
3503
3504   return valid_descriptors;
3505 }
3506
3507 struct DescriptorArrayAppender {
3508   typedef DescriptorArray Array;
3509   static bool Contains(Handle<Name> key,
3510                        Handle<AccessorInfo> entry,
3511                        int valid_descriptors,
3512                        Handle<DescriptorArray> array) {
3513     DisallowHeapAllocation no_gc;
3514     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
3515   }
3516   static void Insert(Handle<Name> key,
3517                      Handle<AccessorInfo> entry,
3518                      int valid_descriptors,
3519                      Handle<DescriptorArray> array) {
3520     DisallowHeapAllocation no_gc;
3521     AccessorConstantDescriptor desc(key, entry, entry->property_attributes());
3522     array->Append(&desc);
3523   }
3524 };
3525
3526
3527 struct FixedArrayAppender {
3528   typedef FixedArray Array;
3529   static bool Contains(Handle<Name> key,
3530                        Handle<AccessorInfo> entry,
3531                        int valid_descriptors,
3532                        Handle<FixedArray> array) {
3533     for (int i = 0; i < valid_descriptors; i++) {
3534       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
3535     }
3536     return false;
3537   }
3538   static void Insert(Handle<Name> key,
3539                      Handle<AccessorInfo> entry,
3540                      int valid_descriptors,
3541                      Handle<FixedArray> array) {
3542     DisallowHeapAllocation no_gc;
3543     array->set(valid_descriptors, *entry);
3544   }
3545 };
3546
3547
3548 void Map::AppendCallbackDescriptors(Handle<Map> map,
3549                                     Handle<Object> descriptors) {
3550   int nof = map->NumberOfOwnDescriptors();
3551   Handle<DescriptorArray> array(map->instance_descriptors());
3552   NeanderArray callbacks(descriptors);
3553   DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
3554   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3555   map->SetNumberOfOwnDescriptors(nof);
3556 }
3557
3558
3559 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
3560                                Handle<FixedArray> array,
3561                                int valid_descriptors) {
3562   NeanderArray callbacks(descriptors);
3563   DCHECK(array->length() >= callbacks.length() + valid_descriptors);
3564   return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3565                                                    array,
3566                                                    valid_descriptors);
3567 }
3568
3569
3570 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
3571   DCHECK(!map.is_null());
3572   for (int i = 0; i < maps->length(); ++i) {
3573     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
3574   }
3575   return false;
3576 }
3577
3578
3579 template <class T>
3580 static Handle<T> MaybeNull(T* p) {
3581   if (p == NULL) return Handle<T>::null();
3582   return Handle<T>(p);
3583 }
3584
3585
3586 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
3587   ElementsKind kind = elements_kind();
3588   Handle<Map> transitioned_map = Handle<Map>::null();
3589   Handle<Map> current_map(this);
3590   bool packed = IsFastPackedElementsKind(kind);
3591   if (IsTransitionableFastElementsKind(kind)) {
3592     while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
3593       kind = GetNextMoreGeneralFastElementsKind(kind, false);
3594       Handle<Map> maybe_transitioned_map =
3595           MaybeNull(current_map->LookupElementsTransitionMap(kind));
3596       if (maybe_transitioned_map.is_null()) break;
3597       if (ContainsMap(candidates, maybe_transitioned_map) &&
3598           (packed || !IsFastPackedElementsKind(kind))) {
3599         transitioned_map = maybe_transitioned_map;
3600         if (!IsFastPackedElementsKind(kind)) packed = false;
3601       }
3602       current_map = maybe_transitioned_map;
3603     }
3604   }
3605   return transitioned_map;
3606 }
3607
3608
3609 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
3610   Map* current_map = map;
3611   int target_kind =
3612       IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
3613       ? to_kind
3614       : TERMINAL_FAST_ELEMENTS_KIND;
3615
3616   // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
3617   // allows to change elements from arbitrary kind to any ExternalArray
3618   // elements kind. Satisfy its requirements, checking whether we already
3619   // have the cached transition.
3620   if (IsExternalArrayElementsKind(to_kind) &&
3621       !IsFixedTypedArrayElementsKind(map->elements_kind())) {
3622     Map* next_map = map->ElementsTransitionMap();
3623     if (next_map != NULL && next_map->elements_kind() == to_kind) {
3624       return next_map;
3625     }
3626     return map;
3627   }
3628
3629   ElementsKind kind = map->elements_kind();
3630   while (kind != target_kind) {
3631     kind = GetNextTransitionElementsKind(kind);
3632     Map* next_map = current_map->ElementsTransitionMap();
3633     if (next_map == NULL) return current_map;
3634     current_map = next_map;
3635   }
3636
3637   Map* next_map = current_map->ElementsTransitionMap();
3638   if (to_kind != kind && next_map != NULL) {
3639     DCHECK(to_kind == DICTIONARY_ELEMENTS);
3640     if (next_map->elements_kind() == to_kind) return next_map;
3641   }
3642
3643   DCHECK(current_map->elements_kind() == target_kind);
3644   return current_map;
3645 }
3646
3647
3648 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3649   Map* to_map = FindClosestElementsTransition(this, to_kind);
3650   if (to_map->elements_kind() == to_kind) return to_map;
3651   return NULL;
3652 }
3653
3654
3655 bool Map::IsMapInArrayPrototypeChain() {
3656   Isolate* isolate = GetIsolate();
3657   if (isolate->initial_array_prototype()->map() == this) {
3658     return true;
3659   }
3660
3661   if (isolate->initial_object_prototype()->map() == this) {
3662     return true;
3663   }
3664
3665   return false;
3666 }
3667
3668
3669 Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
3670   Isolate* isolate = map->GetIsolate();
3671   if (map->weak_cell_cache()->IsWeakCell()) {
3672     return Handle<WeakCell>(WeakCell::cast(map->weak_cell_cache()));
3673   }
3674   Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
3675   map->set_weak_cell_cache(*weak_cell);
3676   return weak_cell;
3677 }
3678
3679
3680 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
3681                                                  ElementsKind to_kind) {
3682   DCHECK(IsTransitionElementsKind(map->elements_kind()));
3683
3684   Handle<Map> current_map = map;
3685
3686   ElementsKind kind = map->elements_kind();
3687   TransitionFlag flag;
3688   if (map->is_prototype_map()) {
3689     flag = OMIT_TRANSITION;
3690   } else {
3691     flag = INSERT_TRANSITION;
3692     while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3693       kind = GetNextTransitionElementsKind(kind);
3694       current_map = Map::CopyAsElementsKind(current_map, kind, flag);
3695     }
3696   }
3697
3698   // In case we are exiting the fast elements kind system, just add the map in
3699   // the end.
3700   if (kind != to_kind) {
3701     current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
3702   }
3703
3704   DCHECK(current_map->elements_kind() == to_kind);
3705   return current_map;
3706 }
3707
3708
3709 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
3710                                       ElementsKind to_kind) {
3711   ElementsKind from_kind = map->elements_kind();
3712   if (from_kind == to_kind) return map;
3713
3714   Isolate* isolate = map->GetIsolate();
3715   Context* native_context = isolate->context()->native_context();
3716   Object* maybe_array_maps = native_context->js_array_maps();
3717   if (maybe_array_maps->IsFixedArray()) {
3718     DisallowHeapAllocation no_gc;
3719     FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
3720     if (array_maps->get(from_kind) == *map) {
3721       Object* maybe_transitioned_map = array_maps->get(to_kind);
3722       if (maybe_transitioned_map->IsMap()) {
3723         return handle(Map::cast(maybe_transitioned_map));
3724       }
3725     }
3726   }
3727
3728   return TransitionElementsToSlow(map, to_kind);
3729 }
3730
3731
3732 Handle<Map> Map::TransitionElementsToSlow(Handle<Map> map,
3733                                           ElementsKind to_kind) {
3734   ElementsKind from_kind = map->elements_kind();
3735
3736   if (from_kind == to_kind) {
3737     return map;
3738   }
3739
3740   bool allow_store_transition =
3741       // Only remember the map transition if there is not an already existing
3742       // non-matching element transition.
3743       !map->IsUndefined() && !map->is_dictionary_map() &&
3744       IsTransitionElementsKind(from_kind);
3745
3746   // Only store fast element maps in ascending generality.
3747   if (IsFastElementsKind(to_kind)) {
3748     allow_store_transition &=
3749         IsTransitionableFastElementsKind(from_kind) &&
3750         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3751   }
3752
3753   if (!allow_store_transition) {
3754     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
3755   }
3756
3757   return Map::AsElementsKind(map, to_kind);
3758 }
3759
3760
3761 // static
3762 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
3763   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
3764
3765   if (closest_map->elements_kind() == kind) {
3766     return closest_map;
3767   }
3768
3769   return AddMissingElementsTransitions(closest_map, kind);
3770 }
3771
3772
3773 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
3774                                                ElementsKind to_kind) {
3775   Handle<Map> map(object->map());
3776   return Map::TransitionElementsTo(map, to_kind);
3777 }
3778
3779
3780 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy,
3781                                             Handle<Name> name) {
3782   Isolate* isolate = proxy->GetIsolate();
3783
3784   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3785   if (name->IsSymbol()) return Just(false);
3786
3787   Handle<Object> args[] = { name };
3788   Handle<Object> result;
3789   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3790       isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(),
3791                                 arraysize(args), args),
3792       Nothing<bool>());
3793
3794   return Just(result->BooleanValue());
3795 }
3796
3797
3798 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(
3799     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3800     Handle<Object> value, LanguageMode language_mode) {
3801   Isolate* isolate = proxy->GetIsolate();
3802
3803   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3804   if (name->IsSymbol()) return value;
3805
3806   Handle<Object> args[] = { receiver, name, value };
3807   RETURN_ON_EXCEPTION(
3808       isolate,
3809       CallTrap(proxy,
3810                "set",
3811                isolate->derived_set_trap(),
3812                arraysize(args),
3813                args),
3814       Object);
3815
3816   return value;
3817 }
3818
3819
3820 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3821     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3822     Handle<Object> value, LanguageMode language_mode, bool* done) {
3823   Isolate* isolate = proxy->GetIsolate();
3824   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy.
3825
3826   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3827   if (name->IsSymbol()) {
3828     *done = false;
3829     return isolate->factory()->the_hole_value();
3830   }
3831
3832   *done = true;  // except where redefined...
3833   Handle<Object> args[] = { name };
3834   Handle<Object> result;
3835   ASSIGN_RETURN_ON_EXCEPTION(
3836       isolate, result,
3837       CallTrap(proxy,
3838                "getPropertyDescriptor",
3839                Handle<Object>(),
3840                arraysize(args),
3841                args),
3842       Object);
3843
3844   if (result->IsUndefined()) {
3845     *done = false;
3846     return isolate->factory()->the_hole_value();
3847   }
3848
3849   // Emulate [[GetProperty]] semantics for proxies.
3850   Handle<Object> argv[] = { result };
3851   Handle<Object> desc;
3852   ASSIGN_RETURN_ON_EXCEPTION(
3853       isolate, desc,
3854       Execution::Call(isolate,
3855                       isolate->to_complete_property_descriptor(),
3856                       result,
3857                       arraysize(argv),
3858                       argv),
3859       Object);
3860
3861   // [[GetProperty]] requires to check that all properties are configurable.
3862   Handle<String> configurable_name =
3863       isolate->factory()->InternalizeOneByteString(
3864           STATIC_CHAR_VECTOR("configurable_"));
3865   Handle<Object> configurable =
3866       Object::GetProperty(desc, configurable_name).ToHandleChecked();
3867   DCHECK(configurable->IsBoolean());
3868   if (configurable->IsFalse()) {
3869     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3870         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3871     Handle<Object> args[] = { handler, trap, name };
3872     THROW_NEW_ERROR(isolate, NewTypeError("proxy_prop_not_configurable",
3873                                           HandleVector(args, arraysize(args))),
3874                     Object);
3875   }
3876   DCHECK(configurable->IsTrue());
3877
3878   // Check for DataDescriptor.
3879   Handle<String> hasWritable_name =
3880       isolate->factory()->InternalizeOneByteString(
3881           STATIC_CHAR_VECTOR("hasWritable_"));
3882   Handle<Object> hasWritable =
3883       Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
3884   DCHECK(hasWritable->IsBoolean());
3885   if (hasWritable->IsTrue()) {
3886     Handle<String> writable_name = isolate->factory()->InternalizeOneByteString(
3887         STATIC_CHAR_VECTOR("writable_"));
3888     Handle<Object> writable =
3889         Object::GetProperty(desc, writable_name).ToHandleChecked();
3890     DCHECK(writable->IsBoolean());
3891     *done = writable->IsFalse();
3892     if (!*done) return isolate->factory()->the_hole_value();
3893     return WriteToReadOnlyProperty(isolate, receiver, name, value,
3894                                    language_mode);
3895   }
3896
3897   // We have an AccessorDescriptor.
3898   Handle<String> set_name =
3899       isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_"));
3900   Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
3901   if (!setter->IsUndefined()) {
3902     // TODO(rossberg): nicer would be to cast to some JSCallable here...
3903     return SetPropertyWithDefinedSetter(
3904         receiver, Handle<JSReceiver>::cast(setter), value);
3905   }
3906
3907   if (is_sloppy(language_mode)) return value;
3908   Handle<Object> args2[] = { name, proxy };
3909   THROW_NEW_ERROR(isolate, NewTypeError("no_setter_in_callback",
3910                                         HandleVector(args2, arraysize(args2))),
3911                   Object);
3912 }
3913
3914
3915 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
3916     Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) {
3917   Isolate* isolate = proxy->GetIsolate();
3918
3919   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3920   if (name->IsSymbol()) return isolate->factory()->false_value();
3921
3922   Handle<Object> args[] = { name };
3923   Handle<Object> result;
3924   ASSIGN_RETURN_ON_EXCEPTION(
3925       isolate, result,
3926       CallTrap(proxy,
3927                "delete",
3928                Handle<Object>(),
3929                arraysize(args),
3930                args),
3931       Object);
3932
3933   bool result_bool = result->BooleanValue();
3934   if (is_strict(language_mode) && !result_bool) {
3935     Handle<Object> handler(proxy->handler(), isolate);
3936     Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
3937         STATIC_CHAR_VECTOR("delete"));
3938     Handle<Object> args[] = { handler, trap_name };
3939     THROW_NEW_ERROR(isolate, NewTypeError("handler_failed",
3940                                           HandleVector(args, arraysize(args))),
3941                     Object);
3942   }
3943   return isolate->factory()->ToBoolean(result_bool);
3944 }
3945
3946
3947 MaybeHandle<Object> JSProxy::DeleteElementWithHandler(
3948     Handle<JSProxy> proxy, uint32_t index, LanguageMode language_mode) {
3949   Isolate* isolate = proxy->GetIsolate();
3950   Handle<String> name = isolate->factory()->Uint32ToString(index);
3951   return JSProxy::DeletePropertyWithHandler(proxy, name, language_mode);
3952 }
3953
3954
3955 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
3956     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
3957   Isolate* isolate = proxy->GetIsolate();
3958   HandleScope scope(isolate);
3959
3960   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3961   if (name->IsSymbol()) return Just(ABSENT);
3962
3963   Handle<Object> args[] = { name };
3964   Handle<Object> result;
3965   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3966       isolate, result, proxy->CallTrap(proxy, "getPropertyDescriptor",
3967                                        Handle<Object>(), arraysize(args), args),
3968       Nothing<PropertyAttributes>());
3969
3970   if (result->IsUndefined()) return Just(ABSENT);
3971
3972   Handle<Object> argv[] = { result };
3973   Handle<Object> desc;
3974   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3975       isolate, desc,
3976       Execution::Call(isolate, isolate->to_complete_property_descriptor(),
3977                       result, arraysize(argv), argv),
3978       Nothing<PropertyAttributes>());
3979
3980   // Convert result to PropertyAttributes.
3981   Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3982       STATIC_CHAR_VECTOR("enumerable_"));
3983   Handle<Object> enumerable;
3984   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable,
3985                                    Object::GetProperty(desc, enum_n),
3986                                    Nothing<PropertyAttributes>());
3987   Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
3988       STATIC_CHAR_VECTOR("configurable_"));
3989   Handle<Object> configurable;
3990   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
3991                                    Object::GetProperty(desc, conf_n),
3992                                    Nothing<PropertyAttributes>());
3993   Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
3994       STATIC_CHAR_VECTOR("writable_"));
3995   Handle<Object> writable;
3996   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
3997                                    Object::GetProperty(desc, writ_n),
3998                                    Nothing<PropertyAttributes>());
3999   if (!writable->BooleanValue()) {
4000     Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
4001         STATIC_CHAR_VECTOR("set_"));
4002     Handle<Object> setter;
4003     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
4004                                      Object::GetProperty(desc, set_n),
4005                                      Nothing<PropertyAttributes>());
4006     writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
4007   }
4008
4009   if (configurable->IsFalse()) {
4010     Handle<Object> handler(proxy->handler(), isolate);
4011     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
4012         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
4013     Handle<Object> args[] = { handler, trap, name };
4014     Handle<Object> error = isolate->factory()->NewTypeError(
4015         "proxy_prop_not_configurable", HandleVector(args, arraysize(args)));
4016     isolate->Throw(*error);
4017     return Just(NONE);
4018   }
4019
4020   int attributes = NONE;
4021   if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
4022   if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
4023   if (!writable->BooleanValue()) attributes |= READ_ONLY;
4024   return Just(static_cast<PropertyAttributes>(attributes));
4025 }
4026
4027
4028 Maybe<PropertyAttributes> JSProxy::GetElementAttributeWithHandler(
4029     Handle<JSProxy> proxy, Handle<JSReceiver> receiver, uint32_t index) {
4030   Isolate* isolate = proxy->GetIsolate();
4031   Handle<String> name = isolate->factory()->Uint32ToString(index);
4032   return GetPropertyAttributesWithHandler(proxy, receiver, name);
4033 }
4034
4035
4036 void JSProxy::Fix(Handle<JSProxy> proxy) {
4037   Isolate* isolate = proxy->GetIsolate();
4038
4039   // Save identity hash.
4040   Handle<Object> hash(proxy->GetIdentityHash(), isolate);
4041
4042   if (proxy->IsJSFunctionProxy()) {
4043     isolate->factory()->BecomeJSFunction(proxy);
4044     // Code will be set on the JavaScript side.
4045   } else {
4046     isolate->factory()->BecomeJSObject(proxy);
4047   }
4048   DCHECK(proxy->IsJSObject());
4049
4050   // Inherit identity, if it was present.
4051   if (hash->IsSmi()) {
4052     JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
4053                               Handle<Smi>::cast(hash));
4054   }
4055 }
4056
4057
4058 MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
4059                                       const char* name,
4060                                       Handle<Object> derived,
4061                                       int argc,
4062                                       Handle<Object> argv[]) {
4063   Isolate* isolate = proxy->GetIsolate();
4064   Handle<Object> handler(proxy->handler(), isolate);
4065
4066   Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
4067   Handle<Object> trap;
4068   ASSIGN_RETURN_ON_EXCEPTION(
4069       isolate, trap,
4070       Object::GetPropertyOrElement(handler, trap_name),
4071       Object);
4072
4073   if (trap->IsUndefined()) {
4074     if (derived.is_null()) {
4075       Handle<Object> args[] = { handler, trap_name };
4076       THROW_NEW_ERROR(isolate,
4077                       NewTypeError("handler_trap_missing",
4078                                    HandleVector(args, arraysize(args))),
4079                       Object);
4080     }
4081     trap = Handle<Object>(derived);
4082   }
4083
4084   return Execution::Call(isolate, trap, handler, argc, argv);
4085 }
4086
4087
4088 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
4089   DCHECK(object->map()->inobject_properties() == map->inobject_properties());
4090   ElementsKind obj_kind = object->map()->elements_kind();
4091   ElementsKind map_kind = map->elements_kind();
4092   if (map_kind != obj_kind) {
4093     ElementsKind to_kind = map_kind;
4094     if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
4095         IsDictionaryElementsKind(obj_kind)) {
4096       to_kind = obj_kind;
4097     }
4098     if (IsDictionaryElementsKind(to_kind)) {
4099       NormalizeElements(object);
4100     } else {
4101       TransitionElementsKind(object, to_kind);
4102     }
4103     map = Map::AsElementsKind(map, to_kind);
4104   }
4105   JSObject::MigrateToMap(object, map);
4106 }
4107
4108
4109 void JSObject::MigrateInstance(Handle<JSObject> object) {
4110   Handle<Map> original_map(object->map());
4111   Handle<Map> map = Map::Update(original_map);
4112   map->set_migration_target(true);
4113   MigrateToMap(object, map);
4114   if (FLAG_trace_migration) {
4115     object->PrintInstanceMigration(stdout, *original_map, *map);
4116   }
4117 }
4118
4119
4120 // static
4121 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
4122   Isolate* isolate = object->GetIsolate();
4123   DisallowDeoptimization no_deoptimization(isolate);
4124   Handle<Map> original_map(object->map(), isolate);
4125   Handle<Map> new_map;
4126   if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
4127     return false;
4128   }
4129   JSObject::MigrateToMap(object, new_map);
4130   if (FLAG_trace_migration) {
4131     object->PrintInstanceMigration(stdout, *original_map, object->map());
4132   }
4133   return true;
4134 }
4135
4136
4137 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
4138                            Handle<Object> value,
4139                            PropertyAttributes attributes) {
4140   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4141   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
4142 #ifdef DEBUG
4143   uint32_t index;
4144   DCHECK(!object->IsJSProxy());
4145   DCHECK(!name->AsArrayIndex(&index));
4146   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
4147   DCHECK(maybe.IsJust());
4148   DCHECK(!it.IsFound());
4149   DCHECK(object->map()->is_extensible() ||
4150          it.isolate()->IsInternallyUsedPropertyName(name));
4151 #endif
4152   AddDataProperty(&it, value, attributes, STRICT,
4153                   CERTAINLY_NOT_STORE_FROM_KEYED).Check();
4154 }
4155
4156
4157 // Reconfigures a property to a data property with attributes, even if it is not
4158 // reconfigurable.
4159 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4160     Handle<JSObject> object,
4161     Handle<Name> name,
4162     Handle<Object> value,
4163     PropertyAttributes attributes,
4164     ExecutableAccessorInfoHandling handling) {
4165   DCHECK(!value->IsTheHole());
4166   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4167   bool is_observed = object->map()->is_observed() &&
4168                      !it.isolate()->IsInternallyUsedPropertyName(name);
4169   for (; it.IsFound(); it.Next()) {
4170     switch (it.state()) {
4171       case LookupIterator::INTEGER_INDEXED_EXOTIC:
4172         return value;
4173
4174       case LookupIterator::INTERCEPTOR:
4175       case LookupIterator::JSPROXY:
4176       case LookupIterator::NOT_FOUND:
4177       case LookupIterator::TRANSITION:
4178         UNREACHABLE();
4179
4180       case LookupIterator::ACCESS_CHECK:
4181         if (!it.isolate()->MayAccess(object)) {
4182           return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4183         }
4184         break;
4185
4186       case LookupIterator::ACCESSOR: {
4187         PropertyDetails details = it.property_details();
4188         // Ensure the context isn't changed after calling into accessors.
4189         AssertNoContextChange ncc(it.isolate());
4190
4191         Handle<Object> accessors = it.GetAccessors();
4192
4193         // Special handling for ExecutableAccessorInfo, which behaves like a
4194         // data property.
4195         if (handling == DONT_FORCE_FIELD &&
4196             accessors->IsExecutableAccessorInfo()) {
4197           Handle<Object> result;
4198           ASSIGN_RETURN_ON_EXCEPTION(
4199               it.isolate(), result,
4200               JSObject::SetPropertyWithAccessor(it.GetReceiver(), it.name(),
4201                                                 value, it.GetHolder<JSObject>(),
4202                                                 accessors, STRICT),
4203               Object);
4204           DCHECK(result->SameValue(*value));
4205
4206           if (details.attributes() == attributes) {
4207             return value;
4208           }
4209
4210           // Reconfigure the accessor if attributes mismatch.
4211           Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4212               it.isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4213           new_data->set_property_attributes(attributes);
4214           // By clearing the setter we don't have to introduce a lookup to
4215           // the setter, simply make it unavailable to reflect the
4216           // attributes.
4217           if (attributes & READ_ONLY) new_data->clear_setter();
4218           SetPropertyCallback(object, name, new_data, attributes);
4219           if (is_observed) {
4220             RETURN_ON_EXCEPTION(
4221                 it.isolate(),
4222                 EnqueueChangeRecord(object, "reconfigure", name,
4223                                     it.isolate()->factory()->the_hole_value()),
4224                 Object);
4225           }
4226           return value;
4227         }
4228
4229         it.ReconfigureDataProperty(value, attributes);
4230         value = it.WriteDataValue(value);
4231
4232         if (is_observed) {
4233           RETURN_ON_EXCEPTION(
4234               it.isolate(),
4235               EnqueueChangeRecord(object, "reconfigure", name,
4236                                   it.isolate()->factory()->the_hole_value()),
4237               Object);
4238         }
4239
4240         return value;
4241       }
4242
4243       case LookupIterator::DATA: {
4244         PropertyDetails details = it.property_details();
4245         Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
4246         // Regular property update if the attributes match.
4247         if (details.attributes() == attributes) {
4248           return SetDataProperty(&it, value);
4249         }
4250         // Reconfigure the data property if the attributes mismatch.
4251         if (is_observed) old_value = it.GetDataValue();
4252
4253         it.ReconfigureDataProperty(value, attributes);
4254         value = it.WriteDataValue(value);
4255
4256         if (is_observed) {
4257           if (old_value->SameValue(*value)) {
4258             old_value = it.isolate()->factory()->the_hole_value();
4259           }
4260           RETURN_ON_EXCEPTION(
4261               it.isolate(),
4262               EnqueueChangeRecord(object, "reconfigure", name, old_value),
4263               Object);
4264         }
4265
4266         return value;
4267       }
4268     }
4269   }
4270
4271   return AddDataProperty(&it, value, attributes, STRICT,
4272                          CERTAINLY_NOT_STORE_FROM_KEYED);
4273 }
4274
4275
4276 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4277     Handle<JSObject> holder,
4278     Handle<Object> receiver,
4279     Handle<Name> name) {
4280   Isolate* isolate = holder->GetIsolate();
4281   HandleScope scope(isolate);
4282
4283   // Make sure that the top context does not change when doing
4284   // callbacks or interceptor calls.
4285   AssertNoContextChange ncc(isolate);
4286
4287   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
4288   if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
4289     return Just(ABSENT);
4290   }
4291   PropertyCallbackArguments args(
4292       isolate, interceptor->data(), *receiver, *holder);
4293   if (!interceptor->query()->IsUndefined()) {
4294     v8::GenericNamedPropertyQueryCallback query =
4295         v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
4296             interceptor->query());
4297     LOG(isolate,
4298         ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
4299     v8::Handle<v8::Integer> result = args.Call(query, v8::Utils::ToLocal(name));
4300     if (!result.IsEmpty()) {
4301       DCHECK(result->IsInt32());
4302       return Just(static_cast<PropertyAttributes>(result->Int32Value()));
4303     }
4304   } else if (!interceptor->getter()->IsUndefined()) {
4305     v8::GenericNamedPropertyGetterCallback getter =
4306         v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
4307             interceptor->getter());
4308     LOG(isolate,
4309         ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
4310     v8::Handle<v8::Value> result = args.Call(getter, v8::Utils::ToLocal(name));
4311     if (!result.IsEmpty()) return Just(DONT_ENUM);
4312   }
4313
4314   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
4315   return Just(ABSENT);
4316 }
4317
4318
4319 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
4320     Handle<JSReceiver> object, Handle<Name> name) {
4321   // Check whether the name is an array index.
4322   uint32_t index = 0;
4323   if (object->IsJSObject() && name->AsArrayIndex(&index)) {
4324     return GetOwnElementAttribute(object, index);
4325   }
4326   LookupIterator it(object, name, LookupIterator::HIDDEN);
4327   return GetPropertyAttributes(&it);
4328 }
4329
4330
4331 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
4332     LookupIterator* it) {
4333   for (; it->IsFound(); it->Next()) {
4334     switch (it->state()) {
4335       case LookupIterator::NOT_FOUND:
4336       case LookupIterator::TRANSITION:
4337         UNREACHABLE();
4338       case LookupIterator::JSPROXY:
4339         return JSProxy::GetPropertyAttributesWithHandler(
4340             it->GetHolder<JSProxy>(), it->GetReceiver(), it->name());
4341       case LookupIterator::INTERCEPTOR: {
4342         Maybe<PropertyAttributes> result =
4343             JSObject::GetPropertyAttributesWithInterceptor(
4344                 it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
4345         if (!result.IsJust()) return result;
4346         if (result.FromJust() != ABSENT) return result;
4347         break;
4348       }
4349       case LookupIterator::ACCESS_CHECK:
4350         if (it->HasAccess()) break;
4351         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
4352       case LookupIterator::INTEGER_INDEXED_EXOTIC:
4353         return Just(ABSENT);
4354       case LookupIterator::ACCESSOR:
4355       case LookupIterator::DATA:
4356         return Just(it->property_details().attributes());
4357     }
4358   }
4359   return Just(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->MayAccess(object)) {
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 Just(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.IsJust()) return Nothing<PropertyAttributes>();
4409   if (from_interceptor.FromJust() != ABSENT)
4410     return Just(from_interceptor.FromJust());
4411
4412   return GetElementAttributeWithoutInterceptor(object, receiver, index,
4413                                                check_prototype);
4414 }
4415
4416
4417 Maybe<PropertyAttributes> JSObject::GetElementAttributeFromInterceptor(
4418     Handle<JSObject> object, Handle<Object> receiver, uint32_t index) {
4419   Isolate* isolate = object->GetIsolate();
4420   AssertNoContextChange ncc(isolate);
4421
4422   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
4423   PropertyCallbackArguments args(
4424       isolate, interceptor->data(), *receiver, *object);
4425   if (!interceptor->query()->IsUndefined()) {
4426     v8::IndexedPropertyQueryCallback query =
4427         v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4428     LOG(isolate,
4429         ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index));
4430     v8::Handle<v8::Integer> result = args.Call(query, index);
4431     if (!result.IsEmpty())
4432       return Just(static_cast<PropertyAttributes>(result->Int32Value()));
4433   } else if (!interceptor->getter()->IsUndefined()) {
4434     v8::IndexedPropertyGetterCallback getter =
4435         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4436     LOG(isolate,
4437         ApiIndexedPropertyAccess(
4438             "interceptor-indexed-get-has", *object, index));
4439     v8::Handle<v8::Value> result = args.Call(getter, index);
4440     if (!result.IsEmpty()) return Just(NONE);
4441   }
4442   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
4443   return Just(ABSENT);
4444 }
4445
4446
4447 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor(
4448     Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4449     bool check_prototype) {
4450   PropertyAttributes attr =
4451       object->GetElementsAccessor()->GetAttributes(object, index);
4452   if (attr != ABSENT) return Just(attr);
4453
4454   // Handle [] on String objects.
4455   if (object->IsStringObjectWithCharacterAt(index)) {
4456     return Just(static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE));
4457   }
4458
4459   if (!check_prototype) return Just(ABSENT);
4460
4461   PrototypeIterator iter(object->GetIsolate(), object);
4462   if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
4463     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
4464     return JSProxy::GetElementAttributeWithHandler(
4465         Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4466         index);
4467   }
4468   if (iter.IsAtEnd()) return Just(ABSENT);
4469   return GetElementAttributeWithReceiver(
4470       Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4471       index, true);
4472 }
4473
4474
4475 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
4476   Handle<FixedArray> array(
4477       isolate->factory()->NewFixedArray(kEntries, TENURED));
4478   return Handle<NormalizedMapCache>::cast(array);
4479 }
4480
4481
4482 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
4483                                          PropertyNormalizationMode mode) {
4484   DisallowHeapAllocation no_gc;
4485   Object* value = FixedArray::get(GetIndex(fast_map));
4486   if (!value->IsMap() ||
4487       !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4488     return MaybeHandle<Map>();
4489   }
4490   return handle(Map::cast(value));
4491 }
4492
4493
4494 void NormalizedMapCache::Set(Handle<Map> fast_map,
4495                              Handle<Map> normalized_map) {
4496   DisallowHeapAllocation no_gc;
4497   DCHECK(normalized_map->is_dictionary_map());
4498   FixedArray::set(GetIndex(fast_map), *normalized_map);
4499 }
4500
4501
4502 void NormalizedMapCache::Clear() {
4503   int entries = length();
4504   for (int i = 0; i != entries; i++) {
4505     set_undefined(i);
4506   }
4507 }
4508
4509
4510 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
4511                                     Handle<Name> name,
4512                                     Handle<Code> code) {
4513   Handle<Map> map(object->map());
4514   Map::UpdateCodeCache(map, name, code);
4515 }
4516
4517
4518 void JSObject::NormalizeProperties(Handle<JSObject> object,
4519                                    PropertyNormalizationMode mode,
4520                                    int expected_additional_properties,
4521                                    const char* reason) {
4522   if (!object->HasFastProperties()) return;
4523
4524   Handle<Map> map(object->map());
4525   Handle<Map> new_map = Map::Normalize(map, mode, reason);
4526
4527   MigrateFastToSlow(object, new_map, expected_additional_properties);
4528 }
4529
4530
4531 void JSObject::MigrateFastToSlow(Handle<JSObject> object,
4532                                  Handle<Map> new_map,
4533                                  int expected_additional_properties) {
4534   // The global object is always normalized.
4535   DCHECK(!object->IsGlobalObject());
4536   // JSGlobalProxy must never be normalized
4537   DCHECK(!object->IsJSGlobalProxy());
4538
4539   Isolate* isolate = object->GetIsolate();
4540   HandleScope scope(isolate);
4541   Handle<Map> map(object->map());
4542
4543   // Allocate new content.
4544   int real_size = map->NumberOfOwnDescriptors();
4545   int property_count = real_size;
4546   if (expected_additional_properties > 0) {
4547     property_count += expected_additional_properties;
4548   } else {
4549     property_count += 2;  // Make space for two more properties.
4550   }
4551   Handle<NameDictionary> dictionary =
4552       NameDictionary::New(isolate, property_count);
4553
4554   Handle<DescriptorArray> descs(map->instance_descriptors());
4555   for (int i = 0; i < real_size; i++) {
4556     PropertyDetails details = descs->GetDetails(i);
4557     Handle<Name> key(descs->GetKey(i));
4558     switch (details.type()) {
4559       case DATA_CONSTANT: {
4560         Handle<Object> value(descs->GetConstant(i), isolate);
4561         PropertyDetails d(details.attributes(), DATA, i + 1,
4562                           PropertyCellType::kInvalid);
4563         dictionary = NameDictionary::Add(dictionary, key, value, d);
4564         break;
4565       }
4566       case DATA: {
4567         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4568         Handle<Object> value;
4569         if (object->IsUnboxedDoubleField(index)) {
4570           double old_value = object->RawFastDoublePropertyAt(index);
4571           value = isolate->factory()->NewHeapNumber(old_value);
4572         } else {
4573           value = handle(object->RawFastPropertyAt(index), isolate);
4574           if (details.representation().IsDouble()) {
4575             DCHECK(value->IsMutableHeapNumber());
4576             Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
4577             value = isolate->factory()->NewHeapNumber(old->value());
4578           }
4579         }
4580         PropertyDetails d(details.attributes(), DATA, i + 1,
4581                           PropertyCellType::kInvalid);
4582         dictionary = NameDictionary::Add(dictionary, key, value, d);
4583         break;
4584       }
4585       case ACCESSOR: {
4586         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4587         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
4588         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
4589                           PropertyCellType::kInvalid);
4590         dictionary = NameDictionary::Add(dictionary, key, value, d);
4591         break;
4592       }
4593       case ACCESSOR_CONSTANT: {
4594         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4595         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
4596                           PropertyCellType::kInvalid);
4597         dictionary = NameDictionary::Add(dictionary, key, value, d);
4598         break;
4599       }
4600     }
4601   }
4602
4603   // Copy the next enumeration index from instance descriptor.
4604   dictionary->SetNextEnumerationIndex(real_size + 1);
4605
4606   // From here on we cannot fail and we shouldn't GC anymore.
4607   DisallowHeapAllocation no_allocation;
4608
4609   // Resize the object in the heap if necessary.
4610   int new_instance_size = new_map->instance_size();
4611   int instance_size_delta = map->instance_size() - new_instance_size;
4612   DCHECK(instance_size_delta >= 0);
4613
4614   if (instance_size_delta > 0) {
4615     Heap* heap = isolate->heap();
4616     heap->CreateFillerObjectAt(object->address() + new_instance_size,
4617                                instance_size_delta);
4618     heap->AdjustLiveBytes(object->address(), -instance_size_delta,
4619                           Heap::FROM_MUTATOR);
4620   }
4621
4622   // We are storing the new map using release store after creating a filler for
4623   // the left-over space to avoid races with the sweeper thread.
4624   object->synchronized_set_map(*new_map);
4625
4626   object->set_properties(*dictionary);
4627
4628   // Ensure that in-object space of slow-mode object does not contain random
4629   // garbage.
4630   int inobject_properties = new_map->inobject_properties();
4631   for (int i = 0; i < inobject_properties; i++) {
4632     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
4633     object->RawFastPropertyAtPut(index, Smi::FromInt(0));
4634   }
4635
4636   isolate->counters()->props_to_dictionary()->Increment();
4637
4638 #ifdef DEBUG
4639   if (FLAG_trace_normalization) {
4640     OFStream os(stdout);
4641     os << "Object properties have been normalized:\n";
4642     object->Print(os);
4643   }
4644 #endif
4645 }
4646
4647
4648 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
4649                                  int unused_property_fields,
4650                                  const char* reason) {
4651   if (object->HasFastProperties()) return;
4652   DCHECK(!object->IsGlobalObject());
4653   Isolate* isolate = object->GetIsolate();
4654   Factory* factory = isolate->factory();
4655   Handle<NameDictionary> dictionary(object->property_dictionary());
4656
4657   // Make sure we preserve dictionary representation if there are too many
4658   // descriptors.
4659   int number_of_elements = dictionary->NumberOfElements();
4660   if (number_of_elements > kMaxNumberOfDescriptors) return;
4661
4662   Handle<FixedArray> iteration_order;
4663   if (number_of_elements != dictionary->NextEnumerationIndex()) {
4664     iteration_order =
4665         NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
4666   } else {
4667     iteration_order = NameDictionary::BuildIterationIndicesArray(dictionary);
4668   }
4669
4670   int instance_descriptor_length = iteration_order->length();
4671   int number_of_fields = 0;
4672
4673   // Compute the length of the instance descriptor.
4674   for (int i = 0; i < instance_descriptor_length; i++) {
4675     int index = Smi::cast(iteration_order->get(i))->value();
4676     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
4677
4678     Object* value = dictionary->ValueAt(index);
4679     PropertyType type = dictionary->DetailsAt(index).type();
4680     if (type == DATA && !value->IsJSFunction()) {
4681       number_of_fields += 1;
4682     }
4683   }
4684
4685   int inobject_props = object->map()->inobject_properties();
4686
4687   // Allocate new map.
4688   Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
4689   new_map->set_dictionary_map(false);
4690
4691 #if TRACE_MAPS
4692   if (FLAG_trace_maps) {
4693     PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
4694            reinterpret_cast<void*>(object->map()),
4695            reinterpret_cast<void*>(*new_map), reason);
4696   }
4697 #endif
4698
4699   if (instance_descriptor_length == 0) {
4700     DisallowHeapAllocation no_gc;
4701     DCHECK_LE(unused_property_fields, inobject_props);
4702     // Transform the object.
4703     new_map->set_unused_property_fields(inobject_props);
4704     object->synchronized_set_map(*new_map);
4705     object->set_properties(isolate->heap()->empty_fixed_array());
4706     // Check that it really works.
4707     DCHECK(object->HasFastProperties());
4708     return;
4709   }
4710
4711   // Allocate the instance descriptor.
4712   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
4713       isolate, instance_descriptor_length);
4714
4715   int number_of_allocated_fields =
4716       number_of_fields + unused_property_fields - inobject_props;
4717   if (number_of_allocated_fields < 0) {
4718     // There is enough inobject space for all fields (including unused).
4719     number_of_allocated_fields = 0;
4720     unused_property_fields = inobject_props - number_of_fields;
4721   }
4722
4723   // Allocate the fixed array for the fields.
4724   Handle<FixedArray> fields = factory->NewFixedArray(
4725       number_of_allocated_fields);
4726
4727   // Fill in the instance descriptor and the fields.
4728   int current_offset = 0;
4729   for (int i = 0; i < instance_descriptor_length; i++) {
4730     int index = Smi::cast(iteration_order->get(i))->value();
4731     Object* k = dictionary->KeyAt(index);
4732     DCHECK(dictionary->IsKey(k));
4733
4734     Object* value = dictionary->ValueAt(index);
4735     Handle<Name> key;
4736     if (k->IsSymbol()) {
4737       key = handle(Symbol::cast(k));
4738     } else {
4739       // Ensure the key is a unique name before writing into the
4740       // instance descriptor.
4741       key = factory->InternalizeString(handle(String::cast(k)));
4742     }
4743
4744     PropertyDetails details = dictionary->DetailsAt(index);
4745     int enumeration_index = details.dictionary_index();
4746     PropertyType type = details.type();
4747
4748     if (value->IsJSFunction()) {
4749       DataConstantDescriptor d(key, handle(value, isolate),
4750                                details.attributes());
4751       descriptors->Set(enumeration_index - 1, &d);
4752     } else if (type == DATA) {
4753       if (current_offset < inobject_props) {
4754         object->InObjectPropertyAtPut(current_offset, value,
4755                                       UPDATE_WRITE_BARRIER);
4756       } else {
4757         int offset = current_offset - inobject_props;
4758         fields->set(offset, value);
4759       }
4760       DataDescriptor d(key, current_offset, details.attributes(),
4761                        // TODO(verwaest): value->OptimalRepresentation();
4762                        Representation::Tagged());
4763       current_offset += d.GetDetails().field_width_in_words();
4764       descriptors->Set(enumeration_index - 1, &d);
4765     } else if (type == ACCESSOR_CONSTANT) {
4766       AccessorConstantDescriptor d(key, handle(value, isolate),
4767                                    details.attributes());
4768       descriptors->Set(enumeration_index - 1, &d);
4769     } else {
4770       UNREACHABLE();
4771     }
4772   }
4773   DCHECK(current_offset == number_of_fields);
4774
4775   descriptors->Sort();
4776
4777   Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
4778       new_map, descriptors, descriptors->number_of_descriptors());
4779
4780   DisallowHeapAllocation no_gc;
4781   new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
4782   new_map->set_unused_property_fields(unused_property_fields);
4783
4784   // Transform the object.
4785   object->synchronized_set_map(*new_map);
4786
4787   object->set_properties(*fields);
4788   DCHECK(object->IsJSObject());
4789
4790   // Check that it really works.
4791   DCHECK(object->HasFastProperties());
4792 }
4793
4794
4795 void JSObject::ResetElements(Handle<JSObject> object) {
4796   Isolate* isolate = object->GetIsolate();
4797   CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
4798   if (object->map()->has_dictionary_elements()) {
4799     Handle<SeededNumberDictionary> new_elements =
4800         SeededNumberDictionary::New(isolate, 0);
4801     object->set_elements(*new_elements);
4802   } else {
4803     object->set_elements(object->map()->GetInitialElements());
4804   }
4805 }
4806
4807
4808 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4809     Handle<FixedArrayBase> array,
4810     int length,
4811     Handle<SeededNumberDictionary> dictionary) {
4812   Isolate* isolate = array->GetIsolate();
4813   Factory* factory = isolate->factory();
4814   bool has_double_elements = array->IsFixedDoubleArray();
4815   for (int i = 0; i < length; i++) {
4816     Handle<Object> value;
4817     if (has_double_elements) {
4818       Handle<FixedDoubleArray> double_array =
4819           Handle<FixedDoubleArray>::cast(array);
4820       if (double_array->is_the_hole(i)) {
4821         value = factory->the_hole_value();
4822       } else {
4823         value = factory->NewHeapNumber(double_array->get_scalar(i));
4824       }
4825     } else {
4826       value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4827     }
4828     if (!value->IsTheHole()) {
4829       PropertyDetails details = PropertyDetails::Empty();
4830       dictionary =
4831           SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4832     }
4833   }
4834   return dictionary;
4835 }
4836
4837
4838 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4839     Handle<JSObject> object) {
4840   DCHECK(!object->HasExternalArrayElements() &&
4841          !object->HasFixedTypedArrayElements());
4842   Isolate* isolate = object->GetIsolate();
4843
4844   // Find the backing store.
4845   Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements()));
4846   bool is_arguments =
4847       (array->map() == isolate->heap()->sloppy_arguments_elements_map());
4848   if (is_arguments) {
4849     array = handle(FixedArrayBase::cast(
4850         Handle<FixedArray>::cast(array)->get(1)));
4851   }
4852   if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array);
4853
4854   DCHECK(object->HasFastSmiOrObjectElements() ||
4855          object->HasFastDoubleElements() ||
4856          object->HasFastArgumentsElements());
4857   // Compute the effective length and allocate a new backing store.
4858   int length = object->IsJSArray()
4859       ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4860       : array->length();
4861   int old_capacity = 0;
4862   int used_elements = 0;
4863   object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4864   Handle<SeededNumberDictionary> dictionary =
4865       SeededNumberDictionary::New(isolate, used_elements);
4866
4867   dictionary = CopyFastElementsToDictionary(array, length, dictionary);
4868
4869   // Switch to using the dictionary as the backing storage for elements.
4870   if (is_arguments) {
4871     FixedArray::cast(object->elements())->set(1, *dictionary);
4872   } else {
4873     // Set the new map first to satify the elements type assert in
4874     // set_elements().
4875     Handle<Map> new_map =
4876         JSObject::GetElementsTransitionMap(object, DICTIONARY_ELEMENTS);
4877
4878     JSObject::MigrateToMap(object, new_map);
4879     object->set_elements(*dictionary);
4880   }
4881
4882   isolate->counters()->elements_to_dictionary()->Increment();
4883
4884 #ifdef DEBUG
4885   if (FLAG_trace_normalization) {
4886     OFStream os(stdout);
4887     os << "Object elements have been normalized:\n";
4888     object->Print(os);
4889   }
4890 #endif
4891
4892   DCHECK(object->HasDictionaryElements() ||
4893          object->HasDictionaryArgumentsElements());
4894   return dictionary;
4895 }
4896
4897
4898 static Smi* GenerateIdentityHash(Isolate* isolate) {
4899   int hash_value;
4900   int attempts = 0;
4901   do {
4902     // Generate a random 32-bit hash value but limit range to fit
4903     // within a smi.
4904     hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4905     attempts++;
4906   } while (hash_value == 0 && attempts < 30);
4907   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
4908
4909   return Smi::FromInt(hash_value);
4910 }
4911
4912
4913 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4914   DCHECK(!object->IsJSGlobalProxy());
4915   Isolate* isolate = object->GetIsolate();
4916   SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4917 }
4918
4919
4920 template<typename ProxyType>
4921 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
4922   Isolate* isolate = proxy->GetIsolate();
4923
4924   Handle<Object> maybe_hash(proxy->hash(), isolate);
4925   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4926
4927   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4928   proxy->set_hash(*hash);
4929   return hash;
4930 }
4931
4932
4933 Object* JSObject::GetIdentityHash() {
4934   DisallowHeapAllocation no_gc;
4935   Isolate* isolate = GetIsolate();
4936   if (IsJSGlobalProxy()) {
4937     return JSGlobalProxy::cast(this)->hash();
4938   }
4939   Object* stored_value =
4940       GetHiddenProperty(isolate->factory()->identity_hash_string());
4941   return stored_value->IsSmi()
4942       ? stored_value
4943       : isolate->heap()->undefined_value();
4944 }
4945
4946
4947 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
4948   if (object->IsJSGlobalProxy()) {
4949     return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
4950   }
4951
4952   Isolate* isolate = object->GetIsolate();
4953
4954   Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
4955   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4956
4957   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4958   SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4959   return hash;
4960 }
4961
4962
4963 Object* JSProxy::GetIdentityHash() {
4964   return this->hash();
4965 }
4966
4967
4968 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
4969   return GetOrCreateIdentityHashHelper(proxy);
4970 }
4971
4972
4973 Object* JSObject::GetHiddenProperty(Handle<Name> key) {
4974   DisallowHeapAllocation no_gc;
4975   DCHECK(key->IsUniqueName());
4976   if (IsJSGlobalProxy()) {
4977     // JSGlobalProxies store their hash internally.
4978     DCHECK(*key != GetHeap()->identity_hash_string());
4979     // For a proxy, use the prototype as target object.
4980     PrototypeIterator iter(GetIsolate(), this);
4981     // If the proxy is detached, return undefined.
4982     if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
4983     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
4984     return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key);
4985   }
4986   DCHECK(!IsJSGlobalProxy());
4987   Object* inline_value = GetHiddenPropertiesHashTable();
4988
4989   if (inline_value->IsSmi()) {
4990     // Handle inline-stored identity hash.
4991     if (*key == GetHeap()->identity_hash_string()) {
4992       return inline_value;
4993     } else {
4994       return GetHeap()->the_hole_value();
4995     }
4996   }
4997
4998   if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
4999
5000   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
5001   Object* entry = hashtable->Lookup(key);
5002   return entry;
5003 }
5004
5005
5006 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
5007                                            Handle<Name> key,
5008                                            Handle<Object> value) {
5009   Isolate* isolate = object->GetIsolate();
5010
5011   DCHECK(key->IsUniqueName());
5012   if (object->IsJSGlobalProxy()) {
5013     // JSGlobalProxies store their hash internally.
5014     DCHECK(*key != *isolate->factory()->identity_hash_string());
5015     // For a proxy, use the prototype as target object.
5016     PrototypeIterator iter(isolate, object);
5017     // If the proxy is detached, return undefined.
5018     if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
5019     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5020     return SetHiddenProperty(
5021         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key,
5022         value);
5023   }
5024   DCHECK(!object->IsJSGlobalProxy());
5025
5026   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5027
5028   // If there is no backing store yet, store the identity hash inline.
5029   if (value->IsSmi() &&
5030       *key == *isolate->factory()->identity_hash_string() &&
5031       (inline_value->IsUndefined() || inline_value->IsSmi())) {
5032     return JSObject::SetHiddenPropertiesHashTable(object, value);
5033   }
5034
5035   Handle<ObjectHashTable> hashtable =
5036       GetOrCreateHiddenPropertiesHashtable(object);
5037
5038   // If it was found, check if the key is already in the dictionary.
5039   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
5040                                                            value);
5041   if (*new_table != *hashtable) {
5042     // If adding the key expanded the dictionary (i.e., Add returned a new
5043     // dictionary), store it back to the object.
5044     SetHiddenPropertiesHashTable(object, new_table);
5045   }
5046
5047   // Return this to mark success.
5048   return object;
5049 }
5050
5051
5052 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
5053   Isolate* isolate = object->GetIsolate();
5054   DCHECK(key->IsUniqueName());
5055
5056   if (object->IsJSGlobalProxy()) {
5057     PrototypeIterator iter(isolate, object);
5058     if (iter.IsAtEnd()) return;
5059     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5060     return DeleteHiddenProperty(
5061         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key);
5062   }
5063
5064   Object* inline_value = object->GetHiddenPropertiesHashTable();
5065
5066   // We never delete (inline-stored) identity hashes.
5067   DCHECK(*key != *isolate->factory()->identity_hash_string());
5068   if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
5069
5070   Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
5071   bool was_present = false;
5072   ObjectHashTable::Remove(hashtable, key, &was_present);
5073 }
5074
5075
5076 bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
5077   Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
5078   LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR);
5079   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
5080   // Cannot get an exception since the hidden_string isn't accessible to JS.
5081   DCHECK(maybe.IsJust());
5082   return maybe.FromJust() != ABSENT;
5083 }
5084
5085
5086 Object* JSObject::GetHiddenPropertiesHashTable() {
5087   DCHECK(!IsJSGlobalProxy());
5088   if (HasFastProperties()) {
5089     // If the object has fast properties, check whether the first slot
5090     // in the descriptor array matches the hidden string. Since the
5091     // hidden strings hash code is zero (and no other name has hash
5092     // code zero) it will always occupy the first entry if present.
5093     DescriptorArray* descriptors = this->map()->instance_descriptors();
5094     if (descriptors->number_of_descriptors() > 0) {
5095       int sorted_index = descriptors->GetSortedKeyIndex(0);
5096       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
5097           sorted_index < map()->NumberOfOwnDescriptors()) {
5098         DCHECK(descriptors->GetType(sorted_index) == DATA);
5099         DCHECK(descriptors->GetDetails(sorted_index).representation().
5100                IsCompatibleForLoad(Representation::Tagged()));
5101         FieldIndex index = FieldIndex::ForDescriptor(this->map(),
5102                                                      sorted_index);
5103         return this->RawFastPropertyAt(index);
5104       } else {
5105         return GetHeap()->undefined_value();
5106       }
5107     } else {
5108       return GetHeap()->undefined_value();
5109     }
5110   } else {
5111     Isolate* isolate = GetIsolate();
5112     LookupIterator it(handle(this), isolate->factory()->hidden_string(),
5113                       LookupIterator::OWN_SKIP_INTERCEPTOR);
5114     // Access check is always skipped for the hidden string anyways.
5115     return *GetDataProperty(&it);
5116   }
5117 }
5118
5119 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
5120     Handle<JSObject> object) {
5121   Isolate* isolate = object->GetIsolate();
5122
5123   static const int kInitialCapacity = 4;
5124   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5125   if (inline_value->IsHashTable()) {
5126     return Handle<ObjectHashTable>::cast(inline_value);
5127   }
5128
5129   Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
5130       isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
5131
5132   if (inline_value->IsSmi()) {
5133     // We were storing the identity hash inline and now allocated an actual
5134     // dictionary.  Put the identity hash into the new dictionary.
5135     hashtable = ObjectHashTable::Put(hashtable,
5136                                      isolate->factory()->identity_hash_string(),
5137                                      inline_value);
5138   }
5139
5140   SetHiddenPropertiesHashTable(object, hashtable);
5141   return hashtable;
5142 }
5143
5144
5145 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
5146                                                       Handle<Object> value) {
5147   DCHECK(!object->IsJSGlobalProxy());
5148   Isolate* isolate = object->GetIsolate();
5149   Handle<Name> name = isolate->factory()->hidden_string();
5150   SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
5151   return object;
5152 }
5153
5154
5155 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
5156     Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name) {
5157   Isolate* isolate = holder->GetIsolate();
5158
5159   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
5160   if (interceptor->deleter()->IsUndefined() ||
5161       (name->IsSymbol() && !interceptor->can_intercept_symbols())) {
5162     return MaybeHandle<Object>();
5163   }
5164
5165   v8::GenericNamedPropertyDeleterCallback deleter =
5166       v8::ToCData<v8::GenericNamedPropertyDeleterCallback>(
5167           interceptor->deleter());
5168   LOG(isolate,
5169       ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name));
5170   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
5171                                  *holder);
5172   v8::Handle<v8::Boolean> result = args.Call(deleter, v8::Utils::ToLocal(name));
5173   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5174   if (result.IsEmpty()) return MaybeHandle<Object>();
5175
5176   DCHECK(result->IsBoolean());
5177   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5178   result_internal->VerifyApiCallResultType();
5179   // Rebox CustomArguments::kReturnValueOffset before returning.
5180   return handle(*result_internal, isolate);
5181 }
5182
5183
5184 MaybeHandle<Object> JSObject::DeleteElementWithInterceptor(
5185     Handle<JSObject> object,
5186     uint32_t index) {
5187   Isolate* isolate = object->GetIsolate();
5188   Factory* factory = isolate->factory();
5189
5190   // Make sure that the top context does not change when doing
5191   // callbacks or interceptor calls.
5192   AssertNoContextChange ncc(isolate);
5193
5194   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
5195   if (interceptor->deleter()->IsUndefined()) return factory->false_value();
5196   v8::IndexedPropertyDeleterCallback deleter =
5197       v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
5198   LOG(isolate,
5199       ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index));
5200   PropertyCallbackArguments args(
5201       isolate, interceptor->data(), *object, *object);
5202   v8::Handle<v8::Boolean> result = args.Call(deleter, index);
5203   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5204   if (!result.IsEmpty()) {
5205     DCHECK(result->IsBoolean());
5206     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5207     result_internal->VerifyApiCallResultType();
5208     // Rebox CustomArguments::kReturnValueOffset before returning.
5209     return handle(*result_internal, isolate);
5210   }
5211   // TODO(verwaest): Shouldn't this be the mode that was passed in?
5212   MaybeHandle<Object> delete_result =
5213       object->GetElementsAccessor()->Delete(object, index, SLOPPY);
5214   return delete_result;
5215 }
5216
5217
5218 MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
5219                                             uint32_t index,
5220                                             LanguageMode language_mode) {
5221   Isolate* isolate = object->GetIsolate();
5222   Factory* factory = isolate->factory();
5223
5224   // Check access rights if needed.
5225   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
5226     isolate->ReportFailedAccessCheck(object);
5227     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5228     return factory->false_value();
5229   }
5230
5231   if (object->IsStringObjectWithCharacterAt(index)) {
5232     if (is_strict(language_mode)) {
5233       // Deleting a non-configurable property in strict mode.
5234       Handle<Object> name = factory->NewNumberFromUint(index);
5235       Handle<Object> args[] = {name, object};
5236       THROW_NEW_ERROR(isolate,
5237                       NewTypeError("strict_delete_property",
5238                                    HandleVector(args, arraysize(args))),
5239                       Object);
5240     }
5241     return factory->false_value();
5242   }
5243
5244   if (object->IsJSGlobalProxy()) {
5245     PrototypeIterator iter(isolate, object);
5246     if (iter.IsAtEnd()) return factory->false_value();
5247     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5248     return DeleteElement(
5249         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
5250         language_mode);
5251   }
5252
5253   Handle<Object> old_value;
5254   bool should_enqueue_change_record = false;
5255   if (object->map()->is_observed()) {
5256     Maybe<bool> maybe = HasOwnElement(object, index);
5257     if (!maybe.IsJust()) return MaybeHandle<Object>();
5258     should_enqueue_change_record = maybe.FromJust();
5259     if (should_enqueue_change_record) {
5260       if (!GetOwnElementAccessorPair(object, index).is_null()) {
5261         old_value = Handle<Object>::cast(factory->the_hole_value());
5262       } else {
5263         old_value = Object::GetElement(
5264             isolate, object, index).ToHandleChecked();
5265       }
5266     }
5267   }
5268
5269   // Skip interceptor if forcing deletion.
5270   MaybeHandle<Object> maybe_result;
5271   if (object->HasIndexedInterceptor()) {
5272     maybe_result = DeleteElementWithInterceptor(object, index);
5273   } else {
5274     maybe_result =
5275         object->GetElementsAccessor()->Delete(object, index, language_mode);
5276   }
5277   Handle<Object> result;
5278   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
5279
5280   if (should_enqueue_change_record) {
5281     Maybe<bool> maybe = HasOwnElement(object, index);
5282     if (!maybe.IsJust()) return MaybeHandle<Object>();
5283     if (!maybe.FromJust()) {
5284       Handle<String> name = factory->Uint32ToString(index);
5285       RETURN_ON_EXCEPTION(
5286           isolate, EnqueueChangeRecord(object, "delete", name, old_value),
5287           Object);
5288     }
5289   }
5290
5291   return result;
5292 }
5293
5294
5295 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
5296                                         Handle<Name> name) {
5297   DCHECK(!object->HasFastProperties());
5298   Isolate* isolate = object->GetIsolate();
5299   Handle<NameDictionary> dictionary(object->property_dictionary());
5300   int entry = dictionary->FindEntry(name);
5301   DCHECK_NE(NameDictionary::kNotFound, entry);
5302
5303   // If we have a global object, invalidate the cell and swap in a new one.
5304   if (object->IsGlobalObject()) {
5305     auto cell = PropertyCell::InvalidateEntry(dictionary, entry);
5306     cell->set_value(isolate->heap()->the_hole_value());
5307     // TODO(dcarney): InvalidateForDelete
5308     dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type(
5309                                         PropertyCellType::kDeleted));
5310     return;
5311   }
5312
5313   NameDictionary::DeleteProperty(dictionary, entry);
5314   Handle<NameDictionary> new_properties =
5315       NameDictionary::Shrink(dictionary, name);
5316   object->set_properties(*new_properties);
5317 }
5318
5319
5320 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
5321                                              Handle<Name> name,
5322                                              LanguageMode language_mode) {
5323   // ECMA-262, 3rd, 8.6.2.5
5324   DCHECK(name->IsName());
5325
5326   uint32_t index = 0;
5327   if (name->AsArrayIndex(&index)) {
5328     return DeleteElement(object, index, language_mode);
5329   }
5330
5331   LookupIterator it(object, name, LookupIterator::HIDDEN);
5332
5333   bool is_observed = object->map()->is_observed() &&
5334                      !it.isolate()->IsInternallyUsedPropertyName(name);
5335   Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
5336
5337   for (; it.IsFound(); it.Next()) {
5338     switch (it.state()) {
5339       case LookupIterator::JSPROXY:
5340       case LookupIterator::NOT_FOUND:
5341       case LookupIterator::TRANSITION:
5342         UNREACHABLE();
5343       case LookupIterator::ACCESS_CHECK:
5344         if (it.HasAccess()) break;
5345         it.isolate()->ReportFailedAccessCheck(it.GetHolder<JSObject>());
5346         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it.isolate(), Object);
5347         return it.isolate()->factory()->false_value();
5348       case LookupIterator::INTERCEPTOR: {
5349         MaybeHandle<Object> maybe_result =
5350             JSObject::DeletePropertyWithInterceptor(it.GetHolder<JSObject>(),
5351                                                     object, it.name());
5352         // Delete with interceptor succeeded. Return result.
5353         if (!maybe_result.is_null()) return maybe_result;
5354         // An exception was thrown in the interceptor. Propagate.
5355         if (it.isolate()->has_pending_exception()) return maybe_result;
5356         break;
5357       }
5358       case LookupIterator::INTEGER_INDEXED_EXOTIC:
5359         return it.isolate()->factory()->true_value();
5360       case LookupIterator::DATA:
5361         if (is_observed) {
5362           old_value = it.GetDataValue();
5363         }
5364       // Fall through.
5365       case LookupIterator::ACCESSOR: {
5366         if (!it.IsConfigurable()) {
5367           // Fail if the property is not configurable.
5368           if (is_strict(language_mode)) {
5369             Handle<Object> args[] = {name, object};
5370             THROW_NEW_ERROR(it.isolate(),
5371                             NewTypeError("strict_delete_property",
5372                                          HandleVector(args, arraysize(args))),
5373                             Object);
5374           }
5375           return it.isolate()->factory()->false_value();
5376         }
5377
5378         PropertyNormalizationMode mode = object->map()->is_prototype_map()
5379                                              ? KEEP_INOBJECT_PROPERTIES
5380                                              : CLEAR_INOBJECT_PROPERTIES;
5381         Handle<JSObject> holder = it.GetHolder<JSObject>();
5382         // TODO(verwaest): Remove this temporary compatibility hack when blink
5383         // tests are updated.
5384         if (!holder.is_identical_to(object) &&
5385             !(object->IsJSGlobalProxy() && holder->IsJSGlobalObject())) {
5386           return it.isolate()->factory()->true_value();
5387         }
5388
5389         NormalizeProperties(holder, mode, 0, "DeletingProperty");
5390         DeleteNormalizedProperty(holder, name);
5391         ReoptimizeIfPrototype(holder);
5392
5393         if (is_observed) {
5394           RETURN_ON_EXCEPTION(
5395               it.isolate(),
5396               EnqueueChangeRecord(object, "delete", name, old_value), Object);
5397         }
5398
5399         return it.isolate()->factory()->true_value();
5400       }
5401     }
5402   }
5403
5404   return it.isolate()->factory()->true_value();
5405 }
5406
5407
5408 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
5409                                               uint32_t index,
5410                                               LanguageMode language_mode) {
5411   if (object->IsJSProxy()) {
5412     return JSProxy::DeleteElementWithHandler(Handle<JSProxy>::cast(object),
5413                                              index, language_mode);
5414   }
5415   return JSObject::DeleteElement(Handle<JSObject>::cast(object), index,
5416                                  language_mode);
5417 }
5418
5419
5420 MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
5421                                                Handle<Name> name,
5422                                                LanguageMode language_mode) {
5423   if (object->IsJSProxy()) {
5424     return JSProxy::DeletePropertyWithHandler(Handle<JSProxy>::cast(object),
5425                                               name, language_mode);
5426   }
5427   return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name,
5428                                   language_mode);
5429 }
5430
5431
5432 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
5433                                             ElementsKind kind,
5434                                             Object* object) {
5435   DCHECK(IsFastObjectElementsKind(kind) ||
5436          kind == DICTIONARY_ELEMENTS);
5437   if (IsFastObjectElementsKind(kind)) {
5438     int length = IsJSArray()
5439         ? Smi::cast(JSArray::cast(this)->length())->value()
5440         : elements->length();
5441     for (int i = 0; i < length; ++i) {
5442       Object* element = elements->get(i);
5443       if (!element->IsTheHole() && element == object) return true;
5444     }
5445   } else {
5446     Object* key =
5447         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5448     if (!key->IsUndefined()) return true;
5449   }
5450   return false;
5451 }
5452
5453
5454 // Check whether this object references another object.
5455 bool JSObject::ReferencesObject(Object* obj) {
5456   Map* map_of_this = map();
5457   Heap* heap = GetHeap();
5458   DisallowHeapAllocation no_allocation;
5459
5460   // Is the object the constructor for this object?
5461   if (map_of_this->GetConstructor() == obj) {
5462     return true;
5463   }
5464
5465   // Is the object the prototype for this object?
5466   if (map_of_this->prototype() == obj) {
5467     return true;
5468   }
5469
5470   // Check if the object is among the named properties.
5471   Object* key = SlowReverseLookup(obj);
5472   if (!key->IsUndefined()) {
5473     return true;
5474   }
5475
5476   // Check if the object is among the indexed properties.
5477   ElementsKind kind = GetElementsKind();
5478   switch (kind) {
5479     // Raw pixels and external arrays do not reference other
5480     // objects.
5481 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5482     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
5483     case TYPE##_ELEMENTS:                                                      \
5484       break;
5485
5486     TYPED_ARRAYS(TYPED_ARRAY_CASE)
5487 #undef TYPED_ARRAY_CASE
5488
5489     case FAST_DOUBLE_ELEMENTS:
5490     case FAST_HOLEY_DOUBLE_ELEMENTS:
5491       break;
5492     case FAST_SMI_ELEMENTS:
5493     case FAST_HOLEY_SMI_ELEMENTS:
5494       break;
5495     case FAST_ELEMENTS:
5496     case FAST_HOLEY_ELEMENTS:
5497     case DICTIONARY_ELEMENTS: {
5498       FixedArray* elements = FixedArray::cast(this->elements());
5499       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5500       break;
5501     }
5502     case SLOPPY_ARGUMENTS_ELEMENTS: {
5503       FixedArray* parameter_map = FixedArray::cast(elements());
5504       // Check the mapped parameters.
5505       int length = parameter_map->length();
5506       for (int i = 2; i < length; ++i) {
5507         Object* value = parameter_map->get(i);
5508         if (!value->IsTheHole() && value == obj) return true;
5509       }
5510       // Check the arguments.
5511       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5512       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5513           FAST_HOLEY_ELEMENTS;
5514       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5515       break;
5516     }
5517   }
5518
5519   // For functions check the context.
5520   if (IsJSFunction()) {
5521     // Get the constructor function for arguments array.
5522     Map* arguments_map =
5523         heap->isolate()->context()->native_context()->sloppy_arguments_map();
5524     JSFunction* arguments_function =
5525         JSFunction::cast(arguments_map->GetConstructor());
5526
5527     // Get the context and don't check if it is the native context.
5528     JSFunction* f = JSFunction::cast(this);
5529     Context* context = f->context();
5530     if (context->IsNativeContext()) {
5531       return false;
5532     }
5533
5534     // Check the non-special context slots.
5535     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5536       // Only check JS objects.
5537       if (context->get(i)->IsJSObject()) {
5538         JSObject* ctxobj = JSObject::cast(context->get(i));
5539         // If it is an arguments array check the content.
5540         if (ctxobj->map()->GetConstructor() == arguments_function) {
5541           if (ctxobj->ReferencesObject(obj)) {
5542             return true;
5543           }
5544         } else if (ctxobj == obj) {
5545           return true;
5546         }
5547       }
5548     }
5549
5550     // Check the context extension (if any) if it can have references.
5551     if (context->has_extension() && !context->IsCatchContext()) {
5552       // With harmony scoping, a JSFunction may have a global context.
5553       // TODO(mvstanton): walk into the ScopeInfo.
5554       if (context->IsScriptContext()) {
5555         return false;
5556       }
5557
5558       return JSObject::cast(context->extension())->ReferencesObject(obj);
5559     }
5560   }
5561
5562   // No references to object.
5563   return false;
5564 }
5565
5566
5567 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5568   if (!object->map()->is_extensible()) return object;
5569
5570   if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) {
5571     return PreventExtensionsWithTransition<NONE>(object);
5572   }
5573
5574   Isolate* isolate = object->GetIsolate();
5575
5576   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
5577     isolate->ReportFailedAccessCheck(object);
5578     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5579     return isolate->factory()->false_value();
5580   }
5581
5582   if (object->IsJSGlobalProxy()) {
5583     PrototypeIterator iter(isolate, object);
5584     if (iter.IsAtEnd()) return object;
5585     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5586     return PreventExtensions(
5587         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5588   }
5589
5590   // It's not possible to seal objects with external array elements
5591   if (object->HasExternalArrayElements() ||
5592       object->HasFixedTypedArrayElements()) {
5593     THROW_NEW_ERROR(isolate,
5594                     NewTypeError("cant_prevent_ext_external_array_elements",
5595                                  HandleVector(&object, 1)),
5596                     Object);
5597   }
5598
5599   // If there are fast elements we normalize.
5600   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5601   DCHECK(object->HasDictionaryElements() ||
5602          object->HasDictionaryArgumentsElements());
5603
5604   // Make sure that we never go back to fast case.
5605   dictionary->set_requires_slow_elements();
5606
5607   // Do a map transition, other objects with this map may still
5608   // be extensible.
5609   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5610   Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
5611
5612   new_map->set_is_extensible(false);
5613   JSObject::MigrateToMap(object, new_map);
5614   DCHECK(!object->map()->is_extensible());
5615
5616   if (object->map()->is_observed()) {
5617     RETURN_ON_EXCEPTION(
5618         isolate,
5619         EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5620                             isolate->factory()->the_hole_value()),
5621         Object);
5622   }
5623   return object;
5624 }
5625
5626
5627 Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
5628     Handle<JSObject> object) {
5629   DCHECK(!object->elements()->IsDictionary());
5630   Isolate* isolate = object->GetIsolate();
5631   int length = object->IsJSArray()
5632                    ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5633                    : object->elements()->length();
5634   if (length > 0) {
5635     int capacity = 0;
5636     int used = 0;
5637     object->GetElementsCapacityAndUsage(&capacity, &used);
5638     Handle<SeededNumberDictionary> new_element_dictionary =
5639         SeededNumberDictionary::New(isolate, used);
5640
5641     // Move elements to a dictionary; avoid calling NormalizeElements to avoid
5642     // unnecessary transitions.
5643     return CopyFastElementsToDictionary(handle(object->elements()), length,
5644                                         new_element_dictionary);
5645   }
5646   // No existing elements, use a pre-allocated empty backing store
5647   return isolate->factory()->empty_slow_element_dictionary();
5648 }
5649
5650
5651 template <typename Dictionary>
5652 static void ApplyAttributesToDictionary(Dictionary* dictionary,
5653                                         const PropertyAttributes attributes) {
5654   int capacity = dictionary->Capacity();
5655   for (int i = 0; i < capacity; i++) {
5656     Object* k = dictionary->KeyAt(i);
5657     if (dictionary->IsKey(k) &&
5658         !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
5659       PropertyDetails details = dictionary->DetailsAt(i);
5660       int attrs = attributes;
5661       // READ_ONLY is an invalid attribute for JS setters/getters.
5662       if ((attributes & READ_ONLY) && details.type() == ACCESSOR_CONSTANT) {
5663         Object* v = dictionary->ValueAt(i);
5664         if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
5665         if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
5666       }
5667       details = details.CopyAddAttributes(
5668           static_cast<PropertyAttributes>(attrs));
5669       dictionary->DetailsAtPut(i, details);
5670     }
5671   }
5672 }
5673
5674
5675 template <PropertyAttributes attrs>
5676 MaybeHandle<Object> JSObject::PreventExtensionsWithTransition(
5677     Handle<JSObject> object) {
5678   STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
5679
5680   // Sealing/freezing sloppy arguments should be handled elsewhere.
5681   DCHECK(!object->HasSloppyArgumentsElements());
5682   DCHECK(!object->map()->is_observed());
5683
5684   Isolate* isolate = object->GetIsolate();
5685   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
5686     isolate->ReportFailedAccessCheck(object);
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   Map* transition =
5725       TransitionArray::SearchSpecial(*old_map, *transition_marker);
5726   if (transition != NULL) {
5727     Handle<Map> transition_map(transition, isolate);
5728     DCHECK(transition_map->has_dictionary_elements());
5729     DCHECK(!transition_map->is_extensible());
5730     JSObject::MigrateToMap(object, transition_map);
5731   } else if (object->HasFastProperties() &&
5732              TransitionArray::CanHaveMoreTransitions(old_map)) {
5733     // Create a new descriptor array with the appropriate property attributes
5734     Handle<Map> new_map = Map::CopyForPreventExtensions(
5735         old_map, attrs, transition_marker, "CopyForPreventExtensions");
5736     JSObject::MigrateToMap(object, new_map);
5737   } else {
5738     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5739     // Slow path: need to normalize properties for safety
5740     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
5741                         "SlowPreventExtensions");
5742
5743     // Create a new map, since other objects with this map may be extensible.
5744     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5745     Handle<Map> new_map =
5746         Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
5747     new_map->set_is_extensible(false);
5748     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5749     JSObject::MigrateToMap(object, new_map);
5750
5751     if (attrs != NONE) {
5752       ApplyAttributesToDictionary(object->property_dictionary(), attrs);
5753     }
5754   }
5755
5756   DCHECK(object->map()->has_dictionary_elements());
5757   if (!new_element_dictionary.is_null()) {
5758     object->set_elements(*new_element_dictionary);
5759   }
5760
5761   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5762     SeededNumberDictionary* dictionary = object->element_dictionary();
5763     // Make sure we never go back to the fast case
5764     dictionary->set_requires_slow_elements();
5765     if (attrs != NONE) {
5766       ApplyAttributesToDictionary(dictionary, attrs);
5767     }
5768   }
5769
5770   return object;
5771 }
5772
5773
5774 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
5775   return PreventExtensionsWithTransition<FROZEN>(object);
5776 }
5777
5778
5779 MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) {
5780   return PreventExtensionsWithTransition<SEALED>(object);
5781 }
5782
5783
5784 void JSObject::SetObserved(Handle<JSObject> object) {
5785   DCHECK(!object->IsJSGlobalProxy());
5786   DCHECK(!object->IsJSGlobalObject());
5787   Isolate* isolate = object->GetIsolate();
5788   Handle<Map> new_map;
5789   Handle<Map> old_map(object->map(), isolate);
5790   DCHECK(!old_map->is_observed());
5791   Map* transition = TransitionArray::SearchSpecial(
5792       *old_map, isolate->heap()->observed_symbol());
5793   if (transition != NULL) {
5794     new_map = handle(transition, isolate);
5795     DCHECK(new_map->is_observed());
5796   } else if (object->HasFastProperties() &&
5797              TransitionArray::CanHaveMoreTransitions(old_map)) {
5798     new_map = Map::CopyForObserved(old_map);
5799   } else {
5800     new_map = Map::Copy(old_map, "SlowObserved");
5801     new_map->set_is_observed();
5802   }
5803   JSObject::MigrateToMap(object, new_map);
5804 }
5805
5806
5807 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
5808                                         Representation representation,
5809                                         FieldIndex index) {
5810   Isolate* isolate = object->GetIsolate();
5811   if (object->IsUnboxedDoubleField(index)) {
5812     double value = object->RawFastDoublePropertyAt(index);
5813     return isolate->factory()->NewHeapNumber(value);
5814   }
5815   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
5816   return Object::WrapForRead(isolate, raw_value, representation);
5817 }
5818
5819
5820 template<class ContextObject>
5821 class JSObjectWalkVisitor {
5822  public:
5823   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5824                       JSObject::DeepCopyHints hints)
5825     : site_context_(site_context),
5826       copying_(copying),
5827       hints_(hints) {}
5828
5829   MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
5830
5831  protected:
5832   MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
5833       Handle<JSObject> object,
5834       Handle<JSObject> value) {
5835     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5836     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
5837     site_context()->ExitScope(current_site, value);
5838     return copy_of_value;
5839   }
5840
5841   inline ContextObject* site_context() { return site_context_; }
5842   inline Isolate* isolate() { return site_context()->isolate(); }
5843
5844   inline bool copying() const { return copying_; }
5845
5846  private:
5847   ContextObject* site_context_;
5848   const bool copying_;
5849   const JSObject::DeepCopyHints hints_;
5850 };
5851
5852
5853 template <class ContextObject>
5854 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
5855     Handle<JSObject> object) {
5856   Isolate* isolate = this->isolate();
5857   bool copying = this->copying();
5858   bool shallow = hints_ == JSObject::kObjectIsShallow;
5859
5860   if (!shallow) {
5861     StackLimitCheck check(isolate);
5862
5863     if (check.HasOverflowed()) {
5864       isolate->StackOverflow();
5865       return MaybeHandle<JSObject>();
5866     }
5867   }
5868
5869   if (object->map()->is_deprecated()) {
5870     JSObject::MigrateInstance(object);
5871   }
5872
5873   Handle<JSObject> copy;
5874   if (copying) {
5875     Handle<AllocationSite> site_to_pass;
5876     if (site_context()->ShouldCreateMemento(object)) {
5877       site_to_pass = site_context()->current();
5878     }
5879     copy = isolate->factory()->CopyJSObjectWithAllocationSite(
5880         object, site_to_pass);
5881   } else {
5882     copy = object;
5883   }
5884
5885   DCHECK(copying || copy.is_identical_to(object));
5886
5887   ElementsKind kind = copy->GetElementsKind();
5888   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5889       FixedArray::cast(copy->elements())->map() ==
5890         isolate->heap()->fixed_cow_array_map()) {
5891     isolate->counters()->cow_arrays_created_runtime()->Increment();
5892   }
5893
5894   if (!shallow) {
5895     HandleScope scope(isolate);
5896
5897     // Deep copy own properties.
5898     if (copy->HasFastProperties()) {
5899       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5900       int limit = copy->map()->NumberOfOwnDescriptors();
5901       for (int i = 0; i < limit; i++) {
5902         PropertyDetails details = descriptors->GetDetails(i);
5903         if (details.type() != DATA) continue;
5904         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
5905         if (object->IsUnboxedDoubleField(index)) {
5906           if (copying) {
5907             double value = object->RawFastDoublePropertyAt(index);
5908             copy->RawFastDoublePropertyAtPut(index, value);
5909           }
5910         } else {
5911           Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5912           if (value->IsJSObject()) {
5913             ASSIGN_RETURN_ON_EXCEPTION(
5914                 isolate, value,
5915                 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5916                 JSObject);
5917             if (copying) {
5918               copy->FastPropertyAtPut(index, *value);
5919             }
5920           } else {
5921             if (copying) {
5922               Representation representation = details.representation();
5923               value = Object::NewStorageFor(isolate, value, representation);
5924               copy->FastPropertyAtPut(index, *value);
5925             }
5926           }
5927         }
5928       }
5929     } else {
5930       Handle<FixedArray> names =
5931           isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
5932       copy->GetOwnPropertyNames(*names, 0);
5933       for (int i = 0; i < names->length(); i++) {
5934         DCHECK(names->get(i)->IsString());
5935         Handle<String> key_string(String::cast(names->get(i)));
5936         Maybe<PropertyAttributes> maybe =
5937             JSReceiver::GetOwnPropertyAttributes(copy, key_string);
5938         DCHECK(maybe.IsJust());
5939         PropertyAttributes attributes = maybe.FromJust();
5940         // Only deep copy fields from the object literal expression.
5941         // In particular, don't try to copy the length attribute of
5942         // an array.
5943         if (attributes != NONE) continue;
5944         Handle<Object> value =
5945             Object::GetProperty(copy, key_string).ToHandleChecked();
5946         if (value->IsJSObject()) {
5947           Handle<JSObject> result;
5948           ASSIGN_RETURN_ON_EXCEPTION(
5949               isolate, result,
5950               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5951               JSObject);
5952           if (copying) {
5953             // Creating object copy for literals. No strict mode needed.
5954             JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert();
5955           }
5956         }
5957       }
5958     }
5959
5960     // Deep copy own elements.
5961     // Pixel elements cannot be created using an object literal.
5962     DCHECK(!copy->HasExternalArrayElements());
5963     switch (kind) {
5964       case FAST_SMI_ELEMENTS:
5965       case FAST_ELEMENTS:
5966       case FAST_HOLEY_SMI_ELEMENTS:
5967       case FAST_HOLEY_ELEMENTS: {
5968         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5969         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5970 #ifdef DEBUG
5971           for (int i = 0; i < elements->length(); i++) {
5972             DCHECK(!elements->get(i)->IsJSObject());
5973           }
5974 #endif
5975         } else {
5976           for (int i = 0; i < elements->length(); i++) {
5977             Handle<Object> value(elements->get(i), isolate);
5978             DCHECK(value->IsSmi() ||
5979                    value->IsTheHole() ||
5980                    (IsFastObjectElementsKind(copy->GetElementsKind())));
5981             if (value->IsJSObject()) {
5982               Handle<JSObject> result;
5983               ASSIGN_RETURN_ON_EXCEPTION(
5984                   isolate, result,
5985                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5986                   JSObject);
5987               if (copying) {
5988                 elements->set(i, *result);
5989               }
5990             }
5991           }
5992         }
5993         break;
5994       }
5995       case DICTIONARY_ELEMENTS: {
5996         Handle<SeededNumberDictionary> element_dictionary(
5997             copy->element_dictionary());
5998         int capacity = element_dictionary->Capacity();
5999         for (int i = 0; i < capacity; i++) {
6000           Object* k = element_dictionary->KeyAt(i);
6001           if (element_dictionary->IsKey(k)) {
6002             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
6003             if (value->IsJSObject()) {
6004               Handle<JSObject> result;
6005               ASSIGN_RETURN_ON_EXCEPTION(
6006                   isolate, result,
6007                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
6008                   JSObject);
6009               if (copying) {
6010                 element_dictionary->ValueAtPut(i, *result);
6011               }
6012             }
6013           }
6014         }
6015         break;
6016       }
6017       case SLOPPY_ARGUMENTS_ELEMENTS:
6018         UNIMPLEMENTED();
6019         break;
6020
6021
6022 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6023       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
6024       case TYPE##_ELEMENTS:                                                    \
6025
6026       TYPED_ARRAYS(TYPED_ARRAY_CASE)
6027 #undef TYPED_ARRAY_CASE
6028
6029       case FAST_DOUBLE_ELEMENTS:
6030       case FAST_HOLEY_DOUBLE_ELEMENTS:
6031         // No contained objects, nothing to do.
6032         break;
6033     }
6034   }
6035
6036   return copy;
6037 }
6038
6039
6040 MaybeHandle<JSObject> JSObject::DeepWalk(
6041     Handle<JSObject> object,
6042     AllocationSiteCreationContext* site_context) {
6043   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
6044                                                        kNoHints);
6045   MaybeHandle<JSObject> result = v.StructureWalk(object);
6046   Handle<JSObject> for_assert;
6047   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
6048   return result;
6049 }
6050
6051
6052 MaybeHandle<JSObject> JSObject::DeepCopy(
6053     Handle<JSObject> object,
6054     AllocationSiteUsageContext* site_context,
6055     DeepCopyHints hints) {
6056   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
6057   MaybeHandle<JSObject> copy = v.StructureWalk(object);
6058   Handle<JSObject> for_assert;
6059   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
6060   return copy;
6061 }
6062
6063
6064 // Tests for the fast common case for property enumeration:
6065 // - This object and all prototypes has an enum cache (which means that
6066 //   it is no proxy, has no interceptors and needs no access checks).
6067 // - This object has no elements.
6068 // - No prototype has enumerable properties/elements.
6069 bool JSReceiver::IsSimpleEnum() {
6070   for (PrototypeIterator iter(GetIsolate(), this,
6071                               PrototypeIterator::START_AT_RECEIVER);
6072        !iter.IsAtEnd(); iter.Advance()) {
6073     if (!iter.GetCurrent()->IsJSObject()) return false;
6074     JSObject* curr = JSObject::cast(iter.GetCurrent());
6075     int enum_length = curr->map()->EnumLength();
6076     if (enum_length == kInvalidEnumCacheSentinel) return false;
6077     if (curr->IsAccessCheckNeeded()) return false;
6078     DCHECK(!curr->HasNamedInterceptor());
6079     DCHECK(!curr->HasIndexedInterceptor());
6080     if (curr->NumberOfEnumElements() > 0) return false;
6081     if (curr != this && enum_length != 0) return false;
6082   }
6083   return true;
6084 }
6085
6086
6087 static bool FilterKey(Object* key, PropertyAttributes filter) {
6088   if ((filter & SYMBOLIC) && key->IsSymbol()) {
6089     return true;
6090   }
6091
6092   if ((filter & PRIVATE_SYMBOL) &&
6093       key->IsSymbol() && Symbol::cast(key)->is_private()) {
6094     return true;
6095   }
6096
6097   if ((filter & STRING) && !key->IsSymbol()) {
6098     return true;
6099   }
6100
6101   return false;
6102 }
6103
6104
6105 int Map::NumberOfDescribedProperties(DescriptorFlag which,
6106                                      PropertyAttributes filter) {
6107   int result = 0;
6108   DescriptorArray* descs = instance_descriptors();
6109   int limit = which == ALL_DESCRIPTORS
6110       ? descs->number_of_descriptors()
6111       : NumberOfOwnDescriptors();
6112   for (int i = 0; i < limit; i++) {
6113     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
6114         !FilterKey(descs->GetKey(i), filter)) {
6115       result++;
6116     }
6117   }
6118   return result;
6119 }
6120
6121
6122 int Map::NextFreePropertyIndex() {
6123   int free_index = 0;
6124   int number_of_own_descriptors = NumberOfOwnDescriptors();
6125   DescriptorArray* descs = instance_descriptors();
6126   for (int i = 0; i < number_of_own_descriptors; i++) {
6127     PropertyDetails details = descs->GetDetails(i);
6128     if (details.location() == kField) {
6129       int candidate = details.field_index() + details.field_width_in_words();
6130       if (candidate > free_index) free_index = candidate;
6131     }
6132   }
6133   return free_index;
6134 }
6135
6136
6137 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
6138   int len = array->length();
6139   for (int i = 0; i < len; i++) {
6140     Object* e = array->get(i);
6141     if (!(e->IsName() || e->IsNumber())) return false;
6142   }
6143   return true;
6144 }
6145
6146
6147 static Handle<FixedArray> ReduceFixedArrayTo(
6148     Handle<FixedArray> array, int length) {
6149   DCHECK(array->length() >= length);
6150   if (array->length() == length) return array;
6151
6152   Handle<FixedArray> new_array =
6153       array->GetIsolate()->factory()->NewFixedArray(length);
6154   for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
6155   return new_array;
6156 }
6157
6158
6159 static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
6160                                               bool cache_result) {
6161   Isolate* isolate = object->GetIsolate();
6162   if (object->HasFastProperties()) {
6163     int own_property_count = object->map()->EnumLength();
6164     // If the enum length of the given map is set to kInvalidEnumCache, this
6165     // means that the map itself has never used the present enum cache. The
6166     // first step to using the cache is to set the enum length of the map by
6167     // counting the number of own descriptors that are not DONT_ENUM or
6168     // SYMBOLIC.
6169     if (own_property_count == kInvalidEnumCacheSentinel) {
6170       own_property_count = object->map()->NumberOfDescribedProperties(
6171           OWN_DESCRIPTORS, DONT_SHOW);
6172     } else {
6173       DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
6174           OWN_DESCRIPTORS, DONT_SHOW));
6175     }
6176
6177     if (object->map()->instance_descriptors()->HasEnumCache()) {
6178       DescriptorArray* desc = object->map()->instance_descriptors();
6179       Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
6180
6181       // In case the number of properties required in the enum are actually
6182       // present, we can reuse the enum cache. Otherwise, this means that the
6183       // enum cache was generated for a previous (smaller) version of the
6184       // Descriptor Array. In that case we regenerate the enum cache.
6185       if (own_property_count <= keys->length()) {
6186         if (cache_result) object->map()->SetEnumLength(own_property_count);
6187         isolate->counters()->enum_cache_hits()->Increment();
6188         return ReduceFixedArrayTo(keys, own_property_count);
6189       }
6190     }
6191
6192     Handle<Map> map(object->map());
6193
6194     if (map->instance_descriptors()->IsEmpty()) {
6195       isolate->counters()->enum_cache_hits()->Increment();
6196       if (cache_result) map->SetEnumLength(0);
6197       return isolate->factory()->empty_fixed_array();
6198     }
6199
6200     isolate->counters()->enum_cache_misses()->Increment();
6201
6202     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
6203         own_property_count);
6204     Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
6205         own_property_count);
6206
6207     Handle<DescriptorArray> descs =
6208         Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
6209
6210     int size = map->NumberOfOwnDescriptors();
6211     int index = 0;
6212
6213     for (int i = 0; i < size; i++) {
6214       PropertyDetails details = descs->GetDetails(i);
6215       Object* key = descs->GetKey(i);
6216       if (!(details.IsDontEnum() || key->IsSymbol())) {
6217         storage->set(index, key);
6218         if (!indices.is_null()) {
6219           if (details.type() != DATA) {
6220             indices = Handle<FixedArray>();
6221           } else {
6222             FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
6223             int load_by_field_index = field_index.GetLoadByFieldIndex();
6224             indices->set(index, Smi::FromInt(load_by_field_index));
6225           }
6226         }
6227         index++;
6228       }
6229     }
6230     DCHECK(index == storage->length());
6231
6232     Handle<FixedArray> bridge_storage =
6233         isolate->factory()->NewFixedArray(
6234             DescriptorArray::kEnumCacheBridgeLength);
6235     DescriptorArray* desc = object->map()->instance_descriptors();
6236     desc->SetEnumCache(*bridge_storage,
6237                        *storage,
6238                        indices.is_null() ? Object::cast(Smi::FromInt(0))
6239                                          : Object::cast(*indices));
6240     if (cache_result) {
6241       object->map()->SetEnumLength(own_property_count);
6242     }
6243     return storage;
6244   } else {
6245     Handle<NameDictionary> dictionary(object->property_dictionary());
6246     int length = dictionary->NumberOfEnumElements(*object);
6247     if (length == 0) {
6248       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6249     }
6250     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6251     dictionary->CopyEnumKeysTo(*object, *storage);
6252     return storage;
6253   }
6254 }
6255
6256
6257 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6258                                             KeyCollectionType type) {
6259   USE(ContainsOnlyValidKeys);
6260   Isolate* isolate = object->GetIsolate();
6261   Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
6262   Handle<JSFunction> arguments_function(
6263       JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
6264
6265   // Only collect keys if access is permitted.
6266   for (PrototypeIterator iter(isolate, object,
6267                               PrototypeIterator::START_AT_RECEIVER);
6268        !iter.IsAtEnd(); iter.Advance()) {
6269     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6270       Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
6271                             isolate);
6272       Handle<Object> args[] = { proxy };
6273       Handle<Object> names;
6274       ASSIGN_RETURN_ON_EXCEPTION(
6275           isolate, names,
6276           Execution::Call(isolate,
6277                           isolate->proxy_enumerate(),
6278                           object,
6279                           arraysize(args),
6280                           args),
6281           FixedArray);
6282       ASSIGN_RETURN_ON_EXCEPTION(
6283           isolate, content,
6284           FixedArray::AddKeysFromArrayLike(
6285               content, Handle<JSObject>::cast(names)),
6286           FixedArray);
6287       break;
6288     }
6289
6290     Handle<JSObject> current =
6291         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
6292
6293     // Check access rights if required.
6294     if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) {
6295       isolate->ReportFailedAccessCheck(current);
6296       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6297       break;
6298     }
6299
6300     // Compute the element keys.
6301     Handle<FixedArray> element_keys =
6302         isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6303     current->GetEnumElementKeys(*element_keys);
6304     ASSIGN_RETURN_ON_EXCEPTION(
6305         isolate, content,
6306         FixedArray::UnionOfKeys(content, element_keys),
6307         FixedArray);
6308     DCHECK(ContainsOnlyValidKeys(content));
6309
6310     // Add the element keys from the interceptor.
6311     if (current->HasIndexedInterceptor()) {
6312       Handle<JSObject> result;
6313       if (JSObject::GetKeysForIndexedInterceptor(
6314               current, object).ToHandle(&result)) {
6315         ASSIGN_RETURN_ON_EXCEPTION(
6316             isolate, content,
6317             FixedArray::AddKeysFromArrayLike(content, result),
6318             FixedArray);
6319       }
6320       DCHECK(ContainsOnlyValidKeys(content));
6321     }
6322
6323     // We can cache the computed property keys if access checks are
6324     // not needed and no interceptors are involved.
6325     //
6326     // We do not use the cache if the object has elements and
6327     // therefore it does not make sense to cache the property names
6328     // for arguments objects.  Arguments objects will always have
6329     // elements.
6330     // Wrapped strings have elements, but don't have an elements
6331     // array or dictionary.  So the fast inline test for whether to
6332     // use the cache says yes, so we should not create a cache.
6333     bool cache_enum_keys =
6334         ((current->map()->GetConstructor() != *arguments_function) &&
6335          !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
6336          !current->HasNamedInterceptor() && !current->HasIndexedInterceptor());
6337     // Compute the property keys and cache them if possible.
6338     ASSIGN_RETURN_ON_EXCEPTION(
6339         isolate, content,
6340         FixedArray::UnionOfKeys(
6341             content, GetEnumPropertyKeys(current, cache_enum_keys)),
6342         FixedArray);
6343     DCHECK(ContainsOnlyValidKeys(content));
6344
6345     // Add the non-symbol property keys from the interceptor.
6346     if (current->HasNamedInterceptor()) {
6347       Handle<JSObject> result;
6348       if (JSObject::GetKeysForNamedInterceptor(
6349               current, object).ToHandle(&result)) {
6350         ASSIGN_RETURN_ON_EXCEPTION(
6351             isolate, content, FixedArray::AddKeysFromArrayLike(
6352                                   content, result, FixedArray::NON_SYMBOL_KEYS),
6353             FixedArray);
6354       }
6355       DCHECK(ContainsOnlyValidKeys(content));
6356     }
6357
6358     // If we only want own properties we bail out after the first
6359     // iteration.
6360     if (type == OWN_ONLY) break;
6361   }
6362   return content;
6363 }
6364
6365
6366 // Try to update an accessor in an elements dictionary. Return true if the
6367 // update succeeded, and false otherwise.
6368 static bool UpdateGetterSetterInDictionary(
6369     SeededNumberDictionary* dictionary,
6370     uint32_t index,
6371     Object* getter,
6372     Object* setter,
6373     PropertyAttributes attributes) {
6374   int entry = dictionary->FindEntry(index);
6375   if (entry != SeededNumberDictionary::kNotFound) {
6376     Object* result = dictionary->ValueAt(entry);
6377     PropertyDetails details = dictionary->DetailsAt(entry);
6378     if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) {
6379       DCHECK(details.IsConfigurable());
6380       if (details.attributes() != attributes) {
6381         dictionary->DetailsAtPut(
6382             entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index,
6383                                    PropertyCellType::kInvalid));
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                                             PropertyCellType::kInvalid);
6487
6488   // Normalize elements to make this operation simple.
6489   bool had_dictionary_elements = object->HasDictionaryElements();
6490   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
6491   DCHECK(object->HasDictionaryElements() ||
6492          object->HasDictionaryArgumentsElements());
6493   // Update the dictionary with the new ACCESSOR_CONSTANT property.
6494   dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
6495                                            details);
6496   dictionary->set_requires_slow_elements();
6497
6498   // Update the dictionary backing store on the object.
6499   if (object->elements()->map() == heap->sloppy_arguments_elements_map()) {
6500     // Also delete any parameter alias.
6501     //
6502     // TODO(kmillikin): when deleting the last parameter alias we could
6503     // switch to a direct backing store without the parameter map.  This
6504     // would allow GC of the context.
6505     FixedArray* parameter_map = FixedArray::cast(object->elements());
6506     if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
6507       parameter_map->set(index + 2, heap->the_hole_value());
6508     }
6509     parameter_map->set(1, *dictionary);
6510   } else {
6511     object->set_elements(*dictionary);
6512
6513     if (!had_dictionary_elements) {
6514       // KeyedStoreICs (at least the non-generic ones) need a reset.
6515       heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
6516     }
6517   }
6518 }
6519
6520
6521 void JSObject::SetPropertyCallback(Handle<JSObject> object,
6522                                    Handle<Name> name,
6523                                    Handle<Object> structure,
6524                                    PropertyAttributes attributes) {
6525   PropertyNormalizationMode mode = object->map()->is_prototype_map()
6526                                        ? KEEP_INOBJECT_PROPERTIES
6527                                        : CLEAR_INOBJECT_PROPERTIES;
6528   // Normalize object to make this operation simple.
6529   NormalizeProperties(object, mode, 0, "SetPropertyCallback");
6530
6531
6532   // Update the dictionary with the new ACCESSOR_CONSTANT property.
6533   PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0,
6534                                             PropertyCellType::kMutable);
6535   SetNormalizedProperty(object, name, structure, details);
6536
6537   ReoptimizeIfPrototype(object);
6538 }
6539
6540
6541 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
6542                                              Handle<Name> name,
6543                                              Handle<Object> getter,
6544                                              Handle<Object> setter,
6545                                              PropertyAttributes attributes) {
6546   Isolate* isolate = object->GetIsolate();
6547   // Check access rights if needed.
6548   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
6549     isolate->ReportFailedAccessCheck(object);
6550     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6551     return isolate->factory()->undefined_value();
6552   }
6553
6554   if (object->IsJSGlobalProxy()) {
6555     PrototypeIterator iter(isolate, object);
6556     if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
6557     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6558     DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
6559                    name, getter, setter, attributes);
6560     return isolate->factory()->undefined_value();
6561   }
6562
6563   // Make sure that the top context does not change when doing callbacks or
6564   // interceptor calls.
6565   AssertNoContextChange ncc(isolate);
6566
6567   // Try to flatten before operating on the string.
6568   if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6569
6570   uint32_t index = 0;
6571   bool is_element = name->AsArrayIndex(&index);
6572
6573   Handle<Object> old_value = isolate->factory()->the_hole_value();
6574   bool is_observed = object->map()->is_observed() &&
6575                      !isolate->IsInternallyUsedPropertyName(name);
6576   bool preexists = false;
6577   if (is_observed) {
6578     if (is_element) {
6579       Maybe<bool> maybe = HasOwnElement(object, index);
6580       // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used
6581       // uninitialized in this function".
6582       if (!maybe.IsJust()) {
6583         DCHECK(false);
6584         return isolate->factory()->undefined_value();
6585       }
6586       preexists = maybe.FromJust();
6587       if (preexists && GetOwnElementAccessorPair(object, index).is_null()) {
6588         old_value =
6589             Object::GetElement(isolate, object, index).ToHandleChecked();
6590       }
6591     } else {
6592       LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6593       CHECK(GetPropertyAttributes(&it).IsJust());
6594       preexists = it.IsFound();
6595       if (preexists && (it.state() == LookupIterator::DATA ||
6596                         it.GetAccessors()->IsAccessorInfo())) {
6597         old_value = GetProperty(&it).ToHandleChecked();
6598       }
6599     }
6600   }
6601
6602   if (is_element) {
6603     DefineElementAccessor(object, index, getter, setter, attributes);
6604   } else {
6605     DCHECK(getter->IsSpecFunction() || getter->IsUndefined() ||
6606            getter->IsNull());
6607     DCHECK(setter->IsSpecFunction() || setter->IsUndefined() ||
6608            setter->IsNull());
6609     // At least one of the accessors needs to be a new value.
6610     DCHECK(!getter->IsNull() || !setter->IsNull());
6611     LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
6612     if (it.state() == LookupIterator::ACCESS_CHECK) {
6613       // We already did an access check before. We do have access.
6614       it.Next();
6615     }
6616     if (!getter->IsNull()) {
6617       it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
6618     }
6619     if (!setter->IsNull()) {
6620       it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
6621     }
6622   }
6623
6624   if (is_observed) {
6625     const char* type = preexists ? "reconfigure" : "add";
6626     RETURN_ON_EXCEPTION(
6627         isolate, EnqueueChangeRecord(object, type, name, old_value), Object);
6628   }
6629
6630   return isolate->factory()->undefined_value();
6631 }
6632
6633
6634 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6635                                           Handle<AccessorInfo> info) {
6636   Isolate* isolate = object->GetIsolate();
6637   Factory* factory = isolate->factory();
6638   Handle<Name> name(Name::cast(info->name()));
6639
6640   // Check access rights if needed.
6641   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
6642     isolate->ReportFailedAccessCheck(object);
6643     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6644     return factory->undefined_value();
6645   }
6646
6647   if (object->IsJSGlobalProxy()) {
6648     PrototypeIterator iter(isolate, object);
6649     if (iter.IsAtEnd()) return object;
6650     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6651     return SetAccessor(
6652         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), info);
6653   }
6654
6655   // Make sure that the top context does not change when doing callbacks or
6656   // interceptor calls.
6657   AssertNoContextChange ncc(isolate);
6658
6659   // Try to flatten before operating on the string.
6660   if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6661
6662   uint32_t index = 0;
6663   bool is_element = name->AsArrayIndex(&index);
6664
6665   if (is_element) {
6666     if (object->IsJSArray()) return factory->undefined_value();
6667
6668     // Accessors overwrite previous callbacks (cf. with getters/setters).
6669     switch (object->GetElementsKind()) {
6670       case FAST_SMI_ELEMENTS:
6671       case FAST_ELEMENTS:
6672       case FAST_DOUBLE_ELEMENTS:
6673       case FAST_HOLEY_SMI_ELEMENTS:
6674       case FAST_HOLEY_ELEMENTS:
6675       case FAST_HOLEY_DOUBLE_ELEMENTS:
6676         break;
6677
6678 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6679       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
6680       case TYPE##_ELEMENTS:                                                    \
6681
6682       TYPED_ARRAYS(TYPED_ARRAY_CASE)
6683 #undef TYPED_ARRAY_CASE
6684         // Ignore getters and setters on pixel and external array
6685         // elements.
6686         return factory->undefined_value();
6687
6688       case DICTIONARY_ELEMENTS:
6689         break;
6690       case SLOPPY_ARGUMENTS_ELEMENTS:
6691         UNIMPLEMENTED();
6692         break;
6693     }
6694
6695     SetElementCallback(object, index, info, info->property_attributes());
6696   } else {
6697     // Lookup the name.
6698     LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6699     CHECK(GetPropertyAttributes(&it).IsJust());
6700     // ES5 forbids turning a property into an accessor if it's not
6701     // configurable. See 8.6.1 (Table 5).
6702     if (it.IsFound() && (it.IsReadOnly() || !it.IsConfigurable())) {
6703       return factory->undefined_value();
6704     }
6705
6706     SetPropertyCallback(object, name, info, info->property_attributes());
6707   }
6708
6709   return object;
6710 }
6711
6712
6713 MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
6714                                           Handle<Name> name,
6715                                           AccessorComponent component) {
6716   Isolate* isolate = object->GetIsolate();
6717
6718   // Make sure that the top context does not change when doing callbacks or
6719   // interceptor calls.
6720   AssertNoContextChange ncc(isolate);
6721
6722   // Make the lookup and include prototypes.
6723   uint32_t index = 0;
6724   if (name->AsArrayIndex(&index)) {
6725     for (PrototypeIterator iter(isolate, object,
6726                                 PrototypeIterator::START_AT_RECEIVER);
6727          !iter.IsAtEnd(); iter.Advance()) {
6728       Handle<Object> current = PrototypeIterator::GetCurrent(iter);
6729       // Check access rights if needed.
6730       if (current->IsAccessCheckNeeded() &&
6731           !isolate->MayAccess(Handle<JSObject>::cast(current))) {
6732         isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(current));
6733         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6734         return isolate->factory()->undefined_value();
6735       }
6736
6737       if (current->IsJSObject() &&
6738           Handle<JSObject>::cast(current)->HasDictionaryElements()) {
6739         JSObject* js_object = JSObject::cast(*current);
6740         SeededNumberDictionary* dictionary = js_object->element_dictionary();
6741         int entry = dictionary->FindEntry(index);
6742         if (entry != SeededNumberDictionary::kNotFound) {
6743           Object* element = dictionary->ValueAt(entry);
6744           if (dictionary->DetailsAt(entry).type() == ACCESSOR_CONSTANT &&
6745               element->IsAccessorPair()) {
6746             return handle(AccessorPair::cast(element)->GetComponent(component),
6747                           isolate);
6748           }
6749         }
6750       }
6751     }
6752   } else {
6753     LookupIterator it(object, name,
6754                       LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
6755     for (; it.IsFound(); it.Next()) {
6756       switch (it.state()) {
6757         case LookupIterator::INTERCEPTOR:
6758         case LookupIterator::NOT_FOUND:
6759         case LookupIterator::TRANSITION:
6760           UNREACHABLE();
6761
6762         case LookupIterator::ACCESS_CHECK:
6763           if (it.HasAccess()) continue;
6764           isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
6765           RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6766           return isolate->factory()->undefined_value();
6767
6768         case LookupIterator::JSPROXY:
6769           return isolate->factory()->undefined_value();
6770
6771         case LookupIterator::INTEGER_INDEXED_EXOTIC:
6772           return isolate->factory()->undefined_value();
6773         case LookupIterator::DATA:
6774           continue;
6775         case LookupIterator::ACCESSOR: {
6776           Handle<Object> maybe_pair = it.GetAccessors();
6777           if (maybe_pair->IsAccessorPair()) {
6778             return handle(
6779                 AccessorPair::cast(*maybe_pair)->GetComponent(component),
6780                 isolate);
6781           }
6782         }
6783       }
6784     }
6785   }
6786   return isolate->factory()->undefined_value();
6787 }
6788
6789
6790 Object* JSObject::SlowReverseLookup(Object* value) {
6791   if (HasFastProperties()) {
6792     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
6793     DescriptorArray* descs = map()->instance_descriptors();
6794     bool value_is_number = value->IsNumber();
6795     for (int i = 0; i < number_of_own_descriptors; i++) {
6796       if (descs->GetType(i) == DATA) {
6797         FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
6798         if (IsUnboxedDoubleField(field_index)) {
6799           if (value_is_number) {
6800             double property = RawFastDoublePropertyAt(field_index);
6801             if (property == value->Number()) {
6802               return descs->GetKey(i);
6803             }
6804           }
6805         } else {
6806           Object* property = RawFastPropertyAt(field_index);
6807           if (field_index.is_double()) {
6808             DCHECK(property->IsMutableHeapNumber());
6809             if (value_is_number && property->Number() == value->Number()) {
6810               return descs->GetKey(i);
6811             }
6812           } else if (property == value) {
6813             return descs->GetKey(i);
6814           }
6815         }
6816       } else if (descs->GetType(i) == DATA_CONSTANT) {
6817         if (descs->GetConstant(i) == value) {
6818           return descs->GetKey(i);
6819         }
6820       }
6821     }
6822     return GetHeap()->undefined_value();
6823   } else {
6824     return property_dictionary()->SlowReverseLookup(value);
6825   }
6826 }
6827
6828
6829 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
6830   Handle<Map> result = map->GetIsolate()->factory()->NewMap(
6831       map->instance_type(), instance_size);
6832   result->SetPrototype(handle(map->prototype(), map->GetIsolate()));
6833   result->set_constructor_or_backpointer(map->GetConstructor());
6834   result->set_bit_field(map->bit_field());
6835   result->set_bit_field2(map->bit_field2());
6836   int new_bit_field3 = map->bit_field3();
6837   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6838   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6839   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6840                                           kInvalidEnumCacheSentinel);
6841   new_bit_field3 = Deprecated::update(new_bit_field3, false);
6842   if (!map->is_dictionary_map()) {
6843     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
6844   }
6845   new_bit_field3 = Counter::update(new_bit_field3, kRetainingCounterStart);
6846   result->set_bit_field3(new_bit_field3);
6847   return result;
6848 }
6849
6850
6851 Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode,
6852                            const char* reason) {
6853   DCHECK(!fast_map->is_dictionary_map());
6854
6855   Isolate* isolate = fast_map->GetIsolate();
6856   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
6857                              isolate);
6858   bool use_cache = !maybe_cache->IsUndefined();
6859   Handle<NormalizedMapCache> cache;
6860   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
6861
6862   Handle<Map> new_map;
6863   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
6864 #ifdef VERIFY_HEAP
6865     if (FLAG_verify_heap) new_map->DictionaryMapVerify();
6866 #endif
6867 #ifdef ENABLE_SLOW_DCHECKS
6868     if (FLAG_enable_slow_asserts) {
6869       // The cached map should match newly created normalized map bit-by-bit,
6870       // except for the code cache, which can contain some ics which can be
6871       // applied to the shared map, dependent code and weak cell cache.
6872       Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
6873
6874       DCHECK(memcmp(fresh->address(),
6875                     new_map->address(),
6876                     Map::kCodeCacheOffset) == 0);
6877       STATIC_ASSERT(Map::kDependentCodeOffset ==
6878                     Map::kCodeCacheOffset + kPointerSize);
6879       STATIC_ASSERT(Map::kWeakCellCacheOffset ==
6880                     Map::kDependentCodeOffset + kPointerSize);
6881       int offset = Map::kWeakCellCacheOffset + kPointerSize;
6882       DCHECK(memcmp(fresh->address() + offset,
6883                     new_map->address() + offset,
6884                     Map::kSize - offset) == 0);
6885     }
6886 #endif
6887   } else {
6888     new_map = Map::CopyNormalized(fast_map, mode);
6889     if (use_cache) {
6890       cache->Set(fast_map, new_map);
6891       isolate->counters()->normalized_maps()->Increment();
6892     }
6893 #if TRACE_MAPS
6894     if (FLAG_trace_maps) {
6895       PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n",
6896              reinterpret_cast<void*>(*fast_map),
6897              reinterpret_cast<void*>(*new_map), reason);
6898     }
6899 #endif
6900   }
6901   fast_map->NotifyLeafMapLayoutChange();
6902   return new_map;
6903 }
6904
6905
6906 Handle<Map> Map::CopyNormalized(Handle<Map> map,
6907                                 PropertyNormalizationMode mode) {
6908   int new_instance_size = map->instance_size();
6909   if (mode == CLEAR_INOBJECT_PROPERTIES) {
6910     new_instance_size -= map->inobject_properties() * kPointerSize;
6911   }
6912
6913   Handle<Map> result = RawCopy(map, new_instance_size);
6914
6915   if (mode != CLEAR_INOBJECT_PROPERTIES) {
6916     result->set_inobject_properties(map->inobject_properties());
6917   }
6918
6919   result->set_dictionary_map(true);
6920   result->set_migration_target(false);
6921
6922 #ifdef VERIFY_HEAP
6923   if (FLAG_verify_heap) result->DictionaryMapVerify();
6924 #endif
6925
6926   return result;
6927 }
6928
6929
6930 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
6931   Handle<Map> result = RawCopy(map, map->instance_size());
6932
6933   // Please note instance_type and instance_size are set when allocated.
6934   result->set_inobject_properties(map->inobject_properties());
6935   result->set_unused_property_fields(map->unused_property_fields());
6936
6937   result->set_pre_allocated_property_fields(
6938       map->pre_allocated_property_fields());
6939   result->ClearCodeCache(map->GetHeap());
6940   map->NotifyLeafMapLayoutChange();
6941   return result;
6942 }
6943
6944
6945 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
6946                                  Handle<DescriptorArray> descriptors,
6947                                  Descriptor* descriptor) {
6948   // Sanity check. This path is only to be taken if the map owns its descriptor
6949   // array, implying that its NumberOfOwnDescriptors equals the number of
6950   // descriptors in the descriptor array.
6951   DCHECK(map->NumberOfOwnDescriptors() ==
6952          map->instance_descriptors()->number_of_descriptors());
6953
6954   Handle<Map> result = CopyDropDescriptors(map);
6955   Handle<Name> name = descriptor->GetKey();
6956
6957   // Ensure there's space for the new descriptor in the shared descriptor array.
6958   if (descriptors->NumberOfSlackDescriptors() == 0) {
6959     int old_size = descriptors->number_of_descriptors();
6960     if (old_size == 0) {
6961       descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
6962     } else {
6963       EnsureDescriptorSlack(
6964           map, SlackForArraySize(old_size, kMaxNumberOfDescriptors));
6965       descriptors = handle(map->instance_descriptors());
6966     }
6967   }
6968
6969   Handle<LayoutDescriptor> layout_descriptor =
6970       FLAG_unbox_double_fields
6971           ? LayoutDescriptor::ShareAppend(map, descriptor->GetDetails())
6972           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
6973
6974   {
6975     DisallowHeapAllocation no_gc;
6976     descriptors->Append(descriptor);
6977     result->InitializeDescriptors(*descriptors, *layout_descriptor);
6978   }
6979
6980   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
6981   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
6982
6983   return result;
6984 }
6985
6986
6987 #if TRACE_MAPS
6988
6989 // static
6990 void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) {
6991   if (FLAG_trace_maps) {
6992     PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
6993            reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
6994     name->NameShortPrint();
6995     PrintF(" ]\n");
6996   }
6997 }
6998
6999
7000 // static
7001 void Map::TraceAllTransitions(Map* map) {
7002   Object* transitions = map->raw_transitions();
7003   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
7004   for (int i = -0; i < num_transitions; ++i) {
7005     Map* target = TransitionArray::GetTarget(transitions, i);
7006     Name* key = TransitionArray::GetKey(transitions, i);
7007     Map::TraceTransition("Transition", map, target, key);
7008     Map::TraceAllTransitions(target);
7009   }
7010 }
7011
7012 #endif  // TRACE_MAPS
7013
7014
7015 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
7016                             Handle<Name> name, SimpleTransitionFlag flag) {
7017   parent->set_owns_descriptors(false);
7018   if (parent->is_prototype_map()) {
7019     DCHECK(child->is_prototype_map());
7020 #if TRACE_MAPS
7021     Map::TraceTransition("NoTransition", *parent, *child, *name);
7022 #endif
7023   } else {
7024     TransitionArray::Insert(parent, name, child, flag);
7025     if (child->prototype()->IsJSObject()) {
7026       Handle<JSObject> proto(JSObject::cast(child->prototype()));
7027       if (!child->ShouldRegisterAsPrototypeUser(proto)) {
7028         JSObject::UnregisterPrototypeUser(proto, child);
7029       }
7030     }
7031 #if TRACE_MAPS
7032     Map::TraceTransition("Transition", *parent, *child, *name);
7033 #endif
7034   }
7035 }
7036
7037
7038 Handle<Map> Map::CopyReplaceDescriptors(
7039     Handle<Map> map, Handle<DescriptorArray> descriptors,
7040     Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
7041     MaybeHandle<Name> maybe_name, const char* reason,
7042     SimpleTransitionFlag simple_flag) {
7043   DCHECK(descriptors->IsSortedNoDuplicates());
7044
7045   Handle<Map> result = CopyDropDescriptors(map);
7046
7047   if (!map->is_prototype_map()) {
7048     if (flag == INSERT_TRANSITION &&
7049         TransitionArray::CanHaveMoreTransitions(map)) {
7050       result->InitializeDescriptors(*descriptors, *layout_descriptor);
7051
7052       Handle<Name> name;
7053       CHECK(maybe_name.ToHandle(&name));
7054       ConnectTransition(map, result, name, simple_flag);
7055     } else {
7056       int length = descriptors->number_of_descriptors();
7057       for (int i = 0; i < length; i++) {
7058         descriptors->SetRepresentation(i, Representation::Tagged());
7059         if (descriptors->GetDetails(i).type() == DATA) {
7060           descriptors->SetValue(i, HeapType::Any());
7061         }
7062       }
7063       result->InitializeDescriptors(*descriptors,
7064                                     LayoutDescriptor::FastPointerLayout());
7065     }
7066   } else {
7067     result->InitializeDescriptors(*descriptors, *layout_descriptor);
7068   }
7069 #if TRACE_MAPS
7070   if (FLAG_trace_maps &&
7071       // Mirror conditions above that did not call ConnectTransition().
7072       (map->is_prototype_map() ||
7073        !(flag == INSERT_TRANSITION &&
7074          TransitionArray::CanHaveMoreTransitions(map)))) {
7075     PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
7076            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
7077            reason);
7078   }
7079 #endif
7080
7081   return result;
7082 }
7083
7084
7085 // Since this method is used to rewrite an existing transition tree, it can
7086 // always insert transitions without checking.
7087 Handle<Map> Map::CopyInstallDescriptors(
7088     Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors,
7089     Handle<LayoutDescriptor> full_layout_descriptor) {
7090   DCHECK(descriptors->IsSortedNoDuplicates());
7091
7092   Handle<Map> result = CopyDropDescriptors(map);
7093
7094   result->set_instance_descriptors(*descriptors);
7095   result->SetNumberOfOwnDescriptors(new_descriptor + 1);
7096
7097   int unused_property_fields = map->unused_property_fields();
7098   PropertyDetails details = descriptors->GetDetails(new_descriptor);
7099   if (details.location() == kField) {
7100     unused_property_fields = map->unused_property_fields() - 1;
7101     if (unused_property_fields < 0) {
7102       unused_property_fields += JSObject::kFieldsAdded;
7103     }
7104   }
7105   result->set_unused_property_fields(unused_property_fields);
7106
7107   if (FLAG_unbox_double_fields) {
7108     Handle<LayoutDescriptor> layout_descriptor =
7109         LayoutDescriptor::AppendIfFastOrUseFull(map, details,
7110                                                 full_layout_descriptor);
7111     result->set_layout_descriptor(*layout_descriptor);
7112 #ifdef VERIFY_HEAP
7113     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
7114     if (FLAG_verify_heap) {
7115       CHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
7116     }
7117 #else
7118     SLOW_DCHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
7119 #endif
7120     result->set_visitor_id(StaticVisitorBase::GetVisitorId(*result));
7121   }
7122
7123   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
7124   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
7125
7126   return result;
7127 }
7128
7129
7130 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
7131                                     TransitionFlag flag) {
7132   Map* maybe_elements_transition_map = NULL;
7133   if (flag == INSERT_TRANSITION) {
7134     maybe_elements_transition_map = map->ElementsTransitionMap();
7135     DCHECK(
7136         maybe_elements_transition_map == NULL ||
7137         ((maybe_elements_transition_map->elements_kind() ==
7138               DICTIONARY_ELEMENTS ||
7139           IsExternalArrayElementsKind(
7140               maybe_elements_transition_map->elements_kind())) &&
7141          (kind == DICTIONARY_ELEMENTS || IsExternalArrayElementsKind(kind))));
7142     DCHECK(!IsFastElementsKind(kind) ||
7143            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
7144     DCHECK(kind != map->elements_kind());
7145   }
7146
7147   bool insert_transition = flag == INSERT_TRANSITION &&
7148                            TransitionArray::CanHaveMoreTransitions(map) &&
7149                            maybe_elements_transition_map == NULL;
7150
7151   if (insert_transition) {
7152     Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
7153     new_map->set_elements_kind(kind);
7154
7155     ConnectElementsTransition(map, new_map);
7156
7157     return new_map;
7158   }
7159
7160   // Create a new free-floating map only if we are not allowed to store it.
7161   Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
7162   new_map->set_elements_kind(kind);
7163   return new_map;
7164 }
7165
7166
7167 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
7168   DCHECK(!map->is_observed());
7169
7170   Isolate* isolate = map->GetIsolate();
7171
7172   bool insert_transition =
7173       TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map();
7174
7175   if (insert_transition) {
7176     Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
7177     new_map->set_is_observed();
7178
7179     Handle<Name> name = isolate->factory()->observed_symbol();
7180     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
7181     return new_map;
7182   }
7183
7184   // Create a new free-floating map only if we are not allowed to store it.
7185   Handle<Map> new_map = Map::Copy(map, "CopyForObserved");
7186   new_map->set_is_observed();
7187   return new_map;
7188 }
7189
7190
7191 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
7192   DCHECK(!map->is_prototype_map());
7193   Handle<Map> new_map = CopyDropDescriptors(map);
7194
7195   if (map->owns_descriptors()) {
7196     // In case the map owned its own descriptors, share the descriptors and
7197     // transfer ownership to the new map.
7198     // The properties did not change, so reuse descriptors.
7199     new_map->InitializeDescriptors(map->instance_descriptors(),
7200                                    map->GetLayoutDescriptor());
7201   } else {
7202     // In case the map did not own its own descriptors, a split is forced by
7203     // copying the map; creating a new descriptor array cell.
7204     Handle<DescriptorArray> descriptors(map->instance_descriptors());
7205     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
7206     Handle<DescriptorArray> new_descriptors =
7207         DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
7208     Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
7209                                                    map->GetIsolate());
7210     new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
7211   }
7212
7213 #if TRACE_MAPS
7214   if (FLAG_trace_maps) {
7215     PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
7216            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
7217            reason);
7218   }
7219 #endif
7220
7221   return new_map;
7222 }
7223
7224
7225 Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
7226   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7227   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
7228   Handle<DescriptorArray> new_descriptors =
7229       DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
7230   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
7231                                                  map->GetIsolate());
7232   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7233                                 OMIT_TRANSITION, MaybeHandle<Name>(), reason,
7234                                 SPECIAL_TRANSITION);
7235 }
7236
7237
7238 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
7239   Handle<Map> copy =
7240       Copy(handle(isolate->object_function()->initial_map()), "MapCreate");
7241
7242   // Check that we do not overflow the instance size when adding the extra
7243   // inobject properties. If the instance size overflows, we allocate as many
7244   // properties as we can as inobject properties.
7245   int max_extra_properties =
7246       (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
7247
7248   if (inobject_properties > max_extra_properties) {
7249     inobject_properties = max_extra_properties;
7250   }
7251
7252   int new_instance_size =
7253       JSObject::kHeaderSize + kPointerSize * inobject_properties;
7254
7255   // Adjust the map with the extra inobject properties.
7256   copy->set_inobject_properties(inobject_properties);
7257   copy->set_unused_property_fields(inobject_properties);
7258   copy->set_instance_size(new_instance_size);
7259   copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
7260   return copy;
7261 }
7262
7263
7264 Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
7265                                           PropertyAttributes attrs_to_add,
7266                                           Handle<Symbol> transition_marker,
7267                                           const char* reason) {
7268   int num_descriptors = map->NumberOfOwnDescriptors();
7269   Isolate* isolate = map->GetIsolate();
7270   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
7271       handle(map->instance_descriptors(), isolate), num_descriptors,
7272       attrs_to_add);
7273   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
7274                                                  isolate);
7275   Handle<Map> new_map = CopyReplaceDescriptors(
7276       map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
7277       transition_marker, reason, SPECIAL_TRANSITION);
7278   new_map->set_is_extensible(false);
7279   new_map->set_elements_kind(DICTIONARY_ELEMENTS);
7280   return new_map;
7281 }
7282
7283
7284 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
7285   PropertyDetails details = GetDetails(descriptor);
7286   switch (details.type()) {
7287     case DATA:
7288       return value->FitsRepresentation(details.representation()) &&
7289              GetFieldType(descriptor)->NowContains(value);
7290
7291     case DATA_CONSTANT:
7292       DCHECK(GetConstant(descriptor) != value ||
7293              value->FitsRepresentation(details.representation()));
7294       return GetConstant(descriptor) == value;
7295
7296     case ACCESSOR:
7297     case ACCESSOR_CONSTANT:
7298       return false;
7299   }
7300
7301   UNREACHABLE();
7302   return false;
7303 }
7304
7305
7306 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
7307                                         Handle<Object> value) {
7308   // Dictionaries can store any property value.
7309   if (map->is_dictionary_map()) return map;
7310
7311   // Migrate to the newest map before storing the property.
7312   map = Update(map);
7313
7314   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7315
7316   if (descriptors->CanHoldValue(descriptor, *value)) return map;
7317
7318   Isolate* isolate = map->GetIsolate();
7319   PropertyAttributes attributes =
7320       descriptors->GetDetails(descriptor).attributes();
7321   Representation representation = value->OptimalRepresentation();
7322   Handle<HeapType> type = value->OptimalType(isolate, representation);
7323
7324   return ReconfigureProperty(map, descriptor, kData, attributes, representation,
7325                              type, FORCE_FIELD);
7326 }
7327
7328
7329 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
7330                                           Handle<Object> value,
7331                                           PropertyAttributes attributes,
7332                                           StoreFromKeyed store_mode) {
7333   // Dictionary maps can always have additional data properties.
7334   if (map->is_dictionary_map()) return map;
7335
7336   // Migrate to the newest map before storing the property.
7337   map = Update(map);
7338
7339   Map* maybe_transition =
7340       TransitionArray::SearchTransition(*map, kData, *name, attributes);
7341   if (maybe_transition != NULL) {
7342     Handle<Map> transition(maybe_transition);
7343     int descriptor = transition->LastAdded();
7344
7345     DCHECK_EQ(attributes, transition->instance_descriptors()
7346                               ->GetDetails(descriptor)
7347                               .attributes());
7348
7349     return Map::PrepareForDataProperty(transition, descriptor, value);
7350   }
7351
7352   TransitionFlag flag = INSERT_TRANSITION;
7353   MaybeHandle<Map> maybe_map;
7354   if (value->IsJSFunction()) {
7355     maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
7356   } else if (!map->TooManyFastProperties(store_mode)) {
7357     Isolate* isolate = name->GetIsolate();
7358     Representation representation = value->OptimalRepresentation();
7359     Handle<HeapType> type = value->OptimalType(isolate, representation);
7360     maybe_map =
7361         Map::CopyWithField(map, name, type, attributes, representation, flag);
7362   }
7363
7364   Handle<Map> result;
7365   if (!maybe_map.ToHandle(&result)) {
7366 #if TRACE_MAPS
7367     if (FLAG_trace_maps) {
7368       Vector<char> name_buffer = Vector<char>::New(100);
7369       name->NameShortPrint(name_buffer);
7370       Vector<char> buffer = Vector<char>::New(128);
7371       SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
7372       return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start());
7373     }
7374 #endif
7375     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
7376                           "TooManyFastProperties");
7377   }
7378
7379   return result;
7380 }
7381
7382
7383 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
7384                                              PropertyKind kind,
7385                                              PropertyAttributes attributes) {
7386   // Dictionaries have to be reconfigured in-place.
7387   DCHECK(!map->is_dictionary_map());
7388
7389   if (!map->GetBackPointer()->IsMap()) {
7390     // There is no benefit from reconstructing transition tree for maps without
7391     // back pointers.
7392     return CopyGeneralizeAllRepresentations(
7393         map, descriptor, FORCE_FIELD, kind, attributes,
7394         "GenAll_AttributesMismatchProtoMap");
7395   }
7396
7397   if (FLAG_trace_generalization) {
7398     map->PrintReconfiguration(stdout, descriptor, kind, attributes);
7399   }
7400
7401   Isolate* isolate = map->GetIsolate();
7402   Handle<Map> new_map = ReconfigureProperty(
7403       map, descriptor, kind, attributes, Representation::None(),
7404       HeapType::None(isolate), FORCE_FIELD);
7405   return new_map;
7406 }
7407
7408
7409 Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
7410                                               Handle<Name> name,
7411                                               AccessorComponent component,
7412                                               Handle<Object> accessor,
7413                                               PropertyAttributes attributes) {
7414   Isolate* isolate = name->GetIsolate();
7415
7416   // Dictionary maps can always have additional data properties.
7417   if (map->is_dictionary_map()) {
7418     // For global objects, property cells are inlined. We need to change the
7419     // map.
7420     if (map->IsGlobalObjectMap()) return Copy(map, "GlobalAccessor");
7421     return map;
7422   }
7423
7424   // Migrate to the newest map before transitioning to the new property.
7425   map = Update(map);
7426
7427   PropertyNormalizationMode mode = map->is_prototype_map()
7428                                        ? KEEP_INOBJECT_PROPERTIES
7429                                        : CLEAR_INOBJECT_PROPERTIES;
7430
7431   Map* maybe_transition =
7432       TransitionArray::SearchTransition(*map, kAccessor, *name, attributes);
7433   if (maybe_transition != NULL) {
7434     Handle<Map> transition(maybe_transition, isolate);
7435     DescriptorArray* descriptors = transition->instance_descriptors();
7436     int descriptor = transition->LastAdded();
7437     DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
7438
7439     DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
7440     DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
7441
7442     Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
7443     if (!maybe_pair->IsAccessorPair()) {
7444       return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
7445     }
7446
7447     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
7448     if (pair->get(component) != *accessor) {
7449       return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
7450     }
7451
7452     return transition;
7453   }
7454
7455   Handle<AccessorPair> pair;
7456   DescriptorArray* old_descriptors = map->instance_descriptors();
7457   int descriptor = old_descriptors->SearchWithCache(*name, *map);
7458   if (descriptor != DescriptorArray::kNotFound) {
7459     if (descriptor != map->LastAdded()) {
7460       return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
7461     }
7462     PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
7463     if (old_details.type() != ACCESSOR_CONSTANT) {
7464       return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
7465     }
7466
7467     if (old_details.attributes() != attributes) {
7468       return Map::Normalize(map, mode, "AccessorsWithAttributes");
7469     }
7470
7471     Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
7472     if (!maybe_pair->IsAccessorPair()) {
7473       return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
7474     }
7475
7476     Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component);
7477     if (current == *accessor) return map;
7478
7479     if (!current->IsTheHole()) {
7480       return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
7481     }
7482
7483     pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
7484   } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
7485              map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
7486     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors");
7487   } else {
7488     pair = isolate->factory()->NewAccessorPair();
7489   }
7490
7491   pair->set(component, *accessor);
7492   TransitionFlag flag = INSERT_TRANSITION;
7493   AccessorConstantDescriptor new_desc(name, pair, attributes);
7494   return Map::CopyInsertDescriptor(map, &new_desc, flag);
7495 }
7496
7497
7498 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7499                                    Descriptor* descriptor,
7500                                    TransitionFlag flag) {
7501   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7502
7503   // Ensure the key is unique.
7504   descriptor->KeyToUniqueName();
7505
7506   if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
7507       TransitionArray::CanHaveMoreTransitions(map)) {
7508     return ShareDescriptor(map, descriptors, descriptor);
7509   }
7510
7511   int nof = map->NumberOfOwnDescriptors();
7512   Handle<DescriptorArray> new_descriptors =
7513       DescriptorArray::CopyUpTo(descriptors, nof, 1);
7514   new_descriptors->Append(descriptor);
7515
7516   Handle<LayoutDescriptor> new_layout_descriptor =
7517       FLAG_unbox_double_fields
7518           ? LayoutDescriptor::New(map, new_descriptors, nof + 1)
7519           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
7520
7521   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7522                                 flag, descriptor->GetKey(), "CopyAddDescriptor",
7523                                 SIMPLE_PROPERTY_TRANSITION);
7524 }
7525
7526
7527 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
7528                                       Descriptor* descriptor,
7529                                       TransitionFlag flag) {
7530   Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
7531
7532   // Ensure the key is unique.
7533   descriptor->KeyToUniqueName();
7534
7535   // We replace the key if it is already present.
7536   int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
7537   if (index != DescriptorArray::kNotFound) {
7538     return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
7539   }
7540   return CopyAddDescriptor(map, descriptor, flag);
7541 }
7542
7543
7544 Handle<DescriptorArray> DescriptorArray::CopyUpTo(
7545     Handle<DescriptorArray> desc,
7546     int enumeration_index,
7547     int slack) {
7548   return DescriptorArray::CopyUpToAddAttributes(
7549       desc, enumeration_index, NONE, slack);
7550 }
7551
7552
7553 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
7554     Handle<DescriptorArray> desc,
7555     int enumeration_index,
7556     PropertyAttributes attributes,
7557     int slack) {
7558   if (enumeration_index + slack == 0) {
7559     return desc->GetIsolate()->factory()->empty_descriptor_array();
7560   }
7561
7562   int size = enumeration_index;
7563
7564   Handle<DescriptorArray> descriptors =
7565       DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
7566   DescriptorArray::WhitenessWitness witness(*descriptors);
7567
7568   if (attributes != NONE) {
7569     for (int i = 0; i < size; ++i) {
7570       Object* value = desc->GetValue(i);
7571       Name* key = desc->GetKey(i);
7572       PropertyDetails details = desc->GetDetails(i);
7573       // Bulk attribute changes never affect private properties.
7574       if (!key->IsSymbol() || !Symbol::cast(key)->is_private()) {
7575         int mask = DONT_DELETE | DONT_ENUM;
7576         // READ_ONLY is an invalid attribute for JS setters/getters.
7577         if (details.type() != ACCESSOR_CONSTANT || !value->IsAccessorPair()) {
7578           mask |= READ_ONLY;
7579         }
7580         details = details.CopyAddAttributes(
7581             static_cast<PropertyAttributes>(attributes & mask));
7582       }
7583       Descriptor inner_desc(
7584           handle(key), handle(value, desc->GetIsolate()), details);
7585       descriptors->Set(i, &inner_desc, witness);
7586     }
7587   } else {
7588     for (int i = 0; i < size; ++i) {
7589       descriptors->CopyFrom(i, *desc, witness);
7590     }
7591   }
7592
7593   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
7594
7595   return descriptors;
7596 }
7597
7598
7599 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
7600                                        Handle<DescriptorArray> descriptors,
7601                                        Descriptor* descriptor,
7602                                        int insertion_index,
7603                                        TransitionFlag flag) {
7604   // Ensure the key is unique.
7605   descriptor->KeyToUniqueName();
7606
7607   Handle<Name> key = descriptor->GetKey();
7608   DCHECK(*key == descriptors->GetKey(insertion_index));
7609
7610   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7611       descriptors, map->NumberOfOwnDescriptors());
7612
7613   new_descriptors->Replace(insertion_index, descriptor);
7614   Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
7615       map, new_descriptors, new_descriptors->number_of_descriptors());
7616
7617   SimpleTransitionFlag simple_flag =
7618       (insertion_index == descriptors->number_of_descriptors() - 1)
7619           ? SIMPLE_PROPERTY_TRANSITION
7620           : PROPERTY_TRANSITION;
7621   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7622                                 flag, key, "CopyReplaceDescriptor",
7623                                 simple_flag);
7624 }
7625
7626
7627 void Map::UpdateCodeCache(Handle<Map> map,
7628                           Handle<Name> name,
7629                           Handle<Code> code) {
7630   Isolate* isolate = map->GetIsolate();
7631   HandleScope scope(isolate);
7632   // Allocate the code cache if not present.
7633   if (map->code_cache()->IsFixedArray()) {
7634     Handle<Object> result = isolate->factory()->NewCodeCache();
7635     map->set_code_cache(*result);
7636   }
7637
7638   // Update the code cache.
7639   Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
7640   CodeCache::Update(code_cache, name, code);
7641 }
7642
7643
7644 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
7645   // Do a lookup if a code cache exists.
7646   if (!code_cache()->IsFixedArray()) {
7647     return CodeCache::cast(code_cache())->Lookup(name, flags);
7648   } else {
7649     return GetHeap()->undefined_value();
7650   }
7651 }
7652
7653
7654 int Map::IndexInCodeCache(Object* name, Code* code) {
7655   // Get the internal index if a code cache exists.
7656   if (!code_cache()->IsFixedArray()) {
7657     return CodeCache::cast(code_cache())->GetIndex(name, code);
7658   }
7659   return -1;
7660 }
7661
7662
7663 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7664   // No GC is supposed to happen between a call to IndexInCodeCache and
7665   // RemoveFromCodeCache so the code cache must be there.
7666   DCHECK(!code_cache()->IsFixedArray());
7667   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7668 }
7669
7670
7671 void CodeCache::Update(
7672     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7673   // The number of monomorphic stubs for normal load/store/call IC's can grow to
7674   // a large number and therefore they need to go into a hash table. They are
7675   // used to load global properties from cells.
7676   if (code->type() == Code::NORMAL) {
7677     // Make sure that a hash table is allocated for the normal load code cache.
7678     if (code_cache->normal_type_cache()->IsUndefined()) {
7679       Handle<Object> result =
7680           CodeCacheHashTable::New(code_cache->GetIsolate(),
7681                                   CodeCacheHashTable::kInitialSize);
7682       code_cache->set_normal_type_cache(*result);
7683     }
7684     UpdateNormalTypeCache(code_cache, name, code);
7685   } else {
7686     DCHECK(code_cache->default_cache()->IsFixedArray());
7687     UpdateDefaultCache(code_cache, name, code);
7688   }
7689 }
7690
7691
7692 void CodeCache::UpdateDefaultCache(
7693     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7694   // When updating the default code cache we disregard the type encoded in the
7695   // flags. This allows call constant stubs to overwrite call field
7696   // stubs, etc.
7697   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7698
7699   // First check whether we can update existing code cache without
7700   // extending it.
7701   Handle<FixedArray> cache = handle(code_cache->default_cache());
7702   int length = cache->length();
7703   {
7704     DisallowHeapAllocation no_alloc;
7705     int deleted_index = -1;
7706     for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7707       Object* key = cache->get(i);
7708       if (key->IsNull()) {
7709         if (deleted_index < 0) deleted_index = i;
7710         continue;
7711       }
7712       if (key->IsUndefined()) {
7713         if (deleted_index >= 0) i = deleted_index;
7714         cache->set(i + kCodeCacheEntryNameOffset, *name);
7715         cache->set(i + kCodeCacheEntryCodeOffset, *code);
7716         return;
7717       }
7718       if (name->Equals(Name::cast(key))) {
7719         Code::Flags found =
7720             Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7721         if (Code::RemoveTypeFromFlags(found) == flags) {
7722           cache->set(i + kCodeCacheEntryCodeOffset, *code);
7723           return;
7724         }
7725       }
7726     }
7727
7728     // Reached the end of the code cache.  If there were deleted
7729     // elements, reuse the space for the first of them.
7730     if (deleted_index >= 0) {
7731       cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
7732       cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
7733       return;
7734     }
7735   }
7736
7737   // Extend the code cache with some new entries (at least one). Must be a
7738   // multiple of the entry size.
7739   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7740   new_length = new_length - new_length % kCodeCacheEntrySize;
7741   DCHECK((new_length % kCodeCacheEntrySize) == 0);
7742   cache = FixedArray::CopySize(cache, new_length);
7743
7744   // Add the (name, code) pair to the new cache.
7745   cache->set(length + kCodeCacheEntryNameOffset, *name);
7746   cache->set(length + kCodeCacheEntryCodeOffset, *code);
7747   code_cache->set_default_cache(*cache);
7748 }
7749
7750
7751 void CodeCache::UpdateNormalTypeCache(
7752     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7753   // Adding a new entry can cause a new cache to be allocated.
7754   Handle<CodeCacheHashTable> cache(
7755       CodeCacheHashTable::cast(code_cache->normal_type_cache()));
7756   Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
7757   code_cache->set_normal_type_cache(*new_cache);
7758 }
7759
7760
7761 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
7762   Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7763   if (result->IsCode()) {
7764     if (Code::cast(result)->flags() == flags) return result;
7765     return GetHeap()->undefined_value();
7766   }
7767   return LookupNormalTypeCache(name, flags);
7768 }
7769
7770
7771 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
7772   FixedArray* cache = default_cache();
7773   int length = cache->length();
7774   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7775     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7776     // Skip deleted elements.
7777     if (key->IsNull()) continue;
7778     if (key->IsUndefined()) return key;
7779     if (name->Equals(Name::cast(key))) {
7780       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
7781       if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
7782         return code;
7783       }
7784     }
7785   }
7786   return GetHeap()->undefined_value();
7787 }
7788
7789
7790 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
7791   if (!normal_type_cache()->IsUndefined()) {
7792     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7793     return cache->Lookup(name, flags);
7794   } else {
7795     return GetHeap()->undefined_value();
7796   }
7797 }
7798
7799
7800 int CodeCache::GetIndex(Object* name, Code* code) {
7801   if (code->type() == Code::NORMAL) {
7802     if (normal_type_cache()->IsUndefined()) return -1;
7803     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7804     return cache->GetIndex(Name::cast(name), code->flags());
7805   }
7806
7807   FixedArray* array = default_cache();
7808   int len = array->length();
7809   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
7810     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
7811   }
7812   return -1;
7813 }
7814
7815
7816 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
7817   if (code->type() == Code::NORMAL) {
7818     DCHECK(!normal_type_cache()->IsUndefined());
7819     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7820     DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
7821     cache->RemoveByIndex(index);
7822   } else {
7823     FixedArray* array = default_cache();
7824     DCHECK(array->length() >= index && array->get(index)->IsCode());
7825     // Use null instead of undefined for deleted elements to distinguish
7826     // deleted elements from unused elements.  This distinction is used
7827     // when looking up in the cache and when updating the cache.
7828     DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
7829     array->set_null(index - 1);  // Name.
7830     array->set_null(index);  // Code.
7831   }
7832 }
7833
7834
7835 // The key in the code cache hash table consists of the property name and the
7836 // code object. The actual match is on the name and the code flags. If a key
7837 // is created using the flags and not a code object it can only be used for
7838 // lookup not to create a new entry.
7839 class CodeCacheHashTableKey : public HashTableKey {
7840  public:
7841   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
7842       : name_(name), flags_(flags), code_() { }
7843
7844   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
7845       : name_(name), flags_(code->flags()), code_(code) { }
7846
7847   bool IsMatch(Object* other) OVERRIDE {
7848     if (!other->IsFixedArray()) return false;
7849     FixedArray* pair = FixedArray::cast(other);
7850     Name* name = Name::cast(pair->get(0));
7851     Code::Flags flags = Code::cast(pair->get(1))->flags();
7852     if (flags != flags_) {
7853       return false;
7854     }
7855     return name_->Equals(name);
7856   }
7857
7858   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
7859     return name->Hash() ^ flags;
7860   }
7861
7862   uint32_t Hash() OVERRIDE { return NameFlagsHashHelper(*name_, flags_); }
7863
7864   uint32_t HashForObject(Object* obj) OVERRIDE {
7865     FixedArray* pair = FixedArray::cast(obj);
7866     Name* name = Name::cast(pair->get(0));
7867     Code* code = Code::cast(pair->get(1));
7868     return NameFlagsHashHelper(name, code->flags());
7869   }
7870
7871   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
7872     Handle<Code> code = code_.ToHandleChecked();
7873     Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
7874     pair->set(0, *name_);
7875     pair->set(1, *code);
7876     return pair;
7877   }
7878
7879  private:
7880   Handle<Name> name_;
7881   Code::Flags flags_;
7882   // TODO(jkummerow): We should be able to get by without this.
7883   MaybeHandle<Code> code_;
7884 };
7885
7886
7887 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
7888   DisallowHeapAllocation no_alloc;
7889   CodeCacheHashTableKey key(handle(name), flags);
7890   int entry = FindEntry(&key);
7891   if (entry == kNotFound) return GetHeap()->undefined_value();
7892   return get(EntryToIndex(entry) + 1);
7893 }
7894
7895
7896 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
7897     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
7898   CodeCacheHashTableKey key(name, code);
7899
7900   Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
7901
7902   int entry = new_cache->FindInsertionEntry(key.Hash());
7903   Handle<Object> k = key.AsHandle(cache->GetIsolate());
7904
7905   new_cache->set(EntryToIndex(entry), *k);
7906   new_cache->set(EntryToIndex(entry) + 1, *code);
7907   new_cache->ElementAdded();
7908   return new_cache;
7909 }
7910
7911
7912 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
7913   DisallowHeapAllocation no_alloc;
7914   CodeCacheHashTableKey key(handle(name), flags);
7915   int entry = FindEntry(&key);
7916   return (entry == kNotFound) ? -1 : entry;
7917 }
7918
7919
7920 void CodeCacheHashTable::RemoveByIndex(int index) {
7921   DCHECK(index >= 0);
7922   Heap* heap = GetHeap();
7923   set(EntryToIndex(index), heap->the_hole_value());
7924   set(EntryToIndex(index) + 1, heap->the_hole_value());
7925   ElementRemoved();
7926 }
7927
7928
7929 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
7930                                   MapHandleList* maps,
7931                                   Code::Flags flags,
7932                                   Handle<Code> code) {
7933   Isolate* isolate = code_cache->GetIsolate();
7934   if (code_cache->cache()->IsUndefined()) {
7935     Handle<PolymorphicCodeCacheHashTable> result =
7936         PolymorphicCodeCacheHashTable::New(
7937             isolate,
7938             PolymorphicCodeCacheHashTable::kInitialSize);
7939     code_cache->set_cache(*result);
7940   } else {
7941     // This entry shouldn't be contained in the cache yet.
7942     DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
7943                ->Lookup(maps, flags)->IsUndefined());
7944   }
7945   Handle<PolymorphicCodeCacheHashTable> hash_table =
7946       handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
7947   Handle<PolymorphicCodeCacheHashTable> new_cache =
7948       PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
7949   code_cache->set_cache(*new_cache);
7950 }
7951
7952
7953 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
7954                                             Code::Flags flags) {
7955   if (!cache()->IsUndefined()) {
7956     PolymorphicCodeCacheHashTable* hash_table =
7957         PolymorphicCodeCacheHashTable::cast(cache());
7958     return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
7959   } else {
7960     return GetIsolate()->factory()->undefined_value();
7961   }
7962 }
7963
7964
7965 // Despite their name, object of this class are not stored in the actual
7966 // hash table; instead they're temporarily used for lookups. It is therefore
7967 // safe to have a weak (non-owning) pointer to a MapList as a member field.
7968 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
7969  public:
7970   // Callers must ensure that |maps| outlives the newly constructed object.
7971   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
7972       : maps_(maps),
7973         code_flags_(code_flags) {}
7974
7975   bool IsMatch(Object* other) OVERRIDE {
7976     MapHandleList other_maps(kDefaultListAllocationSize);
7977     int other_flags;
7978     FromObject(other, &other_flags, &other_maps);
7979     if (code_flags_ != other_flags) return false;
7980     if (maps_->length() != other_maps.length()) return false;
7981     // Compare just the hashes first because it's faster.
7982     int this_hash = MapsHashHelper(maps_, code_flags_);
7983     int other_hash = MapsHashHelper(&other_maps, other_flags);
7984     if (this_hash != other_hash) return false;
7985
7986     // Full comparison: for each map in maps_, look for an equivalent map in
7987     // other_maps. This implementation is slow, but probably good enough for
7988     // now because the lists are short (<= 4 elements currently).
7989     for (int i = 0; i < maps_->length(); ++i) {
7990       bool match_found = false;
7991       for (int j = 0; j < other_maps.length(); ++j) {
7992         if (*(maps_->at(i)) == *(other_maps.at(j))) {
7993           match_found = true;
7994           break;
7995         }
7996       }
7997       if (!match_found) return false;
7998     }
7999     return true;
8000   }
8001
8002   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
8003     uint32_t hash = code_flags;
8004     for (int i = 0; i < maps->length(); ++i) {
8005       hash ^= maps->at(i)->Hash();
8006     }
8007     return hash;
8008   }
8009
8010   uint32_t Hash() OVERRIDE {
8011     return MapsHashHelper(maps_, code_flags_);
8012   }
8013
8014   uint32_t HashForObject(Object* obj) OVERRIDE {
8015     MapHandleList other_maps(kDefaultListAllocationSize);
8016     int other_flags;
8017     FromObject(obj, &other_flags, &other_maps);
8018     return MapsHashHelper(&other_maps, other_flags);
8019   }
8020
8021   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
8022     // The maps in |maps_| must be copied to a newly allocated FixedArray,
8023     // both because the referenced MapList is short-lived, and because C++
8024     // objects can't be stored in the heap anyway.
8025     Handle<FixedArray> list =
8026         isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
8027     list->set(0, Smi::FromInt(code_flags_));
8028     for (int i = 0; i < maps_->length(); ++i) {
8029       list->set(i + 1, *maps_->at(i));
8030     }
8031     return list;
8032   }
8033
8034  private:
8035   static MapHandleList* FromObject(Object* obj,
8036                                    int* code_flags,
8037                                    MapHandleList* maps) {
8038     FixedArray* list = FixedArray::cast(obj);
8039     maps->Rewind(0);
8040     *code_flags = Smi::cast(list->get(0))->value();
8041     for (int i = 1; i < list->length(); ++i) {
8042       maps->Add(Handle<Map>(Map::cast(list->get(i))));
8043     }
8044     return maps;
8045   }
8046
8047   MapHandleList* maps_;  // weak.
8048   int code_flags_;
8049   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
8050 };
8051
8052
8053 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
8054                                               int code_kind) {
8055   DisallowHeapAllocation no_alloc;
8056   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
8057   int entry = FindEntry(&key);
8058   if (entry == kNotFound) return GetHeap()->undefined_value();
8059   return get(EntryToIndex(entry) + 1);
8060 }
8061
8062
8063 Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
8064       Handle<PolymorphicCodeCacheHashTable> hash_table,
8065       MapHandleList* maps,
8066       int code_kind,
8067       Handle<Code> code) {
8068   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
8069   Handle<PolymorphicCodeCacheHashTable> cache =
8070       EnsureCapacity(hash_table, 1, &key);
8071   int entry = cache->FindInsertionEntry(key.Hash());
8072
8073   Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
8074   cache->set(EntryToIndex(entry), *obj);
8075   cache->set(EntryToIndex(entry) + 1, *code);
8076   cache->ElementAdded();
8077   return cache;
8078 }
8079
8080
8081 void FixedArray::Shrink(int new_length) {
8082   DCHECK(0 <= new_length && new_length <= length());
8083   if (new_length < length()) {
8084     GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>(
8085         this, length() - new_length);
8086   }
8087 }
8088
8089
8090 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
8091     Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) {
8092   DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
8093   ElementsAccessor* accessor = array->GetElementsAccessor();
8094   Handle<FixedArray> result;
8095   ASSIGN_RETURN_ON_EXCEPTION(
8096       array->GetIsolate(), result,
8097       accessor->AddElementsToFixedArray(array, array, content, filter),
8098       FixedArray);
8099
8100 #ifdef ENABLE_SLOW_DCHECKS
8101   if (FLAG_enable_slow_asserts) {
8102     DisallowHeapAllocation no_allocation;
8103     for (int i = 0; i < result->length(); i++) {
8104       Object* current = result->get(i);
8105       DCHECK(current->IsNumber() || current->IsName());
8106     }
8107   }
8108 #endif
8109   return result;
8110 }
8111
8112
8113 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
8114                                                 Handle<FixedArray> second) {
8115   ElementsAccessor* accessor = ElementsAccessor::ForArray(second);
8116   Handle<FixedArray> result;
8117   ASSIGN_RETURN_ON_EXCEPTION(
8118       first->GetIsolate(), result,
8119       accessor->AddElementsToFixedArray(
8120           Handle<Object>::null(),    // receiver
8121           Handle<JSObject>::null(),  // holder
8122           first, Handle<FixedArrayBase>::cast(second), ALL_KEYS),
8123       FixedArray);
8124
8125 #ifdef ENABLE_SLOW_DCHECKS
8126   if (FLAG_enable_slow_asserts) {
8127     DisallowHeapAllocation no_allocation;
8128     for (int i = 0; i < result->length(); i++) {
8129       Object* current = result->get(i);
8130       DCHECK(current->IsNumber() || current->IsName());
8131     }
8132   }
8133 #endif
8134   return result;
8135 }
8136
8137
8138 Handle<FixedArray> FixedArray::CopySize(
8139     Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
8140   Isolate* isolate = array->GetIsolate();
8141   if (new_length == 0) return isolate->factory()->empty_fixed_array();
8142   Handle<FixedArray> result =
8143       isolate->factory()->NewFixedArray(new_length, pretenure);
8144   // Copy the content
8145   DisallowHeapAllocation no_gc;
8146   int len = array->length();
8147   if (new_length < len) len = new_length;
8148   // We are taking the map from the old fixed array so the map is sure to
8149   // be an immortal immutable object.
8150   result->set_map_no_write_barrier(array->map());
8151   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
8152   for (int i = 0; i < len; i++) {
8153     result->set(i, array->get(i), mode);
8154   }
8155   return result;
8156 }
8157
8158
8159 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
8160   DisallowHeapAllocation no_gc;
8161   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
8162   for (int index = 0; index < len; index++) {
8163     dest->set(dest_pos+index, get(pos+index), mode);
8164   }
8165 }
8166
8167
8168 #ifdef DEBUG
8169 bool FixedArray::IsEqualTo(FixedArray* other) {
8170   if (length() != other->length()) return false;
8171   for (int i = 0 ; i < length(); ++i) {
8172     if (get(i) != other->get(i)) return false;
8173   }
8174   return true;
8175 }
8176 #endif
8177
8178
8179 // static
8180 void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
8181                          Handle<HeapObject> value) {
8182   DCHECK(array->IsEmptySlot(index));  // Don't overwrite anything.
8183   Handle<WeakCell> cell =
8184       value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
8185                      : array->GetIsolate()->factory()->NewWeakCell(value);
8186   Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
8187   if (FLAG_trace_weak_arrays) {
8188     PrintF("[WeakFixedArray: storing at index %d ]\n", index);
8189   }
8190   array->set_last_used_index(index);
8191 }
8192
8193
8194 // static
8195 Handle<WeakFixedArray> WeakFixedArray::Add(
8196     Handle<Object> maybe_array, Handle<HeapObject> value,
8197     SearchForDuplicates search_for_duplicates) {
8198   Handle<WeakFixedArray> array =
8199       (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
8200           ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
8201           : Handle<WeakFixedArray>::cast(maybe_array);
8202
8203   if (search_for_duplicates == kAddIfNotFound) {
8204     for (int i = 0; i < array->Length(); ++i) {
8205       if (array->Get(i) == *value) return array;
8206     }
8207   } else {
8208 #ifdef DEBUG
8209     for (int i = 0; i < array->Length(); ++i) {
8210       DCHECK_NE(*value, array->Get(i));
8211     }
8212 #endif
8213   }
8214
8215   // Try to store the new entry if there's room. Optimize for consecutive
8216   // accesses.
8217   int first_index = array->last_used_index();
8218   for (int i = first_index;;) {
8219     if (array->IsEmptySlot((i))) {
8220       WeakFixedArray::Set(array, i, value);
8221       return array;
8222     }
8223     if (FLAG_trace_weak_arrays) {
8224       PrintF("[WeakFixedArray: searching for free slot]\n");
8225     }
8226     i = (i + 1) % array->Length();
8227     if (i == first_index) break;
8228   }
8229
8230   // No usable slot found, grow the array.
8231   int new_length = array->Length() + (array->Length() >> 1) + 4;
8232   Handle<WeakFixedArray> new_array =
8233       Allocate(array->GetIsolate(), new_length, array);
8234   if (FLAG_trace_weak_arrays) {
8235     PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
8236   }
8237   WeakFixedArray::Set(new_array, array->Length(), value);
8238   return new_array;
8239 }
8240
8241
8242 void WeakFixedArray::Remove(Handle<HeapObject> value) {
8243   // Optimize for the most recently added element to be removed again.
8244   int first_index = last_used_index();
8245   for (int i = first_index;;) {
8246     if (Get(i) == *value) {
8247       clear(i);
8248       // Users of WeakFixedArray should make sure that there are no duplicates,
8249       // they can use Add(..., kAddIfNotFound) if necessary.
8250       return;
8251     }
8252     i = (i + 1) % Length();
8253     if (i == first_index) break;
8254   }
8255 }
8256
8257
8258 // static
8259 Handle<WeakFixedArray> WeakFixedArray::Allocate(
8260     Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
8261   DCHECK(0 <= size);
8262   Handle<FixedArray> result =
8263       isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
8264   Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result);
8265   if (initialize_from.is_null()) {
8266     for (int i = 0; i < result->length(); ++i) {
8267       result->set(i, Smi::FromInt(0));
8268     }
8269   } else {
8270     DCHECK(initialize_from->Length() <= size);
8271     Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
8272     int target_index = kFirstIndex;
8273     for (int source_index = kFirstIndex; source_index < raw_source->length();
8274          ++source_index) {
8275       // The act of allocating might have caused entries in the source array
8276       // to be cleared. Copy only what's needed.
8277       if (initialize_from->IsEmptySlot(source_index - kFirstIndex)) continue;
8278       result->set(target_index++, raw_source->get(source_index));
8279     }
8280     casted_result->set_last_used_index(target_index - 1 - kFirstIndex);
8281     for (; target_index < result->length(); ++target_index) {
8282       result->set(target_index, Smi::FromInt(0));
8283     }
8284   }
8285   return casted_result;
8286 }
8287
8288
8289 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj,
8290                                  AddMode mode) {
8291   int length = array->Length();
8292   array = EnsureSpace(array, length + 1);
8293   if (mode == kReloadLengthAfterAllocation) {
8294     DCHECK(array->Length() <= length);
8295     length = array->Length();
8296   }
8297   array->Set(length, *obj);
8298   array->SetLength(length + 1);
8299   return array;
8300 }
8301
8302
8303 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1,
8304                                  Handle<Object> obj2, AddMode mode) {
8305   int length = array->Length();
8306   array = EnsureSpace(array, length + 2);
8307   if (mode == kReloadLengthAfterAllocation) {
8308     length = array->Length();
8309   }
8310   array->Set(length, *obj1);
8311   array->Set(length + 1, *obj2);
8312   array->SetLength(length + 2);
8313   return array;
8314 }
8315
8316
8317 Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
8318   int capacity = array->length();
8319   bool empty = (capacity == 0);
8320   if (capacity < kFirstIndex + length) {
8321     capacity = kFirstIndex + length;
8322     capacity = capacity + Max(capacity / 2, 2);
8323     array = Handle<ArrayList>::cast(FixedArray::CopySize(array, capacity));
8324     if (empty) array->SetLength(0);
8325   }
8326   return array;
8327 }
8328
8329
8330 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
8331                                                   int number_of_descriptors,
8332                                                   int slack) {
8333   DCHECK(0 <= number_of_descriptors);
8334   Factory* factory = isolate->factory();
8335   // Do not use DescriptorArray::cast on incomplete object.
8336   int size = number_of_descriptors + slack;
8337   if (size == 0) return factory->empty_descriptor_array();
8338   // Allocate the array of keys.
8339   Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
8340
8341   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
8342   result->set(kEnumCacheIndex, Smi::FromInt(0));
8343   return Handle<DescriptorArray>::cast(result);
8344 }
8345
8346
8347 void DescriptorArray::ClearEnumCache() {
8348   set(kEnumCacheIndex, Smi::FromInt(0));
8349 }
8350
8351
8352 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
8353   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
8354   Set(index, descriptor);
8355 }
8356
8357
8358 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
8359                                    FixedArray* new_cache,
8360                                    Object* new_index_cache) {
8361   DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
8362   DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
8363   DCHECK(!IsEmpty());
8364   DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
8365   FixedArray::cast(bridge_storage)->
8366     set(kEnumCacheBridgeCacheIndex, new_cache);
8367   FixedArray::cast(bridge_storage)->
8368     set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
8369   set(kEnumCacheIndex, bridge_storage);
8370 }
8371
8372
8373 void DescriptorArray::CopyFrom(int index, DescriptorArray* src,
8374                                const WhitenessWitness& witness) {
8375   Object* value = src->GetValue(index);
8376   PropertyDetails details = src->GetDetails(index);
8377   Descriptor desc(handle(src->GetKey(index)),
8378                   handle(value, src->GetIsolate()),
8379                   details);
8380   Set(index, &desc, witness);
8381 }
8382
8383
8384 // We need the whiteness witness since sort will reshuffle the entries in the
8385 // descriptor array. If the descriptor array were to be black, the shuffling
8386 // would move a slot that was already recorded as pointing into an evacuation
8387 // candidate. This would result in missing updates upon evacuation.
8388 void DescriptorArray::Sort() {
8389   // In-place heap sort.
8390   int len = number_of_descriptors();
8391   // Reset sorting since the descriptor array might contain invalid pointers.
8392   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
8393   // Bottom-up max-heap construction.
8394   // Index of the last node with children
8395   const int max_parent_index = (len / 2) - 1;
8396   for (int i = max_parent_index; i >= 0; --i) {
8397     int parent_index = i;
8398     const uint32_t parent_hash = GetSortedKey(i)->Hash();
8399     while (parent_index <= max_parent_index) {
8400       int child_index = 2 * parent_index + 1;
8401       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8402       if (child_index + 1 < len) {
8403         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8404         if (right_child_hash > child_hash) {
8405           child_index++;
8406           child_hash = right_child_hash;
8407         }
8408       }
8409       if (child_hash <= parent_hash) break;
8410       SwapSortedKeys(parent_index, child_index);
8411       // Now element at child_index could be < its children.
8412       parent_index = child_index;  // parent_hash remains correct.
8413     }
8414   }
8415
8416   // Extract elements and create sorted array.
8417   for (int i = len - 1; i > 0; --i) {
8418     // Put max element at the back of the array.
8419     SwapSortedKeys(0, i);
8420     // Shift down the new top element.
8421     int parent_index = 0;
8422     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
8423     const int max_parent_index = (i / 2) - 1;
8424     while (parent_index <= max_parent_index) {
8425       int child_index = parent_index * 2 + 1;
8426       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8427       if (child_index + 1 < i) {
8428         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8429         if (right_child_hash > child_hash) {
8430           child_index++;
8431           child_hash = right_child_hash;
8432         }
8433       }
8434       if (child_hash <= parent_hash) break;
8435       SwapSortedKeys(parent_index, child_index);
8436       parent_index = child_index;
8437     }
8438   }
8439   DCHECK(IsSortedNoDuplicates());
8440 }
8441
8442
8443 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
8444   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
8445   copy->set_getter(pair->getter());
8446   copy->set_setter(pair->setter());
8447   return copy;
8448 }
8449
8450
8451 Object* AccessorPair::GetComponent(AccessorComponent component) {
8452   Object* accessor = get(component);
8453   return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
8454 }
8455
8456
8457 Handle<DeoptimizationInputData> DeoptimizationInputData::New(
8458     Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
8459   return Handle<DeoptimizationInputData>::cast(
8460       isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
8461                                         pretenure));
8462 }
8463
8464
8465 Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
8466     Isolate* isolate,
8467     int number_of_deopt_points,
8468     PretenureFlag pretenure) {
8469   Handle<FixedArray> result;
8470   if (number_of_deopt_points == 0) {
8471     result = isolate->factory()->empty_fixed_array();
8472   } else {
8473     result = isolate->factory()->NewFixedArray(
8474         LengthOfFixedArray(number_of_deopt_points), pretenure);
8475   }
8476   return Handle<DeoptimizationOutputData>::cast(result);
8477 }
8478
8479
8480 int HandlerTable::LookupRange(int pc_offset, int* stack_depth_out) {
8481   int innermost_handler = -1, innermost_start = -1;
8482   for (int i = 0; i < length(); i += kRangeEntrySize) {
8483     int start_offset = Smi::cast(get(i + kRangeStartIndex))->value();
8484     int end_offset = Smi::cast(get(i + kRangeEndIndex))->value();
8485     int handler_offset = Smi::cast(get(i + kRangeHandlerIndex))->value();
8486     int stack_depth = Smi::cast(get(i + kRangeDepthIndex))->value();
8487     if (pc_offset > start_offset && pc_offset <= end_offset) {
8488       DCHECK_NE(start_offset, innermost_start);
8489       if (start_offset < innermost_start) continue;
8490       innermost_handler = handler_offset;
8491       innermost_start = start_offset;
8492       *stack_depth_out = stack_depth;
8493     }
8494   }
8495   return innermost_handler;
8496 }
8497
8498
8499 // TODO(turbofan): Make sure table is sorted and use binary search.
8500 int HandlerTable::LookupReturn(int pc_offset) {
8501   for (int i = 0; i < length(); i += kReturnEntrySize) {
8502     int return_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
8503     int handler_offset = Smi::cast(get(i + kReturnHandlerIndex))->value();
8504     if (pc_offset == return_offset) return handler_offset;
8505   }
8506   return -1;
8507 }
8508
8509
8510 #ifdef DEBUG
8511 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
8512   if (IsEmpty()) return other->IsEmpty();
8513   if (other->IsEmpty()) return false;
8514   if (length() != other->length()) return false;
8515   for (int i = 0; i < length(); ++i) {
8516     if (get(i) != other->get(i)) return false;
8517   }
8518   return true;
8519 }
8520 #endif
8521
8522
8523 bool String::LooksValid() {
8524   if (!GetIsolate()->heap()->Contains(this)) return false;
8525   return true;
8526 }
8527
8528
8529 String::FlatContent String::GetFlatContent() {
8530   DCHECK(!AllowHeapAllocation::IsAllowed());
8531   int length = this->length();
8532   StringShape shape(this);
8533   String* string = this;
8534   int offset = 0;
8535   if (shape.representation_tag() == kConsStringTag) {
8536     ConsString* cons = ConsString::cast(string);
8537     if (cons->second()->length() != 0) {
8538       return FlatContent();
8539     }
8540     string = cons->first();
8541     shape = StringShape(string);
8542   }
8543   if (shape.representation_tag() == kSlicedStringTag) {
8544     SlicedString* slice = SlicedString::cast(string);
8545     offset = slice->offset();
8546     string = slice->parent();
8547     shape = StringShape(string);
8548     DCHECK(shape.representation_tag() != kConsStringTag &&
8549            shape.representation_tag() != kSlicedStringTag);
8550   }
8551   if (shape.encoding_tag() == kOneByteStringTag) {
8552     const uint8_t* start;
8553     if (shape.representation_tag() == kSeqStringTag) {
8554       start = SeqOneByteString::cast(string)->GetChars();
8555     } else {
8556       start = ExternalOneByteString::cast(string)->GetChars();
8557     }
8558     return FlatContent(start + offset, length);
8559   } else {
8560     DCHECK(shape.encoding_tag() == kTwoByteStringTag);
8561     const uc16* start;
8562     if (shape.representation_tag() == kSeqStringTag) {
8563       start = SeqTwoByteString::cast(string)->GetChars();
8564     } else {
8565       start = ExternalTwoByteString::cast(string)->GetChars();
8566     }
8567     return FlatContent(start + offset, length);
8568   }
8569 }
8570
8571
8572 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8573                                           RobustnessFlag robust_flag,
8574                                           int offset,
8575                                           int length,
8576                                           int* length_return) {
8577   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8578     return SmartArrayPointer<char>(NULL);
8579   }
8580   // Negative length means the to the end of the string.
8581   if (length < 0) length = kMaxInt - offset;
8582
8583   // Compute the size of the UTF-8 string. Start at the specified offset.
8584   StringCharacterStream stream(this, offset);
8585   int character_position = offset;
8586   int utf8_bytes = 0;
8587   int last = unibrow::Utf16::kNoPreviousCharacter;
8588   while (stream.HasMore() && character_position++ < offset + length) {
8589     uint16_t character = stream.GetNext();
8590     utf8_bytes += unibrow::Utf8::Length(character, last);
8591     last = character;
8592   }
8593
8594   if (length_return) {
8595     *length_return = utf8_bytes;
8596   }
8597
8598   char* result = NewArray<char>(utf8_bytes + 1);
8599
8600   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8601   stream.Reset(this, offset);
8602   character_position = offset;
8603   int utf8_byte_position = 0;
8604   last = unibrow::Utf16::kNoPreviousCharacter;
8605   while (stream.HasMore() && character_position++ < offset + length) {
8606     uint16_t character = stream.GetNext();
8607     if (allow_nulls == DISALLOW_NULLS && character == 0) {
8608       character = ' ';
8609     }
8610     utf8_byte_position +=
8611         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8612     last = character;
8613   }
8614   result[utf8_byte_position] = 0;
8615   return SmartArrayPointer<char>(result);
8616 }
8617
8618
8619 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8620                                           RobustnessFlag robust_flag,
8621                                           int* length_return) {
8622   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8623 }
8624
8625
8626 const uc16* String::GetTwoByteData(unsigned start) {
8627   DCHECK(!IsOneByteRepresentationUnderneath());
8628   switch (StringShape(this).representation_tag()) {
8629     case kSeqStringTag:
8630       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8631     case kExternalStringTag:
8632       return ExternalTwoByteString::cast(this)->
8633         ExternalTwoByteStringGetData(start);
8634     case kSlicedStringTag: {
8635       SlicedString* slice = SlicedString::cast(this);
8636       return slice->parent()->GetTwoByteData(start + slice->offset());
8637     }
8638     case kConsStringTag:
8639       UNREACHABLE();
8640       return NULL;
8641   }
8642   UNREACHABLE();
8643   return NULL;
8644 }
8645
8646
8647 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
8648   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8649     return SmartArrayPointer<uc16>();
8650   }
8651   StringCharacterStream stream(this);
8652
8653   uc16* result = NewArray<uc16>(length() + 1);
8654
8655   int i = 0;
8656   while (stream.HasMore()) {
8657     uint16_t character = stream.GetNext();
8658     result[i++] = character;
8659   }
8660   result[i] = 0;
8661   return SmartArrayPointer<uc16>(result);
8662 }
8663
8664
8665 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
8666   return reinterpret_cast<uc16*>(
8667       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8668 }
8669
8670
8671 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8672   Relocatable* current = isolate->relocatable_top();
8673   while (current != NULL) {
8674     current->PostGarbageCollection();
8675     current = current->prev_;
8676   }
8677 }
8678
8679
8680 // Reserve space for statics needing saving and restoring.
8681 int Relocatable::ArchiveSpacePerThread() {
8682   return sizeof(Relocatable*);  // NOLINT
8683 }
8684
8685
8686 // Archive statics that are thread-local.
8687 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8688   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8689   isolate->set_relocatable_top(NULL);
8690   return to + ArchiveSpacePerThread();
8691 }
8692
8693
8694 // Restore statics that are thread-local.
8695 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8696   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8697   return from + ArchiveSpacePerThread();
8698 }
8699
8700
8701 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8702   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8703   Iterate(v, top);
8704   return thread_storage + ArchiveSpacePerThread();
8705 }
8706
8707
8708 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8709   Iterate(v, isolate->relocatable_top());
8710 }
8711
8712
8713 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8714   Relocatable* current = top;
8715   while (current != NULL) {
8716     current->IterateInstance(v);
8717     current = current->prev_;
8718   }
8719 }
8720
8721
8722 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
8723     : Relocatable(isolate),
8724       str_(str.location()),
8725       length_(str->length()) {
8726   PostGarbageCollection();
8727 }
8728
8729
8730 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
8731     : Relocatable(isolate),
8732       str_(0),
8733       is_one_byte_(true),
8734       length_(input.length()),
8735       start_(input.start()) {}
8736
8737
8738 void FlatStringReader::PostGarbageCollection() {
8739   if (str_ == NULL) return;
8740   Handle<String> str(str_);
8741   DCHECK(str->IsFlat());
8742   DisallowHeapAllocation no_gc;
8743   // This does not actually prevent the vector from being relocated later.
8744   String::FlatContent content = str->GetFlatContent();
8745   DCHECK(content.IsFlat());
8746   is_one_byte_ = content.IsOneByte();
8747   if (is_one_byte_) {
8748     start_ = content.ToOneByteVector().start();
8749   } else {
8750     start_ = content.ToUC16Vector().start();
8751   }
8752 }
8753
8754
8755 void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
8756   DCHECK(cons_string != NULL);
8757   root_ = cons_string;
8758   consumed_ = offset;
8759   // Force stack blown condition to trigger restart.
8760   depth_ = 1;
8761   maximum_depth_ = kStackSize + depth_;
8762   DCHECK(StackBlown());
8763 }
8764
8765
8766 String* ConsStringIterator::Continue(int* offset_out) {
8767   DCHECK(depth_ != 0);
8768   DCHECK_EQ(0, *offset_out);
8769   bool blew_stack = StackBlown();
8770   String* string = NULL;
8771   // Get the next leaf if there is one.
8772   if (!blew_stack) string = NextLeaf(&blew_stack);
8773   // Restart search from root.
8774   if (blew_stack) {
8775     DCHECK(string == NULL);
8776     string = Search(offset_out);
8777   }
8778   // Ensure future calls return null immediately.
8779   if (string == NULL) Reset(NULL);
8780   return string;
8781 }
8782
8783
8784 String* ConsStringIterator::Search(int* offset_out) {
8785   ConsString* cons_string = root_;
8786   // Reset the stack, pushing the root string.
8787   depth_ = 1;
8788   maximum_depth_ = 1;
8789   frames_[0] = cons_string;
8790   const int consumed = consumed_;
8791   int offset = 0;
8792   while (true) {
8793     // Loop until the string is found which contains the target offset.
8794     String* string = cons_string->first();
8795     int length = string->length();
8796     int32_t type;
8797     if (consumed < offset + length) {
8798       // Target offset is in the left branch.
8799       // Keep going if we're still in a ConString.
8800       type = string->map()->instance_type();
8801       if ((type & kStringRepresentationMask) == kConsStringTag) {
8802         cons_string = ConsString::cast(string);
8803         PushLeft(cons_string);
8804         continue;
8805       }
8806       // Tell the stack we're done descending.
8807       AdjustMaximumDepth();
8808     } else {
8809       // Descend right.
8810       // Update progress through the string.
8811       offset += length;
8812       // Keep going if we're still in a ConString.
8813       string = cons_string->second();
8814       type = string->map()->instance_type();
8815       if ((type & kStringRepresentationMask) == kConsStringTag) {
8816         cons_string = ConsString::cast(string);
8817         PushRight(cons_string);
8818         continue;
8819       }
8820       // Need this to be updated for the current string.
8821       length = string->length();
8822       // Account for the possibility of an empty right leaf.
8823       // This happens only if we have asked for an offset outside the string.
8824       if (length == 0) {
8825         // Reset so future operations will return null immediately.
8826         Reset(NULL);
8827         return NULL;
8828       }
8829       // Tell the stack we're done descending.
8830       AdjustMaximumDepth();
8831       // Pop stack so next iteration is in correct place.
8832       Pop();
8833     }
8834     DCHECK(length != 0);
8835     // Adjust return values and exit.
8836     consumed_ = offset + length;
8837     *offset_out = consumed - offset;
8838     return string;
8839   }
8840   UNREACHABLE();
8841   return NULL;
8842 }
8843
8844
8845 String* ConsStringIterator::NextLeaf(bool* blew_stack) {
8846   while (true) {
8847     // Tree traversal complete.
8848     if (depth_ == 0) {
8849       *blew_stack = false;
8850       return NULL;
8851     }
8852     // We've lost track of higher nodes.
8853     if (StackBlown()) {
8854       *blew_stack = true;
8855       return NULL;
8856     }
8857     // Go right.
8858     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
8859     String* string = cons_string->second();
8860     int32_t type = string->map()->instance_type();
8861     if ((type & kStringRepresentationMask) != kConsStringTag) {
8862       // Pop stack so next iteration is in correct place.
8863       Pop();
8864       int length = string->length();
8865       // Could be a flattened ConsString.
8866       if (length == 0) continue;
8867       consumed_ += length;
8868       return string;
8869     }
8870     cons_string = ConsString::cast(string);
8871     PushRight(cons_string);
8872     // Need to traverse all the way left.
8873     while (true) {
8874       // Continue left.
8875       string = cons_string->first();
8876       type = string->map()->instance_type();
8877       if ((type & kStringRepresentationMask) != kConsStringTag) {
8878         AdjustMaximumDepth();
8879         int length = string->length();
8880         DCHECK(length != 0);
8881         consumed_ += length;
8882         return string;
8883       }
8884       cons_string = ConsString::cast(string);
8885       PushLeft(cons_string);
8886     }
8887   }
8888   UNREACHABLE();
8889   return NULL;
8890 }
8891
8892
8893 uint16_t ConsString::ConsStringGet(int index) {
8894   DCHECK(index >= 0 && index < this->length());
8895
8896   // Check for a flattened cons string
8897   if (second()->length() == 0) {
8898     String* left = first();
8899     return left->Get(index);
8900   }
8901
8902   String* string = String::cast(this);
8903
8904   while (true) {
8905     if (StringShape(string).IsCons()) {
8906       ConsString* cons_string = ConsString::cast(string);
8907       String* left = cons_string->first();
8908       if (left->length() > index) {
8909         string = left;
8910       } else {
8911         index -= left->length();
8912         string = cons_string->second();
8913       }
8914     } else {
8915       return string->Get(index);
8916     }
8917   }
8918
8919   UNREACHABLE();
8920   return 0;
8921 }
8922
8923
8924 uint16_t SlicedString::SlicedStringGet(int index) {
8925   return parent()->Get(offset() + index);
8926 }
8927
8928
8929 template <typename sinkchar>
8930 void String::WriteToFlat(String* src,
8931                          sinkchar* sink,
8932                          int f,
8933                          int t) {
8934   String* source = src;
8935   int from = f;
8936   int to = t;
8937   while (true) {
8938     DCHECK(0 <= from && from <= to && to <= source->length());
8939     switch (StringShape(source).full_representation_tag()) {
8940       case kOneByteStringTag | kExternalStringTag: {
8941         CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
8942                   to - from);
8943         return;
8944       }
8945       case kTwoByteStringTag | kExternalStringTag: {
8946         const uc16* data =
8947             ExternalTwoByteString::cast(source)->GetChars();
8948         CopyChars(sink,
8949                   data + from,
8950                   to - from);
8951         return;
8952       }
8953       case kOneByteStringTag | kSeqStringTag: {
8954         CopyChars(sink,
8955                   SeqOneByteString::cast(source)->GetChars() + from,
8956                   to - from);
8957         return;
8958       }
8959       case kTwoByteStringTag | kSeqStringTag: {
8960         CopyChars(sink,
8961                   SeqTwoByteString::cast(source)->GetChars() + from,
8962                   to - from);
8963         return;
8964       }
8965       case kOneByteStringTag | kConsStringTag:
8966       case kTwoByteStringTag | kConsStringTag: {
8967         ConsString* cons_string = ConsString::cast(source);
8968         String* first = cons_string->first();
8969         int boundary = first->length();
8970         if (to - boundary >= boundary - from) {
8971           // Right hand side is longer.  Recurse over left.
8972           if (from < boundary) {
8973             WriteToFlat(first, sink, from, boundary);
8974             sink += boundary - from;
8975             from = 0;
8976           } else {
8977             from -= boundary;
8978           }
8979           to -= boundary;
8980           source = cons_string->second();
8981         } else {
8982           // Left hand side is longer.  Recurse over right.
8983           if (to > boundary) {
8984             String* second = cons_string->second();
8985             // When repeatedly appending to a string, we get a cons string that
8986             // is unbalanced to the left, a list, essentially.  We inline the
8987             // common case of sequential one-byte right child.
8988             if (to - boundary == 1) {
8989               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
8990             } else if (second->IsSeqOneByteString()) {
8991               CopyChars(sink + boundary - from,
8992                         SeqOneByteString::cast(second)->GetChars(),
8993                         to - boundary);
8994             } else {
8995               WriteToFlat(second,
8996                           sink + boundary - from,
8997                           0,
8998                           to - boundary);
8999             }
9000             to = boundary;
9001           }
9002           source = first;
9003         }
9004         break;
9005       }
9006       case kOneByteStringTag | kSlicedStringTag:
9007       case kTwoByteStringTag | kSlicedStringTag: {
9008         SlicedString* slice = SlicedString::cast(source);
9009         unsigned offset = slice->offset();
9010         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
9011         return;
9012       }
9013     }
9014   }
9015 }
9016
9017
9018
9019 template <typename SourceChar>
9020 static void CalculateLineEndsImpl(Isolate* isolate,
9021                                   List<int>* line_ends,
9022                                   Vector<const SourceChar> src,
9023                                   bool include_ending_line) {
9024   const int src_len = src.length();
9025   UnicodeCache* cache = isolate->unicode_cache();
9026   for (int i = 0; i < src_len - 1; i++) {
9027     SourceChar current = src[i];
9028     SourceChar next = src[i + 1];
9029     if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i);
9030   }
9031
9032   if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
9033     line_ends->Add(src_len - 1);
9034   } else if (include_ending_line) {
9035     // Even if the last line misses a line end, it is counted.
9036     line_ends->Add(src_len);
9037   }
9038 }
9039
9040
9041 Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
9042                                              bool include_ending_line) {
9043   src = Flatten(src);
9044   // Rough estimate of line count based on a roughly estimated average
9045   // length of (unpacked) code.
9046   int line_count_estimate = src->length() >> 4;
9047   List<int> line_ends(line_count_estimate);
9048   Isolate* isolate = src->GetIsolate();
9049   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
9050     // Dispatch on type of strings.
9051     String::FlatContent content = src->GetFlatContent();
9052     DCHECK(content.IsFlat());
9053     if (content.IsOneByte()) {
9054       CalculateLineEndsImpl(isolate,
9055                             &line_ends,
9056                             content.ToOneByteVector(),
9057                             include_ending_line);
9058     } else {
9059       CalculateLineEndsImpl(isolate,
9060                             &line_ends,
9061                             content.ToUC16Vector(),
9062                             include_ending_line);
9063     }
9064   }
9065   int line_count = line_ends.length();
9066   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
9067   for (int i = 0; i < line_count; i++) {
9068     array->set(i, Smi::FromInt(line_ends[i]));
9069   }
9070   return array;
9071 }
9072
9073
9074 // Compares the contents of two strings by reading and comparing
9075 // int-sized blocks of characters.
9076 template <typename Char>
9077 static inline bool CompareRawStringContents(const Char* const a,
9078                                             const Char* const b,
9079                                             int length) {
9080   return CompareChars(a, b, length) == 0;
9081 }
9082
9083
9084 template<typename Chars1, typename Chars2>
9085 class RawStringComparator : public AllStatic {
9086  public:
9087   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
9088     DCHECK(sizeof(Chars1) != sizeof(Chars2));
9089     for (int i = 0; i < len; i++) {
9090       if (a[i] != b[i]) {
9091         return false;
9092       }
9093     }
9094     return true;
9095   }
9096 };
9097
9098
9099 template<>
9100 class RawStringComparator<uint16_t, uint16_t> {
9101  public:
9102   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
9103     return CompareRawStringContents(a, b, len);
9104   }
9105 };
9106
9107
9108 template<>
9109 class RawStringComparator<uint8_t, uint8_t> {
9110  public:
9111   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
9112     return CompareRawStringContents(a, b, len);
9113   }
9114 };
9115
9116
9117 class StringComparator {
9118   class State {
9119    public:
9120     State() : is_one_byte_(true), length_(0), buffer8_(NULL) {}
9121
9122     void Init(String* string) {
9123       ConsString* cons_string = String::VisitFlat(this, string);
9124       iter_.Reset(cons_string);
9125       if (cons_string != NULL) {
9126         int offset;
9127         string = iter_.Next(&offset);
9128         String::VisitFlat(this, string, offset);
9129       }
9130     }
9131
9132     inline void VisitOneByteString(const uint8_t* chars, int length) {
9133       is_one_byte_ = true;
9134       buffer8_ = chars;
9135       length_ = length;
9136     }
9137
9138     inline void VisitTwoByteString(const uint16_t* chars, int length) {
9139       is_one_byte_ = false;
9140       buffer16_ = chars;
9141       length_ = length;
9142     }
9143
9144     void Advance(int consumed) {
9145       DCHECK(consumed <= length_);
9146       // Still in buffer.
9147       if (length_ != consumed) {
9148         if (is_one_byte_) {
9149           buffer8_ += consumed;
9150         } else {
9151           buffer16_ += consumed;
9152         }
9153         length_ -= consumed;
9154         return;
9155       }
9156       // Advance state.
9157       int offset;
9158       String* next = iter_.Next(&offset);
9159       DCHECK_EQ(0, offset);
9160       DCHECK(next != NULL);
9161       String::VisitFlat(this, next);
9162     }
9163
9164     ConsStringIterator iter_;
9165     bool is_one_byte_;
9166     int length_;
9167     union {
9168       const uint8_t* buffer8_;
9169       const uint16_t* buffer16_;
9170     };
9171
9172    private:
9173     DISALLOW_COPY_AND_ASSIGN(State);
9174   };
9175
9176  public:
9177   inline StringComparator() {}
9178
9179   template<typename Chars1, typename Chars2>
9180   static inline bool Equals(State* state_1, State* state_2, int to_check) {
9181     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
9182     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
9183     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
9184   }
9185
9186   bool Equals(String* string_1, String* string_2) {
9187     int length = string_1->length();
9188     state_1_.Init(string_1);
9189     state_2_.Init(string_2);
9190     while (true) {
9191       int to_check = Min(state_1_.length_, state_2_.length_);
9192       DCHECK(to_check > 0 && to_check <= length);
9193       bool is_equal;
9194       if (state_1_.is_one_byte_) {
9195         if (state_2_.is_one_byte_) {
9196           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
9197         } else {
9198           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
9199         }
9200       } else {
9201         if (state_2_.is_one_byte_) {
9202           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
9203         } else {
9204           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
9205         }
9206       }
9207       // Looping done.
9208       if (!is_equal) return false;
9209       length -= to_check;
9210       // Exit condition. Strings are equal.
9211       if (length == 0) return true;
9212       state_1_.Advance(to_check);
9213       state_2_.Advance(to_check);
9214     }
9215   }
9216
9217  private:
9218   State state_1_;
9219   State state_2_;
9220
9221   DISALLOW_COPY_AND_ASSIGN(StringComparator);
9222 };
9223
9224
9225 bool String::SlowEquals(String* other) {
9226   DisallowHeapAllocation no_gc;
9227   // Fast check: negative check with lengths.
9228   int len = length();
9229   if (len != other->length()) return false;
9230   if (len == 0) return true;
9231
9232   // Fast check: if hash code is computed for both strings
9233   // a fast negative check can be performed.
9234   if (HasHashCode() && other->HasHashCode()) {
9235 #ifdef ENABLE_SLOW_DCHECKS
9236     if (FLAG_enable_slow_asserts) {
9237       if (Hash() != other->Hash()) {
9238         bool found_difference = false;
9239         for (int i = 0; i < len; i++) {
9240           if (Get(i) != other->Get(i)) {
9241             found_difference = true;
9242             break;
9243           }
9244         }
9245         DCHECK(found_difference);
9246       }
9247     }
9248 #endif
9249     if (Hash() != other->Hash()) return false;
9250   }
9251
9252   // We know the strings are both non-empty. Compare the first chars
9253   // before we try to flatten the strings.
9254   if (this->Get(0) != other->Get(0)) return false;
9255
9256   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
9257     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
9258     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
9259     return CompareRawStringContents(str1, str2, len);
9260   }
9261
9262   StringComparator comparator;
9263   return comparator.Equals(this, other);
9264 }
9265
9266
9267 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
9268   // Fast check: negative check with lengths.
9269   int one_length = one->length();
9270   if (one_length != two->length()) return false;
9271   if (one_length == 0) return true;
9272
9273   // Fast check: if hash code is computed for both strings
9274   // a fast negative check can be performed.
9275   if (one->HasHashCode() && two->HasHashCode()) {
9276 #ifdef ENABLE_SLOW_DCHECKS
9277     if (FLAG_enable_slow_asserts) {
9278       if (one->Hash() != two->Hash()) {
9279         bool found_difference = false;
9280         for (int i = 0; i < one_length; i++) {
9281           if (one->Get(i) != two->Get(i)) {
9282             found_difference = true;
9283             break;
9284           }
9285         }
9286         DCHECK(found_difference);
9287       }
9288     }
9289 #endif
9290     if (one->Hash() != two->Hash()) return false;
9291   }
9292
9293   // We know the strings are both non-empty. Compare the first chars
9294   // before we try to flatten the strings.
9295   if (one->Get(0) != two->Get(0)) return false;
9296
9297   one = String::Flatten(one);
9298   two = String::Flatten(two);
9299
9300   DisallowHeapAllocation no_gc;
9301   String::FlatContent flat1 = one->GetFlatContent();
9302   String::FlatContent flat2 = two->GetFlatContent();
9303
9304   if (flat1.IsOneByte() && flat2.IsOneByte()) {
9305       return CompareRawStringContents(flat1.ToOneByteVector().start(),
9306                                       flat2.ToOneByteVector().start(),
9307                                       one_length);
9308   } else {
9309     for (int i = 0; i < one_length; i++) {
9310       if (flat1.Get(i) != flat2.Get(i)) return false;
9311     }
9312     return true;
9313   }
9314 }
9315
9316
9317 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
9318   int slen = length();
9319   // Can't check exact length equality, but we can check bounds.
9320   int str_len = str.length();
9321   if (!allow_prefix_match &&
9322       (str_len < slen ||
9323           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
9324     return false;
9325   }
9326   int i;
9327   size_t remaining_in_str = static_cast<size_t>(str_len);
9328   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
9329   for (i = 0; i < slen && remaining_in_str > 0; i++) {
9330     size_t cursor = 0;
9331     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
9332     DCHECK(cursor > 0 && cursor <= remaining_in_str);
9333     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
9334       if (i > slen - 1) return false;
9335       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
9336       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
9337     } else {
9338       if (Get(i) != r) return false;
9339     }
9340     utf8_data += cursor;
9341     remaining_in_str -= cursor;
9342   }
9343   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
9344 }
9345
9346
9347 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
9348   int slen = length();
9349   if (str.length() != slen) return false;
9350   DisallowHeapAllocation no_gc;
9351   FlatContent content = GetFlatContent();
9352   if (content.IsOneByte()) {
9353     return CompareChars(content.ToOneByteVector().start(),
9354                         str.start(), slen) == 0;
9355   }
9356   for (int i = 0; i < slen; i++) {
9357     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
9358   }
9359   return true;
9360 }
9361
9362
9363 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
9364   int slen = length();
9365   if (str.length() != slen) return false;
9366   DisallowHeapAllocation no_gc;
9367   FlatContent content = GetFlatContent();
9368   if (content.IsTwoByte()) {
9369     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
9370   }
9371   for (int i = 0; i < slen; i++) {
9372     if (Get(i) != str[i]) return false;
9373   }
9374   return true;
9375 }
9376
9377
9378 uint32_t String::ComputeAndSetHash() {
9379   // Should only be called if hash code has not yet been computed.
9380   DCHECK(!HasHashCode());
9381
9382   // Store the hash code in the object.
9383   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
9384   set_hash_field(field);
9385
9386   // Check the hash code is there.
9387   DCHECK(HasHashCode());
9388   uint32_t result = field >> kHashShift;
9389   DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
9390   return result;
9391 }
9392
9393
9394 bool String::ComputeArrayIndex(uint32_t* index) {
9395   int length = this->length();
9396   if (length == 0 || length > kMaxArrayIndexSize) return false;
9397   StringCharacterStream stream(this);
9398   return StringToArrayIndex(&stream, index);
9399 }
9400
9401
9402 bool String::SlowAsArrayIndex(uint32_t* index) {
9403   if (length() <= kMaxCachedArrayIndexLength) {
9404     Hash();  // force computation of hash code
9405     uint32_t field = hash_field();
9406     if ((field & kIsNotArrayIndexMask) != 0) return false;
9407     // Isolate the array index form the full hash field.
9408     *index = ArrayIndexValueBits::decode(field);
9409     return true;
9410   } else {
9411     return ComputeArrayIndex(index);
9412   }
9413 }
9414
9415
9416 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
9417   int new_size, old_size;
9418   int old_length = string->length();
9419   if (old_length <= new_length) return string;
9420
9421   if (string->IsSeqOneByteString()) {
9422     old_size = SeqOneByteString::SizeFor(old_length);
9423     new_size = SeqOneByteString::SizeFor(new_length);
9424   } else {
9425     DCHECK(string->IsSeqTwoByteString());
9426     old_size = SeqTwoByteString::SizeFor(old_length);
9427     new_size = SeqTwoByteString::SizeFor(new_length);
9428   }
9429
9430   int delta = old_size - new_size;
9431
9432   Address start_of_string = string->address();
9433   DCHECK_OBJECT_ALIGNED(start_of_string);
9434   DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
9435
9436   Heap* heap = string->GetHeap();
9437   NewSpace* newspace = heap->new_space();
9438   if (newspace->Contains(start_of_string) &&
9439       newspace->top() == start_of_string + old_size) {
9440     // Last allocated object in new space.  Simply lower allocation top.
9441     newspace->set_top(start_of_string + new_size);
9442   } else {
9443     // Sizes are pointer size aligned, so that we can use filler objects
9444     // that are a multiple of pointer size.
9445     heap->CreateFillerObjectAt(start_of_string + new_size, delta);
9446   }
9447   heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR);
9448
9449   // We are storing the new length using release store after creating a filler
9450   // for the left-over space to avoid races with the sweeper thread.
9451   string->synchronized_set_length(new_length);
9452
9453   if (new_length == 0) return heap->isolate()->factory()->empty_string();
9454   return string;
9455 }
9456
9457
9458 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
9459   // For array indexes mix the length into the hash as an array index could
9460   // be zero.
9461   DCHECK(length > 0);
9462   DCHECK(length <= String::kMaxArrayIndexSize);
9463   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
9464          (1 << String::kArrayIndexValueBits));
9465
9466   value <<= String::ArrayIndexValueBits::kShift;
9467   value |= length << String::ArrayIndexLengthBits::kShift;
9468
9469   DCHECK((value & String::kIsNotArrayIndexMask) == 0);
9470   DCHECK((length > String::kMaxCachedArrayIndexLength) ||
9471          (value & String::kContainsCachedArrayIndexMask) == 0);
9472   return value;
9473 }
9474
9475
9476 uint32_t StringHasher::GetHashField() {
9477   if (length_ <= String::kMaxHashCalcLength) {
9478     if (is_array_index_) {
9479       return MakeArrayIndexHash(array_index_, length_);
9480     }
9481     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
9482            String::kIsNotArrayIndexMask;
9483   } else {
9484     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
9485   }
9486 }
9487
9488
9489 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
9490                                        uint32_t seed,
9491                                        int* utf16_length_out) {
9492   int vector_length = chars.length();
9493   // Handle some edge cases
9494   if (vector_length <= 1) {
9495     DCHECK(vector_length == 0 ||
9496            static_cast<uint8_t>(chars.start()[0]) <=
9497                unibrow::Utf8::kMaxOneByteChar);
9498     *utf16_length_out = vector_length;
9499     return HashSequentialString(chars.start(), vector_length, seed);
9500   }
9501   // Start with a fake length which won't affect computation.
9502   // It will be updated later.
9503   StringHasher hasher(String::kMaxArrayIndexSize, seed);
9504   size_t remaining = static_cast<size_t>(vector_length);
9505   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
9506   int utf16_length = 0;
9507   bool is_index = true;
9508   DCHECK(hasher.is_array_index_);
9509   while (remaining > 0) {
9510     size_t consumed = 0;
9511     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
9512     DCHECK(consumed > 0 && consumed <= remaining);
9513     stream += consumed;
9514     remaining -= consumed;
9515     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
9516     utf16_length += is_two_characters ? 2 : 1;
9517     // No need to keep hashing. But we do need to calculate utf16_length.
9518     if (utf16_length > String::kMaxHashCalcLength) continue;
9519     if (is_two_characters) {
9520       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
9521       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
9522       hasher.AddCharacter(c1);
9523       hasher.AddCharacter(c2);
9524       if (is_index) is_index = hasher.UpdateIndex(c1);
9525       if (is_index) is_index = hasher.UpdateIndex(c2);
9526     } else {
9527       hasher.AddCharacter(c);
9528       if (is_index) is_index = hasher.UpdateIndex(c);
9529     }
9530   }
9531   *utf16_length_out = static_cast<int>(utf16_length);
9532   // Must set length here so that hash computation is correct.
9533   hasher.length_ = utf16_length;
9534   return hasher.GetHashField();
9535 }
9536
9537
9538 void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
9539   // Run small ConsStrings through ConsStringIterator.
9540   if (cons_string->length() < 64) {
9541     ConsStringIterator iter(cons_string);
9542     int offset;
9543     String* string;
9544     while (nullptr != (string = iter.Next(&offset))) {
9545       DCHECK_EQ(0, offset);
9546       String::VisitFlat(this, string, 0);
9547     }
9548     return;
9549   }
9550   // Slow case.
9551   const int max_length = String::kMaxHashCalcLength;
9552   int length = std::min(cons_string->length(), max_length);
9553   if (cons_string->HasOnlyOneByteChars()) {
9554     uint8_t* buffer = new uint8_t[length];
9555     String::WriteToFlat(cons_string, buffer, 0, length);
9556     AddCharacters(buffer, length);
9557     delete[] buffer;
9558   } else {
9559     uint16_t* buffer = new uint16_t[length];
9560     String::WriteToFlat(cons_string, buffer, 0, length);
9561     AddCharacters(buffer, length);
9562     delete[] buffer;
9563   }
9564 }
9565
9566
9567 void String::PrintOn(FILE* file) {
9568   int length = this->length();
9569   for (int i = 0; i < length; i++) {
9570     PrintF(file, "%c", Get(i));
9571   }
9572 }
9573
9574
9575 inline static uint32_t ObjectAddressForHashing(Object* object) {
9576   uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
9577   return value & MemoryChunk::kAlignmentMask;
9578 }
9579
9580
9581 int Map::Hash() {
9582   // For performance reasons we only hash the 3 most variable fields of a map:
9583   // constructor, prototype and bit_field2. For predictability reasons we
9584   // use objects' offsets in respective pages for hashing instead of raw
9585   // addresses.
9586
9587   // Shift away the tag.
9588   int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
9589
9590   // XOR-ing the prototype and constructor directly yields too many zero bits
9591   // when the two pointers are close (which is fairly common).
9592   // To avoid this we shift the prototype bits relatively to the constructor.
9593   hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
9594
9595   return hash ^ (hash >> 16) ^ bit_field2();
9596 }
9597
9598
9599 static bool CheckEquivalent(Map* first, Map* second) {
9600   return first->GetConstructor() == second->GetConstructor() &&
9601          first->prototype() == second->prototype() &&
9602          first->instance_type() == second->instance_type() &&
9603          first->bit_field() == second->bit_field() &&
9604          first->is_extensible() == second->is_extensible() &&
9605          first->has_instance_call_handler() ==
9606              second->has_instance_call_handler();
9607 }
9608
9609
9610 bool Map::EquivalentToForTransition(Map* other) {
9611   return CheckEquivalent(this, other);
9612 }
9613
9614
9615 bool Map::EquivalentToForNormalization(Map* other,
9616                                        PropertyNormalizationMode mode) {
9617   int properties = mode == CLEAR_INOBJECT_PROPERTIES
9618       ? 0 : other->inobject_properties();
9619   return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
9620          inobject_properties() == properties;
9621 }
9622
9623
9624 void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) {
9625   // Unfortunately the serializer relies on pointers within an object being
9626   // visited in-order, so we have to iterate both the code and heap pointers in
9627   // the small section before doing so in the extended section.
9628   for (int s = 0; s <= final_section(); ++s) {
9629     LayoutSection section = static_cast<LayoutSection>(s);
9630     ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR,
9631                                           section);
9632     while (!code_iter.is_finished()) {
9633       v->VisitCodeEntry(reinterpret_cast<Address>(
9634           RawFieldOfElementAt(code_iter.next_index())));
9635     }
9636
9637     ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR,
9638                                           section);
9639     while (!heap_iter.is_finished()) {
9640       v->VisitPointer(RawFieldOfElementAt(heap_iter.next_index()));
9641     }
9642   }
9643 }
9644
9645
9646 void ConstantPoolArray::ClearPtrEntries(Isolate* isolate) {
9647   Type type[] = { CODE_PTR, HEAP_PTR };
9648   Address default_value[] = {
9649         isolate->builtins()->builtin(Builtins::kIllegal)->entry(),
9650         reinterpret_cast<Address>(isolate->heap()->undefined_value()) };
9651
9652   for (int i = 0; i < 2; ++i) {
9653     for (int s = 0; s <= final_section(); ++s) {
9654       LayoutSection section = static_cast<LayoutSection>(s);
9655       if (number_of_entries(type[i], section) > 0) {
9656         int offset = OffsetOfElementAt(first_index(type[i], section));
9657         MemsetPointer(
9658           reinterpret_cast<Address*>(HeapObject::RawField(this, offset)),
9659           default_value[i],
9660           number_of_entries(type[i], section));
9661       }
9662     }
9663   }
9664 }
9665
9666
9667 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
9668   // Iterate over all fields in the body but take care in dealing with
9669   // the code entry.
9670   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
9671   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9672   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9673 }
9674
9675
9676 void JSFunction::MarkForOptimization() {
9677   Isolate* isolate = GetIsolate();
9678   DCHECK(!IsOptimized());
9679   DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9680   set_code_no_write_barrier(
9681       isolate->builtins()->builtin(Builtins::kCompileOptimized));
9682   // No write barrier required, since the builtin is part of the root set.
9683 }
9684
9685
9686 void JSFunction::AttemptConcurrentOptimization() {
9687   Isolate* isolate = GetIsolate();
9688   if (!isolate->concurrent_recompilation_enabled() ||
9689       isolate->bootstrapper()->IsActive()) {
9690     MarkForOptimization();
9691     return;
9692   }
9693   if (isolate->concurrent_osr_enabled() &&
9694       isolate->optimizing_compiler_thread()->IsQueuedForOSR(this)) {
9695     // Do not attempt regular recompilation if we already queued this for OSR.
9696     // TODO(yangguo): This is necessary so that we don't install optimized
9697     // code on a function that is already optimized, since OSR and regular
9698     // recompilation race.  This goes away as soon as OSR becomes one-shot.
9699     return;
9700   }
9701   DCHECK(!IsInOptimizationQueue());
9702   DCHECK(!IsOptimized());
9703   DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9704   DCHECK(isolate->concurrent_recompilation_enabled());
9705   if (FLAG_trace_concurrent_recompilation) {
9706     PrintF("  ** Marking ");
9707     ShortPrint();
9708     PrintF(" for concurrent recompilation.\n");
9709   }
9710   set_code_no_write_barrier(
9711       GetIsolate()->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9712   // No write barrier required, since the builtin is part of the root set.
9713 }
9714
9715
9716 Handle<JSFunction> JSFunction::CloneClosure(Handle<JSFunction> function) {
9717   Isolate* isolate = function->GetIsolate();
9718   Handle<Map> map(function->map());
9719   Handle<SharedFunctionInfo> shared(function->shared());
9720   Handle<Context> context(function->context());
9721   Handle<JSFunction> clone =
9722       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
9723
9724   if (shared->bound()) {
9725     clone->set_function_bindings(function->function_bindings());
9726   }
9727
9728   // In typical case, __proto__ of ``function`` is the default Function
9729   // prototype, which means that SetPrototype below is a no-op.
9730   // In rare cases when that is not true, we mutate the clone's __proto__.
9731   Handle<Object> original_prototype(map->prototype(), isolate);
9732   if (*original_prototype != clone->map()->prototype()) {
9733     JSObject::SetPrototype(clone, original_prototype, false).Assert();
9734   }
9735
9736   return clone;
9737 }
9738
9739
9740 void SharedFunctionInfo::AddToOptimizedCodeMap(
9741     Handle<SharedFunctionInfo> shared,
9742     Handle<Context> native_context,
9743     Handle<Code> code,
9744     Handle<FixedArray> literals,
9745     BailoutId osr_ast_id) {
9746   Isolate* isolate = shared->GetIsolate();
9747   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9748   DCHECK(native_context->IsNativeContext());
9749   STATIC_ASSERT(kEntryLength == 4);
9750   Handle<FixedArray> new_code_map;
9751   Handle<Object> value(shared->optimized_code_map(), isolate);
9752   int old_length;
9753   if (value->IsSmi()) {
9754     // No optimized code map.
9755     DCHECK_EQ(0, Smi::cast(*value)->value());
9756     // Create 3 entries per context {context, code, literals}.
9757     new_code_map = isolate->factory()->NewFixedArray(kInitialLength);
9758     old_length = kEntriesStart;
9759   } else {
9760     // Copy old map and append one new entry.
9761     Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value);
9762     DCHECK_EQ(-1, shared->SearchOptimizedCodeMap(*native_context, osr_ast_id));
9763     old_length = old_code_map->length();
9764     new_code_map = FixedArray::CopySize(
9765         old_code_map, old_length + kEntryLength);
9766     // Zap the old map for the sake of the heap verifier.
9767     if (Heap::ShouldZapGarbage()) {
9768       Object** data = old_code_map->data_start();
9769       MemsetPointer(data, isolate->heap()->the_hole_value(), old_length);
9770     }
9771   }
9772   new_code_map->set(old_length + kContextOffset, *native_context);
9773   new_code_map->set(old_length + kCachedCodeOffset, *code);
9774   new_code_map->set(old_length + kLiteralsOffset, *literals);
9775   new_code_map->set(old_length + kOsrAstIdOffset,
9776                     Smi::FromInt(osr_ast_id.ToInt()));
9777
9778 #ifdef DEBUG
9779   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9780     DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext());
9781     DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9782     DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9783            Code::OPTIMIZED_FUNCTION);
9784     DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9785     DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9786   }
9787 #endif
9788   shared->set_optimized_code_map(*new_code_map);
9789 }
9790
9791
9792 FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) {
9793   DCHECK(index > kEntriesStart);
9794   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9795   if (!bound()) {
9796     FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
9797     DCHECK_NOT_NULL(cached_literals);
9798     return cached_literals;
9799   }
9800   return NULL;
9801 }
9802
9803
9804 Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) {
9805   DCHECK(index > kEntriesStart);
9806   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9807   Code* code = Code::cast(code_map->get(index));
9808   DCHECK_NOT_NULL(code);
9809   return code;
9810 }
9811
9812
9813 void SharedFunctionInfo::ClearOptimizedCodeMap() {
9814   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9815
9816   // If the next map link slot is already used then the function was
9817   // enqueued with code flushing and we remove it now.
9818   if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9819     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
9820     flusher->EvictOptimizedCodeMap(this);
9821   }
9822
9823   DCHECK(code_map->get(kNextMapIndex)->IsUndefined());
9824   set_optimized_code_map(Smi::FromInt(0));
9825 }
9826
9827
9828 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
9829                                                    const char* reason) {
9830   DisallowHeapAllocation no_gc;
9831   if (optimized_code_map()->IsSmi()) return;
9832
9833   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9834   int dst = kEntriesStart;
9835   int length = code_map->length();
9836   for (int src = kEntriesStart; src < length; src += kEntryLength) {
9837     DCHECK(code_map->get(src)->IsNativeContext());
9838     if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9839       // Evict the src entry by not copying it to the dst entry.
9840       if (FLAG_trace_opt) {
9841         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9842         ShortPrint();
9843         BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9844         if (osr.IsNone()) {
9845           PrintF("]\n");
9846         } else {
9847           PrintF(" (osr ast id %d)]\n", osr.ToInt());
9848         }
9849       }
9850     } else {
9851       // Keep the src entry by copying it to the dst entry.
9852       if (dst != src) {
9853         code_map->set(dst + kContextOffset,
9854                       code_map->get(src + kContextOffset));
9855         code_map->set(dst + kCachedCodeOffset,
9856                       code_map->get(src + kCachedCodeOffset));
9857         code_map->set(dst + kLiteralsOffset,
9858                       code_map->get(src + kLiteralsOffset));
9859         code_map->set(dst + kOsrAstIdOffset,
9860                       code_map->get(src + kOsrAstIdOffset));
9861       }
9862       dst += kEntryLength;
9863     }
9864   }
9865   if (dst != length) {
9866     // Always trim even when array is cleared because of heap verifier.
9867     GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>(code_map, length - dst);
9868     if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap();
9869   }
9870 }
9871
9872
9873 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
9874   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9875   DCHECK(shrink_by % kEntryLength == 0);
9876   DCHECK(shrink_by <= code_map->length() - kEntriesStart);
9877   // Always trim even when array is cleared because of heap verifier.
9878   GetHeap()->RightTrimFixedArray<Heap::FROM_GC>(code_map, shrink_by);
9879   if (code_map->length() == kEntriesStart) {
9880     ClearOptimizedCodeMap();
9881   }
9882 }
9883
9884
9885 static void GetMinInobjectSlack(Map* map, void* data) {
9886   int slack = map->unused_property_fields();
9887   if (*reinterpret_cast<int*>(data) > slack) {
9888     *reinterpret_cast<int*>(data) = slack;
9889   }
9890 }
9891
9892
9893 static void ShrinkInstanceSize(Map* map, void* data) {
9894   int slack = *reinterpret_cast<int*>(data);
9895   map->set_inobject_properties(map->inobject_properties() - slack);
9896   map->set_unused_property_fields(map->unused_property_fields() - slack);
9897   map->set_instance_size(map->instance_size() - slack * kPointerSize);
9898
9899   // Visitor id might depend on the instance size, recalculate it.
9900   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
9901 }
9902
9903
9904 void JSFunction::CompleteInobjectSlackTracking() {
9905   DCHECK(has_initial_map());
9906   Map* map = initial_map();
9907
9908   DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1);
9909   map->set_counter(Map::kRetainingCounterStart);
9910
9911   int slack = map->unused_property_fields();
9912   TransitionArray::TraverseTransitionTree(map, &GetMinInobjectSlack, &slack);
9913   if (slack != 0) {
9914     // Resize the initial map and all maps in its transition tree.
9915     TransitionArray::TraverseTransitionTree(map, &ShrinkInstanceSize, &slack);
9916   }
9917 }
9918
9919
9920 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
9921   DisallowHeapAllocation no_gc;
9922   if (!object->HasFastProperties()) return false;
9923   Map* map = object->map();
9924   if (map->is_prototype_map()) return false;
9925   DescriptorArray* descriptors = map->instance_descriptors();
9926   for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
9927     PropertyDetails details = descriptors->GetDetails(i);
9928     if (details.location() == kDescriptor) continue;
9929     if (details.representation().IsHeapObject() ||
9930         details.representation().IsTagged()) {
9931       FieldIndex index = FieldIndex::ForDescriptor(map, i);
9932       if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
9933     }
9934   }
9935   return false;
9936 }
9937
9938
9939 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
9940                                    PrototypeOptimizationMode mode) {
9941   if (object->IsGlobalObject()) return;
9942   if (object->IsJSGlobalProxy()) return;
9943   if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
9944     // First normalize to ensure all JSFunctions are DATA_CONSTANT.
9945     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
9946                                   "NormalizeAsPrototype");
9947   }
9948   bool has_just_copied_map = false;
9949   if (!object->HasFastProperties()) {
9950     JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
9951     has_just_copied_map = true;
9952   }
9953   if (mode == FAST_PROTOTYPE && object->HasFastProperties() &&
9954       !object->map()->is_prototype_map()) {
9955     if (!has_just_copied_map) {
9956       Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
9957       JSObject::MigrateToMap(object, new_map);
9958     }
9959     Object* maybe_constructor = object->map()->GetConstructor();
9960     if (maybe_constructor->IsJSFunction()) {
9961       JSFunction* constructor = JSFunction::cast(maybe_constructor);
9962       // Replace the pointer to the exact constructor with the Object function
9963       // from the same context if undetectable from JS. This is to avoid keeping
9964       // memory alive unnecessarily.
9965       if (!constructor->shared()->IsApiFunction() &&
9966           object->class_name() ==
9967               object->GetIsolate()->heap()->Object_string()) {
9968         Context* context = constructor->context()->native_context();
9969         JSFunction* object_function = context->object_function();
9970         object->map()->SetConstructor(object_function);
9971       }
9972     }
9973     object->map()->set_is_prototype_map(true);
9974   }
9975 }
9976
9977
9978 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9979   if (!object->map()->is_prototype_map()) return;
9980   OptimizeAsPrototype(object, FAST_PROTOTYPE);
9981 }
9982
9983
9984 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype,
9985                                      Handle<HeapObject> user) {
9986   DCHECK(FLAG_track_prototype_users);
9987   Isolate* isolate = prototype->GetIsolate();
9988   Handle<Name> symbol = isolate->factory()->prototype_users_symbol();
9989
9990   // Get prototype users array, create it if it doesn't exist yet.
9991   Handle<Object> maybe_array =
9992       JSObject::GetProperty(prototype, symbol).ToHandleChecked();
9993
9994   Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_array, user);
9995   if (!maybe_array.is_identical_to(new_array)) {
9996     JSObject::SetOwnPropertyIgnoreAttributes(prototype, symbol, new_array,
9997                                              DONT_ENUM).Assert();
9998   }
9999 }
10000
10001
10002 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
10003                                        Handle<HeapObject> user) {
10004   Isolate* isolate = prototype->GetIsolate();
10005   Handle<Name> symbol = isolate->factory()->prototype_users_symbol();
10006
10007   Handle<Object> maybe_array =
10008       JSObject::GetProperty(prototype, symbol).ToHandleChecked();
10009   if (!maybe_array->IsWeakFixedArray()) return;
10010   Handle<WeakFixedArray>::cast(maybe_array)->Remove(user);
10011 }
10012
10013
10014 void Map::SetPrototype(Handle<Object> prototype,
10015                        PrototypeOptimizationMode proto_mode) {
10016   if (this->prototype()->IsJSObject() && FLAG_track_prototype_users) {
10017     Handle<JSObject> old_prototype(JSObject::cast(this->prototype()));
10018     JSObject::UnregisterPrototypeUser(old_prototype, handle(this));
10019   }
10020   if (prototype->IsJSObject()) {
10021     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
10022     if (ShouldRegisterAsPrototypeUser(prototype_jsobj)) {
10023       JSObject::RegisterPrototypeUser(prototype_jsobj, handle(this));
10024     }
10025     JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
10026   }
10027   WriteBarrierMode wb_mode =
10028       prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
10029   set_prototype(*prototype, wb_mode);
10030 }
10031
10032
10033 bool Map::ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype) {
10034   if (!FLAG_track_prototype_users) return false;
10035   if (this->is_prototype_map()) return true;
10036   if (this->is_dictionary_map()) return false;
10037   Object* back = GetBackPointer();
10038   if (!back->IsMap()) return true;
10039   if (Map::cast(back)->prototype() != *prototype) return true;
10040   return false;
10041 }
10042
10043
10044 bool Map::CanUseOptimizationsBasedOnPrototypeRegistry() {
10045   if (!FLAG_track_prototype_users) return false;
10046   if (this->is_prototype_map()) return true;
10047   if (GetBackPointer()->IsMap()) return true;
10048   return false;
10049 }
10050
10051
10052 Handle<Object> CacheInitialJSArrayMaps(
10053     Handle<Context> native_context, Handle<Map> initial_map) {
10054   // Replace all of the cached initial array maps in the native context with
10055   // the appropriate transitioned elements kind maps.
10056   Factory* factory = native_context->GetIsolate()->factory();
10057   Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
10058       kElementsKindCount, TENURED);
10059
10060   Handle<Map> current_map = initial_map;
10061   ElementsKind kind = current_map->elements_kind();
10062   DCHECK(kind == GetInitialFastElementsKind());
10063   maps->set(kind, *current_map);
10064   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
10065        i < kFastElementsKindCount; ++i) {
10066     Handle<Map> new_map;
10067     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
10068     Map* maybe_elements_transition = current_map->ElementsTransitionMap();
10069     if (maybe_elements_transition != NULL) {
10070       new_map = handle(maybe_elements_transition);
10071       DCHECK(new_map->elements_kind() == next_kind);
10072     } else {
10073       new_map = Map::CopyAsElementsKind(
10074           current_map, next_kind, INSERT_TRANSITION);
10075     }
10076     maps->set(next_kind, *new_map);
10077     current_map = new_map;
10078   }
10079   native_context->set_js_array_maps(*maps);
10080   return initial_map;
10081 }
10082
10083
10084 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
10085                                       Handle<Object> value) {
10086   Isolate* isolate = function->GetIsolate();
10087
10088   DCHECK(value->IsJSReceiver());
10089
10090   // Now some logic for the maps of the objects that are created by using this
10091   // function as a constructor.
10092   if (function->has_initial_map()) {
10093     // If the function has allocated the initial map replace it with a
10094     // copy containing the new prototype.  Also complete any in-object
10095     // slack tracking that is in progress at this point because it is
10096     // still tracking the old copy.
10097     if (function->IsInobjectSlackTrackingInProgress()) {
10098       function->CompleteInobjectSlackTracking();
10099     }
10100
10101     Handle<Map> initial_map(function->initial_map(), isolate);
10102
10103     if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
10104         initial_map->instance_type() == JS_OBJECT_TYPE) {
10105       // Put the value in the initial map field until an initial map is needed.
10106       // At that point, a new initial map is created and the prototype is put
10107       // into the initial map where it belongs.
10108       function->set_prototype_or_initial_map(*value);
10109     } else {
10110       Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype");
10111       JSFunction::SetInitialMap(function, new_map, value);
10112
10113       // If the function is used as the global Array function, cache the
10114       // initial map (and transitioned versions) in the native context.
10115       Context* native_context = function->context()->native_context();
10116       Object* array_function =
10117           native_context->get(Context::ARRAY_FUNCTION_INDEX);
10118       if (array_function->IsJSFunction() &&
10119           *function == JSFunction::cast(array_function)) {
10120         CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
10121       }
10122     }
10123
10124     // Deoptimize all code that embeds the previous initial map.
10125     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
10126         isolate, DependentCode::kInitialMapChangedGroup);
10127   } else {
10128     // Put the value in the initial map field until an initial map is
10129     // needed.  At that point, a new initial map is created and the
10130     // prototype is put into the initial map where it belongs.
10131     function->set_prototype_or_initial_map(*value);
10132     if (value->IsJSObject()) {
10133       // Optimize as prototype to detach it from its transition tree.
10134       JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value),
10135                                     FAST_PROTOTYPE);
10136     }
10137   }
10138   isolate->heap()->ClearInstanceofCache();
10139 }
10140
10141
10142 void JSFunction::SetPrototype(Handle<JSFunction> function,
10143                               Handle<Object> value) {
10144   DCHECK(function->should_have_prototype());
10145   Handle<Object> construct_prototype = value;
10146
10147   // If the value is not a JSReceiver, store the value in the map's
10148   // constructor field so it can be accessed.  Also, set the prototype
10149   // used for constructing objects to the original object prototype.
10150   // See ECMA-262 13.2.2.
10151   if (!value->IsJSReceiver()) {
10152     // Copy the map so this does not affect unrelated functions.
10153     // Remove map transitions because they point to maps with a
10154     // different prototype.
10155     Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype");
10156
10157     JSObject::MigrateToMap(function, new_map);
10158     new_map->SetConstructor(*value);
10159     new_map->set_non_instance_prototype(true);
10160     Isolate* isolate = new_map->GetIsolate();
10161     construct_prototype = handle(
10162         isolate->context()->native_context()->initial_object_prototype(),
10163         isolate);
10164   } else {
10165     function->map()->set_non_instance_prototype(false);
10166   }
10167
10168   return SetInstancePrototype(function, construct_prototype);
10169 }
10170
10171
10172 bool JSFunction::RemovePrototype() {
10173   Context* native_context = context()->native_context();
10174   Map* no_prototype_map =
10175       is_strict(shared()->language_mode())
10176           ? native_context->strict_function_without_prototype_map()
10177           : native_context->sloppy_function_without_prototype_map();
10178
10179   if (map() == no_prototype_map) return true;
10180
10181 #ifdef DEBUG
10182   if (map() != (is_strict(shared()->language_mode())
10183                     ? native_context->strict_function_map()
10184                     : native_context->sloppy_function_map())) {
10185     return false;
10186   }
10187 #endif
10188
10189   set_map(no_prototype_map);
10190   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
10191   return true;
10192 }
10193
10194
10195 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
10196                                Handle<Object> prototype) {
10197   if (map->prototype() != *prototype) {
10198     map->SetPrototype(prototype, FAST_PROTOTYPE);
10199   }
10200   function->set_prototype_or_initial_map(*map);
10201   map->SetConstructor(*function);
10202 #if TRACE_MAPS
10203   if (FLAG_trace_maps) {
10204     PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
10205            reinterpret_cast<void*>(*map), function->shared()->unique_id(),
10206            function->shared()->DebugName()->ToCString().get());
10207   }
10208 #endif
10209 }
10210
10211
10212 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
10213   if (function->has_initial_map()) return;
10214   Isolate* isolate = function->GetIsolate();
10215
10216   // First create a new map with the size and number of in-object properties
10217   // suggested by the function.
10218   InstanceType instance_type;
10219   int instance_size;
10220   int in_object_properties;
10221   if (function->shared()->is_generator()) {
10222     instance_type = JS_GENERATOR_OBJECT_TYPE;
10223     instance_size = JSGeneratorObject::kSize;
10224     in_object_properties = 0;
10225   } else {
10226     instance_type = JS_OBJECT_TYPE;
10227     instance_size = function->shared()->CalculateInstanceSize();
10228     in_object_properties = function->shared()->CalculateInObjectProperties();
10229   }
10230   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
10231
10232   // Fetch or allocate prototype.
10233   Handle<Object> prototype;
10234   if (function->has_instance_prototype()) {
10235     prototype = handle(function->instance_prototype(), isolate);
10236   } else {
10237     prototype = isolate->factory()->NewFunctionPrototype(function);
10238   }
10239   map->set_inobject_properties(in_object_properties);
10240   map->set_unused_property_fields(in_object_properties);
10241   DCHECK(map->has_fast_object_elements());
10242
10243   // Finally link initial map and constructor function.
10244   JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
10245
10246   if (!function->shared()->is_generator()) {
10247     function->StartInobjectSlackTracking();
10248   }
10249 }
10250
10251
10252 void JSFunction::SetInstanceClassName(String* name) {
10253   shared()->set_instance_class_name(name);
10254 }
10255
10256
10257 void JSFunction::PrintName(FILE* out) {
10258   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
10259   PrintF(out, "%s", name.get());
10260 }
10261
10262
10263 // The filter is a pattern that matches function names in this way:
10264 //   "*"      all; the default
10265 //   "-"      all but the top-level function
10266 //   "-name"  all but the function "name"
10267 //   ""       only the top-level function
10268 //   "name"   only the function "name"
10269 //   "name*"  only functions starting with "name"
10270 //   "~"      none; the tilde is not an identifier
10271 bool JSFunction::PassesFilter(const char* raw_filter) {
10272   if (*raw_filter == '*') return true;
10273   String* name = shared()->DebugName();
10274   Vector<const char> filter = CStrVector(raw_filter);
10275   if (filter.length() == 0) return name->length() == 0;
10276   if (filter[0] == '-') {
10277     // Negative filter.
10278     if (filter.length() == 1) {
10279       return (name->length() != 0);
10280     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
10281       return false;
10282     }
10283     if (filter[filter.length() - 1] == '*' &&
10284         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
10285       return false;
10286     }
10287     return true;
10288
10289   } else if (name->IsUtf8EqualTo(filter)) {
10290     return true;
10291   }
10292   if (filter[filter.length() - 1] == '*' &&
10293       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
10294     return true;
10295   }
10296   return false;
10297 }
10298
10299
10300 Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
10301   Isolate* isolate = function->GetIsolate();
10302   Handle<Object> name =
10303       JSObject::GetDataProperty(function, isolate->factory()->name_string());
10304   if (name->IsString()) return Handle<String>::cast(name);
10305   return handle(function->shared()->DebugName(), isolate);
10306 }
10307
10308
10309 void Oddball::Initialize(Isolate* isolate,
10310                          Handle<Oddball> oddball,
10311                          const char* to_string,
10312                          Handle<Object> to_number,
10313                          byte kind) {
10314   Handle<String> internalized_to_string =
10315       isolate->factory()->InternalizeUtf8String(to_string);
10316   oddball->set_to_string(*internalized_to_string);
10317   oddball->set_to_number(*to_number);
10318   oddball->set_kind(kind);
10319 }
10320
10321
10322 void Script::InitLineEnds(Handle<Script> script) {
10323   if (!script->line_ends()->IsUndefined()) return;
10324
10325   Isolate* isolate = script->GetIsolate();
10326
10327   if (!script->source()->IsString()) {
10328     DCHECK(script->source()->IsUndefined());
10329     Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
10330     script->set_line_ends(*empty);
10331     DCHECK(script->line_ends()->IsFixedArray());
10332     return;
10333   }
10334
10335   Handle<String> src(String::cast(script->source()), isolate);
10336
10337   Handle<FixedArray> array = String::CalculateLineEnds(src, true);
10338
10339   if (*array != isolate->heap()->empty_fixed_array()) {
10340     array->set_map(isolate->heap()->fixed_cow_array_map());
10341   }
10342
10343   script->set_line_ends(*array);
10344   DCHECK(script->line_ends()->IsFixedArray());
10345 }
10346
10347
10348 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
10349   int line_number = GetLineNumber(script, code_pos);
10350   if (line_number == -1) return -1;
10351
10352   DisallowHeapAllocation no_allocation;
10353   FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
10354   line_number = line_number - script->line_offset()->value();
10355   if (line_number == 0) return code_pos + script->column_offset()->value();
10356   int prev_line_end_pos =
10357       Smi::cast(line_ends_array->get(line_number - 1))->value();
10358   return code_pos - (prev_line_end_pos + 1);
10359 }
10360
10361
10362 int Script::GetLineNumberWithArray(int position) {
10363   DisallowHeapAllocation no_allocation;
10364   FixedArray* line_ends = FixedArray::cast(this->line_ends());
10365   int upper = line_ends->length() - 1;
10366   if (upper < 0) return -1;
10367   int offset = line_offset()->value();
10368
10369   if (position > Smi::cast(line_ends->get(upper))->value()) {
10370     return upper + 1 + offset;
10371   }
10372   if (position <= Smi::cast(line_ends->get(0))->value()) return offset;
10373
10374   int lower = 1;
10375   // Binary search.
10376   while (true) {
10377     int mid = (lower + upper) / 2;
10378     if (position <= Smi::cast(line_ends->get(mid - 1))->value()) {
10379       upper = mid - 1;
10380     } else if (position > Smi::cast(line_ends->get(mid))->value()) {
10381       lower = mid + 1;
10382     } else {
10383       return mid + offset;
10384     }
10385   }
10386   return -1;
10387 }
10388
10389
10390 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
10391   InitLineEnds(script);
10392   return script->GetLineNumberWithArray(code_pos);
10393 }
10394
10395
10396 int Script::GetLineNumber(int code_pos) {
10397   DisallowHeapAllocation no_allocation;
10398   if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
10399
10400   // Slow mode: we do not have line_ends. We have to iterate through source.
10401   if (!source()->IsString()) return -1;
10402
10403   String* source_string = String::cast(source());
10404   int line = 0;
10405   int len = source_string->length();
10406   for (int pos = 0; pos < len; pos++) {
10407     if (pos == code_pos) break;
10408     if (source_string->Get(pos) == '\n') line++;
10409   }
10410   return line;
10411 }
10412
10413
10414 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
10415   Isolate* isolate = script->GetIsolate();
10416   Handle<String> name_or_source_url_key =
10417       isolate->factory()->InternalizeOneByteString(
10418           STATIC_CHAR_VECTOR("nameOrSourceURL"));
10419   Handle<JSObject> script_wrapper = Script::GetWrapper(script);
10420   Handle<Object> property = Object::GetProperty(
10421       script_wrapper, name_or_source_url_key).ToHandleChecked();
10422   DCHECK(property->IsJSFunction());
10423   Handle<JSFunction> method = Handle<JSFunction>::cast(property);
10424   Handle<Object> result;
10425   // Do not check against pending exception, since this function may be called
10426   // when an exception has already been pending.
10427   if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
10428     return isolate->factory()->undefined_value();
10429   }
10430   return result;
10431 }
10432
10433
10434 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
10435   Isolate* isolate = script->GetIsolate();
10436   if (!script->wrapper()->IsUndefined()) {
10437     DCHECK(script->wrapper()->IsWeakCell());
10438     Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
10439     if (!cell->cleared()) {
10440       // Return a handle for the existing script wrapper from the cache.
10441       return handle(JSObject::cast(cell->value()));
10442     }
10443     // If we found an empty WeakCell, that means the script wrapper was
10444     // GCed.  We are not notified directly of that, so we decrement here
10445     // so that we at least don't count double for any given script.
10446     isolate->counters()->script_wrappers()->Decrement();
10447   }
10448   // Construct a new script wrapper.
10449   isolate->counters()->script_wrappers()->Increment();
10450   Handle<JSFunction> constructor = isolate->script_function();
10451   Handle<JSValue> result =
10452       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
10453   result->set_value(*script);
10454   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
10455   script->set_wrapper(*cell);
10456   return result;
10457 }
10458
10459
10460 String* SharedFunctionInfo::DebugName() {
10461   Object* n = name();
10462   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
10463   return String::cast(n);
10464 }
10465
10466
10467 bool SharedFunctionInfo::HasSourceCode() const {
10468   return !script()->IsUndefined() &&
10469          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
10470 }
10471
10472
10473 Handle<Object> SharedFunctionInfo::GetSourceCode() {
10474   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
10475   Handle<String> source(String::cast(Script::cast(script())->source()));
10476   return GetIsolate()->factory()->NewSubString(
10477       source, start_position(), end_position());
10478 }
10479
10480
10481 bool SharedFunctionInfo::IsInlineable() {
10482   // Check that the function has a script associated with it.
10483   if (!script()->IsScript()) return false;
10484   if (optimization_disabled()) return false;
10485   // If we never ran this (unlikely) then lets try to optimize it.
10486   if (code()->kind() != Code::FUNCTION) return true;
10487   return code()->optimizable();
10488 }
10489
10490
10491 int SharedFunctionInfo::SourceSize() {
10492   return end_position() - start_position();
10493 }
10494
10495
10496 int SharedFunctionInfo::CalculateInstanceSize() {
10497   int instance_size =
10498       JSObject::kHeaderSize +
10499       expected_nof_properties() * kPointerSize;
10500   if (instance_size > JSObject::kMaxInstanceSize) {
10501     instance_size = JSObject::kMaxInstanceSize;
10502   }
10503   return instance_size;
10504 }
10505
10506
10507 int SharedFunctionInfo::CalculateInObjectProperties() {
10508   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
10509 }
10510
10511
10512 // Output the source code without any allocation in the heap.
10513 std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
10514   const SharedFunctionInfo* s = v.value;
10515   // For some native functions there is no source.
10516   if (!s->HasSourceCode()) return os << "<No Source>";
10517
10518   // Get the source for the script which this function came from.
10519   // Don't use String::cast because we don't want more assertion errors while
10520   // we are already creating a stack dump.
10521   String* script_source =
10522       reinterpret_cast<String*>(Script::cast(s->script())->source());
10523
10524   if (!script_source->LooksValid()) return os << "<Invalid Source>";
10525
10526   if (!s->is_toplevel()) {
10527     os << "function ";
10528     Object* name = s->name();
10529     if (name->IsString() && String::cast(name)->length() > 0) {
10530       String::cast(name)->PrintUC16(os);
10531     }
10532   }
10533
10534   int len = s->end_position() - s->start_position();
10535   if (len <= v.max_length || v.max_length < 0) {
10536     script_source->PrintUC16(os, s->start_position(), s->end_position());
10537     return os;
10538   } else {
10539     script_source->PrintUC16(os, s->start_position(),
10540                              s->start_position() + v.max_length);
10541     return os << "...\n";
10542   }
10543 }
10544
10545
10546 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
10547   if (code->instruction_size() != recompiled->instruction_size()) return false;
10548   ByteArray* code_relocation = code->relocation_info();
10549   ByteArray* recompiled_relocation = recompiled->relocation_info();
10550   int length = code_relocation->length();
10551   if (length != recompiled_relocation->length()) return false;
10552   int compare = memcmp(code_relocation->GetDataStartAddress(),
10553                        recompiled_relocation->GetDataStartAddress(),
10554                        length);
10555   return compare == 0;
10556 }
10557
10558
10559 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
10560   DCHECK(!has_deoptimization_support());
10561   DisallowHeapAllocation no_allocation;
10562   Code* code = this->code();
10563   if (IsCodeEquivalent(code, recompiled)) {
10564     // Copy the deoptimization data from the recompiled code.
10565     code->set_deoptimization_data(recompiled->deoptimization_data());
10566     code->set_has_deoptimization_support(true);
10567   } else {
10568     // TODO(3025757): In case the recompiled isn't equivalent to the
10569     // old code, we have to replace it. We should try to avoid this
10570     // altogether because it flushes valuable type feedback by
10571     // effectively resetting all IC state.
10572     ReplaceCode(recompiled);
10573   }
10574   DCHECK(has_deoptimization_support());
10575 }
10576
10577
10578 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
10579   // Disable optimization for the shared function info and mark the
10580   // code as non-optimizable. The marker on the shared function info
10581   // is there because we flush non-optimized code thereby loosing the
10582   // non-optimizable information for the code. When the code is
10583   // regenerated and set on the shared function info it is marked as
10584   // non-optimizable if optimization is disabled for the shared
10585   // function info.
10586   DCHECK(reason != kNoReason);
10587   set_optimization_disabled(true);
10588   set_disable_optimization_reason(reason);
10589   // Code should be the lazy compilation stub or else unoptimized.  If the
10590   // latter, disable optimization for the code too.
10591   DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
10592   if (code()->kind() == Code::FUNCTION) {
10593     code()->set_optimizable(false);
10594   }
10595   PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
10596   if (FLAG_trace_opt) {
10597     PrintF("[disabled optimization for ");
10598     ShortPrint();
10599     PrintF(", reason: %s]\n", GetBailoutReason(reason));
10600   }
10601 }
10602
10603
10604 void SharedFunctionInfo::InitFromFunctionLiteral(
10605     Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
10606   shared_info->set_length(lit->scope()->default_function_length());
10607   if (IsSubclassConstructor(lit->kind())) {
10608     shared_info->set_internal_formal_parameter_count(lit->parameter_count() +
10609                                                      1);
10610   } else {
10611     shared_info->set_internal_formal_parameter_count(lit->parameter_count());
10612   }
10613   shared_info->set_function_token_position(lit->function_token_position());
10614   shared_info->set_start_position(lit->start_position());
10615   shared_info->set_end_position(lit->end_position());
10616   shared_info->set_is_expression(lit->is_expression());
10617   shared_info->set_is_anonymous(lit->is_anonymous());
10618   shared_info->set_inferred_name(*lit->inferred_name());
10619   shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
10620   shared_info->set_allows_lazy_compilation_without_context(
10621       lit->AllowsLazyCompilationWithoutContext());
10622   shared_info->set_language_mode(lit->language_mode());
10623   shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
10624   shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
10625   shared_info->set_ast_node_count(lit->ast_node_count());
10626   shared_info->set_is_function(lit->is_function());
10627   if (lit->dont_optimize_reason() != kNoReason) {
10628     shared_info->DisableOptimization(lit->dont_optimize_reason());
10629   }
10630   shared_info->set_dont_cache(
10631       lit->flags()->Contains(AstPropertiesFlag::kDontCache));
10632   shared_info->set_kind(lit->kind());
10633   shared_info->set_uses_super_property(lit->uses_super_property());
10634   shared_info->set_asm_function(lit->scope()->asm_function());
10635 }
10636
10637
10638 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
10639   DCHECK(!id.IsNone());
10640   Code* unoptimized = code();
10641   DeoptimizationOutputData* data =
10642       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
10643   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
10644   USE(ignore);
10645   return true;  // Return true if there was no DCHECK.
10646 }
10647
10648
10649 void JSFunction::StartInobjectSlackTracking() {
10650   DCHECK(has_initial_map() && !IsInobjectSlackTrackingInProgress());
10651
10652   Map* map = initial_map();
10653
10654   // No tracking during the snapshot construction phase.
10655   Isolate* isolate = GetIsolate();
10656   if (isolate->serializer_enabled()) return;
10657
10658   if (map->unused_property_fields() == 0) return;
10659
10660   map->set_counter(Map::kSlackTrackingCounterStart);
10661 }
10662
10663
10664 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
10665   code()->ClearInlineCaches();
10666   // If we clear ICs, we need to clear the type feedback vector too, since
10667   // CallICs are synced with a feedback vector slot.
10668   ClearTypeFeedbackInfo();
10669   set_ic_age(new_ic_age);
10670   if (code()->kind() == Code::FUNCTION) {
10671     code()->set_profiler_ticks(0);
10672     if (optimization_disabled() &&
10673         opt_count() >= FLAG_max_opt_count) {
10674       // Re-enable optimizations if they were disabled due to opt_count limit.
10675       set_optimization_disabled(false);
10676       code()->set_optimizable(true);
10677     }
10678     set_opt_count(0);
10679     set_deopt_count(0);
10680   }
10681 }
10682
10683
10684 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
10685                                                BailoutId osr_ast_id) {
10686   DisallowHeapAllocation no_gc;
10687   DCHECK(native_context->IsNativeContext());
10688   if (!FLAG_cache_optimized_code) return -1;
10689   Object* value = optimized_code_map();
10690   if (!value->IsSmi()) {
10691     FixedArray* optimized_code_map = FixedArray::cast(value);
10692     int length = optimized_code_map->length();
10693     Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
10694     for (int i = kEntriesStart; i < length; i += kEntryLength) {
10695       if (optimized_code_map->get(i + kContextOffset) == native_context &&
10696           optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
10697         return i + kCachedCodeOffset;
10698       }
10699     }
10700     if (FLAG_trace_opt) {
10701       PrintF("[didn't find optimized code in optimized code map for ");
10702       ShortPrint();
10703       PrintF("]\n");
10704     }
10705   }
10706   return -1;
10707 }
10708
10709
10710 #define DECLARE_TAG(ignore1, name, ignore2) name,
10711 const char* const VisitorSynchronization::kTags[
10712     VisitorSynchronization::kNumberOfSyncTags] = {
10713   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10714 };
10715 #undef DECLARE_TAG
10716
10717
10718 #define DECLARE_TAG(ignore1, ignore2, name) name,
10719 const char* const VisitorSynchronization::kTagNames[
10720     VisitorSynchronization::kNumberOfSyncTags] = {
10721   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10722 };
10723 #undef DECLARE_TAG
10724
10725
10726 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10727   DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
10728   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10729   Object* old_target = target;
10730   VisitPointer(&target);
10731   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10732 }
10733
10734
10735 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10736   DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10737   Object* stub = rinfo->code_age_stub();
10738   if (stub) {
10739     VisitPointer(&stub);
10740   }
10741 }
10742
10743
10744 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10745   Object* code = Code::GetObjectFromEntryAddress(entry_address);
10746   Object* old_code = code;
10747   VisitPointer(&code);
10748   if (code != old_code) {
10749     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10750   }
10751 }
10752
10753
10754 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10755   DCHECK(rinfo->rmode() == RelocInfo::CELL);
10756   Object* cell = rinfo->target_cell();
10757   Object* old_cell = cell;
10758   VisitPointer(&cell);
10759   if (cell != old_cell) {
10760     rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10761   }
10762 }
10763
10764
10765 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10766   DCHECK((RelocInfo::IsJSReturn(rinfo->rmode()) &&
10767           rinfo->IsPatchedReturnSequence()) ||
10768          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10769           rinfo->IsPatchedDebugBreakSlotSequence()));
10770   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
10771   Object* old_target = target;
10772   VisitPointer(&target);
10773   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10774 }
10775
10776
10777 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10778   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10779   Object* p = rinfo->target_object();
10780   VisitPointer(&p);
10781 }
10782
10783
10784 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10785   Address p = rinfo->target_external_reference();
10786   VisitExternalReference(&p);
10787 }
10788
10789
10790 void Code::InvalidateRelocation() {
10791   InvalidateEmbeddedObjects();
10792   set_relocation_info(GetHeap()->empty_byte_array());
10793 }
10794
10795
10796 void Code::InvalidateEmbeddedObjects() {
10797   Object* undefined = GetHeap()->undefined_value();
10798   Cell* undefined_cell = GetHeap()->undefined_cell();
10799   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10800                   RelocInfo::ModeMask(RelocInfo::CELL);
10801   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10802     RelocInfo::Mode mode = it.rinfo()->rmode();
10803     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10804       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10805     } else if (mode == RelocInfo::CELL) {
10806       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10807     }
10808   }
10809 }
10810
10811
10812 void Code::Relocate(intptr_t delta) {
10813   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10814     it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10815   }
10816   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10817 }
10818
10819
10820 void Code::CopyFrom(const CodeDesc& desc) {
10821   DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT);
10822
10823   // copy code
10824   CopyBytes(instruction_start(), desc.buffer,
10825             static_cast<size_t>(desc.instr_size));
10826
10827   // copy reloc info
10828   CopyBytes(relocation_start(),
10829             desc.buffer + desc.buffer_size - desc.reloc_size,
10830             static_cast<size_t>(desc.reloc_size));
10831
10832   // unbox handles and relocate
10833   intptr_t delta = instruction_start() - desc.buffer;
10834   int mode_mask = RelocInfo::kCodeTargetMask |
10835                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10836                   RelocInfo::ModeMask(RelocInfo::CELL) |
10837                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
10838                   RelocInfo::kApplyMask;
10839   // Needed to find target_object and runtime_entry on X64
10840   Assembler* origin = desc.origin;
10841   AllowDeferredHandleDereference embedding_raw_address;
10842   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10843     RelocInfo::Mode mode = it.rinfo()->rmode();
10844     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10845       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10846       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10847     } else if (mode == RelocInfo::CELL) {
10848       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
10849       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10850     } else if (RelocInfo::IsCodeTarget(mode)) {
10851       // rewrite code handles in inline cache targets to direct
10852       // pointers to the first instruction in the code object
10853       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10854       Code* code = Code::cast(*p);
10855       it.rinfo()->set_target_address(code->instruction_start(),
10856                                      SKIP_WRITE_BARRIER,
10857                                      SKIP_ICACHE_FLUSH);
10858     } else if (RelocInfo::IsRuntimeEntry(mode)) {
10859       Address p = it.rinfo()->target_runtime_entry(origin);
10860       it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
10861                                            SKIP_ICACHE_FLUSH);
10862     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10863       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10864       Code* code = Code::cast(*p);
10865       it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
10866     } else {
10867       it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10868     }
10869   }
10870   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10871 }
10872
10873
10874 // Locate the source position which is closest to the address in the code. This
10875 // is using the source position information embedded in the relocation info.
10876 // The position returned is relative to the beginning of the script where the
10877 // source for this function is found.
10878 int Code::SourcePosition(Address pc) {
10879   int distance = kMaxInt;
10880   int position = RelocInfo::kNoPosition;  // Initially no position found.
10881   // Run through all the relocation info to find the best matching source
10882   // position. All the code needs to be considered as the sequence of the
10883   // instructions in the code does not necessarily follow the same order as the
10884   // source.
10885   RelocIterator it(this, RelocInfo::kPositionMask);
10886   while (!it.done()) {
10887     // Only look at positions after the current pc.
10888     if (it.rinfo()->pc() < pc) {
10889       // Get position and distance.
10890
10891       int dist = static_cast<int>(pc - it.rinfo()->pc());
10892       int pos = static_cast<int>(it.rinfo()->data());
10893       // If this position is closer than the current candidate or if it has the
10894       // same distance as the current candidate and the position is higher then
10895       // this position is the new candidate.
10896       if ((dist < distance) ||
10897           (dist == distance && pos > position)) {
10898         position = pos;
10899         distance = dist;
10900       }
10901     }
10902     it.next();
10903   }
10904   return position;
10905 }
10906
10907
10908 // Same as Code::SourcePosition above except it only looks for statement
10909 // positions.
10910 int Code::SourceStatementPosition(Address pc) {
10911   // First find the position as close as possible using all position
10912   // information.
10913   int position = SourcePosition(pc);
10914   // Now find the closest statement position before the position.
10915   int statement_position = 0;
10916   RelocIterator it(this, RelocInfo::kPositionMask);
10917   while (!it.done()) {
10918     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
10919       int p = static_cast<int>(it.rinfo()->data());
10920       if (statement_position < p && p <= position) {
10921         statement_position = p;
10922       }
10923     }
10924     it.next();
10925   }
10926   return statement_position;
10927 }
10928
10929
10930 SafepointEntry Code::GetSafepointEntry(Address pc) {
10931   SafepointTable table(this);
10932   return table.FindEntry(pc);
10933 }
10934
10935
10936 Object* Code::FindNthObject(int n, Map* match_map) {
10937   DCHECK(is_inline_cache_stub());
10938   DisallowHeapAllocation no_allocation;
10939   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10940   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10941     RelocInfo* info = it.rinfo();
10942     Object* object = info->target_object();
10943     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10944     if (object->IsHeapObject()) {
10945       if (HeapObject::cast(object)->map() == match_map) {
10946         if (--n == 0) return object;
10947       }
10948     }
10949   }
10950   return NULL;
10951 }
10952
10953
10954 AllocationSite* Code::FindFirstAllocationSite() {
10955   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
10956   return (result != NULL) ? AllocationSite::cast(result) : NULL;
10957 }
10958
10959
10960 Map* Code::FindFirstMap() {
10961   Object* result = FindNthObject(1, GetHeap()->meta_map());
10962   return (result != NULL) ? Map::cast(result) : NULL;
10963 }
10964
10965
10966 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
10967   DCHECK(is_inline_cache_stub() || is_handler());
10968   DisallowHeapAllocation no_allocation;
10969   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10970   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
10971   int current_pattern = 0;
10972   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10973     RelocInfo* info = it.rinfo();
10974     Object* object = info->target_object();
10975     if (object->IsHeapObject()) {
10976       if (object->IsWeakCell()) {
10977         object = HeapObject::cast(WeakCell::cast(object)->value());
10978       }
10979       Map* map = HeapObject::cast(object)->map();
10980       if (map == *pattern.find_[current_pattern]) {
10981         info->set_target_object(*pattern.replace_[current_pattern]);
10982         if (++current_pattern == pattern.count_) return;
10983       }
10984     }
10985   }
10986   UNREACHABLE();
10987 }
10988
10989
10990 void Code::FindAllMaps(MapHandleList* maps) {
10991   DCHECK(is_inline_cache_stub());
10992   DisallowHeapAllocation no_allocation;
10993   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10994   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10995     RelocInfo* info = it.rinfo();
10996     Object* object = info->target_object();
10997     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10998     if (object->IsMap()) maps->Add(handle(Map::cast(object)));
10999   }
11000 }
11001
11002
11003 Code* Code::FindFirstHandler() {
11004   DCHECK(is_inline_cache_stub());
11005   DisallowHeapAllocation no_allocation;
11006   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
11007              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11008   bool skip_next_handler = false;
11009   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11010     RelocInfo* info = it.rinfo();
11011     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
11012       Object* obj = info->target_object();
11013       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
11014     } else {
11015       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
11016       if (code->kind() == Code::HANDLER) {
11017         if (!skip_next_handler) return code;
11018         skip_next_handler = false;
11019       }
11020     }
11021   }
11022   return NULL;
11023 }
11024
11025
11026 bool Code::FindHandlers(CodeHandleList* code_list, int length) {
11027   DCHECK(is_inline_cache_stub());
11028   DisallowHeapAllocation no_allocation;
11029   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
11030              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11031   bool skip_next_handler = false;
11032   int i = 0;
11033   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11034     if (i == length) return true;
11035     RelocInfo* info = it.rinfo();
11036     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
11037       Object* obj = info->target_object();
11038       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
11039     } else {
11040       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
11041       // IC stubs with handlers never contain non-handler code objects before
11042       // handler targets.
11043       if (code->kind() != Code::HANDLER) break;
11044       if (!skip_next_handler) {
11045         code_list->Add(Handle<Code>(code));
11046         i++;
11047       }
11048       skip_next_handler = false;
11049     }
11050   }
11051   return i == length;
11052 }
11053
11054
11055 MaybeHandle<Code> Code::FindHandlerForMap(Map* map) {
11056   DCHECK(is_inline_cache_stub());
11057   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
11058              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11059   bool return_next = false;
11060   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11061     RelocInfo* info = it.rinfo();
11062     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
11063       Object* object = info->target_object();
11064       if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
11065       if (object == map) return_next = true;
11066     } else if (return_next) {
11067       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
11068       DCHECK(code->kind() == Code::HANDLER);
11069       return handle(code);
11070     }
11071   }
11072   return MaybeHandle<Code>();
11073 }
11074
11075
11076 Name* Code::FindFirstName() {
11077   DCHECK(is_inline_cache_stub());
11078   DisallowHeapAllocation no_allocation;
11079   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
11080   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11081     RelocInfo* info = it.rinfo();
11082     Object* object = info->target_object();
11083     if (object->IsName()) return Name::cast(object);
11084   }
11085   return NULL;
11086 }
11087
11088
11089 void Code::ClearInlineCaches() {
11090   ClearInlineCaches(NULL);
11091 }
11092
11093
11094 void Code::ClearInlineCaches(Code::Kind kind) {
11095   ClearInlineCaches(&kind);
11096 }
11097
11098
11099 void Code::ClearInlineCaches(Code::Kind* kind) {
11100   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
11101              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
11102              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
11103   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11104     RelocInfo* info = it.rinfo();
11105     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
11106     if (target->is_inline_cache_stub()) {
11107       if (kind == NULL || *kind == target->kind()) {
11108         IC::Clear(this->GetIsolate(), info->pc(),
11109                   info->host()->constant_pool());
11110       }
11111     }
11112   }
11113 }
11114
11115
11116 void SharedFunctionInfo::ClearTypeFeedbackInfo() {
11117   feedback_vector()->ClearSlots(this);
11118   feedback_vector()->ClearICSlots(this);
11119 }
11120
11121
11122 void SharedFunctionInfo::ClearTypeFeedbackInfoAtGCTime() {
11123   feedback_vector()->ClearSlots(this);
11124   feedback_vector()->ClearICSlotsAtGCTime(this);
11125 }
11126
11127
11128 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
11129   DisallowHeapAllocation no_gc;
11130   DCHECK(kind() == FUNCTION);
11131   BackEdgeTable back_edges(this, &no_gc);
11132   for (uint32_t i = 0; i < back_edges.length(); i++) {
11133     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
11134   }
11135   return BailoutId::None();
11136 }
11137
11138
11139 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
11140   DisallowHeapAllocation no_gc;
11141   DCHECK(kind() == FUNCTION);
11142   BackEdgeTable back_edges(this, &no_gc);
11143   for (uint32_t i = 0; i < back_edges.length(); i++) {
11144     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
11145   }
11146   UNREACHABLE();  // We expect to find the back edge.
11147   return 0;
11148 }
11149
11150
11151 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
11152   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
11153 }
11154
11155
11156 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
11157   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
11158       NO_MARKING_PARITY);
11159 }
11160
11161
11162 static Code::Age EffectiveAge(Code::Age age) {
11163   if (age == Code::kNotExecutedCodeAge) {
11164     // Treat that's never been executed as old immediately.
11165     age = Code::kIsOldCodeAge;
11166   } else if (age == Code::kExecutedOnceCodeAge) {
11167     // Pre-age code that has only been executed once.
11168     age = Code::kPreAgedCodeAge;
11169   }
11170   return age;
11171 }
11172
11173
11174 void Code::MakeYoung(Isolate* isolate) {
11175   byte* sequence = FindCodeAgeSequence();
11176   if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, isolate);
11177 }
11178
11179
11180 void Code::MakeOlder(MarkingParity current_parity) {
11181   byte* sequence = FindCodeAgeSequence();
11182   if (sequence != NULL) {
11183     Age age;
11184     MarkingParity code_parity;
11185     Isolate* isolate = GetIsolate();
11186     GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
11187     age = EffectiveAge(age);
11188     if (age != kLastCodeAge && code_parity != current_parity) {
11189       PatchPlatformCodeAge(isolate,
11190                            sequence,
11191                            static_cast<Age>(age + 1),
11192                            current_parity);
11193     }
11194   }
11195 }
11196
11197
11198 bool Code::IsOld() {
11199   return GetAge() >= kIsOldCodeAge;
11200 }
11201
11202
11203 byte* Code::FindCodeAgeSequence() {
11204   return FLAG_age_code &&
11205       prologue_offset() != Code::kPrologueOffsetNotSet &&
11206       (kind() == OPTIMIZED_FUNCTION ||
11207        (kind() == FUNCTION && !has_debug_break_slots()))
11208       ? instruction_start() + prologue_offset()
11209       : NULL;
11210 }
11211
11212
11213 Code::Age Code::GetAge() {
11214   return EffectiveAge(GetRawAge());
11215 }
11216
11217
11218 Code::Age Code::GetRawAge() {
11219   byte* sequence = FindCodeAgeSequence();
11220   if (sequence == NULL) {
11221     return kNoAgeCodeAge;
11222   }
11223   Age age;
11224   MarkingParity parity;
11225   GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
11226   return age;
11227 }
11228
11229
11230 void Code::GetCodeAgeAndParity(Code* code, Age* age,
11231                                MarkingParity* parity) {
11232   Isolate* isolate = code->GetIsolate();
11233   Builtins* builtins = isolate->builtins();
11234   Code* stub = NULL;
11235 #define HANDLE_CODE_AGE(AGE)                                            \
11236   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
11237   if (code == stub) {                                                   \
11238     *age = k##AGE##CodeAge;                                             \
11239     *parity = EVEN_MARKING_PARITY;                                      \
11240     return;                                                             \
11241   }                                                                     \
11242   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
11243   if (code == stub) {                                                   \
11244     *age = k##AGE##CodeAge;                                             \
11245     *parity = ODD_MARKING_PARITY;                                       \
11246     return;                                                             \
11247   }
11248   CODE_AGE_LIST(HANDLE_CODE_AGE)
11249 #undef HANDLE_CODE_AGE
11250   stub = *builtins->MarkCodeAsExecutedOnce();
11251   if (code == stub) {
11252     *age = kNotExecutedCodeAge;
11253     *parity = NO_MARKING_PARITY;
11254     return;
11255   }
11256   stub = *builtins->MarkCodeAsExecutedTwice();
11257   if (code == stub) {
11258     *age = kExecutedOnceCodeAge;
11259     *parity = NO_MARKING_PARITY;
11260     return;
11261   }
11262   UNREACHABLE();
11263 }
11264
11265
11266 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
11267   Builtins* builtins = isolate->builtins();
11268   switch (age) {
11269 #define HANDLE_CODE_AGE(AGE)                                            \
11270     case k##AGE##CodeAge: {                                             \
11271       Code* stub = parity == EVEN_MARKING_PARITY                        \
11272           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
11273           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
11274       return stub;                                                      \
11275     }
11276     CODE_AGE_LIST(HANDLE_CODE_AGE)
11277 #undef HANDLE_CODE_AGE
11278     case kNotExecutedCodeAge: {
11279       DCHECK(parity == NO_MARKING_PARITY);
11280       return *builtins->MarkCodeAsExecutedOnce();
11281     }
11282     case kExecutedOnceCodeAge: {
11283       DCHECK(parity == NO_MARKING_PARITY);
11284       return *builtins->MarkCodeAsExecutedTwice();
11285     }
11286     default:
11287       UNREACHABLE();
11288       break;
11289   }
11290   return NULL;
11291 }
11292
11293
11294 void Code::PrintDeoptLocation(FILE* out, Address pc) {
11295   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
11296   class SourcePosition pos = info.position;
11297   if (info.deopt_reason != Deoptimizer::kNoReason || !pos.IsUnknown()) {
11298     if (FLAG_hydrogen_track_positions) {
11299       PrintF(out, "            ;;; deoptimize at %d_%d: %s\n",
11300              pos.inlining_id(), pos.position(),
11301              Deoptimizer::GetDeoptReason(info.deopt_reason));
11302     } else {
11303       PrintF(out, "            ;;; deoptimize at %d: %s\n", pos.raw(),
11304              Deoptimizer::GetDeoptReason(info.deopt_reason));
11305     }
11306   }
11307 }
11308
11309
11310 bool Code::CanDeoptAt(Address pc) {
11311   DeoptimizationInputData* deopt_data =
11312       DeoptimizationInputData::cast(deoptimization_data());
11313   Address code_start_address = instruction_start();
11314   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
11315     if (deopt_data->Pc(i)->value() == -1) continue;
11316     Address address = code_start_address + deopt_data->Pc(i)->value();
11317     if (address == pc) return true;
11318   }
11319   return false;
11320 }
11321
11322
11323 // Identify kind of code.
11324 const char* Code::Kind2String(Kind kind) {
11325   switch (kind) {
11326 #define CASE(name) case name: return #name;
11327     CODE_KIND_LIST(CASE)
11328 #undef CASE
11329     case NUMBER_OF_KINDS: break;
11330   }
11331   UNREACHABLE();
11332   return NULL;
11333 }
11334
11335
11336 Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
11337   DCHECK(code->kind() == OPTIMIZED_FUNCTION);
11338   WeakCell* raw_cell = code->CachedWeakCell();
11339   if (raw_cell != NULL) return Handle<WeakCell>(raw_cell);
11340   Handle<WeakCell> cell = code->GetIsolate()->factory()->NewWeakCell(code);
11341   DeoptimizationInputData::cast(code->deoptimization_data())
11342       ->SetWeakCellCache(*cell);
11343   return cell;
11344 }
11345
11346
11347 WeakCell* Code::CachedWeakCell() {
11348   DCHECK(kind() == OPTIMIZED_FUNCTION);
11349   Object* weak_cell_cache =
11350       DeoptimizationInputData::cast(deoptimization_data())->WeakCellCache();
11351   if (weak_cell_cache->IsWeakCell()) {
11352     DCHECK(this == WeakCell::cast(weak_cell_cache)->value());
11353     return WeakCell::cast(weak_cell_cache);
11354   }
11355   return NULL;
11356 }
11357
11358
11359 #ifdef ENABLE_DISASSEMBLER
11360
11361 void DeoptimizationInputData::DeoptimizationInputDataPrint(
11362     std::ostream& os) {  // NOLINT
11363   disasm::NameConverter converter;
11364   int deopt_count = DeoptCount();
11365   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
11366   if (0 != deopt_count) {
11367     os << " index  ast id    argc     pc";
11368     if (FLAG_print_code_verbose) os << "  commands";
11369     os << "\n";
11370   }
11371   for (int i = 0; i < deopt_count; i++) {
11372     os << std::setw(6) << i << "  " << std::setw(6) << AstId(i).ToInt() << "  "
11373        << std::setw(6) << ArgumentsStackHeight(i)->value() << " "
11374        << std::setw(6) << Pc(i)->value();
11375
11376     if (!FLAG_print_code_verbose) {
11377       os << "\n";
11378       continue;
11379     }
11380     // Print details of the frame translation.
11381     int translation_index = TranslationIndex(i)->value();
11382     TranslationIterator iterator(TranslationByteArray(), translation_index);
11383     Translation::Opcode opcode =
11384         static_cast<Translation::Opcode>(iterator.Next());
11385     DCHECK(Translation::BEGIN == opcode);
11386     int frame_count = iterator.Next();
11387     int jsframe_count = iterator.Next();
11388     os << "  " << Translation::StringFor(opcode)
11389        << " {frame count=" << frame_count
11390        << ", js frame count=" << jsframe_count << "}\n";
11391
11392     while (iterator.HasNext() &&
11393            Translation::BEGIN !=
11394            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
11395       os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
11396
11397       switch (opcode) {
11398         case Translation::BEGIN:
11399           UNREACHABLE();
11400           break;
11401
11402         case Translation::JS_FRAME: {
11403           int ast_id = iterator.Next();
11404           int function_id = iterator.Next();
11405           unsigned height = iterator.Next();
11406           os << "{ast_id=" << ast_id << ", function=";
11407           if (function_id != Translation::kSelfLiteralId) {
11408             Object* function = LiteralArray()->get(function_id);
11409             os << Brief(JSFunction::cast(function)->shared()->DebugName());
11410           } else {
11411             os << "<self>";
11412           }
11413           os << ", height=" << height << "}";
11414           break;
11415         }
11416
11417         case Translation::COMPILED_STUB_FRAME: {
11418           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
11419           os << "{kind=" << stub_kind << "}";
11420           break;
11421         }
11422
11423         case Translation::ARGUMENTS_ADAPTOR_FRAME:
11424         case Translation::CONSTRUCT_STUB_FRAME: {
11425           int function_id = iterator.Next();
11426           JSFunction* function =
11427               JSFunction::cast(LiteralArray()->get(function_id));
11428           unsigned height = iterator.Next();
11429           os << "{function=" << Brief(function->shared()->DebugName())
11430              << ", height=" << height << "}";
11431           break;
11432         }
11433
11434         case Translation::GETTER_STUB_FRAME:
11435         case Translation::SETTER_STUB_FRAME: {
11436           int function_id = iterator.Next();
11437           JSFunction* function =
11438               JSFunction::cast(LiteralArray()->get(function_id));
11439           os << "{function=" << Brief(function->shared()->DebugName()) << "}";
11440           break;
11441         }
11442
11443         case Translation::REGISTER: {
11444           int reg_code = iterator.Next();
11445           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11446           break;
11447         }
11448
11449         case Translation::INT32_REGISTER: {
11450           int reg_code = iterator.Next();
11451           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11452           break;
11453         }
11454
11455         case Translation::UINT32_REGISTER: {
11456           int reg_code = iterator.Next();
11457           os << "{input=" << converter.NameOfCPURegister(reg_code)
11458              << " (unsigned)}";
11459           break;
11460         }
11461
11462         case Translation::DOUBLE_REGISTER: {
11463           int reg_code = iterator.Next();
11464           os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
11465              << "}";
11466           break;
11467         }
11468
11469         case Translation::STACK_SLOT: {
11470           int input_slot_index = iterator.Next();
11471           os << "{input=" << input_slot_index << "}";
11472           break;
11473         }
11474
11475         case Translation::INT32_STACK_SLOT: {
11476           int input_slot_index = iterator.Next();
11477           os << "{input=" << input_slot_index << "}";
11478           break;
11479         }
11480
11481         case Translation::UINT32_STACK_SLOT: {
11482           int input_slot_index = iterator.Next();
11483           os << "{input=" << input_slot_index << " (unsigned)}";
11484           break;
11485         }
11486
11487         case Translation::DOUBLE_STACK_SLOT: {
11488           int input_slot_index = iterator.Next();
11489           os << "{input=" << input_slot_index << "}";
11490           break;
11491         }
11492
11493         case Translation::LITERAL: {
11494           unsigned literal_index = iterator.Next();
11495           os << "{literal_id=" << literal_index << "}";
11496           break;
11497         }
11498
11499         case Translation::DUPLICATED_OBJECT: {
11500           int object_index = iterator.Next();
11501           os << "{object_index=" << object_index << "}";
11502           break;
11503         }
11504
11505         case Translation::ARGUMENTS_OBJECT:
11506         case Translation::CAPTURED_OBJECT: {
11507           int args_length = iterator.Next();
11508           os << "{length=" << args_length << "}";
11509           break;
11510         }
11511       }
11512       os << "\n";
11513     }
11514   }
11515 }
11516
11517
11518 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
11519     std::ostream& os) {  // NOLINT
11520   os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
11521      << ")\n";
11522   if (this->DeoptPoints() == 0) return;
11523
11524   os << "ast id        pc  state\n";
11525   for (int i = 0; i < this->DeoptPoints(); i++) {
11526     int pc_and_state = this->PcAndState(i)->value();
11527     os << std::setw(6) << this->AstId(i).ToInt() << "  " << std::setw(8)
11528        << FullCodeGenerator::PcField::decode(pc_and_state) << "  "
11529        << FullCodeGenerator::State2String(
11530               FullCodeGenerator::StateField::decode(pc_and_state)) << "\n";
11531   }
11532 }
11533
11534
11535 void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
11536   os << "   from   to       hdlr\n";
11537   for (int i = 0; i < length(); i += kRangeEntrySize) {
11538     int pc_start = Smi::cast(get(i + kRangeStartIndex))->value();
11539     int pc_end = Smi::cast(get(i + kRangeEndIndex))->value();
11540     int handler = Smi::cast(get(i + kRangeHandlerIndex))->value();
11541     int depth = Smi::cast(get(i + kRangeDepthIndex))->value();
11542     os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
11543        << ")  ->  " << std::setw(4) << handler << " (depth=" << depth << ")\n";
11544   }
11545 }
11546
11547
11548 void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
11549   os << "   off      hdlr\n";
11550   for (int i = 0; i < length(); i += kReturnEntrySize) {
11551     int pc_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
11552     int handler = Smi::cast(get(i + kReturnHandlerIndex))->value();
11553     os << "  " << std::setw(4) << pc_offset << "  ->  " << std::setw(4)
11554        << handler << "\n";
11555   }
11556 }
11557
11558
11559 const char* Code::ICState2String(InlineCacheState state) {
11560   switch (state) {
11561     case UNINITIALIZED: return "UNINITIALIZED";
11562     case PREMONOMORPHIC: return "PREMONOMORPHIC";
11563     case MONOMORPHIC: return "MONOMORPHIC";
11564     case PROTOTYPE_FAILURE:
11565       return "PROTOTYPE_FAILURE";
11566     case POLYMORPHIC: return "POLYMORPHIC";
11567     case MEGAMORPHIC: return "MEGAMORPHIC";
11568     case GENERIC: return "GENERIC";
11569     case DEBUG_STUB: return "DEBUG_STUB";
11570     case DEFAULT:
11571       return "DEFAULT";
11572   }
11573   UNREACHABLE();
11574   return NULL;
11575 }
11576
11577
11578 const char* Code::StubType2String(StubType type) {
11579   switch (type) {
11580     case NORMAL: return "NORMAL";
11581     case FAST: return "FAST";
11582   }
11583   UNREACHABLE();  // keep the compiler happy
11584   return NULL;
11585 }
11586
11587
11588 void Code::PrintExtraICState(std::ostream& os,  // NOLINT
11589                              Kind kind, ExtraICState extra) {
11590   os << "extra_ic_state = ";
11591   if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
11592       is_strict(static_cast<LanguageMode>(extra))) {
11593     os << "STRICT\n";
11594   } else {
11595     os << extra << "\n";
11596   }
11597 }
11598
11599
11600 void Code::Disassemble(const char* name, std::ostream& os) {  // NOLINT
11601   os << "kind = " << Kind2String(kind()) << "\n";
11602   if (IsCodeStubOrIC()) {
11603     const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true);
11604     os << "major_key = " << (n == NULL ? "null" : n) << "\n";
11605   }
11606   if (is_inline_cache_stub()) {
11607     os << "ic_state = " << ICState2String(ic_state()) << "\n";
11608     PrintExtraICState(os, kind(), extra_ic_state());
11609     if (ic_state() == MONOMORPHIC) {
11610       os << "type = " << StubType2String(type()) << "\n";
11611     }
11612     if (is_compare_ic_stub()) {
11613       DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
11614       CompareICStub stub(stub_key(), GetIsolate());
11615       os << "compare_state = " << CompareICState::GetStateName(stub.left())
11616          << "*" << CompareICState::GetStateName(stub.right()) << " -> "
11617          << CompareICState::GetStateName(stub.state()) << "\n";
11618       os << "compare_operation = " << Token::Name(stub.op()) << "\n";
11619     }
11620   }
11621   if ((name != NULL) && (name[0] != '\0')) {
11622     os << "name = " << name << "\n";
11623   }
11624   if (kind() == OPTIMIZED_FUNCTION) {
11625     os << "stack_slots = " << stack_slots() << "\n";
11626   }
11627
11628   os << "Instructions (size = " << instruction_size() << ")\n";
11629   {
11630     Isolate* isolate = GetIsolate();
11631     int decode_size = is_crankshafted()
11632                           ? static_cast<int>(safepoint_table_offset())
11633                           : instruction_size();
11634     // If there might be a back edge table, stop before reaching it.
11635     if (kind() == Code::FUNCTION) {
11636       decode_size =
11637           Min(decode_size, static_cast<int>(back_edge_table_offset()));
11638     }
11639     byte* begin = instruction_start();
11640     byte* end = begin + decode_size;
11641     Disassembler::Decode(isolate, &os, begin, end, this);
11642   }
11643   os << "\n";
11644
11645   if (kind() == FUNCTION) {
11646     DeoptimizationOutputData* data =
11647         DeoptimizationOutputData::cast(this->deoptimization_data());
11648     data->DeoptimizationOutputDataPrint(os);
11649   } else if (kind() == OPTIMIZED_FUNCTION) {
11650     DeoptimizationInputData* data =
11651         DeoptimizationInputData::cast(this->deoptimization_data());
11652     data->DeoptimizationInputDataPrint(os);
11653   }
11654   os << "\n";
11655
11656   if (is_crankshafted()) {
11657     SafepointTable table(this);
11658     os << "Safepoints (size = " << table.size() << ")\n";
11659     for (unsigned i = 0; i < table.length(); i++) {
11660       unsigned pc_offset = table.GetPcOffset(i);
11661       os << static_cast<const void*>(instruction_start() + pc_offset) << "  ";
11662       os << std::setw(4) << pc_offset << "  ";
11663       table.PrintEntry(i, os);
11664       os << " (sp -> fp)  ";
11665       SafepointEntry entry = table.GetEntry(i);
11666       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
11667         os << std::setw(6) << entry.deoptimization_index();
11668       } else {
11669         os << "<none>";
11670       }
11671       if (entry.argument_count() > 0) {
11672         os << " argc: " << entry.argument_count();
11673       }
11674       os << "\n";
11675     }
11676     os << "\n";
11677   } else if (kind() == FUNCTION) {
11678     unsigned offset = back_edge_table_offset();
11679     // If there is no back edge table, the "table start" will be at or after
11680     // (due to alignment) the end of the instruction stream.
11681     if (static_cast<int>(offset) < instruction_size()) {
11682       DisallowHeapAllocation no_gc;
11683       BackEdgeTable back_edges(this, &no_gc);
11684
11685       os << "Back edges (size = " << back_edges.length() << ")\n";
11686       os << "ast_id  pc_offset  loop_depth\n";
11687
11688       for (uint32_t i = 0; i < back_edges.length(); i++) {
11689         os << std::setw(6) << back_edges.ast_id(i).ToInt() << "  "
11690            << std::setw(9) << back_edges.pc_offset(i) << "  " << std::setw(10)
11691            << back_edges.loop_depth(i) << "\n";
11692       }
11693
11694       os << "\n";
11695     }
11696 #ifdef OBJECT_PRINT
11697     if (!type_feedback_info()->IsUndefined()) {
11698       OFStream os(stdout);
11699       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
11700       os << "\n";
11701     }
11702 #endif
11703   }
11704
11705   if (handler_table()->length() > 0) {
11706     os << "Handler Table (size = " << handler_table()->Size() << ")\n";
11707     if (kind() == FUNCTION) {
11708       HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
11709     } else if (kind() == OPTIMIZED_FUNCTION) {
11710       HandlerTable::cast(handler_table())->HandlerTableReturnPrint(os);
11711     }
11712     os << "\n";
11713   }
11714
11715   os << "RelocInfo (size = " << relocation_size() << ")\n";
11716   for (RelocIterator it(this); !it.done(); it.next()) {
11717     it.rinfo()->Print(GetIsolate(), os);
11718   }
11719   os << "\n";
11720
11721 #ifdef OBJECT_PRINT
11722   if (FLAG_enable_ool_constant_pool) {
11723     ConstantPoolArray* pool = constant_pool();
11724     if (pool->length()) {
11725       os << "Constant Pool\n";
11726       pool->Print(os);
11727       os << "\n";
11728     }
11729   }
11730 #endif
11731 }
11732 #endif  // ENABLE_DISASSEMBLER
11733
11734
11735 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
11736     Handle<JSObject> object,
11737     int capacity,
11738     int length,
11739     SetFastElementsCapacitySmiMode smi_mode) {
11740   // We should never end in here with a pixel or external array.
11741   DCHECK(!object->HasExternalArrayElements());
11742
11743   // Allocate a new fast elements backing store.
11744   Handle<FixedArray> new_elements =
11745       object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
11746
11747   ElementsKind elements_kind = object->GetElementsKind();
11748   ElementsKind new_elements_kind;
11749   // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
11750   // or if it's allowed and the old elements array contained only SMIs.
11751   bool has_fast_smi_elements =
11752       (smi_mode == kForceSmiElements) ||
11753       ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements());
11754   if (has_fast_smi_elements) {
11755     if (IsHoleyElementsKind(elements_kind)) {
11756       new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
11757     } else {
11758       new_elements_kind = FAST_SMI_ELEMENTS;
11759     }
11760   } else {
11761     if (IsHoleyElementsKind(elements_kind)) {
11762       new_elements_kind = FAST_HOLEY_ELEMENTS;
11763     } else {
11764       new_elements_kind = FAST_ELEMENTS;
11765     }
11766   }
11767   Handle<FixedArrayBase> old_elements(object->elements());
11768   ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
11769   accessor->CopyElements(object, new_elements, elements_kind);
11770
11771   if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
11772     Handle<Map> new_map = (new_elements_kind != elements_kind)
11773         ? GetElementsTransitionMap(object, new_elements_kind)
11774         : handle(object->map());
11775     JSObject::ValidateElements(object);
11776     JSObject::SetMapAndElements(object, new_map, new_elements);
11777
11778     // Transition through the allocation site as well if present.
11779     JSObject::UpdateAllocationSite(object, new_elements_kind);
11780   } else {
11781     Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11782     parameter_map->set(1, *new_elements);
11783   }
11784
11785   if (FLAG_trace_elements_transitions) {
11786     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11787                             object->GetElementsKind(), new_elements);
11788   }
11789
11790   if (object->IsJSArray()) {
11791     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11792   }
11793   return new_elements;
11794 }
11795
11796
11797 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object,
11798                                                       int capacity,
11799                                                       int length) {
11800   // We should never end in here with a pixel or external array.
11801   DCHECK(!object->HasExternalArrayElements());
11802
11803   Handle<FixedArrayBase> elems =
11804       object->GetIsolate()->factory()->NewFixedDoubleArray(capacity);
11805
11806   ElementsKind elements_kind = object->GetElementsKind();
11807   CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS);
11808   ElementsKind new_elements_kind = elements_kind;
11809   if (IsHoleyElementsKind(elements_kind)) {
11810     new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
11811   } else {
11812     new_elements_kind = FAST_DOUBLE_ELEMENTS;
11813   }
11814
11815   Handle<Map> new_map = GetElementsTransitionMap(object, new_elements_kind);
11816
11817   Handle<FixedArrayBase> old_elements(object->elements());
11818   ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
11819   accessor->CopyElements(object, elems, elements_kind);
11820
11821   JSObject::ValidateElements(object);
11822   JSObject::SetMapAndElements(object, new_map, elems);
11823
11824   if (FLAG_trace_elements_transitions) {
11825     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11826                             object->GetElementsKind(), elems);
11827   }
11828
11829   if (object->IsJSArray()) {
11830     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11831   }
11832 }
11833
11834
11835 // static
11836 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11837   DCHECK(capacity >= 0);
11838   array->GetIsolate()->factory()->NewJSArrayStorage(
11839       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11840 }
11841
11842
11843 void JSArray::Expand(Handle<JSArray> array, int required_size) {
11844   ElementsAccessor* accessor = array->GetElementsAccessor();
11845   accessor->SetCapacityAndLength(array, required_size, required_size);
11846 }
11847
11848
11849 // Returns false if the passed-in index is marked non-configurable,
11850 // which will cause the ES5 truncation operation to halt, and thus
11851 // no further old values need be collected.
11852 static bool GetOldValue(Isolate* isolate,
11853                         Handle<JSObject> object,
11854                         uint32_t index,
11855                         List<Handle<Object> >* old_values,
11856                         List<uint32_t>* indices) {
11857   Maybe<PropertyAttributes> maybe =
11858       JSReceiver::GetOwnElementAttribute(object, index);
11859   DCHECK(maybe.IsJust());
11860   DCHECK(maybe.FromJust() != ABSENT);
11861   if (maybe.FromJust() == DONT_DELETE) return false;
11862   Handle<Object> value;
11863   if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
11864     value = Handle<Object>::cast(isolate->factory()->the_hole_value());
11865   } else {
11866     value = Object::GetElement(isolate, object, index).ToHandleChecked();
11867   }
11868   old_values->Add(value);
11869   indices->Add(index);
11870   return true;
11871 }
11872
11873 MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
11874     Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
11875     uint32_t add_count) {
11876   Isolate* isolate = object->GetIsolate();
11877   HandleScope scope(isolate);
11878   Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
11879   Handle<Object> add_count_object =
11880       isolate->factory()->NewNumberFromUint(add_count);
11881
11882   Handle<Object> args[] =
11883       { object, index_object, deleted, add_count_object };
11884
11885   return Execution::Call(
11886       isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
11887       isolate->factory()->undefined_value(), arraysize(args), args);
11888 }
11889
11890
11891 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
11892     Handle<JSArray> object) {
11893   Isolate* isolate = object->GetIsolate();
11894   HandleScope scope(isolate);
11895   Handle<Object> args[] = { object };
11896
11897   return Execution::Call(
11898       isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
11899       isolate->factory()->undefined_value(), arraysize(args), args);
11900 }
11901
11902
11903 MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
11904     Handle<JSArray> object) {
11905   Isolate* isolate = object->GetIsolate();
11906   HandleScope scope(isolate);
11907   Handle<Object> args[] = { object };
11908
11909   return Execution::Call(
11910       isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
11911       isolate->factory()->undefined_value(), arraysize(args), args);
11912 }
11913
11914
11915 MaybeHandle<Object> JSArray::SetElementsLength(
11916     Handle<JSArray> array,
11917     Handle<Object> new_length_handle) {
11918   if (array->HasFastElements()) {
11919     // If the new array won't fit in a some non-trivial fraction of the max old
11920     // space size, then force it to go dictionary mode.
11921     int max_fast_array_size = static_cast<int>(
11922         (array->GetHeap()->MaxOldGenerationSize() / kDoubleSize) / 4);
11923     if (new_length_handle->IsNumber() &&
11924         NumberToInt32(*new_length_handle) >= max_fast_array_size) {
11925       NormalizeElements(array);
11926     }
11927   }
11928
11929   // We should never end in here with a pixel or external array.
11930   DCHECK(array->AllowsSetElementsLength());
11931   if (!array->map()->is_observed()) {
11932     return array->GetElementsAccessor()->SetLength(array, new_length_handle);
11933   }
11934
11935   Isolate* isolate = array->GetIsolate();
11936   List<uint32_t> indices;
11937   List<Handle<Object> > old_values;
11938   Handle<Object> old_length_handle(array->length(), isolate);
11939   uint32_t old_length = 0;
11940   CHECK(old_length_handle->ToArrayIndex(&old_length));
11941   uint32_t new_length = 0;
11942   CHECK(new_length_handle->ToArrayIndex(&new_length));
11943
11944   static const PropertyAttributes kNoAttrFilter = NONE;
11945   int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
11946   if (num_elements > 0) {
11947     if (old_length == static_cast<uint32_t>(num_elements)) {
11948       // Simple case for arrays without holes.
11949       for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
11950         if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
11951       }
11952     } else {
11953       // For sparse arrays, only iterate over existing elements.
11954       // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
11955       // the to-be-removed indices twice.
11956       Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
11957       array->GetOwnElementKeys(*keys, kNoAttrFilter);
11958       while (num_elements-- > 0) {
11959         uint32_t index = NumberToUint32(keys->get(num_elements));
11960         if (index < new_length) break;
11961         if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
11962       }
11963     }
11964   }
11965
11966   Handle<Object> hresult;
11967   ASSIGN_RETURN_ON_EXCEPTION(
11968       isolate, hresult,
11969       array->GetElementsAccessor()->SetLength(array, new_length_handle),
11970       Object);
11971
11972   CHECK(array->length()->ToArrayIndex(&new_length));
11973   if (old_length == new_length) return hresult;
11974
11975   RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
11976
11977   for (int i = 0; i < indices.length(); ++i) {
11978     // For deletions where the property was an accessor, old_values[i]
11979     // will be the hole, which instructs EnqueueChangeRecord to elide
11980     // the "oldValue" property.
11981     RETURN_ON_EXCEPTION(
11982         isolate,
11983         JSObject::EnqueueChangeRecord(
11984             array, "delete", isolate->factory()->Uint32ToString(indices[i]),
11985             old_values[i]),
11986         Object);
11987   }
11988   RETURN_ON_EXCEPTION(isolate,
11989                       JSObject::EnqueueChangeRecord(
11990                           array, "update", isolate->factory()->length_string(),
11991                           old_length_handle),
11992                       Object);
11993
11994   RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
11995
11996   uint32_t index = Min(old_length, new_length);
11997   uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11998   uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11999   Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12000   if (delete_count > 0) {
12001     for (int i = indices.length() - 1; i >= 0; i--) {
12002       // Skip deletions where the property was an accessor, leaving holes
12003       // in the array of old values.
12004       if (old_values[i]->IsTheHole()) continue;
12005       JSObject::SetOwnElement(deleted, indices[i] - index, old_values[i],
12006                               SLOPPY).Assert();
12007     }
12008
12009     RETURN_ON_EXCEPTION(
12010         isolate,
12011         SetProperty(deleted, isolate->factory()->length_string(),
12012                     isolate->factory()->NewNumberFromUint(delete_count),
12013                     STRICT),
12014         Object);
12015   }
12016
12017   RETURN_ON_EXCEPTION(
12018       isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
12019
12020   return hresult;
12021 }
12022
12023
12024 // static
12025 void Map::AddDependentCompilationInfo(Handle<Map> map,
12026                                       DependentCode::DependencyGroup group,
12027                                       CompilationInfo* info) {
12028   Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
12029       handle(map->dependent_code(), info->isolate()), group,
12030       info->object_wrapper());
12031   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
12032   info->dependencies(group)->Add(map, info->zone());
12033 }
12034
12035
12036 // static
12037 void Map::AddDependentCode(Handle<Map> map,
12038                            DependentCode::DependencyGroup group,
12039                            Handle<Code> code) {
12040   Handle<WeakCell> cell = Code::WeakCellFor(code);
12041   Handle<DependentCode> codes = DependentCode::InsertWeakCode(
12042       Handle<DependentCode>(map->dependent_code()), group, cell);
12043   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
12044 }
12045
12046
12047 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
12048   Recompute(entries);
12049 }
12050
12051
12052 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
12053   start_indexes_[0] = 0;
12054   for (int g = 1; g <= kGroupCount; g++) {
12055     int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
12056     start_indexes_[g] = start_indexes_[g - 1] + count;
12057   }
12058 }
12059
12060
12061 DependentCode* DependentCode::ForObject(Handle<HeapObject> object,
12062                                         DependencyGroup group) {
12063   AllowDeferredHandleDereference dependencies_are_safe;
12064   if (group == DependentCode::kPropertyCellChangedGroup) {
12065     return Handle<PropertyCell>::cast(object)->dependent_code();
12066   } else if (group == DependentCode::kAllocationSiteTenuringChangedGroup ||
12067       group == DependentCode::kAllocationSiteTransitionChangedGroup) {
12068     return Handle<AllocationSite>::cast(object)->dependent_code();
12069   }
12070   return Handle<Map>::cast(object)->dependent_code();
12071 }
12072
12073
12074 Handle<DependentCode> DependentCode::InsertCompilationInfo(
12075     Handle<DependentCode> entries, DependencyGroup group,
12076     Handle<Foreign> info) {
12077   return Insert(entries, group, info);
12078 }
12079
12080
12081 Handle<DependentCode> DependentCode::InsertWeakCode(
12082     Handle<DependentCode> entries, DependencyGroup group,
12083     Handle<WeakCell> code_cell) {
12084   return Insert(entries, group, code_cell);
12085 }
12086
12087
12088 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
12089                                             DependencyGroup group,
12090                                             Handle<Object> object) {
12091   GroupStartIndexes starts(*entries);
12092   int start = starts.at(group);
12093   int end = starts.at(group + 1);
12094   int number_of_entries = starts.number_of_entries();
12095   // Check for existing entry to avoid duplicates.
12096   for (int i = start; i < end; i++) {
12097     if (entries->object_at(i) == *object) return entries;
12098   }
12099   if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
12100     entries = EnsureSpace(entries);
12101     // The number of codes can change after Compact and GC.
12102     starts.Recompute(*entries);
12103     start = starts.at(group);
12104     end = starts.at(group + 1);
12105   }
12106
12107   entries->ExtendGroup(group);
12108   entries->set_object_at(end, *object);
12109   entries->set_number_of_entries(group, end + 1 - start);
12110   return entries;
12111 }
12112
12113
12114 Handle<DependentCode> DependentCode::EnsureSpace(
12115     Handle<DependentCode> entries) {
12116   if (entries->length() == 0) {
12117     entries = Handle<DependentCode>::cast(
12118         FixedArray::CopySize(entries, kCodesStartIndex + 1, TENURED));
12119     for (int g = 0; g < kGroupCount; g++) {
12120       entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
12121     }
12122     return entries;
12123   }
12124   if (entries->Compact()) return entries;
12125   GroupStartIndexes starts(*entries);
12126   int capacity =
12127       kCodesStartIndex + DependentCode::Grow(starts.number_of_entries());
12128   return Handle<DependentCode>::cast(
12129       FixedArray::CopySize(entries, capacity, TENURED));
12130 }
12131
12132
12133 bool DependentCode::Compact() {
12134   GroupStartIndexes starts(this);
12135   int n = 0;
12136   for (int g = 0; g < kGroupCount; g++) {
12137     int start = starts.at(g);
12138     int end = starts.at(g + 1);
12139     int count = 0;
12140     DCHECK(start >= n);
12141     for (int i = start; i < end; i++) {
12142       Object* obj = object_at(i);
12143       if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) {
12144         if (i != n + count) {
12145           copy(i, n + count);
12146         }
12147         count++;
12148       }
12149     }
12150     if (count != end - start) {
12151       set_number_of_entries(static_cast<DependencyGroup>(g), count);
12152     }
12153     n += count;
12154   }
12155   return n < starts.number_of_entries();
12156 }
12157
12158
12159 void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
12160                                          WeakCell* code_cell) {
12161   DisallowHeapAllocation no_gc;
12162   GroupStartIndexes starts(this);
12163   int start = starts.at(group);
12164   int end = starts.at(group + 1);
12165   for (int i = start; i < end; i++) {
12166     if (object_at(i) == info) {
12167       set_object_at(i, code_cell);
12168       break;
12169     }
12170   }
12171
12172 #ifdef DEBUG
12173   for (int i = start; i < end; i++) {
12174     DCHECK(object_at(i) != info);
12175   }
12176 #endif
12177 }
12178
12179
12180 void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
12181                                           Foreign* info) {
12182   DisallowHeapAllocation no_allocation;
12183   GroupStartIndexes starts(this);
12184   int start = starts.at(group);
12185   int end = starts.at(group + 1);
12186   // Find compilation info wrapper.
12187   int info_pos = -1;
12188   for (int i = start; i < end; i++) {
12189     if (object_at(i) == info) {
12190       info_pos = i;
12191       break;
12192     }
12193   }
12194   if (info_pos == -1) return;  // Not found.
12195   int gap = info_pos;
12196   // Use the last of each group to fill the gap in the previous group.
12197   for (int i = group; i < kGroupCount; i++) {
12198     int last_of_group = starts.at(i + 1) - 1;
12199     DCHECK(last_of_group >= gap);
12200     if (last_of_group == gap) continue;
12201     copy(last_of_group, gap);
12202     gap = last_of_group;
12203   }
12204   DCHECK(gap == starts.number_of_entries() - 1);
12205   clear_at(gap);  // Clear last gap.
12206   set_number_of_entries(group, end - start - 1);
12207
12208 #ifdef DEBUG
12209   for (int i = start; i < end - 1; i++) {
12210     DCHECK(object_at(i) != info);
12211   }
12212 #endif
12213 }
12214
12215
12216 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) {
12217   GroupStartIndexes starts(this);
12218   int start = starts.at(group);
12219   int end = starts.at(group + 1);
12220   for (int i = start; i < end; i++) {
12221     if (object_at(i) == code_cell) return true;
12222   }
12223   return false;
12224 }
12225
12226
12227 bool DependentCode::MarkCodeForDeoptimization(
12228     Isolate* isolate,
12229     DependentCode::DependencyGroup group) {
12230   DisallowHeapAllocation no_allocation_scope;
12231   DependentCode::GroupStartIndexes starts(this);
12232   int start = starts.at(group);
12233   int end = starts.at(group + 1);
12234   int code_entries = starts.number_of_entries();
12235   if (start == end) return false;
12236
12237   // Mark all the code that needs to be deoptimized.
12238   bool marked = false;
12239   bool invalidate_embedded_objects = group == kWeakCodeGroup;
12240   for (int i = start; i < end; i++) {
12241     Object* obj = object_at(i);
12242     if (obj->IsWeakCell()) {
12243       WeakCell* cell = WeakCell::cast(obj);
12244       if (cell->cleared()) continue;
12245       Code* code = Code::cast(cell->value());
12246       if (!code->marked_for_deoptimization()) {
12247         SetMarkedForDeoptimization(code, group);
12248         if (invalidate_embedded_objects) {
12249           code->InvalidateEmbeddedObjects();
12250         }
12251         marked = true;
12252       }
12253     } else {
12254       DCHECK(obj->IsForeign());
12255       CompilationInfo* info = reinterpret_cast<CompilationInfo*>(
12256           Foreign::cast(obj)->foreign_address());
12257       info->AbortDueToDependencyChange();
12258     }
12259   }
12260   // Compact the array by moving all subsequent groups to fill in the new holes.
12261   for (int src = end, dst = start; src < code_entries; src++, dst++) {
12262     copy(src, dst);
12263   }
12264   // Now the holes are at the end of the array, zap them for heap-verifier.
12265   int removed = end - start;
12266   for (int i = code_entries - removed; i < code_entries; i++) {
12267     clear_at(i);
12268   }
12269   set_number_of_entries(group, 0);
12270   return marked;
12271 }
12272
12273
12274 void DependentCode::DeoptimizeDependentCodeGroup(
12275     Isolate* isolate,
12276     DependentCode::DependencyGroup group) {
12277   DCHECK(AllowCodeDependencyChange::IsAllowed());
12278   DisallowHeapAllocation no_allocation_scope;
12279   bool marked = MarkCodeForDeoptimization(isolate, group);
12280   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
12281 }
12282
12283
12284 void DependentCode::SetMarkedForDeoptimization(Code* code,
12285                                                DependencyGroup group) {
12286   code->set_marked_for_deoptimization(true);
12287   if (FLAG_trace_deopt &&
12288       (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
12289     DeoptimizationInputData* deopt_data =
12290         DeoptimizationInputData::cast(code->deoptimization_data());
12291     CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
12292     PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
12293                          " (opt #%d) for deoptimization, reason: %s]\n",
12294            reinterpret_cast<intptr_t>(code),
12295            deopt_data->OptimizationId()->value(), DependencyGroupName(group));
12296   }
12297 }
12298
12299
12300 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
12301   switch (group) {
12302     case kWeakCodeGroup:
12303       return "weak-code";
12304     case kTransitionGroup:
12305       return "transition";
12306     case kPrototypeCheckGroup:
12307       return "prototype-check";
12308     case kElementsCantBeAddedGroup:
12309       return "elements-cant-be-added";
12310     case kPropertyCellChangedGroup:
12311       return "property-cell-changed";
12312     case kFieldTypeGroup:
12313       return "field-type";
12314     case kInitialMapChangedGroup:
12315       return "initial-map-changed";
12316     case kAllocationSiteTenuringChangedGroup:
12317       return "allocation-site-tenuring-changed";
12318     case kAllocationSiteTransitionChangedGroup:
12319       return "allocation-site-transition-changed";
12320   }
12321   UNREACHABLE();
12322   return "?";
12323 }
12324
12325
12326 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
12327                                        Handle<Object> prototype,
12328                                        PrototypeOptimizationMode mode) {
12329   Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
12330   if (new_map.is_null()) {
12331     new_map = Copy(map, "TransitionToPrototype");
12332     TransitionArray::PutPrototypeTransition(map, prototype, new_map);
12333     new_map->SetPrototype(prototype, mode);
12334   }
12335   return new_map;
12336 }
12337
12338
12339 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12340                                            Handle<Object> value,
12341                                            bool from_javascript) {
12342 #ifdef DEBUG
12343   int size = object->Size();
12344 #endif
12345
12346   Isolate* isolate = object->GetIsolate();
12347   Heap* heap = isolate->heap();
12348   // Silently ignore the change if value is not a JSObject or null.
12349   // SpiderMonkey behaves this way.
12350   if (!value->IsJSReceiver() && !value->IsNull()) return value;
12351
12352   // From 8.6.2 Object Internal Methods
12353   // ...
12354   // In addition, if [[Extensible]] is false the value of the [[Class]] and
12355   // [[Prototype]] internal properties of the object may not be modified.
12356   // ...
12357   // Implementation specific extensions that modify [[Class]], [[Prototype]]
12358   // or [[Extensible]] must not violate the invariants defined in the preceding
12359   // paragraph.
12360   if (!object->map()->is_extensible()) {
12361     Handle<Object> args[] = { object };
12362     THROW_NEW_ERROR(isolate, NewTypeError("non_extensible_proto",
12363                                           HandleVector(args, arraysize(args))),
12364                     Object);
12365   }
12366
12367   // Before we can set the prototype we need to be sure
12368   // prototype cycles are prevented.
12369   // It is sufficient to validate that the receiver is not in the new prototype
12370   // chain.
12371   for (PrototypeIterator iter(isolate, *value,
12372                               PrototypeIterator::START_AT_RECEIVER);
12373        !iter.IsAtEnd(); iter.Advance()) {
12374     if (JSReceiver::cast(iter.GetCurrent()) == *object) {
12375       // Cycle detected.
12376       THROW_NEW_ERROR(isolate,
12377                       NewError("cyclic_proto", HandleVector<Object>(NULL, 0)),
12378                       Object);
12379     }
12380   }
12381
12382   bool dictionary_elements_in_chain =
12383       object->map()->DictionaryElementsInPrototypeChainOnly();
12384   Handle<JSObject> real_receiver = object;
12385
12386   if (from_javascript) {
12387     // Find the first object in the chain whose prototype object is not
12388     // hidden and set the new prototype on that object.
12389     PrototypeIterator iter(isolate, real_receiver);
12390     while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
12391       real_receiver =
12392           Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
12393       iter.Advance();
12394       if (!real_receiver->map()->is_extensible()) {
12395         Handle<Object> args[] = {object};
12396         THROW_NEW_ERROR(isolate,
12397                         NewTypeError("non_extensible_proto",
12398                                      HandleVector(args, arraysize(args))),
12399                         Object);
12400       }
12401     }
12402   }
12403
12404   // Set the new prototype of the object.
12405   Handle<Map> map(real_receiver->map());
12406
12407   // Nothing to do if prototype is already set.
12408   if (map->prototype() == *value) return value;
12409
12410   PrototypeOptimizationMode mode =
12411       from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
12412   Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
12413   DCHECK(new_map->prototype() == *value);
12414   JSObject::MigrateToMap(real_receiver, new_map);
12415
12416   if (from_javascript && !dictionary_elements_in_chain &&
12417       new_map->DictionaryElementsInPrototypeChainOnly()) {
12418     // If the prototype chain didn't previously have element callbacks, then
12419     // KeyedStoreICs need to be cleared to ensure any that involve this
12420     // map go generic.
12421     object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
12422   }
12423
12424   heap->ClearInstanceofCache();
12425   DCHECK(size == object->Size());
12426   return value;
12427 }
12428
12429
12430 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
12431                                         Arguments* args,
12432                                         uint32_t first_arg,
12433                                         uint32_t arg_count,
12434                                         EnsureElementsMode mode) {
12435   // Elements in |Arguments| are ordered backwards (because they're on the
12436   // stack), but the method that's called here iterates over them in forward
12437   // direction.
12438   return EnsureCanContainElements(
12439       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
12440 }
12441
12442
12443 MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair(
12444     Handle<JSObject> object,
12445     uint32_t index) {
12446   if (object->IsJSGlobalProxy()) {
12447     PrototypeIterator iter(object->GetIsolate(), object);
12448     if (iter.IsAtEnd()) return MaybeHandle<AccessorPair>();
12449     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
12450     return GetOwnElementAccessorPair(
12451         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
12452   }
12453
12454   // Check for lookup interceptor.
12455   if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>();
12456
12457   return object->GetElementsAccessor()->GetAccessorPair(object, index);
12458 }
12459
12460
12461 MaybeHandle<Object> JSObject::SetElementWithInterceptor(
12462     Handle<JSObject> object, uint32_t index, Handle<Object> value,
12463     PropertyAttributes attributes, LanguageMode language_mode,
12464     bool check_prototype, SetPropertyMode set_mode) {
12465   Isolate* isolate = object->GetIsolate();
12466
12467   // Make sure that the top context does not change when doing
12468   // callbacks or interceptor calls.
12469   AssertNoContextChange ncc(isolate);
12470
12471   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
12472   if (!interceptor->setter()->IsUndefined()) {
12473     v8::IndexedPropertySetterCallback setter =
12474         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
12475     LOG(isolate,
12476         ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
12477     PropertyCallbackArguments args(isolate, interceptor->data(), *object,
12478                                    *object);
12479     v8::Handle<v8::Value> result =
12480         args.Call(setter, index, v8::Utils::ToLocal(value));
12481     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12482     if (!result.IsEmpty()) return value;
12483   }
12484
12485   return SetElementWithoutInterceptor(object, index, value, attributes,
12486                                       language_mode, check_prototype, set_mode);
12487 }
12488
12489
12490 MaybeHandle<Object> JSObject::GetElementWithCallback(
12491     Handle<JSObject> object,
12492     Handle<Object> receiver,
12493     Handle<Object> structure,
12494     uint32_t index,
12495     Handle<Object> holder) {
12496   Isolate* isolate = object->GetIsolate();
12497   DCHECK(!structure->IsForeign());
12498   // api style callbacks.
12499   if (structure->IsExecutableAccessorInfo()) {
12500     Handle<ExecutableAccessorInfo> data =
12501         Handle<ExecutableAccessorInfo>::cast(structure);
12502     Object* fun_obj = data->getter();
12503     v8::AccessorNameGetterCallback call_fun =
12504         v8::ToCData<v8::AccessorNameGetterCallback>(fun_obj);
12505     if (call_fun == NULL) return isolate->factory()->undefined_value();
12506     Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder);
12507     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12508     Handle<String> key = isolate->factory()->NumberToString(number);
12509     LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key));
12510     PropertyCallbackArguments
12511         args(isolate, data->data(), *receiver, *holder_handle);
12512     v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
12513     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12514     if (result.IsEmpty()) return isolate->factory()->undefined_value();
12515     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12516     result_internal->VerifyApiCallResultType();
12517     // Rebox handle before return.
12518     return handle(*result_internal, isolate);
12519   }
12520
12521   // __defineGetter__ callback
12522   if (structure->IsAccessorPair()) {
12523     Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
12524                           isolate);
12525     if (getter->IsSpecFunction()) {
12526       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12527       return GetPropertyWithDefinedGetter(
12528           receiver, Handle<JSReceiver>::cast(getter));
12529     }
12530     // Getter is not a function.
12531     return isolate->factory()->undefined_value();
12532   }
12533
12534   UNREACHABLE();
12535   return MaybeHandle<Object>();
12536 }
12537
12538
12539 MaybeHandle<Object> JSObject::SetElementWithCallback(
12540     Handle<Object> object, Handle<Object> structure, uint32_t index,
12541     Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) {
12542   Isolate* isolate = holder->GetIsolate();
12543
12544   // We should never get here to initialize a const with the hole
12545   // value since a const declaration would conflict with the setter.
12546   DCHECK(!value->IsTheHole());
12547   DCHECK(!structure->IsForeign());
12548   if (structure->IsExecutableAccessorInfo()) {
12549     // api style callbacks
12550     Handle<ExecutableAccessorInfo> data =
12551         Handle<ExecutableAccessorInfo>::cast(structure);
12552     Object* call_obj = data->setter();
12553     v8::AccessorNameSetterCallback call_fun =
12554         v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
12555     if (call_fun == NULL) return value;
12556     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12557     Handle<String> key(isolate->factory()->NumberToString(number));
12558     LOG(isolate, ApiNamedPropertyAccess("store", *holder, *key));
12559     PropertyCallbackArguments
12560         args(isolate, data->data(), *object, *holder);
12561     args.Call(call_fun,
12562               v8::Utils::ToLocal(key),
12563               v8::Utils::ToLocal(value));
12564     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12565     return value;
12566   }
12567
12568   if (structure->IsAccessorPair()) {
12569     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
12570     if (setter->IsSpecFunction()) {
12571       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12572       return SetPropertyWithDefinedSetter(
12573           object, Handle<JSReceiver>::cast(setter), value);
12574     } else {
12575       if (is_sloppy(language_mode)) return value;
12576       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
12577       Handle<Object> args[] = {key, holder};
12578       THROW_NEW_ERROR(isolate,
12579                       NewTypeError("no_setter_in_callback",
12580                                    HandleVector(args, arraysize(args))),
12581                       Object);
12582     }
12583   }
12584
12585   UNREACHABLE();
12586   return MaybeHandle<Object>();
12587 }
12588
12589
12590 bool JSObject::HasFastArgumentsElements() {
12591   Heap* heap = GetHeap();
12592   if (!elements()->IsFixedArray()) return false;
12593   FixedArray* elements = FixedArray::cast(this->elements());
12594   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12595     return false;
12596   }
12597   FixedArray* arguments = FixedArray::cast(elements->get(1));
12598   return !arguments->IsDictionary();
12599 }
12600
12601
12602 bool JSObject::HasDictionaryArgumentsElements() {
12603   Heap* heap = GetHeap();
12604   if (!elements()->IsFixedArray()) return false;
12605   FixedArray* elements = FixedArray::cast(this->elements());
12606   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12607     return false;
12608   }
12609   FixedArray* arguments = FixedArray::cast(elements->get(1));
12610   return arguments->IsDictionary();
12611 }
12612
12613
12614 // Adding n elements in fast case is O(n*n).
12615 // Note: revisit design to have dual undefined values to capture absent
12616 // elements.
12617 MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
12618                                              uint32_t index,
12619                                              Handle<Object> value,
12620                                              LanguageMode language_mode,
12621                                              bool check_prototype) {
12622   DCHECK(object->HasFastSmiOrObjectElements() ||
12623          object->HasFastArgumentsElements());
12624
12625   Isolate* isolate = object->GetIsolate();
12626
12627   // Array optimizations rely on the prototype lookups of Array objects always
12628   // returning undefined. If there is a store to the initial prototype object,
12629   // make sure all of these optimizations are invalidated.
12630   if (isolate->is_initial_object_prototype(*object) ||
12631       isolate->is_initial_array_prototype(*object)) {
12632     object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate,
12633         DependentCode::kElementsCantBeAddedGroup);
12634   }
12635
12636   Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12637   if (backing_store->map() ==
12638       isolate->heap()->sloppy_arguments_elements_map()) {
12639     backing_store = handle(FixedArray::cast(backing_store->get(1)));
12640   } else {
12641     backing_store = EnsureWritableFastElements(object);
12642   }
12643   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12644
12645   if (check_prototype &&
12646       (index >= capacity || backing_store->get(index)->IsTheHole())) {
12647     bool found;
12648     MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12649         object, index, value, &found, language_mode);
12650     if (found) return result;
12651   }
12652
12653   uint32_t new_capacity = capacity;
12654   // Check if the length property of this object needs to be updated.
12655   uint32_t array_length = 0;
12656   bool must_update_array_length = false;
12657   bool introduces_holes = true;
12658   if (object->IsJSArray()) {
12659     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12660     introduces_holes = index > array_length;
12661     if (index >= array_length) {
12662       must_update_array_length = true;
12663       array_length = index + 1;
12664     }
12665   } else {
12666     introduces_holes = index >= capacity;
12667   }
12668
12669   // If the array is growing, and it's not growth by a single element at the
12670   // end, make sure that the ElementsKind is HOLEY.
12671   ElementsKind elements_kind = object->GetElementsKind();
12672   if (introduces_holes &&
12673       IsFastElementsKind(elements_kind) &&
12674       !IsFastHoleyElementsKind(elements_kind)) {
12675     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12676     TransitionElementsKind(object, transitioned_kind);
12677   }
12678
12679   // Check if the capacity of the backing store needs to be increased, or if
12680   // a transition to slow elements is necessary.
12681   if (index >= capacity) {
12682     bool convert_to_slow = true;
12683     if ((index - capacity) < kMaxGap) {
12684       new_capacity = NewElementsCapacity(index + 1);
12685       DCHECK(new_capacity > index);
12686       if (!object->ShouldConvertToSlowElements(new_capacity)) {
12687         convert_to_slow = false;
12688       }
12689     }
12690     if (convert_to_slow) {
12691       NormalizeElements(object);
12692       return SetDictionaryElement(object, index, value, NONE, language_mode,
12693                                   check_prototype);
12694     }
12695   }
12696   // Convert to fast double elements if appropriate.
12697   if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12698     // Consider fixing the boilerplate as well if we have one.
12699     ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
12700         ? FAST_HOLEY_DOUBLE_ELEMENTS
12701         : FAST_DOUBLE_ELEMENTS;
12702
12703     UpdateAllocationSite(object, to_kind);
12704
12705     SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12706     FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12707     JSObject::ValidateElements(object);
12708     return value;
12709   }
12710   // Change elements kind from Smi-only to generic FAST if necessary.
12711   if (object->HasFastSmiElements() && !value->IsSmi()) {
12712     ElementsKind kind = object->HasFastHoleyElements()
12713         ? FAST_HOLEY_ELEMENTS
12714         : FAST_ELEMENTS;
12715
12716     UpdateAllocationSite(object, kind);
12717     Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12718     JSObject::MigrateToMap(object, new_map);
12719     DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12720   }
12721   // Increase backing store capacity if that's been decided previously.
12722   if (new_capacity != capacity) {
12723     SetFastElementsCapacitySmiMode smi_mode =
12724         value->IsSmi() && object->HasFastSmiElements()
12725             ? kAllowSmiElements
12726             : kDontAllowSmiElements;
12727     Handle<FixedArray> new_elements =
12728         SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12729                                          smi_mode);
12730     new_elements->set(index, *value);
12731     JSObject::ValidateElements(object);
12732     return value;
12733   }
12734
12735   // Finally, set the new element and length.
12736   DCHECK(object->elements()->IsFixedArray());
12737   backing_store->set(index, *value);
12738   if (must_update_array_length) {
12739     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12740   }
12741   return value;
12742 }
12743
12744
12745 MaybeHandle<Object> JSObject::SetDictionaryElement(
12746     Handle<JSObject> object, uint32_t index, Handle<Object> value,
12747     PropertyAttributes attributes, LanguageMode language_mode,
12748     bool check_prototype, SetPropertyMode set_mode) {
12749   DCHECK(object->HasDictionaryElements() ||
12750          object->HasDictionaryArgumentsElements());
12751   Isolate* isolate = object->GetIsolate();
12752
12753   // Insert element in the dictionary.
12754   Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12755   bool is_arguments =
12756       (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12757   Handle<SeededNumberDictionary> dictionary(is_arguments
12758     ? SeededNumberDictionary::cast(elements->get(1))
12759     : SeededNumberDictionary::cast(*elements));
12760
12761   int entry = dictionary->FindEntry(index);
12762   if (entry != SeededNumberDictionary::kNotFound) {
12763     Handle<Object> element(dictionary->ValueAt(entry), isolate);
12764     PropertyDetails details = dictionary->DetailsAt(entry);
12765     if (details.type() == ACCESSOR_CONSTANT && set_mode == SET_PROPERTY) {
12766       return SetElementWithCallback(object, element, index, value, object,
12767                                     language_mode);
12768     } else if (set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
12769                details.kind() == kAccessor) {
12770       return RedefineNonconfigurableProperty(
12771           isolate, isolate->factory()->NewNumberFromUint(index),
12772           isolate->factory()->undefined_value(), language_mode);
12773
12774     } else if ((set_mode == DEFINE_PROPERTY && !details.IsConfigurable() &&
12775                 details.IsReadOnly()) ||
12776                (set_mode == SET_PROPERTY && details.IsReadOnly() &&
12777                 !element->IsTheHole())) {
12778       // If a value has not been initialized we allow writing to it even if it
12779       // is read-only (a declared const that has not been initialized).
12780       return WriteToReadOnlyProperty(
12781           isolate, object, isolate->factory()->NewNumberFromUint(index),
12782           isolate->factory()->undefined_value(), language_mode);
12783     } else {
12784       DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
12785              element->IsTheHole());
12786       dictionary->UpdateMaxNumberKey(index);
12787       if (set_mode == DEFINE_PROPERTY) {
12788         details = PropertyDetails(attributes, DATA, details.dictionary_index(),
12789                                   PropertyCellType::kInvalid);
12790         dictionary->DetailsAtPut(entry, details);
12791       }
12792
12793       // Elements of the arguments object in slow mode might be slow aliases.
12794       if (is_arguments && element->IsAliasedArgumentsEntry()) {
12795         Handle<AliasedArgumentsEntry> entry =
12796             Handle<AliasedArgumentsEntry>::cast(element);
12797         Handle<Context> context(Context::cast(elements->get(0)));
12798         int context_index = entry->aliased_context_slot();
12799         DCHECK(!context->get(context_index)->IsTheHole());
12800         context->set(context_index, *value);
12801         // For elements that are still writable we keep slow aliasing.
12802         if (!details.IsReadOnly()) value = element;
12803       }
12804       dictionary->ValueAtPut(entry, *value);
12805     }
12806   } else {
12807     // Index not already used. Look for an accessor in the prototype chain.
12808     // Can cause GC!
12809     if (check_prototype) {
12810       bool found;
12811       MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12812           object, index, value, &found, language_mode);
12813       if (found) return result;
12814     }
12815
12816     // When we set the is_extensible flag to false we always force the
12817     // element into dictionary mode (and force them to stay there).
12818     if (!object->map()->is_extensible()) {
12819       if (is_sloppy(language_mode)) {
12820         return isolate->factory()->undefined_value();
12821       } else {
12822         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12823         Handle<String> name = isolate->factory()->NumberToString(number);
12824         Handle<Object> args[] = {name};
12825         THROW_NEW_ERROR(isolate,
12826                         NewTypeError("object_not_extensible",
12827                                      HandleVector(args, arraysize(args))),
12828                         Object);
12829       }
12830     }
12831
12832     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid);
12833     Handle<SeededNumberDictionary> new_dictionary =
12834         SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
12835                                                details);
12836     if (*dictionary != *new_dictionary) {
12837       if (is_arguments) {
12838         elements->set(1, *new_dictionary);
12839       } else {
12840         object->set_elements(*new_dictionary);
12841       }
12842       dictionary = new_dictionary;
12843     }
12844   }
12845
12846   // Update the array length if this JSObject is an array.
12847   if (object->IsJSArray()) {
12848     JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index,
12849                                           value);
12850   }
12851
12852   // Attempt to put this object back in fast case.
12853   if (object->ShouldConvertToFastElements()) {
12854     uint32_t new_length = 0;
12855     if (object->IsJSArray()) {
12856       CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length));
12857     } else {
12858       new_length = dictionary->max_number_key() + 1;
12859     }
12860     bool has_smi_only_elements = false;
12861     bool should_convert_to_fast_double_elements =
12862         object->ShouldConvertToFastDoubleElements(&has_smi_only_elements);
12863     SetFastElementsCapacitySmiMode smi_mode =
12864         has_smi_only_elements ? kForceSmiElements : kAllowSmiElements;
12865
12866     if (should_convert_to_fast_double_elements) {
12867       SetFastDoubleElementsCapacityAndLength(object, new_length, new_length);
12868     } else {
12869       SetFastElementsCapacityAndLength(object, new_length, new_length,
12870                                        smi_mode);
12871     }
12872     JSObject::ValidateElements(object);
12873 #ifdef DEBUG
12874     if (FLAG_trace_normalization) {
12875       OFStream os(stdout);
12876       os << "Object elements are fast case again:\n";
12877       object->Print(os);
12878     }
12879 #endif
12880   }
12881   return value;
12882 }
12883
12884 MaybeHandle<Object> JSObject::SetFastDoubleElement(Handle<JSObject> object,
12885                                                    uint32_t index,
12886                                                    Handle<Object> value,
12887                                                    LanguageMode language_mode,
12888                                                    bool check_prototype) {
12889   DCHECK(object->HasFastDoubleElements());
12890
12891   Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12892   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
12893
12894   // If storing to an element that isn't in the array, pass the store request
12895   // up the prototype chain before storing in the receiver's elements.
12896   if (check_prototype &&
12897       (index >= elms_length ||
12898        Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
12899     bool found;
12900     MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12901         object, index, value, &found, language_mode);
12902     if (found) return result;
12903   }
12904
12905   // If the value object is not a heap number, switch to fast elements and try
12906   // again.
12907   bool value_is_smi = value->IsSmi();
12908   bool introduces_holes = true;
12909   uint32_t length = elms_length;
12910   if (object->IsJSArray()) {
12911     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length));
12912     introduces_holes = index > length;
12913   } else {
12914     introduces_holes = index >= elms_length;
12915   }
12916
12917   if (!value->IsNumber()) {
12918     SetFastElementsCapacityAndLength(object, elms_length, length,
12919                                      kDontAllowSmiElements);
12920     Handle<Object> result;
12921     ASSIGN_RETURN_ON_EXCEPTION(
12922         object->GetIsolate(), result,
12923         SetFastElement(object, index, value, language_mode, check_prototype),
12924         Object);
12925     JSObject::ValidateElements(object);
12926     return result;
12927   }
12928
12929   double double_value = value_is_smi
12930       ? static_cast<double>(Handle<Smi>::cast(value)->value())
12931       : Handle<HeapNumber>::cast(value)->value();
12932
12933   // If the array is growing, and it's not growth by a single element at the
12934   // end, make sure that the ElementsKind is HOLEY.
12935   ElementsKind elements_kind = object->GetElementsKind();
12936   if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
12937     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12938     TransitionElementsKind(object, transitioned_kind);
12939   }
12940
12941   // Check whether there is extra space in the fixed array.
12942   if (index < elms_length) {
12943     Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
12944     elms->set(index, double_value);
12945     if (object->IsJSArray()) {
12946       // Update the length of the array if needed.
12947       uint32_t array_length = 0;
12948       CHECK(
12949           Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12950       if (index >= array_length) {
12951         Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12952       }
12953     }
12954     return value;
12955   }
12956
12957   // Allow gap in fast case.
12958   if ((index - elms_length) < kMaxGap) {
12959     // Try allocating extra space.
12960     int new_capacity = NewElementsCapacity(index+1);
12961     if (!object->ShouldConvertToSlowElements(new_capacity)) {
12962       DCHECK(static_cast<uint32_t>(new_capacity) > index);
12963       SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
12964       FixedDoubleArray::cast(object->elements())->set(index, double_value);
12965       JSObject::ValidateElements(object);
12966       return value;
12967     }
12968   }
12969
12970   // Otherwise default to slow case.
12971   DCHECK(object->HasFastDoubleElements());
12972   DCHECK(object->map()->has_fast_double_elements());
12973   DCHECK(object->elements()->IsFixedDoubleArray() ||
12974          object->elements()->length() == 0);
12975
12976   NormalizeElements(object);
12977   DCHECK(object->HasDictionaryElements());
12978   return SetElement(object, index, value, NONE, language_mode, check_prototype);
12979 }
12980
12981
12982 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12983                                            uint32_t index, Handle<Object> value,
12984                                            PropertyAttributes attributes,
12985                                            LanguageMode language_mode) {
12986   if (object->IsJSProxy()) {
12987     return JSProxy::SetElementWithHandler(Handle<JSProxy>::cast(object), object,
12988                                           index, value, language_mode);
12989   }
12990   return JSObject::SetElement(Handle<JSObject>::cast(object), index, value,
12991                               attributes, language_mode);
12992 }
12993
12994
12995 MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
12996                                             uint32_t index,
12997                                             Handle<Object> value,
12998                                             PropertyAttributes attributes,
12999                                             LanguageMode language_mode) {
13000   DCHECK(!object->HasExternalArrayElements());
13001   return JSObject::SetElement(object, index, value, attributes, language_mode,
13002                               false);
13003 }
13004
13005
13006 MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object,
13007                                          uint32_t index, Handle<Object> value,
13008                                          PropertyAttributes attributes,
13009                                          LanguageMode language_mode,
13010                                          bool check_prototype,
13011                                          SetPropertyMode set_mode) {
13012   Isolate* isolate = object->GetIsolate();
13013
13014   if (object->HasExternalArrayElements() ||
13015       object->HasFixedTypedArrayElements()) {
13016     if (!value->IsNumber() && !value->IsUndefined()) {
13017       ASSIGN_RETURN_ON_EXCEPTION(
13018           isolate, value,
13019           Execution::ToNumber(isolate, value), Object);
13020     }
13021   }
13022
13023   // Check access rights if needed.
13024   if (object->IsAccessCheckNeeded()) {
13025     if (!isolate->MayAccess(object)) {
13026       isolate->ReportFailedAccessCheck(object);
13027       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13028       return value;
13029     }
13030   }
13031
13032   if (object->IsJSGlobalProxy()) {
13033     PrototypeIterator iter(isolate, object);
13034     if (iter.IsAtEnd()) return value;
13035     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
13036     return SetElement(
13037         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
13038         value, attributes, language_mode, check_prototype, set_mode);
13039   }
13040
13041   // Don't allow element properties to be redefined for external arrays.
13042   if ((object->HasExternalArrayElements() ||
13043           object->HasFixedTypedArrayElements()) &&
13044       set_mode == DEFINE_PROPERTY) {
13045     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
13046     Handle<Object> args[] = { object, number };
13047     THROW_NEW_ERROR(isolate, NewTypeError("redef_external_array_element",
13048                                           HandleVector(args, arraysize(args))),
13049                     Object);
13050   }
13051
13052   // Normalize the elements to enable attributes on the property.
13053   if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
13054     Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
13055     // Make sure that we never go back to fast case.
13056     dictionary->set_requires_slow_elements();
13057   }
13058
13059   if (!object->map()->is_observed()) {
13060     return object->HasIndexedInterceptor()
13061                ? SetElementWithInterceptor(object, index, value, attributes,
13062                                            language_mode, check_prototype,
13063                                            set_mode)
13064                : SetElementWithoutInterceptor(object, index, value, attributes,
13065                                               language_mode, check_prototype,
13066                                               set_mode);
13067   }
13068
13069   Maybe<PropertyAttributes> maybe =
13070       JSReceiver::GetOwnElementAttribute(object, index);
13071   if (!maybe.IsJust()) return MaybeHandle<Object>();
13072   PropertyAttributes old_attributes = maybe.FromJust();
13073
13074   Handle<Object> old_value = isolate->factory()->the_hole_value();
13075   Handle<Object> old_length_handle;
13076   Handle<Object> new_length_handle;
13077
13078   if (old_attributes != ABSENT) {
13079     if (GetOwnElementAccessorPair(object, index).is_null()) {
13080       old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
13081     }
13082   } else if (object->IsJSArray()) {
13083     // Store old array length in case adding an element grows the array.
13084     old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13085                                isolate);
13086   }
13087
13088   // Check for lookup interceptor
13089   Handle<Object> result;
13090   ASSIGN_RETURN_ON_EXCEPTION(
13091       isolate, result,
13092       object->HasIndexedInterceptor()
13093           ? SetElementWithInterceptor(object, index, value, attributes,
13094                                       language_mode, check_prototype, set_mode)
13095           : SetElementWithoutInterceptor(object, index, value, attributes,
13096                                          language_mode, check_prototype,
13097                                          set_mode),
13098       Object);
13099
13100   Handle<String> name = isolate->factory()->Uint32ToString(index);
13101   maybe = GetOwnElementAttribute(object, index);
13102   if (!maybe.IsJust()) return MaybeHandle<Object>();
13103   PropertyAttributes new_attributes = maybe.FromJust();
13104
13105   if (old_attributes == ABSENT) {
13106     if (object->IsJSArray() &&
13107         !old_length_handle->SameValue(
13108             Handle<JSArray>::cast(object)->length())) {
13109       new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13110                                  isolate);
13111       uint32_t old_length = 0;
13112       uint32_t new_length = 0;
13113       CHECK(old_length_handle->ToArrayIndex(&old_length));
13114       CHECK(new_length_handle->ToArrayIndex(&new_length));
13115
13116       RETURN_ON_EXCEPTION(
13117           isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object);
13118       RETURN_ON_EXCEPTION(
13119           isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
13120       RETURN_ON_EXCEPTION(
13121           isolate, EnqueueChangeRecord(object, "update",
13122                                        isolate->factory()->length_string(),
13123                                        old_length_handle),
13124           Object);
13125       RETURN_ON_EXCEPTION(
13126           isolate, EndPerformSplice(Handle<JSArray>::cast(object)), Object);
13127       Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
13128       RETURN_ON_EXCEPTION(
13129           isolate,
13130           EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length,
13131                               deleted, new_length - old_length),
13132           Object);
13133     } else {
13134       RETURN_ON_EXCEPTION(
13135           isolate, EnqueueChangeRecord(object, "add", name, old_value), Object);
13136     }
13137   } else if (old_value->IsTheHole()) {
13138     RETURN_ON_EXCEPTION(
13139         isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value),
13140         Object);
13141   } else {
13142     Handle<Object> new_value =
13143         Object::GetElement(isolate, object, index).ToHandleChecked();
13144     bool value_changed = !old_value->SameValue(*new_value);
13145     if (old_attributes != new_attributes) {
13146       if (!value_changed) old_value = isolate->factory()->the_hole_value();
13147       RETURN_ON_EXCEPTION(
13148           isolate, EnqueueChangeRecord(object, "reconfigure", name, old_value),
13149           Object);
13150     } else if (value_changed) {
13151       RETURN_ON_EXCEPTION(
13152           isolate, EnqueueChangeRecord(object, "update", name, old_value),
13153           Object);
13154     }
13155   }
13156
13157   return result;
13158 }
13159
13160
13161 MaybeHandle<Object> JSObject::SetElementWithoutInterceptor(
13162     Handle<JSObject> object, uint32_t index, Handle<Object> value,
13163     PropertyAttributes attributes, LanguageMode language_mode,
13164     bool check_prototype, SetPropertyMode set_mode) {
13165   DCHECK(object->HasDictionaryElements() ||
13166          object->HasDictionaryArgumentsElements() ||
13167          (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
13168   Isolate* isolate = object->GetIsolate();
13169   if (FLAG_trace_external_array_abuse &&
13170       IsExternalArrayElementsKind(object->GetElementsKind())) {
13171     CheckArrayAbuse(object, "external elements write", index);
13172   }
13173   if (FLAG_trace_js_array_abuse &&
13174       !IsExternalArrayElementsKind(object->GetElementsKind())) {
13175     if (object->IsJSArray()) {
13176       CheckArrayAbuse(object, "elements write", index, true);
13177     }
13178   }
13179   if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
13180       Handle<JSArray>::cast(object), index)) {
13181     if (is_sloppy(language_mode)) {
13182       return value;
13183     } else {
13184       return JSArray::ReadOnlyLengthError(Handle<JSArray>::cast(object));
13185     }
13186   }
13187   switch (object->GetElementsKind()) {
13188     case FAST_SMI_ELEMENTS:
13189     case FAST_ELEMENTS:
13190     case FAST_HOLEY_SMI_ELEMENTS:
13191     case FAST_HOLEY_ELEMENTS:
13192       return SetFastElement(object, index, value, language_mode,
13193                             check_prototype);
13194     case FAST_DOUBLE_ELEMENTS:
13195     case FAST_HOLEY_DOUBLE_ELEMENTS:
13196       return SetFastDoubleElement(object, index, value, language_mode,
13197                                   check_prototype);
13198
13199 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
13200     case EXTERNAL_##TYPE##_ELEMENTS: {                                        \
13201       Handle<External##Type##Array> array(                                    \
13202           External##Type##Array::cast(object->elements()));                   \
13203       return External##Type##Array::SetValue(array, index, value);            \
13204     }                                                                         \
13205     case TYPE##_ELEMENTS: {                                                   \
13206       Handle<Fixed##Type##Array> array(                                       \
13207           Fixed##Type##Array::cast(object->elements()));                      \
13208       return Fixed##Type##Array::SetValue(array, index, value);               \
13209     }
13210
13211     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13212
13213 #undef TYPED_ARRAY_CASE
13214
13215     case DICTIONARY_ELEMENTS:
13216       return SetDictionaryElement(object, index, value, attributes,
13217                                   language_mode, check_prototype, set_mode);
13218     case SLOPPY_ARGUMENTS_ELEMENTS: {
13219       Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
13220       uint32_t length = parameter_map->length();
13221       Handle<Object> probe = index < length - 2 ?
13222           Handle<Object>(parameter_map->get(index + 2), isolate) :
13223           Handle<Object>();
13224       if (!probe.is_null() && !probe->IsTheHole()) {
13225         Handle<Context> context(Context::cast(parameter_map->get(0)));
13226         int context_index = Handle<Smi>::cast(probe)->value();
13227         DCHECK(!context->get(context_index)->IsTheHole());
13228         context->set(context_index, *value);
13229         // Redefining attributes of an aliased element destroys fast aliasing.
13230         if (set_mode == SET_PROPERTY || attributes == NONE) return value;
13231         parameter_map->set_the_hole(index + 2);
13232         // For elements that are still writable we re-establish slow aliasing.
13233         if ((attributes & READ_ONLY) == 0) {
13234           value = Handle<Object>::cast(
13235               isolate->factory()->NewAliasedArgumentsEntry(context_index));
13236         }
13237       }
13238       Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
13239       if (arguments->IsDictionary()) {
13240         return SetDictionaryElement(object, index, value, attributes,
13241                                     language_mode, check_prototype, set_mode);
13242       } else {
13243         return SetFastElement(object, index, value, language_mode,
13244                               check_prototype);
13245       }
13246     }
13247   }
13248   // All possible cases have been handled above. Add a return to avoid the
13249   // complaints from the compiler.
13250   UNREACHABLE();
13251   return isolate->factory()->null_value();
13252 }
13253
13254
13255 const double AllocationSite::kPretenureRatio = 0.85;
13256
13257
13258 void AllocationSite::ResetPretenureDecision() {
13259   set_pretenure_decision(kUndecided);
13260   set_memento_found_count(0);
13261   set_memento_create_count(0);
13262 }
13263
13264
13265 PretenureFlag AllocationSite::GetPretenureMode() {
13266   PretenureDecision mode = pretenure_decision();
13267   // Zombie objects "decide" to be untenured.
13268   return mode == kTenure ? TENURED : NOT_TENURED;
13269 }
13270
13271
13272 bool AllocationSite::IsNestedSite() {
13273   DCHECK(FLAG_trace_track_allocation_sites);
13274   Object* current = GetHeap()->allocation_sites_list();
13275   while (current->IsAllocationSite()) {
13276     AllocationSite* current_site = AllocationSite::cast(current);
13277     if (current_site->nested_site() == this) {
13278       return true;
13279     }
13280     current = current_site->weak_next();
13281   }
13282   return false;
13283 }
13284
13285
13286 void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
13287                                               ElementsKind to_kind) {
13288   Isolate* isolate = site->GetIsolate();
13289
13290   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
13291     Handle<JSArray> transition_info =
13292         handle(JSArray::cast(site->transition_info()));
13293     ElementsKind kind = transition_info->GetElementsKind();
13294     // if kind is holey ensure that to_kind is as well.
13295     if (IsHoleyElementsKind(kind)) {
13296       to_kind = GetHoleyElementsKind(to_kind);
13297     }
13298     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
13299       // If the array is huge, it's not likely to be defined in a local
13300       // function, so we shouldn't make new instances of it very often.
13301       uint32_t length = 0;
13302       CHECK(transition_info->length()->ToArrayIndex(&length));
13303       if (length <= kMaximumArrayBytesToPretransition) {
13304         if (FLAG_trace_track_allocation_sites) {
13305           bool is_nested = site->IsNestedSite();
13306           PrintF(
13307               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
13308               reinterpret_cast<void*>(*site),
13309               is_nested ? "(nested)" : "",
13310               ElementsKindToString(kind),
13311               ElementsKindToString(to_kind));
13312         }
13313         JSObject::TransitionElementsKind(transition_info, to_kind);
13314         site->dependent_code()->DeoptimizeDependentCodeGroup(
13315             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
13316       }
13317     }
13318   } else {
13319     ElementsKind kind = site->GetElementsKind();
13320     // if kind is holey ensure that to_kind is as well.
13321     if (IsHoleyElementsKind(kind)) {
13322       to_kind = GetHoleyElementsKind(to_kind);
13323     }
13324     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
13325       if (FLAG_trace_track_allocation_sites) {
13326         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
13327                reinterpret_cast<void*>(*site),
13328                ElementsKindToString(kind),
13329                ElementsKindToString(to_kind));
13330       }
13331       site->SetElementsKind(to_kind);
13332       site->dependent_code()->DeoptimizeDependentCodeGroup(
13333           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
13334     }
13335   }
13336 }
13337
13338
13339 // static
13340 void AllocationSite::RegisterForDeoptOnTenureChange(Handle<AllocationSite> site,
13341                                                     CompilationInfo* info) {
13342   AddDependentCompilationInfo(
13343       site, DependentCode::kAllocationSiteTenuringChangedGroup, info);
13344 }
13345
13346
13347 // static
13348 void AllocationSite::RegisterForDeoptOnTransitionChange(
13349     Handle<AllocationSite> site, CompilationInfo* info) {
13350   // Do nothing if the object doesn't have any useful element transitions left.
13351   ElementsKind kind =
13352       site->SitePointsToLiteral()
13353           ? JSObject::cast(site->transition_info())->GetElementsKind()
13354           : site->GetElementsKind();
13355   if (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) {
13356     AddDependentCompilationInfo(
13357         site, DependentCode::kAllocationSiteTransitionChangedGroup, info);
13358   }
13359 }
13360
13361
13362 // static
13363 void AllocationSite::AddDependentCompilationInfo(
13364     Handle<AllocationSite> site, DependentCode::DependencyGroup group,
13365     CompilationInfo* info) {
13366   Handle<DependentCode> dep(site->dependent_code());
13367   Handle<DependentCode> codes =
13368       DependentCode::InsertCompilationInfo(dep, group, info->object_wrapper());
13369   if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
13370   info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
13371 }
13372
13373
13374 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
13375   switch (decision) {
13376     case kUndecided: return "undecided";
13377     case kDontTenure: return "don't tenure";
13378     case kMaybeTenure: return "maybe tenure";
13379     case kTenure: return "tenure";
13380     case kZombie: return "zombie";
13381     default: UNREACHABLE();
13382   }
13383   return NULL;
13384 }
13385
13386
13387 void JSObject::UpdateAllocationSite(Handle<JSObject> object,
13388                                     ElementsKind to_kind) {
13389   if (!object->IsJSArray()) return;
13390
13391   Heap* heap = object->GetHeap();
13392   if (!heap->InNewSpace(*object)) return;
13393
13394   Handle<AllocationSite> site;
13395   {
13396     DisallowHeapAllocation no_allocation;
13397
13398     AllocationMemento* memento = heap->FindAllocationMemento(*object);
13399     if (memento == NULL) return;
13400
13401     // Walk through to the Allocation Site
13402     site = handle(memento->GetAllocationSite());
13403   }
13404   AllocationSite::DigestTransitionFeedback(site, to_kind);
13405 }
13406
13407
13408 void JSObject::TransitionElementsKind(Handle<JSObject> object,
13409                                       ElementsKind to_kind) {
13410   ElementsKind from_kind = object->map()->elements_kind();
13411
13412   if (IsFastHoleyElementsKind(from_kind)) {
13413     to_kind = GetHoleyElementsKind(to_kind);
13414   }
13415
13416   if (from_kind == to_kind) return;
13417   // Don't update the site if to_kind isn't fast
13418   if (IsFastElementsKind(to_kind)) {
13419     UpdateAllocationSite(object, to_kind);
13420   }
13421
13422   Isolate* isolate = object->GetIsolate();
13423   if (object->elements() == isolate->heap()->empty_fixed_array() ||
13424       (IsFastSmiOrObjectElementsKind(from_kind) &&
13425        IsFastSmiOrObjectElementsKind(to_kind)) ||
13426       (from_kind == FAST_DOUBLE_ELEMENTS &&
13427        to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
13428     DCHECK(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
13429     // No change is needed to the elements() buffer, the transition
13430     // only requires a map change.
13431     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
13432     MigrateToMap(object, new_map);
13433     if (FLAG_trace_elements_transitions) {
13434       Handle<FixedArrayBase> elms(object->elements());
13435       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
13436     }
13437     return;
13438   }
13439
13440   Handle<FixedArrayBase> elms(object->elements());
13441   uint32_t capacity = static_cast<uint32_t>(elms->length());
13442   uint32_t length = capacity;
13443
13444   if (object->IsJSArray()) {
13445     Object* raw_length = Handle<JSArray>::cast(object)->length();
13446     if (raw_length->IsUndefined()) {
13447       // If length is undefined, then JSArray is being initialized and has no
13448       // elements, assume a length of zero.
13449       length = 0;
13450     } else {
13451       CHECK(raw_length->ToArrayIndex(&length));
13452     }
13453   }
13454
13455   if (IsFastSmiElementsKind(from_kind) &&
13456       IsFastDoubleElementsKind(to_kind)) {
13457     SetFastDoubleElementsCapacityAndLength(object, capacity, length);
13458     JSObject::ValidateElements(object);
13459     return;
13460   }
13461
13462   if (IsFastDoubleElementsKind(from_kind) &&
13463       IsFastObjectElementsKind(to_kind)) {
13464     SetFastElementsCapacityAndLength(object, capacity, length,
13465                                      kDontAllowSmiElements);
13466     JSObject::ValidateElements(object);
13467     return;
13468   }
13469
13470   // This method should never be called for any other case than the ones
13471   // handled above.
13472   UNREACHABLE();
13473 }
13474
13475
13476 // static
13477 bool Map::IsValidElementsTransition(ElementsKind from_kind,
13478                                     ElementsKind to_kind) {
13479   // Transitions can't go backwards.
13480   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
13481     return false;
13482   }
13483
13484   // Transitions from HOLEY -> PACKED are not allowed.
13485   return !IsFastHoleyElementsKind(from_kind) ||
13486       IsFastHoleyElementsKind(to_kind);
13487 }
13488
13489
13490 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array,
13491                                            uint32_t index,
13492                                            Handle<Object> value) {
13493   uint32_t old_len = 0;
13494   CHECK(array->length()->ToArrayIndex(&old_len));
13495   // Check to see if we need to update the length. For now, we make
13496   // sure that the length stays within 32-bits (unsigned).
13497   if (index >= old_len && index != 0xffffffff) {
13498     Handle<Object> len = array->GetIsolate()->factory()->NewNumber(
13499         static_cast<double>(index) + 1);
13500     array->set_length(*len);
13501   }
13502 }
13503
13504
13505 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
13506   LookupIterator it(array, array->GetIsolate()->factory()->length_string(),
13507                     LookupIterator::OWN_SKIP_INTERCEPTOR);
13508   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
13509   CHECK(it.IsFound());
13510   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
13511   return it.IsReadOnly();
13512 }
13513
13514
13515 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
13516                                         uint32_t index) {
13517   uint32_t length = 0;
13518   CHECK(array->length()->ToArrayIndex(&length));
13519   if (length <= index) return HasReadOnlyLength(array);
13520   return false;
13521 }
13522
13523
13524 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
13525   Isolate* isolate = array->GetIsolate();
13526   Handle<Name> length = isolate->factory()->length_string();
13527   Handle<Object> args[] = {length, array};
13528   THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
13529                                         HandleVector(args, arraysize(args))),
13530                   Object);
13531 }
13532
13533
13534 MaybeHandle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object,
13535                                                         Handle<Object> receiver,
13536                                                         uint32_t index,
13537                                                         bool check_prototype) {
13538   Isolate* isolate = object->GetIsolate();
13539
13540   // Make sure that the top context does not change when doing
13541   // callbacks or interceptor calls.
13542   AssertNoContextChange ncc(isolate);
13543
13544   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate);
13545   if (!interceptor->getter()->IsUndefined()) {
13546     v8::IndexedPropertyGetterCallback getter =
13547         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
13548     LOG(isolate,
13549         ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
13550     PropertyCallbackArguments
13551         args(isolate, interceptor->data(), *receiver, *object);
13552     v8::Handle<v8::Value> result = args.Call(getter, index);
13553     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13554     if (!result.IsEmpty()) {
13555       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13556       result_internal->VerifyApiCallResultType();
13557       // Rebox handle before return.
13558       return handle(*result_internal, isolate);
13559     }
13560   }
13561
13562   if (!check_prototype) return MaybeHandle<Object>();
13563
13564   ElementsAccessor* handler = object->GetElementsAccessor();
13565   Handle<Object> result;
13566   ASSIGN_RETURN_ON_EXCEPTION(
13567       isolate, result, handler->Get(receiver,  object, index),
13568       Object);
13569   if (!result->IsTheHole()) return result;
13570
13571   PrototypeIterator iter(isolate, object);
13572   if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
13573   return Object::GetElementWithReceiver(
13574       isolate, PrototypeIterator::GetCurrent(iter), receiver, index);
13575 }
13576
13577
13578 bool JSObject::HasDenseElements() {
13579   int capacity = 0;
13580   int used = 0;
13581   GetElementsCapacityAndUsage(&capacity, &used);
13582   return (capacity == 0) || (used > (capacity / 2));
13583 }
13584
13585
13586 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
13587   *capacity = 0;
13588   *used = 0;
13589
13590   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
13591   FixedArray* backing_store = NULL;
13592   switch (GetElementsKind()) {
13593     case SLOPPY_ARGUMENTS_ELEMENTS:
13594       backing_store_base =
13595           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
13596       backing_store = FixedArray::cast(backing_store_base);
13597       if (backing_store->IsDictionary()) {
13598         SeededNumberDictionary* dictionary =
13599             SeededNumberDictionary::cast(backing_store);
13600         *capacity = dictionary->Capacity();
13601         *used = dictionary->NumberOfElements();
13602         break;
13603       }
13604       // Fall through.
13605     case FAST_SMI_ELEMENTS:
13606     case FAST_ELEMENTS:
13607       if (IsJSArray()) {
13608         *capacity = backing_store_base->length();
13609         *used = Smi::cast(JSArray::cast(this)->length())->value();
13610         break;
13611       }
13612       // Fall through if packing is not guaranteed.
13613     case FAST_HOLEY_SMI_ELEMENTS:
13614     case FAST_HOLEY_ELEMENTS:
13615       backing_store = FixedArray::cast(backing_store_base);
13616       *capacity = backing_store->length();
13617       for (int i = 0; i < *capacity; ++i) {
13618         if (!backing_store->get(i)->IsTheHole()) ++(*used);
13619       }
13620       break;
13621     case DICTIONARY_ELEMENTS: {
13622       SeededNumberDictionary* dictionary = element_dictionary();
13623       *capacity = dictionary->Capacity();
13624       *used = dictionary->NumberOfElements();
13625       break;
13626     }
13627     case FAST_DOUBLE_ELEMENTS:
13628       if (IsJSArray()) {
13629         *capacity = backing_store_base->length();
13630         *used = Smi::cast(JSArray::cast(this)->length())->value();
13631         break;
13632       }
13633       // Fall through if packing is not guaranteed.
13634     case FAST_HOLEY_DOUBLE_ELEMENTS: {
13635       *capacity = elements()->length();
13636       if (*capacity == 0) break;
13637       FixedDoubleArray * elms = FixedDoubleArray::cast(elements());
13638       for (int i = 0; i < *capacity; i++) {
13639         if (!elms->is_the_hole(i)) ++(*used);
13640       }
13641       break;
13642     }
13643
13644 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
13645     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
13646     case TYPE##_ELEMENTS:                                                    \
13647
13648     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13649 #undef TYPED_ARRAY_CASE
13650     {
13651       // External arrays are considered 100% used.
13652       FixedArrayBase* external_array = FixedArrayBase::cast(elements());
13653       *capacity = external_array->length();
13654       *used = external_array->length();
13655       break;
13656     }
13657   }
13658 }
13659
13660
13661 bool JSObject::WouldConvertToSlowElements(Handle<Object> key) {
13662   uint32_t index;
13663   if (HasFastElements() && key->ToArrayIndex(&index)) {
13664     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
13665     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
13666     if (index >= capacity) {
13667       if ((index - capacity) >= kMaxGap) return true;
13668       uint32_t new_capacity = NewElementsCapacity(index + 1);
13669       return ShouldConvertToSlowElements(new_capacity);
13670     }
13671   }
13672   return false;
13673 }
13674
13675
13676 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
13677   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
13678                 kMaxUncheckedFastElementsLength);
13679   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
13680       (new_capacity <= kMaxUncheckedFastElementsLength &&
13681        GetHeap()->InNewSpace(this))) {
13682     return false;
13683   }
13684   // If the fast-case backing storage takes up roughly three times as
13685   // much space (in machine words) as a dictionary backing storage
13686   // would, the object should have slow elements.
13687   int old_capacity = 0;
13688   int used_elements = 0;
13689   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
13690   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
13691       SeededNumberDictionary::kEntrySize;
13692   return 3 * dictionary_size <= new_capacity;
13693 }
13694
13695
13696 bool JSObject::ShouldConvertToFastElements() {
13697   DCHECK(HasDictionaryElements() || HasDictionaryArgumentsElements());
13698   // If the elements are sparse, we should not go back to fast case.
13699   if (!HasDenseElements()) return false;
13700   // An object requiring access checks is never allowed to have fast
13701   // elements.  If it had fast elements we would skip security checks.
13702   if (IsAccessCheckNeeded()) return false;
13703   // Observed objects may not go to fast mode because they rely on map checks,
13704   // and for fast element accesses we sometimes check element kinds only.
13705   if (map()->is_observed()) return false;
13706
13707   FixedArray* elements = FixedArray::cast(this->elements());
13708   SeededNumberDictionary* dictionary = NULL;
13709   if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) {
13710     dictionary = SeededNumberDictionary::cast(elements->get(1));
13711   } else {
13712     dictionary = SeededNumberDictionary::cast(elements);
13713   }
13714   // If an element has been added at a very high index in the elements
13715   // dictionary, we cannot go back to fast case.
13716   if (dictionary->requires_slow_elements()) return false;
13717   // If the dictionary backing storage takes up roughly half as much
13718   // space (in machine words) as a fast-case backing storage would,
13719   // the object should have fast elements.
13720   uint32_t array_size = 0;
13721   if (IsJSArray()) {
13722     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
13723   } else {
13724     array_size = dictionary->max_number_key();
13725   }
13726   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
13727       SeededNumberDictionary::kEntrySize;
13728   return 2 * dictionary_size >= array_size;
13729 }
13730
13731
13732 bool JSObject::ShouldConvertToFastDoubleElements(
13733     bool* has_smi_only_elements) {
13734   *has_smi_only_elements = false;
13735   if (HasSloppyArgumentsElements()) return false;
13736   if (FLAG_unbox_double_arrays) {
13737     DCHECK(HasDictionaryElements());
13738     SeededNumberDictionary* dictionary = element_dictionary();
13739     bool found_double = false;
13740     for (int i = 0; i < dictionary->Capacity(); i++) {
13741       Object* key = dictionary->KeyAt(i);
13742       if (key->IsNumber()) {
13743         Object* value = dictionary->ValueAt(i);
13744         if (!value->IsNumber()) return false;
13745         if (!value->IsSmi()) {
13746           found_double = true;
13747         }
13748       }
13749     }
13750     *has_smi_only_elements = !found_double;
13751     return found_double;
13752   } else {
13753     return false;
13754   }
13755 }
13756
13757
13758 // Certain compilers request function template instantiation when they
13759 // see the definition of the other template functions in the
13760 // class. This requires us to have the template functions put
13761 // together, so even though this function belongs in objects-debug.cc,
13762 // we keep it here instead to satisfy certain compilers.
13763 #ifdef OBJECT_PRINT
13764 template <typename Derived, typename Shape, typename Key>
13765 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
13766   int capacity = DerivedHashTable::Capacity();
13767   for (int i = 0; i < capacity; i++) {
13768     Object* k = DerivedHashTable::KeyAt(i);
13769     if (DerivedHashTable::IsKey(k)) {
13770       os << " ";
13771       if (k->IsString()) {
13772         String::cast(k)->StringPrint(os);
13773       } else {
13774         os << Brief(k);
13775       }
13776       os << ": " << Brief(ValueAt(i)) << " " << DetailsAt(i) << "\n";
13777     }
13778   }
13779 }
13780 #endif
13781
13782
13783 template<typename Derived, typename Shape, typename Key>
13784 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
13785   int pos = 0;
13786   int capacity = DerivedHashTable::Capacity();
13787   DisallowHeapAllocation no_gc;
13788   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
13789   for (int i = 0; i < capacity; i++) {
13790     Object* k =  Dictionary::KeyAt(i);
13791     if (Dictionary::IsKey(k)) {
13792       elements->set(pos++, ValueAt(i), mode);
13793     }
13794   }
13795   DCHECK(pos == elements->length());
13796 }
13797
13798
13799 InterceptorInfo* JSObject::GetNamedInterceptor() {
13800   DCHECK(map()->has_named_interceptor());
13801   JSFunction* constructor = JSFunction::cast(map()->GetConstructor());
13802   DCHECK(constructor->shared()->IsApiFunction());
13803   Object* result =
13804       constructor->shared()->get_api_func_data()->named_property_handler();
13805   return InterceptorInfo::cast(result);
13806 }
13807
13808
13809 InterceptorInfo* JSObject::GetIndexedInterceptor() {
13810   DCHECK(map()->has_indexed_interceptor());
13811   JSFunction* constructor = JSFunction::cast(map()->GetConstructor());
13812   DCHECK(constructor->shared()->IsApiFunction());
13813   Object* result =
13814       constructor->shared()->get_api_func_data()->indexed_property_handler();
13815   return InterceptorInfo::cast(result);
13816 }
13817
13818
13819 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(
13820     Handle<JSObject> holder,
13821     Handle<Object> receiver,
13822     Handle<Name> name) {
13823   Isolate* isolate = holder->GetIsolate();
13824
13825   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor(), isolate);
13826   if (interceptor->getter()->IsUndefined()) return MaybeHandle<Object>();
13827
13828   if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
13829     return MaybeHandle<Object>();
13830   }
13831
13832   v8::GenericNamedPropertyGetterCallback getter =
13833       v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
13834           interceptor->getter());
13835   LOG(isolate,
13836       ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
13837   PropertyCallbackArguments
13838       args(isolate, interceptor->data(), *receiver, *holder);
13839   v8::Handle<v8::Value> result = args.Call(getter, v8::Utils::ToLocal(name));
13840   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13841   if (result.IsEmpty()) return MaybeHandle<Object>();
13842
13843   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13844   result_internal->VerifyApiCallResultType();
13845   // Rebox handle before return
13846   return handle(*result_internal, isolate);
13847 }
13848
13849
13850 // Compute the property keys from the interceptor.
13851 MaybeHandle<JSObject> JSObject::GetKeysForNamedInterceptor(
13852     Handle<JSObject> object, Handle<JSReceiver> receiver) {
13853   Isolate* isolate = receiver->GetIsolate();
13854   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
13855   PropertyCallbackArguments
13856       args(isolate, interceptor->data(), *receiver, *object);
13857   v8::Handle<v8::Object> result;
13858   if (!interceptor->enumerator()->IsUndefined()) {
13859     v8::GenericNamedPropertyEnumeratorCallback enum_fun =
13860         v8::ToCData<v8::GenericNamedPropertyEnumeratorCallback>(
13861             interceptor->enumerator());
13862     LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
13863     result = args.Call(enum_fun);
13864   }
13865   if (result.IsEmpty()) return MaybeHandle<JSObject>();
13866   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13867          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13868   // Rebox before returning.
13869   return handle(*v8::Utils::OpenHandle(*result), isolate);
13870 }
13871
13872
13873 // Compute the element keys from the interceptor.
13874 MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor(
13875     Handle<JSObject> object, Handle<JSReceiver> receiver) {
13876   Isolate* isolate = receiver->GetIsolate();
13877   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
13878   PropertyCallbackArguments
13879       args(isolate, interceptor->data(), *receiver, *object);
13880   v8::Handle<v8::Object> result;
13881   if (!interceptor->enumerator()->IsUndefined()) {
13882     v8::IndexedPropertyEnumeratorCallback enum_fun =
13883         v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
13884             interceptor->enumerator());
13885     LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
13886     result = args.Call(enum_fun);
13887   }
13888   if (result.IsEmpty()) return MaybeHandle<JSObject>();
13889   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13890          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13891   // Rebox before returning.
13892   return handle(*v8::Utils::OpenHandle(*result), isolate);
13893 }
13894
13895
13896 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
13897                                            Handle<Name> key) {
13898   LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
13899   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
13900   if (!maybe_result.IsJust()) return Nothing<bool>();
13901   return Just(it.IsFound());
13902 }
13903
13904
13905 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
13906                                              uint32_t index) {
13907   Isolate* isolate = object->GetIsolate();
13908   HandleScope scope(isolate);
13909   // Check access rights if needed.
13910   if (object->IsAccessCheckNeeded()) {
13911     if (!isolate->MayAccess(object)) {
13912       isolate->ReportFailedAccessCheck(object);
13913       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
13914       return Just(false);
13915     }
13916   }
13917
13918   if (object->IsJSGlobalProxy()) {
13919     HandleScope scope(isolate);
13920     PrototypeIterator iter(isolate, object);
13921     if (iter.IsAtEnd()) return Just(false);
13922     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
13923     return HasRealElementProperty(
13924         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
13925   }
13926
13927   Maybe<PropertyAttributes> result =
13928       GetElementAttributeWithoutInterceptor(object, object, index, false);
13929   return result.IsJust() ? Just(result.FromJust() != ABSENT) : Nothing<bool>();
13930 }
13931
13932
13933 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
13934                                                    Handle<Name> key) {
13935   LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
13936   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
13937   return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
13938                                : Nothing<bool>();
13939 }
13940
13941
13942 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) {
13943   if (HasFastProperties()) {
13944     Map* map = this->map();
13945     if (filter == NONE) return map->NumberOfOwnDescriptors();
13946     if (filter & DONT_ENUM) {
13947       int result = map->EnumLength();
13948       if (result != kInvalidEnumCacheSentinel) return result;
13949     }
13950     return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
13951   }
13952   return property_dictionary()->NumberOfElementsFilterAttributes(this, filter);
13953 }
13954
13955
13956 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
13957   Object* temp = get(i);
13958   set(i, get(j));
13959   set(j, temp);
13960   if (this != numbers) {
13961     temp = numbers->get(i);
13962     numbers->set(i, Smi::cast(numbers->get(j)));
13963     numbers->set(j, Smi::cast(temp));
13964   }
13965 }
13966
13967
13968 static void InsertionSortPairs(FixedArray* content,
13969                                FixedArray* numbers,
13970                                int len) {
13971   for (int i = 1; i < len; i++) {
13972     int j = i;
13973     while (j > 0 &&
13974            (NumberToUint32(numbers->get(j - 1)) >
13975             NumberToUint32(numbers->get(j)))) {
13976       content->SwapPairs(numbers, j - 1, j);
13977       j--;
13978     }
13979   }
13980 }
13981
13982
13983 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
13984   // In-place heap sort.
13985   DCHECK(content->length() == numbers->length());
13986
13987   // Bottom-up max-heap construction.
13988   for (int i = 1; i < len; ++i) {
13989     int child_index = i;
13990     while (child_index > 0) {
13991       int parent_index = ((child_index + 1) >> 1) - 1;
13992       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13993       uint32_t child_value = NumberToUint32(numbers->get(child_index));
13994       if (parent_value < child_value) {
13995         content->SwapPairs(numbers, parent_index, child_index);
13996       } else {
13997         break;
13998       }
13999       child_index = parent_index;
14000     }
14001   }
14002
14003   // Extract elements and create sorted array.
14004   for (int i = len - 1; i > 0; --i) {
14005     // Put max element at the back of the array.
14006     content->SwapPairs(numbers, 0, i);
14007     // Sift down the new top element.
14008     int parent_index = 0;
14009     while (true) {
14010       int child_index = ((parent_index + 1) << 1) - 1;
14011       if (child_index >= i) break;
14012       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
14013       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
14014       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
14015       if (child_index + 1 >= i || child1_value > child2_value) {
14016         if (parent_value > child1_value) break;
14017         content->SwapPairs(numbers, parent_index, child_index);
14018         parent_index = child_index;
14019       } else {
14020         if (parent_value > child2_value) break;
14021         content->SwapPairs(numbers, parent_index, child_index + 1);
14022         parent_index = child_index + 1;
14023       }
14024     }
14025   }
14026 }
14027
14028
14029 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
14030 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
14031   DCHECK(this->length() == numbers->length());
14032   // For small arrays, simply use insertion sort.
14033   if (len <= 10) {
14034     InsertionSortPairs(this, numbers, len);
14035     return;
14036   }
14037   // Check the range of indices.
14038   uint32_t min_index = NumberToUint32(numbers->get(0));
14039   uint32_t max_index = min_index;
14040   uint32_t i;
14041   for (i = 1; i < len; i++) {
14042     if (NumberToUint32(numbers->get(i)) < min_index) {
14043       min_index = NumberToUint32(numbers->get(i));
14044     } else if (NumberToUint32(numbers->get(i)) > max_index) {
14045       max_index = NumberToUint32(numbers->get(i));
14046     }
14047   }
14048   if (max_index - min_index + 1 == len) {
14049     // Indices form a contiguous range, unless there are duplicates.
14050     // Do an in-place linear time sort assuming distinct numbers, but
14051     // avoid hanging in case they are not.
14052     for (i = 0; i < len; i++) {
14053       uint32_t p;
14054       uint32_t j = 0;
14055       // While the current element at i is not at its correct position p,
14056       // swap the elements at these two positions.
14057       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
14058              j++ < len) {
14059         SwapPairs(numbers, i, p);
14060       }
14061     }
14062   } else {
14063     HeapSortPairs(this, numbers, len);
14064     return;
14065   }
14066 }
14067
14068
14069 // Fill in the names of own properties into the supplied storage. The main
14070 // purpose of this function is to provide reflection information for the object
14071 // mirrors.
14072 void JSObject::GetOwnPropertyNames(
14073     FixedArray* storage, int index, PropertyAttributes filter) {
14074   DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index));
14075   if (HasFastProperties()) {
14076     int real_size = map()->NumberOfOwnDescriptors();
14077     DescriptorArray* descs = map()->instance_descriptors();
14078     for (int i = 0; i < real_size; i++) {
14079       if ((descs->GetDetails(i).attributes() & filter) == 0 &&
14080           !FilterKey(descs->GetKey(i), filter)) {
14081         storage->set(index++, descs->GetKey(i));
14082       }
14083     }
14084   } else {
14085     property_dictionary()->CopyKeysTo(this, storage, index, filter,
14086                                       NameDictionary::UNSORTED);
14087   }
14088 }
14089
14090
14091 int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
14092   return GetOwnElementKeys(NULL, filter);
14093 }
14094
14095
14096 int JSObject::NumberOfEnumElements() {
14097   // Fast case for objects with no elements.
14098   if (!IsJSValue() && HasFastObjectElements()) {
14099     uint32_t length = IsJSArray() ?
14100         static_cast<uint32_t>(
14101             Smi::cast(JSArray::cast(this)->length())->value()) :
14102         static_cast<uint32_t>(FixedArray::cast(elements())->length());
14103     if (length == 0) return 0;
14104   }
14105   // Compute the number of enumerable elements.
14106   return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
14107 }
14108
14109
14110 int JSObject::GetOwnElementKeys(FixedArray* storage,
14111                                 PropertyAttributes filter) {
14112   int counter = 0;
14113   switch (GetElementsKind()) {
14114     case FAST_SMI_ELEMENTS:
14115     case FAST_ELEMENTS:
14116     case FAST_HOLEY_SMI_ELEMENTS:
14117     case FAST_HOLEY_ELEMENTS: {
14118       int length = IsJSArray() ?
14119           Smi::cast(JSArray::cast(this)->length())->value() :
14120           FixedArray::cast(elements())->length();
14121       for (int i = 0; i < length; i++) {
14122         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
14123           if (storage != NULL) {
14124             storage->set(counter, Smi::FromInt(i));
14125           }
14126           counter++;
14127         }
14128       }
14129       DCHECK(!storage || storage->length() >= counter);
14130       break;
14131     }
14132     case FAST_DOUBLE_ELEMENTS:
14133     case FAST_HOLEY_DOUBLE_ELEMENTS: {
14134       int length = IsJSArray() ?
14135           Smi::cast(JSArray::cast(this)->length())->value() :
14136           FixedArrayBase::cast(elements())->length();
14137       for (int i = 0; i < length; i++) {
14138         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
14139           if (storage != NULL) {
14140             storage->set(counter, Smi::FromInt(i));
14141           }
14142           counter++;
14143         }
14144       }
14145       DCHECK(!storage || storage->length() >= counter);
14146       break;
14147     }
14148
14149 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
14150     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
14151     case TYPE##_ELEMENTS:                                                    \
14152
14153     TYPED_ARRAYS(TYPED_ARRAY_CASE)
14154 #undef TYPED_ARRAY_CASE
14155     {
14156       int length = FixedArrayBase::cast(elements())->length();
14157       while (counter < length) {
14158         if (storage != NULL) {
14159           storage->set(counter, Smi::FromInt(counter));
14160         }
14161         counter++;
14162       }
14163       DCHECK(!storage || storage->length() >= counter);
14164       break;
14165     }
14166
14167     case DICTIONARY_ELEMENTS: {
14168       if (storage != NULL) {
14169         element_dictionary()->CopyKeysTo<DictionaryEntryType::kObjects>(
14170             storage, filter, SeededNumberDictionary::SORTED);
14171       }
14172       counter +=
14173           element_dictionary()
14174               ->NumberOfElementsFilterAttributes<DictionaryEntryType::kObjects>(
14175                   filter);
14176       break;
14177     }
14178     case SLOPPY_ARGUMENTS_ELEMENTS: {
14179       FixedArray* parameter_map = FixedArray::cast(elements());
14180       int mapped_length = parameter_map->length() - 2;
14181       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
14182       if (arguments->IsDictionary()) {
14183         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
14184         // will insert in storage starting at index 0.
14185         SeededNumberDictionary* dictionary =
14186             SeededNumberDictionary::cast(arguments);
14187         if (storage != NULL) {
14188           dictionary->CopyKeysTo<DictionaryEntryType::kObjects>(
14189               storage, filter, SeededNumberDictionary::UNSORTED);
14190         }
14191         counter += dictionary->NumberOfElementsFilterAttributes<
14192             DictionaryEntryType::kObjects>(filter);
14193         for (int i = 0; i < mapped_length; ++i) {
14194           if (!parameter_map->get(i + 2)->IsTheHole()) {
14195             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14196             ++counter;
14197           }
14198         }
14199         if (storage != NULL) storage->SortPairs(storage, counter);
14200
14201       } else {
14202         int backing_length = arguments->length();
14203         int i = 0;
14204         for (; i < mapped_length; ++i) {
14205           if (!parameter_map->get(i + 2)->IsTheHole()) {
14206             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14207             ++counter;
14208           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
14209             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14210             ++counter;
14211           }
14212         }
14213         for (; i < backing_length; ++i) {
14214           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14215           ++counter;
14216         }
14217       }
14218       break;
14219     }
14220   }
14221
14222   if (this->IsJSValue()) {
14223     Object* val = JSValue::cast(this)->value();
14224     if (val->IsString()) {
14225       String* str = String::cast(val);
14226       if (storage) {
14227         for (int i = 0; i < str->length(); i++) {
14228           storage->set(counter + i, Smi::FromInt(i));
14229         }
14230       }
14231       counter += str->length();
14232     }
14233   }
14234   DCHECK(!storage || storage->length() == counter);
14235   return counter;
14236 }
14237
14238
14239 int JSObject::GetEnumElementKeys(FixedArray* storage) {
14240   return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
14241 }
14242
14243
14244 const char* Symbol::PrivateSymbolToName() const {
14245   Heap* heap = GetIsolate()->heap();
14246 #define SYMBOL_CHECK_AND_PRINT(name) \
14247   if (this == heap->name()) return #name;
14248   PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
14249 #undef SYMBOL_CHECK_AND_PRINT
14250   return "UNKNOWN";
14251 }
14252
14253
14254 void Symbol::SymbolShortPrint(std::ostream& os) {
14255   os << "<Symbol: " << Hash();
14256   if (!name()->IsUndefined()) {
14257     os << " ";
14258     HeapStringAllocator allocator;
14259     StringStream accumulator(&allocator);
14260     String::cast(name())->StringShortPrint(&accumulator);
14261     os << accumulator.ToCString().get();
14262   } else {
14263     os << " (" << PrivateSymbolToName() << ")";
14264   }
14265   os << ">";
14266 }
14267
14268
14269 // StringSharedKeys are used as keys in the eval cache.
14270 class StringSharedKey : public HashTableKey {
14271  public:
14272   StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
14273                   LanguageMode language_mode, int scope_position)
14274       : source_(source),
14275         shared_(shared),
14276         language_mode_(language_mode),
14277         scope_position_(scope_position) {}
14278
14279   bool IsMatch(Object* other) OVERRIDE {
14280     DisallowHeapAllocation no_allocation;
14281     if (!other->IsFixedArray()) {
14282       if (!other->IsNumber()) return false;
14283       uint32_t other_hash = static_cast<uint32_t>(other->Number());
14284       return Hash() == other_hash;
14285     }
14286     FixedArray* other_array = FixedArray::cast(other);
14287     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
14288     if (shared != *shared_) return false;
14289     int language_unchecked = Smi::cast(other_array->get(2))->value();
14290     DCHECK(is_valid_language_mode(language_unchecked));
14291     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
14292     if (language_mode != language_mode_) return false;
14293     int scope_position = Smi::cast(other_array->get(3))->value();
14294     if (scope_position != scope_position_) return false;
14295     String* source = String::cast(other_array->get(1));
14296     return source->Equals(*source_);
14297   }
14298
14299   static uint32_t StringSharedHashHelper(String* source,
14300                                          SharedFunctionInfo* shared,
14301                                          LanguageMode language_mode,
14302                                          int scope_position) {
14303     uint32_t hash = source->Hash();
14304     if (shared->HasSourceCode()) {
14305       // Instead of using the SharedFunctionInfo pointer in the hash
14306       // code computation, we use a combination of the hash of the
14307       // script source code and the start position of the calling scope.
14308       // We do this to ensure that the cache entries can survive garbage
14309       // collection.
14310       Script* script(Script::cast(shared->script()));
14311       hash ^= String::cast(script->source())->Hash();
14312       STATIC_ASSERT(LANGUAGE_END == 3);
14313       if (is_strict(language_mode)) hash ^= 0x8000;
14314       if (is_strong(language_mode)) hash ^= 0x10000;
14315       hash += scope_position;
14316     }
14317     return hash;
14318   }
14319
14320   uint32_t Hash() OVERRIDE {
14321     return StringSharedHashHelper(*source_, *shared_, language_mode_,
14322                                   scope_position_);
14323   }
14324
14325   uint32_t HashForObject(Object* obj) OVERRIDE {
14326     DisallowHeapAllocation no_allocation;
14327     if (obj->IsNumber()) {
14328       return static_cast<uint32_t>(obj->Number());
14329     }
14330     FixedArray* other_array = FixedArray::cast(obj);
14331     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
14332     String* source = String::cast(other_array->get(1));
14333     int language_unchecked = Smi::cast(other_array->get(2))->value();
14334     DCHECK(is_valid_language_mode(language_unchecked));
14335     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
14336     int scope_position = Smi::cast(other_array->get(3))->value();
14337     return StringSharedHashHelper(source, shared, language_mode,
14338                                   scope_position);
14339   }
14340
14341
14342   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
14343     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
14344     array->set(0, *shared_);
14345     array->set(1, *source_);
14346     array->set(2, Smi::FromInt(language_mode_));
14347     array->set(3, Smi::FromInt(scope_position_));
14348     return array;
14349   }
14350
14351  private:
14352   Handle<String> source_;
14353   Handle<SharedFunctionInfo> shared_;
14354   LanguageMode language_mode_;
14355   int scope_position_;
14356 };
14357
14358
14359 // RegExpKey carries the source and flags of a regular expression as key.
14360 class RegExpKey : public HashTableKey {
14361  public:
14362   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
14363       : string_(string),
14364         flags_(Smi::FromInt(flags.value())) { }
14365
14366   // Rather than storing the key in the hash table, a pointer to the
14367   // stored value is stored where the key should be.  IsMatch then
14368   // compares the search key to the found object, rather than comparing
14369   // a key to a key.
14370   bool IsMatch(Object* obj) OVERRIDE {
14371     FixedArray* val = FixedArray::cast(obj);
14372     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
14373         && (flags_ == val->get(JSRegExp::kFlagsIndex));
14374   }
14375
14376   uint32_t Hash() OVERRIDE { return RegExpHash(*string_, flags_); }
14377
14378   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
14379     // Plain hash maps, which is where regexp keys are used, don't
14380     // use this function.
14381     UNREACHABLE();
14382     return MaybeHandle<Object>().ToHandleChecked();
14383   }
14384
14385   uint32_t HashForObject(Object* obj) OVERRIDE {
14386     FixedArray* val = FixedArray::cast(obj);
14387     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
14388                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
14389   }
14390
14391   static uint32_t RegExpHash(String* string, Smi* flags) {
14392     return string->Hash() + flags->value();
14393   }
14394
14395   Handle<String> string_;
14396   Smi* flags_;
14397 };
14398
14399
14400 Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
14401   if (hash_field_ == 0) Hash();
14402   return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
14403 }
14404
14405
14406 Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
14407   if (hash_field_ == 0) Hash();
14408   return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
14409 }
14410
14411
14412 Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
14413   if (hash_field_ == 0) Hash();
14414   return isolate->factory()->NewOneByteInternalizedSubString(
14415       string_, from_, length_, hash_field_);
14416 }
14417
14418
14419 bool SeqOneByteSubStringKey::IsMatch(Object* string) {
14420   Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
14421   return String::cast(string)->IsOneByteEqualTo(chars);
14422 }
14423
14424
14425 // InternalizedStringKey carries a string/internalized-string object as key.
14426 class InternalizedStringKey : public HashTableKey {
14427  public:
14428   explicit InternalizedStringKey(Handle<String> string)
14429       : string_(string) { }
14430
14431   bool IsMatch(Object* string) OVERRIDE {
14432     return String::cast(string)->Equals(*string_);
14433   }
14434
14435   uint32_t Hash() OVERRIDE { return string_->Hash(); }
14436
14437   uint32_t HashForObject(Object* other) OVERRIDE {
14438     return String::cast(other)->Hash();
14439   }
14440
14441   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
14442     // Internalize the string if possible.
14443     MaybeHandle<Map> maybe_map =
14444         isolate->factory()->InternalizedStringMapForString(string_);
14445     Handle<Map> map;
14446     if (maybe_map.ToHandle(&map)) {
14447       string_->set_map_no_write_barrier(*map);
14448       DCHECK(string_->IsInternalizedString());
14449       return string_;
14450     }
14451     // Otherwise allocate a new internalized string.
14452     return isolate->factory()->NewInternalizedStringImpl(
14453         string_, string_->length(), string_->hash_field());
14454   }
14455
14456   static uint32_t StringHash(Object* obj) {
14457     return String::cast(obj)->Hash();
14458   }
14459
14460   Handle<String> string_;
14461 };
14462
14463
14464 template<typename Derived, typename Shape, typename Key>
14465 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
14466   IteratePointers(v, 0, kElementsStartOffset);
14467 }
14468
14469
14470 template<typename Derived, typename Shape, typename Key>
14471 void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
14472   IteratePointers(v,
14473                   kElementsStartOffset,
14474                   kHeaderSize + length() * kPointerSize);
14475 }
14476
14477
14478 template<typename Derived, typename Shape, typename Key>
14479 Handle<Derived> HashTable<Derived, Shape, Key>::New(
14480     Isolate* isolate,
14481     int at_least_space_for,
14482     MinimumCapacity capacity_option,
14483     PretenureFlag pretenure) {
14484   DCHECK(0 <= at_least_space_for);
14485   DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
14486   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
14487                      ? at_least_space_for
14488                      : ComputeCapacity(at_least_space_for);
14489   if (capacity > HashTable::kMaxCapacity) {
14490     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
14491   }
14492
14493   Factory* factory = isolate->factory();
14494   int length = EntryToIndex(capacity);
14495   Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
14496   array->set_map_no_write_barrier(*factory->hash_table_map());
14497   Handle<Derived> table = Handle<Derived>::cast(array);
14498
14499   table->SetNumberOfElements(0);
14500   table->SetNumberOfDeletedElements(0);
14501   table->SetCapacity(capacity);
14502   return table;
14503 }
14504
14505
14506 // Find entry for key otherwise return kNotFound.
14507 int NameDictionary::FindEntry(Handle<Name> key) {
14508   if (!key->IsUniqueName()) {
14509     return DerivedHashTable::FindEntry(key);
14510   }
14511
14512   // Optimized for unique names. Knowledge of the key type allows:
14513   // 1. Move the check if the key is unique out of the loop.
14514   // 2. Avoid comparing hash codes in unique-to-unique comparison.
14515   // 3. Detect a case when a dictionary key is not unique but the key is.
14516   //    In case of positive result the dictionary key may be replaced by the
14517   //    internalized string with minimal performance penalty. It gives a chance
14518   //    to perform further lookups in code stubs (and significant performance
14519   //    boost a certain style of code).
14520
14521   // EnsureCapacity will guarantee the hash table is never full.
14522   uint32_t capacity = Capacity();
14523   uint32_t entry = FirstProbe(key->Hash(), capacity);
14524   uint32_t count = 1;
14525
14526   while (true) {
14527     int index = EntryToIndex(entry);
14528     Object* element = get(index);
14529     if (element->IsUndefined()) break;  // Empty entry.
14530     if (*key == element) return entry;
14531     if (!element->IsUniqueName() &&
14532         !element->IsTheHole() &&
14533         Name::cast(element)->Equals(*key)) {
14534       // Replace a key that is a non-internalized string by the equivalent
14535       // internalized string for faster further lookups.
14536       set(index, *key);
14537       return entry;
14538     }
14539     DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
14540     entry = NextProbe(entry, count++, capacity);
14541   }
14542   return kNotFound;
14543 }
14544
14545
14546 template<typename Derived, typename Shape, typename Key>
14547 void HashTable<Derived, Shape, Key>::Rehash(
14548     Handle<Derived> new_table,
14549     Key key) {
14550   DCHECK(NumberOfElements() < new_table->Capacity());
14551
14552   DisallowHeapAllocation no_gc;
14553   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
14554
14555   // Copy prefix to new array.
14556   for (int i = kPrefixStartIndex;
14557        i < kPrefixStartIndex + Shape::kPrefixSize;
14558        i++) {
14559     new_table->set(i, get(i), mode);
14560   }
14561
14562   // Rehash the elements.
14563   int capacity = Capacity();
14564   for (int i = 0; i < capacity; i++) {
14565     uint32_t from_index = EntryToIndex(i);
14566     Object* k = get(from_index);
14567     if (IsKey(k)) {
14568       uint32_t hash = HashTable::HashForObject(key, k);
14569       uint32_t insertion_index =
14570           EntryToIndex(new_table->FindInsertionEntry(hash));
14571       for (int j = 0; j < Shape::kEntrySize; j++) {
14572         new_table->set(insertion_index + j, get(from_index + j), mode);
14573       }
14574     }
14575   }
14576   new_table->SetNumberOfElements(NumberOfElements());
14577   new_table->SetNumberOfDeletedElements(0);
14578 }
14579
14580
14581 template<typename Derived, typename Shape, typename Key>
14582 uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
14583     Key key,
14584     Object* k,
14585     int probe,
14586     uint32_t expected) {
14587   uint32_t hash = HashTable::HashForObject(key, k);
14588   uint32_t capacity = Capacity();
14589   uint32_t entry = FirstProbe(hash, capacity);
14590   for (int i = 1; i < probe; i++) {
14591     if (entry == expected) return expected;
14592     entry = NextProbe(entry, i, capacity);
14593   }
14594   return entry;
14595 }
14596
14597
14598 template<typename Derived, typename Shape, typename Key>
14599 void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
14600                                           uint32_t entry2,
14601                                           WriteBarrierMode mode) {
14602   int index1 = EntryToIndex(entry1);
14603   int index2 = EntryToIndex(entry2);
14604   Object* temp[Shape::kEntrySize];
14605   for (int j = 0; j < Shape::kEntrySize; j++) {
14606     temp[j] = get(index1 + j);
14607   }
14608   for (int j = 0; j < Shape::kEntrySize; j++) {
14609     set(index1 + j, get(index2 + j), mode);
14610   }
14611   for (int j = 0; j < Shape::kEntrySize; j++) {
14612     set(index2 + j, temp[j], mode);
14613   }
14614 }
14615
14616
14617 template<typename Derived, typename Shape, typename Key>
14618 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
14619   DisallowHeapAllocation no_gc;
14620   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
14621   uint32_t capacity = Capacity();
14622   bool done = false;
14623   for (int probe = 1; !done; probe++) {
14624     // All elements at entries given by one of the first _probe_ probes
14625     // are placed correctly. Other elements might need to be moved.
14626     done = true;
14627     for (uint32_t current = 0; current < capacity; current++) {
14628       Object* current_key = get(EntryToIndex(current));
14629       if (IsKey(current_key)) {
14630         uint32_t target = EntryForProbe(key, current_key, probe, current);
14631         if (current == target) continue;
14632         Object* target_key = get(EntryToIndex(target));
14633         if (!IsKey(target_key) ||
14634             EntryForProbe(key, target_key, probe, target) != target) {
14635           // Put the current element into the correct position.
14636           Swap(current, target, mode);
14637           // The other element will be processed on the next iteration.
14638           current--;
14639         } else {
14640           // The place for the current element is occupied. Leave the element
14641           // for the next probe.
14642           done = false;
14643         }
14644       }
14645     }
14646   }
14647 }
14648
14649
14650 template<typename Derived, typename Shape, typename Key>
14651 Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
14652     Handle<Derived> table,
14653     int n,
14654     Key key,
14655     PretenureFlag pretenure) {
14656   Isolate* isolate = table->GetIsolate();
14657   int capacity = table->Capacity();
14658   int nof = table->NumberOfElements() + n;
14659   int nod = table->NumberOfDeletedElements();
14660   // Return if:
14661   //   50% is still free after adding n elements and
14662   //   at most 50% of the free elements are deleted elements.
14663   if (nod <= (capacity - nof) >> 1) {
14664     int needed_free = nof >> 1;
14665     if (nof + needed_free <= capacity) return table;
14666   }
14667
14668   const int kMinCapacityForPretenure = 256;
14669   bool should_pretenure = pretenure == TENURED ||
14670       ((capacity > kMinCapacityForPretenure) &&
14671           !isolate->heap()->InNewSpace(*table));
14672   Handle<Derived> new_table = HashTable::New(
14673       isolate,
14674       nof * 2,
14675       USE_DEFAULT_MINIMUM_CAPACITY,
14676       should_pretenure ? TENURED : NOT_TENURED);
14677
14678   table->Rehash(new_table, key);
14679   return new_table;
14680 }
14681
14682
14683 template<typename Derived, typename Shape, typename Key>
14684 Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
14685                                                        Key key) {
14686   int capacity = table->Capacity();
14687   int nof = table->NumberOfElements();
14688
14689   // Shrink to fit the number of elements if only a quarter of the
14690   // capacity is filled with elements.
14691   if (nof > (capacity >> 2)) return table;
14692   // Allocate a new dictionary with room for at least the current
14693   // number of elements. The allocation method will make sure that
14694   // there is extra room in the dictionary for additions. Don't go
14695   // lower than room for 16 elements.
14696   int at_least_room_for = nof;
14697   if (at_least_room_for < 16) return table;
14698
14699   Isolate* isolate = table->GetIsolate();
14700   const int kMinCapacityForPretenure = 256;
14701   bool pretenure =
14702       (at_least_room_for > kMinCapacityForPretenure) &&
14703       !isolate->heap()->InNewSpace(*table);
14704   Handle<Derived> new_table = HashTable::New(
14705       isolate,
14706       at_least_room_for,
14707       USE_DEFAULT_MINIMUM_CAPACITY,
14708       pretenure ? TENURED : NOT_TENURED);
14709
14710   table->Rehash(new_table, key);
14711   return new_table;
14712 }
14713
14714
14715 template<typename Derived, typename Shape, typename Key>
14716 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
14717   uint32_t capacity = Capacity();
14718   uint32_t entry = FirstProbe(hash, capacity);
14719   uint32_t count = 1;
14720   // EnsureCapacity will guarantee the hash table is never full.
14721   while (true) {
14722     Object* element = KeyAt(entry);
14723     if (element->IsUndefined() || element->IsTheHole()) break;
14724     entry = NextProbe(entry, count++, capacity);
14725   }
14726   return entry;
14727 }
14728
14729
14730 // Force instantiation of template instances class.
14731 // Please note this list is compiler dependent.
14732
14733 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
14734
14735 template class HashTable<CompilationCacheTable,
14736                          CompilationCacheShape,
14737                          HashTableKey*>;
14738
14739 template class HashTable<ObjectHashTable,
14740                          ObjectHashTableShape,
14741                          Handle<Object> >;
14742
14743 template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
14744
14745 template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
14746
14747 template class Dictionary<SeededNumberDictionary,
14748                           SeededNumberDictionaryShape,
14749                           uint32_t>;
14750
14751 template class Dictionary<UnseededNumberDictionary,
14752                           UnseededNumberDictionaryShape,
14753                           uint32_t>;
14754
14755 template Handle<SeededNumberDictionary>
14756 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14757     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14758
14759 template Handle<UnseededNumberDictionary>
14760 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14761     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14762
14763 template Handle<NameDictionary>
14764 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14765     New(Isolate*, int n, PretenureFlag pretenure);
14766
14767 template Handle<SeededNumberDictionary>
14768 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14769     AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
14770
14771 template Handle<UnseededNumberDictionary>
14772 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14773     AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
14774
14775 template Object*
14776 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14777     SlowReverseLookup(Object* value);
14778
14779 template Object*
14780 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14781     SlowReverseLookup(Object* value);
14782
14783 template Handle<Object>
14784 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
14785     Handle<NameDictionary>, int);
14786
14787 template Handle<Object>
14788 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
14789            uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
14790
14791 template Handle<NameDictionary>
14792 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14793     New(Isolate*, int, MinimumCapacity, PretenureFlag);
14794
14795 template Handle<NameDictionary>
14796 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14797     Shrink(Handle<NameDictionary>, Handle<Name>);
14798
14799 template Handle<SeededNumberDictionary>
14800 HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14801     Shrink(Handle<SeededNumberDictionary>, uint32_t);
14802
14803 template Handle<NameDictionary>
14804 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
14805     Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
14806
14807 template Handle<FixedArray> Dictionary<
14808     NameDictionary, NameDictionaryShape,
14809     Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
14810
14811 template Handle<FixedArray> Dictionary<
14812     NameDictionary, NameDictionaryShape,
14813     Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
14814
14815 template Handle<SeededNumberDictionary>
14816 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14817     Add(Handle<SeededNumberDictionary>,
14818         uint32_t,
14819         Handle<Object>,
14820         PropertyDetails);
14821
14822 template Handle<UnseededNumberDictionary>
14823 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14824     Add(Handle<UnseededNumberDictionary>,
14825         uint32_t,
14826         Handle<Object>,
14827         PropertyDetails);
14828
14829 template Handle<SeededNumberDictionary>
14830 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14831     EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
14832
14833 template Handle<UnseededNumberDictionary>
14834 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14835     EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
14836
14837 template Handle<NameDictionary>
14838 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14839     EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
14840
14841 template bool
14842 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
14843            uint32_t>::HasComplexElements<DictionaryEntryType::kCells>();
14844
14845 template bool
14846 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
14847            uint32_t>::HasComplexElements<DictionaryEntryType::kObjects>();
14848
14849 template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
14850                        uint32_t>::FindEntry(uint32_t);
14851
14852
14853 Handle<Object> JSObject::PrepareSlowElementsForSort(
14854     Handle<JSObject> object, uint32_t limit) {
14855   DCHECK(object->HasDictionaryElements());
14856   Isolate* isolate = object->GetIsolate();
14857   // Must stay in dictionary mode, either because of requires_slow_elements,
14858   // or because we are not going to sort (and therefore compact) all of the
14859   // elements.
14860   Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
14861   Handle<SeededNumberDictionary> new_dict =
14862       SeededNumberDictionary::New(isolate, dict->NumberOfElements());
14863
14864   uint32_t pos = 0;
14865   uint32_t undefs = 0;
14866   int capacity = dict->Capacity();
14867   Handle<Smi> bailout(Smi::FromInt(-1), isolate);
14868   // Entry to the new dictionary does not cause it to grow, as we have
14869   // allocated one that is large enough for all entries.
14870   DisallowHeapAllocation no_gc;
14871   for (int i = 0; i < capacity; i++) {
14872     Object* k = dict->KeyAt(i);
14873     if (!dict->IsKey(k)) continue;
14874
14875     DCHECK(k->IsNumber());
14876     DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
14877     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
14878     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
14879
14880     HandleScope scope(isolate);
14881     Handle<Object> value(dict->ValueAt(i), isolate);
14882     PropertyDetails details = dict->DetailsAt(i);
14883     if (details.type() == ACCESSOR_CONSTANT || details.IsReadOnly()) {
14884       // Bail out and do the sorting of undefineds and array holes in JS.
14885       // Also bail out if the element is not supposed to be moved.
14886       return bailout;
14887     }
14888
14889     uint32_t key = NumberToUint32(k);
14890     if (key < limit) {
14891       if (value->IsUndefined()) {
14892         undefs++;
14893       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14894         // Adding an entry with the key beyond smi-range requires
14895         // allocation. Bailout.
14896         return bailout;
14897       } else {
14898         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14899             new_dict, pos, value, details);
14900         DCHECK(result.is_identical_to(new_dict));
14901         USE(result);
14902         pos++;
14903       }
14904     } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
14905       // Adding an entry with the key beyond smi-range requires
14906       // allocation. Bailout.
14907       return bailout;
14908     } else {
14909       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14910           new_dict, key, value, details);
14911       DCHECK(result.is_identical_to(new_dict));
14912       USE(result);
14913     }
14914   }
14915
14916   uint32_t result = pos;
14917   PropertyDetails no_details = PropertyDetails::Empty();
14918   while (undefs > 0) {
14919     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14920       // Adding an entry with the key beyond smi-range requires
14921       // allocation. Bailout.
14922       return bailout;
14923     }
14924     HandleScope scope(isolate);
14925     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14926         new_dict, pos, isolate->factory()->undefined_value(), no_details);
14927     DCHECK(result.is_identical_to(new_dict));
14928     USE(result);
14929     pos++;
14930     undefs--;
14931   }
14932
14933   object->set_elements(*new_dict);
14934
14935   AllowHeapAllocation allocate_return_value;
14936   return isolate->factory()->NewNumberFromUint(result);
14937 }
14938
14939
14940 // Collects all defined (non-hole) and non-undefined (array) elements at
14941 // the start of the elements array.
14942 // If the object is in dictionary mode, it is converted to fast elements
14943 // mode.
14944 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
14945                                                 uint32_t limit) {
14946   Isolate* isolate = object->GetIsolate();
14947   if (object->HasSloppyArgumentsElements() ||
14948       object->map()->is_observed()) {
14949     return handle(Smi::FromInt(-1), isolate);
14950   }
14951
14952   if (object->HasDictionaryElements()) {
14953     // Convert to fast elements containing only the existing properties.
14954     // Ordering is irrelevant, since we are going to sort anyway.
14955     Handle<SeededNumberDictionary> dict(object->element_dictionary());
14956     if (object->IsJSArray() || dict->requires_slow_elements() ||
14957         dict->max_number_key() >= limit) {
14958       return JSObject::PrepareSlowElementsForSort(object, limit);
14959     }
14960     // Convert to fast elements.
14961
14962     Handle<Map> new_map =
14963         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
14964
14965     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
14966         NOT_TENURED: TENURED;
14967     Handle<FixedArray> fast_elements =
14968         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
14969     dict->CopyValuesTo(*fast_elements);
14970     JSObject::ValidateElements(object);
14971
14972     JSObject::SetMapAndElements(object, new_map, fast_elements);
14973   } else if (object->HasExternalArrayElements() ||
14974              object->HasFixedTypedArrayElements()) {
14975     // Typed arrays cannot have holes or undefined elements.
14976     return handle(Smi::FromInt(
14977         FixedArrayBase::cast(object->elements())->length()), isolate);
14978   } else if (!object->HasFastDoubleElements()) {
14979     EnsureWritableFastElements(object);
14980   }
14981   DCHECK(object->HasFastSmiOrObjectElements() ||
14982          object->HasFastDoubleElements());
14983
14984   // Collect holes at the end, undefined before that and the rest at the
14985   // start, and return the number of non-hole, non-undefined values.
14986
14987   Handle<FixedArrayBase> elements_base(object->elements());
14988   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
14989   if (limit > elements_length) {
14990     limit = elements_length ;
14991   }
14992   if (limit == 0) {
14993     return handle(Smi::FromInt(0), isolate);
14994   }
14995
14996   uint32_t result = 0;
14997   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
14998     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
14999     // Split elements into defined and the_hole, in that order.
15000     unsigned int holes = limit;
15001     // Assume most arrays contain no holes and undefined values, so minimize the
15002     // number of stores of non-undefined, non-the-hole values.
15003     for (unsigned int i = 0; i < holes; i++) {
15004       if (elements->is_the_hole(i)) {
15005         holes--;
15006       } else {
15007         continue;
15008       }
15009       // Position i needs to be filled.
15010       while (holes > i) {
15011         if (elements->is_the_hole(holes)) {
15012           holes--;
15013         } else {
15014           elements->set(i, elements->get_scalar(holes));
15015           break;
15016         }
15017       }
15018     }
15019     result = holes;
15020     while (holes < limit) {
15021       elements->set_the_hole(holes);
15022       holes++;
15023     }
15024   } else {
15025     FixedArray* elements = FixedArray::cast(*elements_base);
15026     DisallowHeapAllocation no_gc;
15027
15028     // Split elements into defined, undefined and the_hole, in that order.  Only
15029     // count locations for undefined and the hole, and fill them afterwards.
15030     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
15031     unsigned int undefs = limit;
15032     unsigned int holes = limit;
15033     // Assume most arrays contain no holes and undefined values, so minimize the
15034     // number of stores of non-undefined, non-the-hole values.
15035     for (unsigned int i = 0; i < undefs; i++) {
15036       Object* current = elements->get(i);
15037       if (current->IsTheHole()) {
15038         holes--;
15039         undefs--;
15040       } else if (current->IsUndefined()) {
15041         undefs--;
15042       } else {
15043         continue;
15044       }
15045       // Position i needs to be filled.
15046       while (undefs > i) {
15047         current = elements->get(undefs);
15048         if (current->IsTheHole()) {
15049           holes--;
15050           undefs--;
15051         } else if (current->IsUndefined()) {
15052           undefs--;
15053         } else {
15054           elements->set(i, current, write_barrier);
15055           break;
15056         }
15057       }
15058     }
15059     result = undefs;
15060     while (undefs < holes) {
15061       elements->set_undefined(undefs);
15062       undefs++;
15063     }
15064     while (holes < limit) {
15065       elements->set_the_hole(holes);
15066       holes++;
15067     }
15068   }
15069
15070   return isolate->factory()->NewNumberFromUint(result);
15071 }
15072
15073
15074 ExternalArrayType JSTypedArray::type() {
15075   switch (elements()->map()->instance_type()) {
15076 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
15077     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
15078     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
15079       return kExternal##Type##Array;
15080
15081     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
15082 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
15083
15084     default:
15085       UNREACHABLE();
15086       return static_cast<ExternalArrayType>(-1);
15087   }
15088 }
15089
15090
15091 size_t JSTypedArray::element_size() {
15092   switch (elements()->map()->instance_type()) {
15093 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)          \
15094     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
15095       return size;
15096
15097     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
15098 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
15099
15100     default:
15101       UNREACHABLE();
15102       return 0;
15103   }
15104 }
15105
15106
15107 Handle<Object> ExternalUint8ClampedArray::SetValue(
15108     Handle<ExternalUint8ClampedArray> array,
15109     uint32_t index,
15110     Handle<Object> value) {
15111   uint8_t clamped_value = 0;
15112   if (index < static_cast<uint32_t>(array->length())) {
15113     if (value->IsSmi()) {
15114       int int_value = Handle<Smi>::cast(value)->value();
15115       if (int_value < 0) {
15116         clamped_value = 0;
15117       } else if (int_value > 255) {
15118         clamped_value = 255;
15119       } else {
15120         clamped_value = static_cast<uint8_t>(int_value);
15121       }
15122     } else if (value->IsHeapNumber()) {
15123       double double_value = Handle<HeapNumber>::cast(value)->value();
15124       if (!(double_value > 0)) {
15125         // NaN and less than zero clamp to zero.
15126         clamped_value = 0;
15127       } else if (double_value > 255) {
15128         // Greater than 255 clamp to 255.
15129         clamped_value = 255;
15130       } else {
15131         // Other doubles are rounded to the nearest integer.
15132         clamped_value = static_cast<uint8_t>(lrint(double_value));
15133       }
15134     } else {
15135       // Clamp undefined to zero (default). All other types have been
15136       // converted to a number type further up in the call chain.
15137       DCHECK(value->IsUndefined());
15138     }
15139     array->set(index, clamped_value);
15140   }
15141   return handle(Smi::FromInt(clamped_value), array->GetIsolate());
15142 }
15143
15144
15145 template<typename ExternalArrayClass, typename ValueType>
15146 static Handle<Object> ExternalArrayIntSetter(
15147     Isolate* isolate,
15148     Handle<ExternalArrayClass> receiver,
15149     uint32_t index,
15150     Handle<Object> value) {
15151   ValueType cast_value = 0;
15152   if (index < static_cast<uint32_t>(receiver->length())) {
15153     if (value->IsSmi()) {
15154       int int_value = Handle<Smi>::cast(value)->value();
15155       cast_value = static_cast<ValueType>(int_value);
15156     } else if (value->IsHeapNumber()) {
15157       double double_value = Handle<HeapNumber>::cast(value)->value();
15158       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
15159     } else {
15160       // Clamp undefined to zero (default). All other types have been
15161       // converted to a number type further up in the call chain.
15162       DCHECK(value->IsUndefined());
15163     }
15164     receiver->set(index, cast_value);
15165   }
15166   return isolate->factory()->NewNumberFromInt(cast_value);
15167 }
15168
15169
15170 Handle<Object> ExternalInt8Array::SetValue(Handle<ExternalInt8Array> array,
15171                                            uint32_t index,
15172                                            Handle<Object> value) {
15173   return ExternalArrayIntSetter<ExternalInt8Array, int8_t>(
15174       array->GetIsolate(), array, index, value);
15175 }
15176
15177
15178 Handle<Object> ExternalUint8Array::SetValue(Handle<ExternalUint8Array> array,
15179                                             uint32_t index,
15180                                             Handle<Object> value) {
15181   return ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(
15182       array->GetIsolate(), array, index, value);
15183 }
15184
15185
15186 Handle<Object> ExternalInt16Array::SetValue(Handle<ExternalInt16Array> array,
15187                                             uint32_t index,
15188                                             Handle<Object> value) {
15189   return ExternalArrayIntSetter<ExternalInt16Array, int16_t>(
15190       array->GetIsolate(), array, index, value);
15191 }
15192
15193
15194 Handle<Object> ExternalUint16Array::SetValue(Handle<ExternalUint16Array> array,
15195                                              uint32_t index,
15196                                              Handle<Object> value) {
15197   return ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(
15198       array->GetIsolate(), array, index, value);
15199 }
15200
15201
15202 Handle<Object> ExternalInt32Array::SetValue(Handle<ExternalInt32Array> array,
15203                                             uint32_t index,
15204                                             Handle<Object> value) {
15205   return ExternalArrayIntSetter<ExternalInt32Array, int32_t>(
15206       array->GetIsolate(), array, index, value);
15207 }
15208
15209
15210 Handle<Object> ExternalUint32Array::SetValue(
15211     Handle<ExternalUint32Array> array,
15212     uint32_t index,
15213     Handle<Object> value) {
15214   uint32_t cast_value = 0;
15215   if (index < static_cast<uint32_t>(array->length())) {
15216     if (value->IsSmi()) {
15217       int int_value = Handle<Smi>::cast(value)->value();
15218       cast_value = static_cast<uint32_t>(int_value);
15219     } else if (value->IsHeapNumber()) {
15220       double double_value = Handle<HeapNumber>::cast(value)->value();
15221       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
15222     } else {
15223       // Clamp undefined to zero (default). All other types have been
15224       // converted to a number type further up in the call chain.
15225       DCHECK(value->IsUndefined());
15226     }
15227     array->set(index, cast_value);
15228   }
15229   return array->GetIsolate()->factory()->NewNumberFromUint(cast_value);
15230 }
15231
15232
15233 Handle<Object> ExternalFloat32Array::SetValue(
15234     Handle<ExternalFloat32Array> array,
15235     uint32_t index,
15236     Handle<Object> value) {
15237   float cast_value = std::numeric_limits<float>::quiet_NaN();
15238   if (index < static_cast<uint32_t>(array->length())) {
15239     if (value->IsSmi()) {
15240       int int_value = Handle<Smi>::cast(value)->value();
15241       cast_value = static_cast<float>(int_value);
15242     } else if (value->IsHeapNumber()) {
15243       double double_value = Handle<HeapNumber>::cast(value)->value();
15244       cast_value = static_cast<float>(double_value);
15245     } else {
15246       // Clamp undefined to NaN (default). All other types have been
15247       // converted to a number type further up in the call chain.
15248       DCHECK(value->IsUndefined());
15249     }
15250     array->set(index, cast_value);
15251   }
15252   return array->GetIsolate()->factory()->NewNumber(cast_value);
15253 }
15254
15255
15256 Handle<Object> ExternalFloat64Array::SetValue(
15257     Handle<ExternalFloat64Array> array,
15258     uint32_t index,
15259     Handle<Object> value) {
15260   double double_value = std::numeric_limits<double>::quiet_NaN();
15261   if (index < static_cast<uint32_t>(array->length())) {
15262     if (value->IsNumber()) {
15263       double_value = value->Number();
15264     } else {
15265       // Clamp undefined to NaN (default). All other types have been
15266       // converted to a number type further up in the call chain.
15267       DCHECK(value->IsUndefined());
15268     }
15269     array->set(index, double_value);
15270   }
15271   return array->GetIsolate()->factory()->NewNumber(double_value);
15272 }
15273
15274
15275 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global,
15276                                           Handle<Name> name) {
15277   DCHECK(!global->HasFastProperties());
15278   auto dictionary = handle(global->property_dictionary());
15279   int entry = dictionary->FindEntry(name);
15280   if (entry == NameDictionary::kNotFound) return;
15281   PropertyCell::InvalidateEntry(dictionary, entry);
15282 }
15283
15284
15285 // TODO(dcarney): rename to EnsureEmptyPropertyCell or something.
15286 Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
15287     Handle<GlobalObject> global, Handle<Name> name) {
15288   DCHECK(!global->HasFastProperties());
15289   auto dictionary = handle(global->property_dictionary());
15290   int entry = dictionary->FindEntry(name);
15291   Handle<PropertyCell> cell;
15292   if (entry != NameDictionary::kNotFound) {
15293     // This call should be idempotent.
15294     DCHECK(dictionary->DetailsAt(entry).cell_type() ==
15295                PropertyCellType::kUninitialized ||
15296            dictionary->DetailsAt(entry).cell_type() ==
15297                PropertyCellType::kDeleted);
15298     DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
15299     cell = handle(PropertyCell::cast(dictionary->ValueAt(entry)));
15300     DCHECK(cell->value()->IsTheHole());
15301     return cell;
15302   }
15303   Isolate* isolate = global->GetIsolate();
15304   cell = isolate->factory()->NewPropertyCell();
15305   PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized);
15306   dictionary = NameDictionary::Add(dictionary, name, cell, details);
15307   global->set_properties(*dictionary);
15308   return cell;
15309 }
15310
15311
15312 // This class is used for looking up two character strings in the string table.
15313 // If we don't have a hit we don't want to waste much time so we unroll the
15314 // string hash calculation loop here for speed.  Doesn't work if the two
15315 // characters form a decimal integer, since such strings have a different hash
15316 // algorithm.
15317 class TwoCharHashTableKey : public HashTableKey {
15318  public:
15319   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
15320     : c1_(c1), c2_(c2) {
15321     // Char 1.
15322     uint32_t hash = seed;
15323     hash += c1;
15324     hash += hash << 10;
15325     hash ^= hash >> 6;
15326     // Char 2.
15327     hash += c2;
15328     hash += hash << 10;
15329     hash ^= hash >> 6;
15330     // GetHash.
15331     hash += hash << 3;
15332     hash ^= hash >> 11;
15333     hash += hash << 15;
15334     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
15335     hash_ = hash;
15336 #ifdef DEBUG
15337     // If this assert fails then we failed to reproduce the two-character
15338     // version of the string hashing algorithm above.  One reason could be
15339     // that we were passed two digits as characters, since the hash
15340     // algorithm is different in that case.
15341     uint16_t chars[2] = {c1, c2};
15342     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
15343     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
15344     DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
15345 #endif
15346   }
15347
15348   bool IsMatch(Object* o) OVERRIDE {
15349     if (!o->IsString()) return false;
15350     String* other = String::cast(o);
15351     if (other->length() != 2) return false;
15352     if (other->Get(0) != c1_) return false;
15353     return other->Get(1) == c2_;
15354   }
15355
15356   uint32_t Hash() OVERRIDE { return hash_; }
15357   uint32_t HashForObject(Object* key) OVERRIDE {
15358     if (!key->IsString()) return 0;
15359     return String::cast(key)->Hash();
15360   }
15361
15362   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
15363     // The TwoCharHashTableKey is only used for looking in the string
15364     // table, not for adding to it.
15365     UNREACHABLE();
15366     return MaybeHandle<Object>().ToHandleChecked();
15367   }
15368
15369  private:
15370   uint16_t c1_;
15371   uint16_t c2_;
15372   uint32_t hash_;
15373 };
15374
15375
15376 MaybeHandle<String> StringTable::InternalizeStringIfExists(
15377     Isolate* isolate,
15378     Handle<String> string) {
15379   if (string->IsInternalizedString()) {
15380     return string;
15381   }
15382   return LookupStringIfExists(isolate, string);
15383 }
15384
15385
15386 MaybeHandle<String> StringTable::LookupStringIfExists(
15387     Isolate* isolate,
15388     Handle<String> string) {
15389   Handle<StringTable> string_table = isolate->factory()->string_table();
15390   InternalizedStringKey key(string);
15391   int entry = string_table->FindEntry(&key);
15392   if (entry == kNotFound) {
15393     return MaybeHandle<String>();
15394   } else {
15395     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
15396     DCHECK(StringShape(*result).IsInternalized());
15397     return result;
15398   }
15399 }
15400
15401
15402 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
15403     Isolate* isolate,
15404     uint16_t c1,
15405     uint16_t c2) {
15406   Handle<StringTable> string_table = isolate->factory()->string_table();
15407   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
15408   int entry = string_table->FindEntry(&key);
15409   if (entry == kNotFound) {
15410     return MaybeHandle<String>();
15411   } else {
15412     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
15413     DCHECK(StringShape(*result).IsInternalized());
15414     return result;
15415   }
15416 }
15417
15418
15419 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
15420                                                    int expected) {
15421   Handle<StringTable> table = isolate->factory()->string_table();
15422   // We need a key instance for the virtual hash function.
15423   InternalizedStringKey dummy_key(Handle<String>::null());
15424   table = StringTable::EnsureCapacity(table, expected, &dummy_key);
15425   isolate->factory()->set_string_table(table);
15426 }
15427
15428
15429 Handle<String> StringTable::LookupString(Isolate* isolate,
15430                                          Handle<String> string) {
15431   InternalizedStringKey key(string);
15432   return LookupKey(isolate, &key);
15433 }
15434
15435
15436 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
15437   Handle<StringTable> table = isolate->factory()->string_table();
15438   int entry = table->FindEntry(key);
15439
15440   // String already in table.
15441   if (entry != kNotFound) {
15442     return handle(String::cast(table->KeyAt(entry)), isolate);
15443   }
15444
15445   // Adding new string. Grow table if needed.
15446   table = StringTable::EnsureCapacity(table, 1, key);
15447
15448   // Create string object.
15449   Handle<Object> string = key->AsHandle(isolate);
15450   // There must be no attempts to internalize strings that could throw
15451   // InvalidStringLength error.
15452   CHECK(!string.is_null());
15453
15454   // Add the new string and return it along with the string table.
15455   entry = table->FindInsertionEntry(key->Hash());
15456   table->set(EntryToIndex(entry), *string);
15457   table->ElementAdded();
15458
15459   isolate->factory()->set_string_table(table);
15460   return Handle<String>::cast(string);
15461 }
15462
15463
15464 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
15465                                              Handle<Context> context,
15466                                              LanguageMode language_mode) {
15467   Isolate* isolate = GetIsolate();
15468   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15469   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
15470   int entry = FindEntry(&key);
15471   if (entry == kNotFound) return isolate->factory()->undefined_value();
15472   int index = EntryToIndex(entry);
15473   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
15474   return Handle<Object>(get(index + 1), isolate);
15475 }
15476
15477
15478 Handle<Object> CompilationCacheTable::LookupEval(
15479     Handle<String> src, Handle<SharedFunctionInfo> outer_info,
15480     LanguageMode language_mode, int scope_position) {
15481   Isolate* isolate = GetIsolate();
15482   // Cache key is the tuple (source, outer shared function info, scope position)
15483   // to unambiguously identify the context chain the cached eval code assumes.
15484   StringSharedKey key(src, outer_info, language_mode, scope_position);
15485   int entry = FindEntry(&key);
15486   if (entry == kNotFound) return isolate->factory()->undefined_value();
15487   int index = EntryToIndex(entry);
15488   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
15489   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15490 }
15491
15492
15493 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
15494                                                    JSRegExp::Flags flags) {
15495   Isolate* isolate = GetIsolate();
15496   DisallowHeapAllocation no_allocation;
15497   RegExpKey key(src, flags);
15498   int entry = FindEntry(&key);
15499   if (entry == kNotFound) return isolate->factory()->undefined_value();
15500   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15501 }
15502
15503
15504 Handle<CompilationCacheTable> CompilationCacheTable::Put(
15505     Handle<CompilationCacheTable> cache, Handle<String> src,
15506     Handle<Context> context, LanguageMode language_mode, Handle<Object> value) {
15507   Isolate* isolate = cache->GetIsolate();
15508   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15509   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
15510   {
15511     Handle<Object> k = key.AsHandle(isolate);
15512     DisallowHeapAllocation no_allocation_scope;
15513     int entry = cache->FindEntry(&key);
15514     if (entry != kNotFound) {
15515       cache->set(EntryToIndex(entry), *k);
15516       cache->set(EntryToIndex(entry) + 1, *value);
15517       return cache;
15518     }
15519   }
15520
15521   cache = EnsureCapacity(cache, 1, &key);
15522   int entry = cache->FindInsertionEntry(key.Hash());
15523   Handle<Object> k =
15524       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
15525   cache->set(EntryToIndex(entry), *k);
15526   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
15527   cache->ElementAdded();
15528   return cache;
15529 }
15530
15531
15532 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
15533     Handle<CompilationCacheTable> cache, Handle<String> src,
15534     Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
15535     int scope_position) {
15536   Isolate* isolate = cache->GetIsolate();
15537   StringSharedKey key(src, outer_info, value->language_mode(), scope_position);
15538   {
15539     Handle<Object> k = key.AsHandle(isolate);
15540     DisallowHeapAllocation no_allocation_scope;
15541     int entry = cache->FindEntry(&key);
15542     if (entry != kNotFound) {
15543       cache->set(EntryToIndex(entry), *k);
15544       cache->set(EntryToIndex(entry) + 1, *value);
15545       return cache;
15546     }
15547   }
15548
15549   cache = EnsureCapacity(cache, 1, &key);
15550   int entry = cache->FindInsertionEntry(key.Hash());
15551   Handle<Object> k =
15552       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
15553   cache->set(EntryToIndex(entry), *k);
15554   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
15555   cache->ElementAdded();
15556   return cache;
15557 }
15558
15559
15560 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
15561       Handle<CompilationCacheTable> cache, Handle<String> src,
15562       JSRegExp::Flags flags, Handle<FixedArray> value) {
15563   RegExpKey key(src, flags);
15564   cache = EnsureCapacity(cache, 1, &key);
15565   int entry = cache->FindInsertionEntry(key.Hash());
15566   // We store the value in the key slot, and compare the search key
15567   // to the stored value with a custon IsMatch function during lookups.
15568   cache->set(EntryToIndex(entry), *value);
15569   cache->set(EntryToIndex(entry) + 1, *value);
15570   cache->ElementAdded();
15571   return cache;
15572 }
15573
15574
15575 void CompilationCacheTable::Age() {
15576   DisallowHeapAllocation no_allocation;
15577   Object* the_hole_value = GetHeap()->the_hole_value();
15578   for (int entry = 0, size = Capacity(); entry < size; entry++) {
15579     int entry_index = EntryToIndex(entry);
15580     int value_index = entry_index + 1;
15581
15582     if (get(entry_index)->IsNumber()) {
15583       Smi* count = Smi::cast(get(value_index));
15584       count = Smi::FromInt(count->value() - 1);
15585       if (count->value() == 0) {
15586         NoWriteBarrierSet(this, entry_index, the_hole_value);
15587         NoWriteBarrierSet(this, value_index, the_hole_value);
15588         ElementRemoved();
15589       } else {
15590         NoWriteBarrierSet(this, value_index, count);
15591       }
15592     } else if (get(entry_index)->IsFixedArray()) {
15593       SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
15594       if (info->code()->kind() != Code::FUNCTION || info->code()->IsOld()) {
15595         NoWriteBarrierSet(this, entry_index, the_hole_value);
15596         NoWriteBarrierSet(this, value_index, the_hole_value);
15597         ElementRemoved();
15598       }
15599     }
15600   }
15601 }
15602
15603
15604 void CompilationCacheTable::Remove(Object* value) {
15605   DisallowHeapAllocation no_allocation;
15606   Object* the_hole_value = GetHeap()->the_hole_value();
15607   for (int entry = 0, size = Capacity(); entry < size; entry++) {
15608     int entry_index = EntryToIndex(entry);
15609     int value_index = entry_index + 1;
15610     if (get(value_index) == value) {
15611       NoWriteBarrierSet(this, entry_index, the_hole_value);
15612       NoWriteBarrierSet(this, value_index, the_hole_value);
15613       ElementRemoved();
15614     }
15615   }
15616   return;
15617 }
15618
15619
15620 // StringsKey used for HashTable where key is array of internalized strings.
15621 class StringsKey : public HashTableKey {
15622  public:
15623   explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
15624
15625   bool IsMatch(Object* strings) OVERRIDE {
15626     FixedArray* o = FixedArray::cast(strings);
15627     int len = strings_->length();
15628     if (o->length() != len) return false;
15629     for (int i = 0; i < len; i++) {
15630       if (o->get(i) != strings_->get(i)) return false;
15631     }
15632     return true;
15633   }
15634
15635   uint32_t Hash() OVERRIDE { return HashForObject(*strings_); }
15636
15637   uint32_t HashForObject(Object* obj) OVERRIDE {
15638     FixedArray* strings = FixedArray::cast(obj);
15639     int len = strings->length();
15640     uint32_t hash = 0;
15641     for (int i = 0; i < len; i++) {
15642       hash ^= String::cast(strings->get(i))->Hash();
15643     }
15644     return hash;
15645   }
15646
15647   Handle<Object> AsHandle(Isolate* isolate) OVERRIDE { return strings_; }
15648
15649  private:
15650   Handle<FixedArray> strings_;
15651 };
15652
15653
15654 template<typename Derived, typename Shape, typename Key>
15655 Handle<Derived> Dictionary<Derived, Shape, Key>::New(
15656     Isolate* isolate,
15657     int at_least_space_for,
15658     PretenureFlag pretenure) {
15659   DCHECK(0 <= at_least_space_for);
15660   Handle<Derived> dict = DerivedHashTable::New(isolate,
15661                                                at_least_space_for,
15662                                                USE_DEFAULT_MINIMUM_CAPACITY,
15663                                                pretenure);
15664
15665   // Initialize the next enumeration index.
15666   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
15667   return dict;
15668 }
15669
15670
15671 template <typename Derived, typename Shape, typename Key>
15672 Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
15673     Handle<Derived> dictionary) {
15674   Factory* factory = dictionary->GetIsolate()->factory();
15675   int length = dictionary->NumberOfElements();
15676
15677   Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
15678   Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
15679
15680   // Fill both the iteration order array and the enumeration order array
15681   // with property details.
15682   int capacity = dictionary->Capacity();
15683   int pos = 0;
15684   for (int i = 0; i < capacity; i++) {
15685     if (dictionary->IsKey(dictionary->KeyAt(i))) {
15686       int index = dictionary->DetailsAt(i).dictionary_index();
15687       iteration_order->set(pos, Smi::FromInt(i));
15688       enumeration_order->set(pos, Smi::FromInt(index));
15689       pos++;
15690     }
15691   }
15692   DCHECK(pos == length);
15693
15694   // Sort the arrays wrt. enumeration order.
15695   iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
15696   return iteration_order;
15697 }
15698
15699
15700 template <typename Derived, typename Shape, typename Key>
15701 Handle<FixedArray>
15702 Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
15703     Handle<Derived> dictionary) {
15704   int length = dictionary->NumberOfElements();
15705
15706   Handle<FixedArray> iteration_order = BuildIterationIndicesArray(dictionary);
15707   DCHECK(iteration_order->length() == length);
15708
15709   // Iterate over the dictionary using the enumeration order and update
15710   // the dictionary with new enumeration indices.
15711   for (int i = 0; i < length; i++) {
15712     int index = Smi::cast(iteration_order->get(i))->value();
15713     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
15714
15715     int enum_index = PropertyDetails::kInitialIndex + i;
15716
15717     PropertyDetails details = dictionary->DetailsAt(index);
15718     PropertyDetails new_details = details.set_index(enum_index);
15719     dictionary->DetailsAtPut(index, new_details);
15720   }
15721
15722   // Set the next enumeration index.
15723   dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
15724   return iteration_order;
15725 }
15726
15727
15728 template<typename Derived, typename Shape, typename Key>
15729 Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
15730     Handle<Derived> dictionary, int n, Key key) {
15731   // Check whether there are enough enumeration indices to add n elements.
15732   if (Shape::kIsEnumerable &&
15733       !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
15734     // If not, we generate new indices for the properties.
15735     GenerateNewEnumerationIndices(dictionary);
15736   }
15737   return DerivedHashTable::EnsureCapacity(dictionary, n, key);
15738 }
15739
15740
15741 template <typename Derived, typename Shape, typename Key>
15742 Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
15743     Handle<Derived> dictionary, int entry) {
15744   Factory* factory = dictionary->GetIsolate()->factory();
15745   PropertyDetails details = dictionary->DetailsAt(entry);
15746   if (!details.IsConfigurable()) return factory->false_value();
15747
15748   dictionary->SetEntry(
15749       entry, factory->the_hole_value(), factory->the_hole_value());
15750   dictionary->ElementRemoved();
15751   return factory->true_value();
15752 }
15753
15754
15755 template<typename Derived, typename Shape, typename Key>
15756 Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
15757     Handle<Derived> dictionary, Key key, Handle<Object> value) {
15758   int entry = dictionary->FindEntry(key);
15759
15760   // If the entry is present set the value;
15761   if (entry != Dictionary::kNotFound) {
15762     dictionary->ValueAtPut(entry, *value);
15763     return dictionary;
15764   }
15765
15766   // Check whether the dictionary should be extended.
15767   dictionary = EnsureCapacity(dictionary, 1, key);
15768 #ifdef DEBUG
15769   USE(Shape::AsHandle(dictionary->GetIsolate(), key));
15770 #endif
15771   PropertyDetails details = PropertyDetails::Empty();
15772
15773   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15774   return dictionary;
15775 }
15776
15777
15778 template<typename Derived, typename Shape, typename Key>
15779 Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
15780     Handle<Derived> dictionary,
15781     Key key,
15782     Handle<Object> value,
15783     PropertyDetails details) {
15784   // Valdate key is absent.
15785   SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
15786   // Check whether the dictionary should be extended.
15787   dictionary = EnsureCapacity(dictionary, 1, key);
15788
15789   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15790   return dictionary;
15791 }
15792
15793
15794 // Add a key, value pair to the dictionary.
15795 template<typename Derived, typename Shape, typename Key>
15796 void Dictionary<Derived, Shape, Key>::AddEntry(
15797     Handle<Derived> dictionary,
15798     Key key,
15799     Handle<Object> value,
15800     PropertyDetails details,
15801     uint32_t hash) {
15802   // Compute the key object.
15803   Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
15804
15805   uint32_t entry = dictionary->FindInsertionEntry(hash);
15806   // Insert element at empty or deleted entry
15807   if (details.dictionary_index() == 0 && Shape::kIsEnumerable) {
15808     // Assign an enumeration index to the property and update
15809     // SetNextEnumerationIndex.
15810     int index = dictionary->NextEnumerationIndex();
15811     details = details.set_index(index);
15812     dictionary->SetNextEnumerationIndex(index + 1);
15813   }
15814   dictionary->SetEntry(entry, k, value, details);
15815   DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
15816           dictionary->KeyAt(entry)->IsName()));
15817   dictionary->ElementAdded();
15818 }
15819
15820
15821 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
15822   DisallowHeapAllocation no_allocation;
15823   // If the dictionary requires slow elements an element has already
15824   // been added at a high index.
15825   if (requires_slow_elements()) return;
15826   // Check if this index is high enough that we should require slow
15827   // elements.
15828   if (key > kRequiresSlowElementsLimit) {
15829     set_requires_slow_elements();
15830     return;
15831   }
15832   // Update max key value.
15833   Object* max_index_object = get(kMaxNumberKeyIndex);
15834   if (!max_index_object->IsSmi() || max_number_key() < key) {
15835     FixedArray::set(kMaxNumberKeyIndex,
15836                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
15837   }
15838 }
15839
15840
15841 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
15842     Handle<SeededNumberDictionary> dictionary,
15843     uint32_t key,
15844     Handle<Object> value,
15845     PropertyDetails details) {
15846   dictionary->UpdateMaxNumberKey(key);
15847   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
15848   return Add(dictionary, key, value, details);
15849 }
15850
15851
15852 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
15853     Handle<UnseededNumberDictionary> dictionary,
15854     uint32_t key,
15855     Handle<Object> value) {
15856   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
15857   return Add(dictionary, key, value, PropertyDetails::Empty());
15858 }
15859
15860
15861 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
15862     Handle<SeededNumberDictionary> dictionary,
15863     uint32_t key,
15864     Handle<Object> value) {
15865   dictionary->UpdateMaxNumberKey(key);
15866   return AtPut(dictionary, key, value);
15867 }
15868
15869
15870 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
15871     Handle<UnseededNumberDictionary> dictionary,
15872     uint32_t key,
15873     Handle<Object> value) {
15874   return AtPut(dictionary, key, value);
15875 }
15876
15877
15878 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
15879     Handle<SeededNumberDictionary> dictionary,
15880     uint32_t key,
15881     Handle<Object> value,
15882     PropertyDetails details) {
15883   int entry = dictionary->FindEntry(key);
15884   if (entry == kNotFound) {
15885     return AddNumberEntry(dictionary, key, value, details);
15886   }
15887   // Preserve enumeration index.
15888   details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
15889   Handle<Object> object_key =
15890       SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15891   dictionary->SetEntry(entry, object_key, value, details);
15892   return dictionary;
15893 }
15894
15895
15896 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
15897     Handle<UnseededNumberDictionary> dictionary,
15898     uint32_t key,
15899     Handle<Object> value) {
15900   int entry = dictionary->FindEntry(key);
15901   if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
15902   Handle<Object> object_key =
15903       UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15904   dictionary->SetEntry(entry, object_key, value);
15905   return dictionary;
15906 }
15907
15908
15909 template <DictionaryEntryType type, typename D>
15910 static inline bool IsDeleted(D d, int i) {
15911   switch (type) {
15912     case DictionaryEntryType::kObjects:
15913       return false;
15914     case DictionaryEntryType::kCells:
15915       DCHECK(d->ValueAt(i)->IsPropertyCell());
15916       return PropertyCell::cast(d->ValueAt(i))->value()->IsTheHole();
15917   }
15918   UNREACHABLE();
15919   return false;
15920 }
15921
15922
15923 template <typename Derived, typename Shape, typename Key>
15924 template <DictionaryEntryType type>
15925 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
15926     PropertyAttributes filter) {
15927   int capacity = DerivedHashTable::Capacity();
15928   int result = 0;
15929   for (int i = 0; i < capacity; i++) {
15930     Object* k = DerivedHashTable::KeyAt(i);
15931     if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15932       if (IsDeleted<type>(this, i)) continue;
15933       PropertyDetails details = DetailsAt(i);
15934       PropertyAttributes attr = details.attributes();
15935       if ((attr & filter) == 0) result++;
15936     }
15937   }
15938   return result;
15939 }
15940
15941
15942 template <typename Derived, typename Shape, typename Key>
15943 template <DictionaryEntryType type>
15944 bool Dictionary<Derived, Shape, Key>::HasComplexElements() {
15945   int capacity = DerivedHashTable::Capacity();
15946   for (int i = 0; i < capacity; i++) {
15947     Object* k = DerivedHashTable::KeyAt(i);
15948     if (DerivedHashTable::IsKey(k) && !FilterKey(k, NONE)) {
15949       if (IsDeleted<type>(this, i)) continue;
15950       PropertyDetails details = DetailsAt(i);
15951       if (details.type() == ACCESSOR_CONSTANT) return true;
15952       PropertyAttributes attr = details.attributes();
15953       if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true;
15954     }
15955   }
15956   return false;
15957 }
15958
15959
15960 template <typename Derived, typename Shape, typename Key>
15961 template <DictionaryEntryType type>
15962 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
15963     FixedArray* storage, PropertyAttributes filter,
15964     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
15965   DCHECK(storage->length() >= NumberOfElementsFilterAttributes<type>(filter));
15966   int capacity = DerivedHashTable::Capacity();
15967   int index = 0;
15968   for (int i = 0; i < capacity; i++) {
15969      Object* k = DerivedHashTable::KeyAt(i);
15970      if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15971        if (IsDeleted<type>(this, i)) continue;
15972        PropertyDetails details = DetailsAt(i);
15973        PropertyAttributes attr = details.attributes();
15974        if ((attr & filter) == 0) storage->set(index++, k);
15975      }
15976   }
15977   if (sort_mode == Dictionary::SORTED) {
15978     storage->SortPairs(storage, index);
15979   }
15980   DCHECK(storage->length() >= index);
15981 }
15982
15983
15984 struct EnumIndexComparator {
15985   explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { }
15986   bool operator() (Smi* a, Smi* b) {
15987     PropertyDetails da(dict->DetailsAt(a->value()));
15988     PropertyDetails db(dict->DetailsAt(b->value()));
15989     return da.dictionary_index() < db.dictionary_index();
15990   }
15991   NameDictionary* dict;
15992 };
15993
15994
15995 template <DictionaryEntryType type>
15996 void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
15997   int length = storage->length();
15998   int capacity = Capacity();
15999   int properties = 0;
16000   for (int i = 0; i < capacity; i++) {
16001      Object* k = KeyAt(i);
16002      if (IsKey(k) && !k->IsSymbol()) {
16003        PropertyDetails details = DetailsAt(i);
16004        if (details.IsDontEnum() || IsDeleted<type>(this, i)) continue;
16005        storage->set(properties, Smi::FromInt(i));
16006        properties++;
16007        if (properties == length) break;
16008      }
16009   }
16010   CHECK_EQ(length, properties);
16011   EnumIndexComparator cmp(this);
16012   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
16013   std::sort(start, start + length, cmp);
16014   for (int i = 0; i < length; i++) {
16015     int index = Smi::cast(storage->get(i))->value();
16016     storage->set(i, KeyAt(index));
16017   }
16018 }
16019
16020
16021 template <typename Derived, typename Shape, typename Key>
16022 template <DictionaryEntryType type>
16023 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
16024     FixedArray* storage, int index, PropertyAttributes filter,
16025     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
16026   DCHECK(storage->length() >= NumberOfElementsFilterAttributes<type>(filter));
16027   int capacity = DerivedHashTable::Capacity();
16028   for (int i = 0; i < capacity; i++) {
16029     Object* k = DerivedHashTable::KeyAt(i);
16030     if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
16031       if (IsDeleted<type>(this, i)) continue;
16032       PropertyDetails details = DetailsAt(i);
16033       PropertyAttributes attr = details.attributes();
16034       if ((attr & filter) == 0) storage->set(index++, k);
16035     }
16036   }
16037   if (sort_mode == Dictionary::SORTED) {
16038     storage->SortPairs(storage, index);
16039   }
16040   DCHECK(storage->length() >= index);
16041 }
16042
16043
16044 // Backwards lookup (slow).
16045 template<typename Derived, typename Shape, typename Key>
16046 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
16047   int capacity = DerivedHashTable::Capacity();
16048   for (int i = 0; i < capacity; i++) {
16049     Object* k =  DerivedHashTable::KeyAt(i);
16050     if (Dictionary::IsKey(k)) {
16051       Object* e = ValueAt(i);
16052       // TODO(dcarney): this should be templatized.
16053       if (e->IsPropertyCell()) {
16054         e = PropertyCell::cast(e)->value();
16055       }
16056       if (e == value) return k;
16057     }
16058   }
16059   Heap* heap = Dictionary::GetHeap();
16060   return heap->undefined_value();
16061 }
16062
16063
16064 Object* ObjectHashTable::Lookup(Handle<Object> key) {
16065   DisallowHeapAllocation no_gc;
16066   DCHECK(IsKey(*key));
16067
16068   // If the object does not have an identity hash, it was never used as a key.
16069   Object* hash = key->GetHash();
16070   if (hash->IsUndefined()) {
16071     return GetHeap()->the_hole_value();
16072   }
16073   int entry = FindEntry(key);
16074   if (entry == kNotFound) return GetHeap()->the_hole_value();
16075   return get(EntryToIndex(entry) + 1);
16076 }
16077
16078
16079 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
16080                                              Handle<Object> key,
16081                                              Handle<Object> value) {
16082   DCHECK(table->IsKey(*key));
16083   DCHECK(!value->IsTheHole());
16084
16085   Isolate* isolate = table->GetIsolate();
16086
16087   // Make sure the key object has an identity hash code.
16088   Handle<Smi> hash = Object::GetOrCreateHash(isolate, key);
16089
16090   int entry = table->FindEntry(key);
16091
16092   // Key is already in table, just overwrite value.
16093   if (entry != kNotFound) {
16094     table->set(EntryToIndex(entry) + 1, *value);
16095     return table;
16096   }
16097
16098   // Check whether the hash table should be extended.
16099   table = EnsureCapacity(table, 1, key);
16100   table->AddEntry(table->FindInsertionEntry(hash->value()),
16101                   *key,
16102                   *value);
16103   return table;
16104 }
16105
16106
16107 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
16108                                                 Handle<Object> key,
16109                                                 bool* was_present) {
16110   DCHECK(table->IsKey(*key));
16111
16112   Object* hash = key->GetHash();
16113   if (hash->IsUndefined()) {
16114     *was_present = false;
16115     return table;
16116   }
16117
16118   int entry = table->FindEntry(key);
16119   if (entry == kNotFound) {
16120     *was_present = false;
16121     return table;
16122   }
16123
16124   *was_present = true;
16125   table->RemoveEntry(entry);
16126   return Shrink(table, key);
16127 }
16128
16129
16130 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
16131   set(EntryToIndex(entry), key);
16132   set(EntryToIndex(entry) + 1, value);
16133   ElementAdded();
16134 }
16135
16136
16137 void ObjectHashTable::RemoveEntry(int entry) {
16138   set_the_hole(EntryToIndex(entry));
16139   set_the_hole(EntryToIndex(entry) + 1);
16140   ElementRemoved();
16141 }
16142
16143
16144 Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
16145   DisallowHeapAllocation no_gc;
16146   DCHECK(IsKey(*key));
16147   int entry = FindEntry(key);
16148   if (entry == kNotFound) return GetHeap()->the_hole_value();
16149   return get(EntryToValueIndex(entry));
16150 }
16151
16152
16153 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
16154                                          Handle<HeapObject> key,
16155                                          Handle<HeapObject> value) {
16156   DCHECK(table->IsKey(*key));
16157   int entry = table->FindEntry(key);
16158   // Key is already in table, just overwrite value.
16159   if (entry != kNotFound) {
16160     table->set(EntryToValueIndex(entry), *value);
16161     return table;
16162   }
16163
16164   Handle<WeakCell> key_cell = key->GetIsolate()->factory()->NewWeakCell(key);
16165
16166   // Check whether the hash table should be extended.
16167   table = EnsureCapacity(table, 1, key, TENURED);
16168
16169   table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
16170   return table;
16171 }
16172
16173
16174 void WeakHashTable::AddEntry(int entry, Handle<WeakCell> key_cell,
16175                              Handle<HeapObject> value) {
16176   DisallowHeapAllocation no_allocation;
16177   set(EntryToIndex(entry), *key_cell);
16178   set(EntryToValueIndex(entry), *value);
16179   ElementAdded();
16180 }
16181
16182
16183 template<class Derived, class Iterator, int entrysize>
16184 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
16185     Isolate* isolate, int capacity, PretenureFlag pretenure) {
16186   // Capacity must be a power of two, since we depend on being able
16187   // to divide and multiple by 2 (kLoadFactor) to derive capacity
16188   // from number of buckets. If we decide to change kLoadFactor
16189   // to something other than 2, capacity should be stored as another
16190   // field of this object.
16191   capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
16192   if (capacity > kMaxCapacity) {
16193     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
16194   }
16195   int num_buckets = capacity / kLoadFactor;
16196   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
16197       kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
16198   backing_store->set_map_no_write_barrier(
16199       isolate->heap()->ordered_hash_table_map());
16200   Handle<Derived> table = Handle<Derived>::cast(backing_store);
16201   for (int i = 0; i < num_buckets; ++i) {
16202     table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
16203   }
16204   table->SetNumberOfBuckets(num_buckets);
16205   table->SetNumberOfElements(0);
16206   table->SetNumberOfDeletedElements(0);
16207   return table;
16208 }
16209
16210
16211 template<class Derived, class Iterator, int entrysize>
16212 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
16213     Handle<Derived> table) {
16214   DCHECK(!table->IsObsolete());
16215
16216   int nof = table->NumberOfElements();
16217   int nod = table->NumberOfDeletedElements();
16218   int capacity = table->Capacity();
16219   if ((nof + nod) < capacity) return table;
16220   // Don't need to grow if we can simply clear out deleted entries instead.
16221   // Note that we can't compact in place, though, so we always allocate
16222   // a new table.
16223   return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
16224 }
16225
16226
16227 template<class Derived, class Iterator, int entrysize>
16228 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
16229     Handle<Derived> table) {
16230   DCHECK(!table->IsObsolete());
16231
16232   int nof = table->NumberOfElements();
16233   int capacity = table->Capacity();
16234   if (nof >= (capacity >> 2)) return table;
16235   return Rehash(table, capacity / 2);
16236 }
16237
16238
16239 template<class Derived, class Iterator, int entrysize>
16240 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
16241     Handle<Derived> table) {
16242   DCHECK(!table->IsObsolete());
16243
16244   Handle<Derived> new_table =
16245       Allocate(table->GetIsolate(),
16246                kMinCapacity,
16247                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
16248
16249   table->SetNextTable(*new_table);
16250   table->SetNumberOfDeletedElements(kClearedTableSentinel);
16251
16252   return new_table;
16253 }
16254
16255
16256 template<class Derived, class Iterator, int entrysize>
16257 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Remove(
16258     Handle<Derived> table, Handle<Object> key, bool* was_present) {
16259   int entry = table->FindEntry(key);
16260   if (entry == kNotFound) {
16261     *was_present = false;
16262     return table;
16263   }
16264   *was_present = true;
16265   table->RemoveEntry(entry);
16266   return Shrink(table);
16267 }
16268
16269
16270 template<class Derived, class Iterator, int entrysize>
16271 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
16272     Handle<Derived> table, int new_capacity) {
16273   DCHECK(!table->IsObsolete());
16274
16275   Handle<Derived> new_table =
16276       Allocate(table->GetIsolate(),
16277                new_capacity,
16278                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
16279   int nof = table->NumberOfElements();
16280   int nod = table->NumberOfDeletedElements();
16281   int new_buckets = new_table->NumberOfBuckets();
16282   int new_entry = 0;
16283   int removed_holes_index = 0;
16284
16285   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
16286     Object* key = table->KeyAt(old_entry);
16287     if (key->IsTheHole()) {
16288       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
16289       continue;
16290     }
16291
16292     Object* hash = key->GetHash();
16293     int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
16294     Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
16295     new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
16296     int new_index = new_table->EntryToIndex(new_entry);
16297     int old_index = table->EntryToIndex(old_entry);
16298     for (int i = 0; i < entrysize; ++i) {
16299       Object* value = table->get(old_index + i);
16300       new_table->set(new_index + i, value);
16301     }
16302     new_table->set(new_index + kChainOffset, chain_entry);
16303     ++new_entry;
16304   }
16305
16306   DCHECK_EQ(nod, removed_holes_index);
16307
16308   new_table->SetNumberOfElements(nof);
16309   table->SetNextTable(*new_table);
16310
16311   return new_table;
16312 }
16313
16314
16315 template <class Derived, class Iterator, int entrysize>
16316 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(
16317     Handle<Object> key, int hash) {
16318   DCHECK(!IsObsolete());
16319
16320   DisallowHeapAllocation no_gc;
16321   DCHECK(!key->IsTheHole());
16322   for (int entry = HashToEntry(hash); entry != kNotFound;
16323        entry = ChainAt(entry)) {
16324     Object* candidate = KeyAt(entry);
16325     if (candidate->SameValueZero(*key))
16326       return entry;
16327   }
16328   return kNotFound;
16329 }
16330
16331
16332 template <class Derived, class Iterator, int entrysize>
16333 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(
16334     Handle<Object> key) {
16335   DisallowHeapAllocation no_gc;
16336   Object* hash = key->GetHash();
16337   if (!hash->IsSmi()) return kNotFound;
16338   return FindEntry(key, Smi::cast(hash)->value());
16339 }
16340
16341
16342 template <class Derived, class Iterator, int entrysize>
16343 int OrderedHashTable<Derived, Iterator, entrysize>::AddEntry(int hash) {
16344   DCHECK(!IsObsolete());
16345
16346   int entry = UsedCapacity();
16347   int bucket = HashToBucket(hash);
16348   int index = EntryToIndex(entry);
16349   Object* chain_entry = get(kHashTableStartIndex + bucket);
16350   set(kHashTableStartIndex + bucket, Smi::FromInt(entry));
16351   set(index + kChainOffset, chain_entry);
16352   SetNumberOfElements(NumberOfElements() + 1);
16353   return index;
16354 }
16355
16356
16357 template<class Derived, class Iterator, int entrysize>
16358 void OrderedHashTable<Derived, Iterator, entrysize>::RemoveEntry(int entry) {
16359   DCHECK(!IsObsolete());
16360
16361   int index = EntryToIndex(entry);
16362   for (int i = 0; i < entrysize; ++i) {
16363     set_the_hole(index + i);
16364   }
16365   SetNumberOfElements(NumberOfElements() - 1);
16366   SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
16367 }
16368
16369
16370 template Handle<OrderedHashSet>
16371 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
16372     Isolate* isolate, int capacity, PretenureFlag pretenure);
16373
16374 template Handle<OrderedHashSet>
16375 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
16376     Handle<OrderedHashSet> table);
16377
16378 template Handle<OrderedHashSet>
16379 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
16380     Handle<OrderedHashSet> table);
16381
16382 template Handle<OrderedHashSet>
16383 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
16384     Handle<OrderedHashSet> table);
16385
16386 template Handle<OrderedHashSet>
16387 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Remove(
16388     Handle<OrderedHashSet> table, Handle<Object> key, bool* was_present);
16389
16390 template int OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(
16391     Handle<Object> key, int hash);
16392 template int OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(
16393     Handle<Object> key);
16394
16395 template int
16396 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::AddEntry(int hash);
16397
16398 template void
16399 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::RemoveEntry(int entry);
16400
16401
16402 template Handle<OrderedHashMap>
16403 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
16404     Isolate* isolate, int capacity, PretenureFlag pretenure);
16405
16406 template Handle<OrderedHashMap>
16407 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
16408     Handle<OrderedHashMap> table);
16409
16410 template Handle<OrderedHashMap>
16411 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
16412     Handle<OrderedHashMap> table);
16413
16414 template Handle<OrderedHashMap>
16415 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
16416     Handle<OrderedHashMap> table);
16417
16418 template Handle<OrderedHashMap>
16419 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Remove(
16420     Handle<OrderedHashMap> table, Handle<Object> key, bool* was_present);
16421
16422 template int OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(
16423     Handle<Object> key, int hash);
16424 template int OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(
16425     Handle<Object> key);
16426
16427 template int
16428 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::AddEntry(int hash);
16429
16430 template void
16431 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::RemoveEntry(int entry);
16432
16433
16434 bool OrderedHashSet::Contains(Handle<Object> key) {
16435   return FindEntry(key) != kNotFound;
16436 }
16437
16438
16439 Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
16440                                            Handle<Object> key) {
16441   int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
16442   if (table->FindEntry(key, hash) != kNotFound) return table;
16443
16444   table = EnsureGrowable(table);
16445
16446   int index = table->AddEntry(hash);
16447   table->set(index, *key);
16448   return table;
16449 }
16450
16451
16452 Object* OrderedHashMap::Lookup(Handle<Object> key) {
16453   DisallowHeapAllocation no_gc;
16454   int entry = FindEntry(key);
16455   if (entry == kNotFound) return GetHeap()->the_hole_value();
16456   return ValueAt(entry);
16457 }
16458
16459
16460 Handle<OrderedHashMap> OrderedHashMap::Put(Handle<OrderedHashMap> table,
16461                                            Handle<Object> key,
16462                                            Handle<Object> value) {
16463   DCHECK(!key->IsTheHole());
16464
16465   int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
16466   int entry = table->FindEntry(key, hash);
16467
16468   if (entry != kNotFound) {
16469     table->set(table->EntryToIndex(entry) + kValueOffset, *value);
16470     return table;
16471   }
16472
16473   table = EnsureGrowable(table);
16474
16475   int index = table->AddEntry(hash);
16476   table->set(index, *key);
16477   table->set(index + kValueOffset, *value);
16478   return table;
16479 }
16480
16481
16482 template<class Derived, class TableType>
16483 void OrderedHashTableIterator<Derived, TableType>::Transition() {
16484   DisallowHeapAllocation no_allocation;
16485   TableType* table = TableType::cast(this->table());
16486   if (!table->IsObsolete()) return;
16487
16488   int index = Smi::cast(this->index())->value();
16489   while (table->IsObsolete()) {
16490     TableType* next_table = table->NextTable();
16491
16492     if (index > 0) {
16493       int nod = table->NumberOfDeletedElements();
16494
16495       if (nod == TableType::kClearedTableSentinel) {
16496         index = 0;
16497       } else {
16498         int old_index = index;
16499         for (int i = 0; i < nod; ++i) {
16500           int removed_index = table->RemovedIndexAt(i);
16501           if (removed_index >= old_index) break;
16502           --index;
16503         }
16504       }
16505     }
16506
16507     table = next_table;
16508   }
16509
16510   set_table(table);
16511   set_index(Smi::FromInt(index));
16512 }
16513
16514
16515 template<class Derived, class TableType>
16516 bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
16517   DisallowHeapAllocation no_allocation;
16518   if (this->table()->IsUndefined()) return false;
16519
16520   Transition();
16521
16522   TableType* table = TableType::cast(this->table());
16523   int index = Smi::cast(this->index())->value();
16524   int used_capacity = table->UsedCapacity();
16525
16526   while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
16527     index++;
16528   }
16529
16530   set_index(Smi::FromInt(index));
16531
16532   if (index < used_capacity) return true;
16533
16534   set_table(GetHeap()->undefined_value());
16535   return false;
16536 }
16537
16538
16539 template<class Derived, class TableType>
16540 Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
16541   DisallowHeapAllocation no_allocation;
16542   if (HasMore()) {
16543     FixedArray* array = FixedArray::cast(value_array->elements());
16544     static_cast<Derived*>(this)->PopulateValueArray(array);
16545     MoveNext();
16546     return Smi::cast(kind());
16547   }
16548   return Smi::FromInt(0);
16549 }
16550
16551
16552 template Smi*
16553 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
16554     JSArray* value_array);
16555
16556 template bool
16557 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
16558
16559 template void
16560 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
16561
16562 template Object*
16563 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
16564
16565 template void
16566 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
16567
16568
16569 template Smi*
16570 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
16571     JSArray* value_array);
16572
16573 template bool
16574 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
16575
16576 template void
16577 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
16578
16579 template Object*
16580 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
16581
16582 template void
16583 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
16584
16585
16586 // Check if there is a break point at this code position.
16587 bool DebugInfo::HasBreakPoint(int code_position) {
16588   // Get the break point info object for this code position.
16589   Object* break_point_info = GetBreakPointInfo(code_position);
16590
16591   // If there is no break point info object or no break points in the break
16592   // point info object there is no break point at this code position.
16593   if (break_point_info->IsUndefined()) return false;
16594   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
16595 }
16596
16597
16598 // Get the break point info object for this code position.
16599 Object* DebugInfo::GetBreakPointInfo(int code_position) {
16600   // Find the index of the break point info object for this code position.
16601   int index = GetBreakPointInfoIndex(code_position);
16602
16603   // Return the break point info object if any.
16604   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
16605   return BreakPointInfo::cast(break_points()->get(index));
16606 }
16607
16608
16609 // Clear a break point at the specified code position.
16610 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
16611                                 int code_position,
16612                                 Handle<Object> break_point_object) {
16613   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16614                                   debug_info->GetIsolate());
16615   if (break_point_info->IsUndefined()) return;
16616   BreakPointInfo::ClearBreakPoint(
16617       Handle<BreakPointInfo>::cast(break_point_info),
16618       break_point_object);
16619 }
16620
16621
16622 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
16623                               int code_position,
16624                               int source_position,
16625                               int statement_position,
16626                               Handle<Object> break_point_object) {
16627   Isolate* isolate = debug_info->GetIsolate();
16628   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16629                                   isolate);
16630   if (!break_point_info->IsUndefined()) {
16631     BreakPointInfo::SetBreakPoint(
16632         Handle<BreakPointInfo>::cast(break_point_info),
16633         break_point_object);
16634     return;
16635   }
16636
16637   // Adding a new break point for a code position which did not have any
16638   // break points before. Try to find a free slot.
16639   int index = kNoBreakPointInfo;
16640   for (int i = 0; i < debug_info->break_points()->length(); i++) {
16641     if (debug_info->break_points()->get(i)->IsUndefined()) {
16642       index = i;
16643       break;
16644     }
16645   }
16646   if (index == kNoBreakPointInfo) {
16647     // No free slot - extend break point info array.
16648     Handle<FixedArray> old_break_points =
16649         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
16650     Handle<FixedArray> new_break_points =
16651         isolate->factory()->NewFixedArray(
16652             old_break_points->length() +
16653             DebugInfo::kEstimatedNofBreakPointsInFunction);
16654
16655     debug_info->set_break_points(*new_break_points);
16656     for (int i = 0; i < old_break_points->length(); i++) {
16657       new_break_points->set(i, old_break_points->get(i));
16658     }
16659     index = old_break_points->length();
16660   }
16661   DCHECK(index != kNoBreakPointInfo);
16662
16663   // Allocate new BreakPointInfo object and set the break point.
16664   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
16665       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
16666   new_break_point_info->set_code_position(Smi::FromInt(code_position));
16667   new_break_point_info->set_source_position(Smi::FromInt(source_position));
16668   new_break_point_info->
16669       set_statement_position(Smi::FromInt(statement_position));
16670   new_break_point_info->set_break_point_objects(
16671       isolate->heap()->undefined_value());
16672   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
16673   debug_info->break_points()->set(index, *new_break_point_info);
16674 }
16675
16676
16677 // Get the break point objects for a code position.
16678 Handle<Object> DebugInfo::GetBreakPointObjects(int code_position) {
16679   Object* break_point_info = GetBreakPointInfo(code_position);
16680   if (break_point_info->IsUndefined()) {
16681     return GetIsolate()->factory()->undefined_value();
16682   }
16683   return Handle<Object>(
16684       BreakPointInfo::cast(break_point_info)->break_point_objects(),
16685       GetIsolate());
16686 }
16687
16688
16689 // Get the total number of break points.
16690 int DebugInfo::GetBreakPointCount() {
16691   if (break_points()->IsUndefined()) return 0;
16692   int count = 0;
16693   for (int i = 0; i < break_points()->length(); i++) {
16694     if (!break_points()->get(i)->IsUndefined()) {
16695       BreakPointInfo* break_point_info =
16696           BreakPointInfo::cast(break_points()->get(i));
16697       count += break_point_info->GetBreakPointCount();
16698     }
16699   }
16700   return count;
16701 }
16702
16703
16704 Handle<Object> DebugInfo::FindBreakPointInfo(
16705     Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
16706   Isolate* isolate = debug_info->GetIsolate();
16707   if (!debug_info->break_points()->IsUndefined()) {
16708     for (int i = 0; i < debug_info->break_points()->length(); i++) {
16709       if (!debug_info->break_points()->get(i)->IsUndefined()) {
16710         Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
16711             BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
16712         if (BreakPointInfo::HasBreakPointObject(break_point_info,
16713                                                 break_point_object)) {
16714           return break_point_info;
16715         }
16716       }
16717     }
16718   }
16719   return isolate->factory()->undefined_value();
16720 }
16721
16722
16723 // Find the index of the break point info object for the specified code
16724 // position.
16725 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
16726   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
16727   for (int i = 0; i < break_points()->length(); i++) {
16728     if (!break_points()->get(i)->IsUndefined()) {
16729       BreakPointInfo* break_point_info =
16730           BreakPointInfo::cast(break_points()->get(i));
16731       if (break_point_info->code_position()->value() == code_position) {
16732         return i;
16733       }
16734     }
16735   }
16736   return kNoBreakPointInfo;
16737 }
16738
16739
16740 // Remove the specified break point object.
16741 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
16742                                      Handle<Object> break_point_object) {
16743   Isolate* isolate = break_point_info->GetIsolate();
16744   // If there are no break points just ignore.
16745   if (break_point_info->break_point_objects()->IsUndefined()) return;
16746   // If there is a single break point clear it if it is the same.
16747   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16748     if (break_point_info->break_point_objects() == *break_point_object) {
16749       break_point_info->set_break_point_objects(
16750           isolate->heap()->undefined_value());
16751     }
16752     return;
16753   }
16754   // If there are multiple break points shrink the array
16755   DCHECK(break_point_info->break_point_objects()->IsFixedArray());
16756   Handle<FixedArray> old_array =
16757       Handle<FixedArray>(
16758           FixedArray::cast(break_point_info->break_point_objects()));
16759   Handle<FixedArray> new_array =
16760       isolate->factory()->NewFixedArray(old_array->length() - 1);
16761   int found_count = 0;
16762   for (int i = 0; i < old_array->length(); i++) {
16763     if (old_array->get(i) == *break_point_object) {
16764       DCHECK(found_count == 0);
16765       found_count++;
16766     } else {
16767       new_array->set(i - found_count, old_array->get(i));
16768     }
16769   }
16770   // If the break point was found in the list change it.
16771   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
16772 }
16773
16774
16775 // Add the specified break point object.
16776 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
16777                                    Handle<Object> break_point_object) {
16778   Isolate* isolate = break_point_info->GetIsolate();
16779
16780   // If there was no break point objects before just set it.
16781   if (break_point_info->break_point_objects()->IsUndefined()) {
16782     break_point_info->set_break_point_objects(*break_point_object);
16783     return;
16784   }
16785   // If the break point object is the same as before just ignore.
16786   if (break_point_info->break_point_objects() == *break_point_object) return;
16787   // If there was one break point object before replace with array.
16788   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16789     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
16790     array->set(0, break_point_info->break_point_objects());
16791     array->set(1, *break_point_object);
16792     break_point_info->set_break_point_objects(*array);
16793     return;
16794   }
16795   // If there was more than one break point before extend array.
16796   Handle<FixedArray> old_array =
16797       Handle<FixedArray>(
16798           FixedArray::cast(break_point_info->break_point_objects()));
16799   Handle<FixedArray> new_array =
16800       isolate->factory()->NewFixedArray(old_array->length() + 1);
16801   for (int i = 0; i < old_array->length(); i++) {
16802     // If the break point was there before just ignore.
16803     if (old_array->get(i) == *break_point_object) return;
16804     new_array->set(i, old_array->get(i));
16805   }
16806   // Add the new break point.
16807   new_array->set(old_array->length(), *break_point_object);
16808   break_point_info->set_break_point_objects(*new_array);
16809 }
16810
16811
16812 bool BreakPointInfo::HasBreakPointObject(
16813     Handle<BreakPointInfo> break_point_info,
16814     Handle<Object> break_point_object) {
16815   // No break point.
16816   if (break_point_info->break_point_objects()->IsUndefined()) return false;
16817   // Single break point.
16818   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16819     return break_point_info->break_point_objects() == *break_point_object;
16820   }
16821   // Multiple break points.
16822   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
16823   for (int i = 0; i < array->length(); i++) {
16824     if (array->get(i) == *break_point_object) {
16825       return true;
16826     }
16827   }
16828   return false;
16829 }
16830
16831
16832 // Get the number of break points.
16833 int BreakPointInfo::GetBreakPointCount() {
16834   // No break point.
16835   if (break_point_objects()->IsUndefined()) return 0;
16836   // Single break point.
16837   if (!break_point_objects()->IsFixedArray()) return 1;
16838   // Multiple break points.
16839   return FixedArray::cast(break_point_objects())->length();
16840 }
16841
16842
16843 Object* JSDate::GetField(Object* object, Smi* index) {
16844   return JSDate::cast(object)->DoGetField(
16845       static_cast<FieldIndex>(index->value()));
16846 }
16847
16848
16849 Object* JSDate::DoGetField(FieldIndex index) {
16850   DCHECK(index != kDateValue);
16851
16852   DateCache* date_cache = GetIsolate()->date_cache();
16853
16854   if (index < kFirstUncachedField) {
16855     Object* stamp = cache_stamp();
16856     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
16857       // Since the stamp is not NaN, the value is also not NaN.
16858       int64_t local_time_ms =
16859           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
16860       SetCachedFields(local_time_ms, date_cache);
16861     }
16862     switch (index) {
16863       case kYear: return year();
16864       case kMonth: return month();
16865       case kDay: return day();
16866       case kWeekday: return weekday();
16867       case kHour: return hour();
16868       case kMinute: return min();
16869       case kSecond: return sec();
16870       default: UNREACHABLE();
16871     }
16872   }
16873
16874   if (index >= kFirstUTCField) {
16875     return GetUTCField(index, value()->Number(), date_cache);
16876   }
16877
16878   double time = value()->Number();
16879   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
16880
16881   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
16882   int days = DateCache::DaysFromTime(local_time_ms);
16883
16884   if (index == kDays) return Smi::FromInt(days);
16885
16886   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16887   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
16888   DCHECK(index == kTimeInDay);
16889   return Smi::FromInt(time_in_day_ms);
16890 }
16891
16892
16893 Object* JSDate::GetUTCField(FieldIndex index,
16894                             double value,
16895                             DateCache* date_cache) {
16896   DCHECK(index >= kFirstUTCField);
16897
16898   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
16899
16900   int64_t time_ms = static_cast<int64_t>(value);
16901
16902   if (index == kTimezoneOffset) {
16903     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
16904   }
16905
16906   int days = DateCache::DaysFromTime(time_ms);
16907
16908   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
16909
16910   if (index <= kDayUTC) {
16911     int year, month, day;
16912     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16913     if (index == kYearUTC) return Smi::FromInt(year);
16914     if (index == kMonthUTC) return Smi::FromInt(month);
16915     DCHECK(index == kDayUTC);
16916     return Smi::FromInt(day);
16917   }
16918
16919   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
16920   switch (index) {
16921     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
16922     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
16923     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
16924     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
16925     case kDaysUTC: return Smi::FromInt(days);
16926     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
16927     default: UNREACHABLE();
16928   }
16929
16930   UNREACHABLE();
16931   return NULL;
16932 }
16933
16934
16935 void JSDate::SetValue(Object* value, bool is_value_nan) {
16936   set_value(value);
16937   if (is_value_nan) {
16938     HeapNumber* nan = GetIsolate()->heap()->nan_value();
16939     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
16940     set_year(nan, SKIP_WRITE_BARRIER);
16941     set_month(nan, SKIP_WRITE_BARRIER);
16942     set_day(nan, SKIP_WRITE_BARRIER);
16943     set_hour(nan, SKIP_WRITE_BARRIER);
16944     set_min(nan, SKIP_WRITE_BARRIER);
16945     set_sec(nan, SKIP_WRITE_BARRIER);
16946     set_weekday(nan, SKIP_WRITE_BARRIER);
16947   } else {
16948     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
16949   }
16950 }
16951
16952
16953 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
16954   int days = DateCache::DaysFromTime(local_time_ms);
16955   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16956   int year, month, day;
16957   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16958   int weekday = date_cache->Weekday(days);
16959   int hour = time_in_day_ms / (60 * 60 * 1000);
16960   int min = (time_in_day_ms / (60 * 1000)) % 60;
16961   int sec = (time_in_day_ms / 1000) % 60;
16962   set_cache_stamp(date_cache->stamp());
16963   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
16964   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
16965   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
16966   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
16967   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
16968   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
16969   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
16970 }
16971
16972
16973 void JSArrayBuffer::Neuter() {
16974   CHECK(is_neuterable());
16975   CHECK(is_external());
16976   set_backing_store(NULL);
16977   set_byte_length(Smi::FromInt(0));
16978 }
16979
16980
16981 void JSArrayBufferView::NeuterView() {
16982   CHECK(JSArrayBuffer::cast(buffer())->is_neuterable());
16983   set_byte_offset(Smi::FromInt(0));
16984   set_byte_length(Smi::FromInt(0));
16985 }
16986
16987
16988 void JSDataView::Neuter() {
16989   NeuterView();
16990 }
16991
16992
16993 void JSTypedArray::Neuter() {
16994   NeuterView();
16995   set_length(Smi::FromInt(0));
16996   set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
16997 }
16998
16999
17000 static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) {
17001   switch (elements_kind) {
17002 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
17003     case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
17004
17005     TYPED_ARRAYS(TYPED_ARRAY_CASE)
17006 #undef TYPED_ARRAY_CASE
17007
17008     default:
17009       UNREACHABLE();
17010       return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
17011   }
17012 }
17013
17014
17015 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
17016     Handle<JSTypedArray> typed_array) {
17017
17018   Handle<Map> map(typed_array->map());
17019   Isolate* isolate = typed_array->GetIsolate();
17020
17021   DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
17022
17023   Handle<Map> new_map = Map::TransitionElementsTo(
17024           map,
17025           FixedToExternalElementsKind(map->elements_kind()));
17026
17027   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
17028   Handle<FixedTypedArrayBase> fixed_typed_array(
17029       FixedTypedArrayBase::cast(typed_array->elements()));
17030   Runtime::SetupArrayBufferAllocatingData(isolate, buffer,
17031       fixed_typed_array->DataSize(), false);
17032   memcpy(buffer->backing_store(),
17033          fixed_typed_array->DataPtr(),
17034          fixed_typed_array->DataSize());
17035   Handle<ExternalArray> new_elements =
17036       isolate->factory()->NewExternalArray(
17037           fixed_typed_array->length(), typed_array->type(),
17038           static_cast<uint8_t*>(buffer->backing_store()));
17039
17040   Heap* heap = isolate->heap();
17041   if (heap->InNewSpace(*typed_array)) {
17042     DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value());
17043     typed_array->set_weak_next(heap->new_array_buffer_views_list());
17044     heap->set_new_array_buffer_views_list(*typed_array);
17045   } else {
17046     buffer->set_weak_first_view(*typed_array);
17047     DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value());
17048   }
17049   typed_array->set_buffer(*buffer);
17050   JSObject::SetMapAndElements(typed_array, new_map, new_elements);
17051
17052   return buffer;
17053 }
17054
17055
17056 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
17057   Handle<Object> result(buffer(), GetIsolate());
17058   if (*result != Smi::FromInt(0)) {
17059     DCHECK(IsExternalArrayElementsKind(map()->elements_kind()));
17060     return Handle<JSArrayBuffer>::cast(result);
17061   }
17062   Handle<JSTypedArray> self(this);
17063   return MaterializeArrayBuffer(self);
17064 }
17065
17066
17067 Handle<PropertyCell> PropertyCell::InvalidateEntry(
17068     Handle<NameDictionary> dictionary, int entry) {
17069   Isolate* isolate = dictionary->GetIsolate();
17070   // Swap with a copy.
17071   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
17072   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
17073   auto new_cell = isolate->factory()->NewPropertyCell();
17074   new_cell->set_value(cell->value());
17075   dictionary->ValueAtPut(entry, *new_cell);
17076   bool is_the_hole = cell->value()->IsTheHole();
17077   // Cell is officially mutable henceforth.
17078   auto details = dictionary->DetailsAt(entry);
17079   details = details.set_cell_type(is_the_hole ? PropertyCellType::kDeleted
17080                                               : PropertyCellType::kMutable);
17081   dictionary->DetailsAtPut(entry, details);
17082   // Old cell is ready for invalidation.
17083   if (is_the_hole) {
17084     cell->set_value(isolate->heap()->undefined_value());
17085   } else {
17086     cell->set_value(isolate->heap()->the_hole_value());
17087   }
17088   cell->dependent_code()->DeoptimizeDependentCodeGroup(
17089       isolate, DependentCode::kPropertyCellChangedGroup);
17090   return new_cell;
17091 }
17092
17093
17094 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell,
17095                                            Handle<Object> value,
17096                                            PropertyDetails details) {
17097   PropertyCellType type = details.cell_type();
17098   DCHECK(!value->IsTheHole());
17099   DCHECK_IMPLIES(cell->value()->IsTheHole(),
17100                  type == PropertyCellType::kUninitialized ||
17101                      type == PropertyCellType::kDeleted);
17102   switch (type) {
17103     // Only allow a cell to transition once into constant state.
17104     case PropertyCellType::kUninitialized:
17105       if (value->IsUndefined()) return PropertyCellType::kUndefined;
17106       return PropertyCellType::kConstant;
17107     case PropertyCellType::kUndefined:
17108       return PropertyCellType::kConstant;
17109     case PropertyCellType::kConstant:
17110       // No transition.
17111       if (*value == cell->value()) return PropertyCellType::kConstant;
17112     // Fall through.
17113     case PropertyCellType::kMutable:
17114       return PropertyCellType::kMutable;
17115   }
17116   UNREACHABLE();
17117   return PropertyCellType::kMutable;
17118 }
17119
17120
17121 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary,
17122                                         int entry, Handle<Object> value,
17123                                         PropertyDetails details) {
17124   DCHECK(!value->IsTheHole());
17125   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
17126   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
17127   const PropertyDetails original_details = dictionary->DetailsAt(entry);
17128   // Data accesses could be cached in ics or optimized code.
17129   bool invalidate =
17130       original_details.kind() == kData && details.kind() == kAccessor;
17131   int index = original_details.dictionary_index();
17132   auto old_type = original_details.cell_type();
17133   // Preserve the enumeration index unless the property was deleted or never
17134   // initialized.
17135   if (cell->value()->IsTheHole()) {
17136     index = dictionary->NextEnumerationIndex();
17137     dictionary->SetNextEnumerationIndex(index + 1);
17138     // Negative lookup cells must be invalidated.
17139     invalidate = true;
17140   }
17141   DCHECK(index > 0);
17142   details = details.set_index(index);
17143
17144   // Heuristic: if a small-ish string is stored in a previously uninitialized
17145   // property cell, internalize it.
17146   const int kMaxLengthForInternalization = 200;
17147   if ((old_type == PropertyCellType::kUninitialized ||
17148        old_type == PropertyCellType::kUndefined) &&
17149       value->IsString()) {
17150     auto string = Handle<String>::cast(value);
17151     if (string->length() <= kMaxLengthForInternalization) {
17152       value = cell->GetIsolate()->factory()->InternalizeString(string);
17153     }
17154   }
17155
17156   auto new_type = UpdatedType(cell, value, original_details);
17157   if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry);
17158
17159   // Install new property details and cell value.
17160   details = details.set_cell_type(new_type);
17161   dictionary->DetailsAtPut(entry, details);
17162   cell->set_value(*value);
17163
17164   // Deopt when transitioning from a constant type.
17165   if (!invalidate && old_type == PropertyCellType::kConstant &&
17166       new_type != PropertyCellType::kConstant) {
17167     auto isolate = dictionary->GetIsolate();
17168     cell->dependent_code()->DeoptimizeDependentCodeGroup(
17169         isolate, DependentCode::kPropertyCellChangedGroup);
17170   }
17171   return value;
17172 }
17173
17174
17175 // static
17176 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell,
17177                                                CompilationInfo* info) {
17178   Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
17179       handle(cell->dependent_code(), info->isolate()),
17180       DependentCode::kPropertyCellChangedGroup, info->object_wrapper());
17181   if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
17182   info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
17183       cell, info->zone());
17184 }
17185
17186 } }  // namespace v8::internal