efe35ed30ecab035dc602df3b821b8f9002fd238
[platform/upstream/v8.git] / src / objects.cc
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <iomanip>
6 #include <sstream>
7
8 #include "src/v8.h"
9
10 #include "src/accessors.h"
11 #include "src/allocation-site-scopes.h"
12 #include "src/api.h"
13 #include "src/arguments.h"
14 #include "src/base/bits.h"
15 #include "src/base/utils/random-number-generator.h"
16 #include "src/bootstrapper.h"
17 #include "src/code-stubs.h"
18 #include "src/codegen.h"
19 #include "src/compilation-dependencies.h"
20 #include "src/compiler.h"
21 #include "src/cpu-profiler.h"
22 #include "src/date.h"
23 #include "src/debug.h"
24 #include "src/deoptimizer.h"
25 #include "src/elements.h"
26 #include "src/execution.h"
27 #include "src/field-index-inl.h"
28 #include "src/field-index.h"
29 #include "src/full-codegen.h"
30 #include "src/heap/mark-compact.h"
31 #include "src/heap/objects-visiting-inl.h"
32 #include "src/hydrogen.h"
33 #include "src/ic/ic.h"
34 #include "src/log.h"
35 #include "src/lookup.h"
36 #include "src/macro-assembler.h"
37 #include "src/messages.h"
38 #include "src/objects-inl.h"
39 #include "src/prototype.h"
40 #include "src/safepoint-table.h"
41 #include "src/string-search.h"
42 #include "src/string-stream.h"
43 #include "src/utils.h"
44
45 #ifdef ENABLE_DISASSEMBLER
46 #include "src/disasm.h"
47 #include "src/disassembler.h"
48 #endif
49
50 namespace v8 {
51 namespace internal {
52
53 Handle<HeapType> Object::OptimalType(Isolate* isolate,
54                                      Representation representation) {
55   if (representation.IsNone()) return HeapType::None(isolate);
56   if (FLAG_track_field_types) {
57     if (representation.IsHeapObject() && IsHeapObject()) {
58       // We can track only JavaScript objects with stable maps.
59       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
60       if (map->is_stable() &&
61           map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
62           map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
63         return HeapType::Class(map, isolate);
64       }
65     }
66   }
67   return HeapType::Any(isolate);
68 }
69
70
71 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
72                                          Handle<Object> object,
73                                          Handle<Context> native_context) {
74   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
75   Handle<JSFunction> constructor;
76   if (object->IsNumber()) {
77     constructor = handle(native_context->number_function(), isolate);
78   } else if (object->IsBoolean()) {
79     constructor = handle(native_context->boolean_function(), isolate);
80   } else if (object->IsString()) {
81     constructor = handle(native_context->string_function(), isolate);
82   } else if (object->IsSymbol()) {
83     constructor = handle(native_context->symbol_function(), isolate);
84   } else if (object->IsFloat32x4()) {
85     constructor = handle(native_context->float32x4_function(), isolate);
86   } else {
87     return MaybeHandle<JSReceiver>();
88   }
89   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
90   Handle<JSValue>::cast(result)->set_value(*object);
91   return result;
92 }
93
94
95 bool Object::BooleanValue() {
96   if (IsBoolean()) return IsTrue();
97   if (IsSmi()) return Smi::cast(this)->value() != 0;
98   if (IsUndefined() || IsNull()) return false;
99   if (IsUndetectableObject()) return false;   // Undetectable object is false.
100   if (IsString()) return String::cast(this)->length() != 0;
101   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
102   if (IsFloat32x4()) return true;  // Simd value types always evaluate to true.
103   return true;
104 }
105
106
107 bool Object::IsCallable() const {
108   const Object* fun = this;
109   while (fun->IsJSFunctionProxy()) {
110     fun = JSFunctionProxy::cast(fun)->call_trap();
111   }
112   return fun->IsJSFunction() ||
113          (fun->IsHeapObject() &&
114           HeapObject::cast(fun)->map()->has_instance_call_handler());
115 }
116
117
118 bool Object::IsPromise(Handle<Object> object) {
119   if (!object->IsJSObject()) return false;
120   auto js_object = Handle<JSObject>::cast(object);
121   // Promises can't have access checks.
122   if (js_object->map()->is_access_check_needed()) return false;
123   auto isolate = js_object->GetIsolate();
124   // TODO(dcarney): this should just be read from the symbol registry so as not
125   // to be context dependent.
126   auto key = isolate->promise_status();
127   // Shouldn't be possible to throw here.
128   return JSObject::HasRealNamedProperty(js_object, key).FromJust();
129 }
130
131
132 MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
133                                         LanguageMode language_mode) {
134   for (; it->IsFound(); it->Next()) {
135     switch (it->state()) {
136       case LookupIterator::NOT_FOUND:
137       case LookupIterator::TRANSITION:
138         UNREACHABLE();
139       case LookupIterator::JSPROXY:
140         return JSProxy::GetPropertyWithHandler(
141             it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName());
142       case LookupIterator::INTERCEPTOR: {
143         bool done;
144         Handle<Object> result;
145         ASSIGN_RETURN_ON_EXCEPTION(
146             it->isolate(), result,
147             JSObject::GetPropertyWithInterceptor(it, &done), Object);
148         if (done) return result;
149         break;
150       }
151       case LookupIterator::ACCESS_CHECK:
152         if (it->HasAccess()) break;
153         return JSObject::GetPropertyWithFailedAccessCheck(it);
154       case LookupIterator::ACCESSOR:
155         return GetPropertyWithAccessor(it, language_mode);
156       case LookupIterator::INTEGER_INDEXED_EXOTIC:
157         return ReadAbsentProperty(it, language_mode);
158       case LookupIterator::DATA:
159         return it->GetDataValue();
160     }
161   }
162   return ReadAbsentProperty(it, language_mode);
163 }
164
165
166 Handle<Object> JSReceiver::GetDataProperty(Handle<JSReceiver> object,
167                                            Handle<Name> name) {
168   LookupIterator it(object, name,
169                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
170   return GetDataProperty(&it);
171 }
172
173
174 Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
175   for (; it->IsFound(); it->Next()) {
176     switch (it->state()) {
177       case LookupIterator::INTERCEPTOR:
178       case LookupIterator::NOT_FOUND:
179       case LookupIterator::TRANSITION:
180         UNREACHABLE();
181       case LookupIterator::ACCESS_CHECK:
182         if (it->HasAccess()) continue;
183       // Fall through.
184       case LookupIterator::JSPROXY:
185         it->NotFound();
186         return it->isolate()->factory()->undefined_value();
187       case LookupIterator::ACCESSOR:
188         // TODO(verwaest): For now this doesn't call into
189         // ExecutableAccessorInfo, since clients don't need it. Update once
190         // relevant.
191         it->NotFound();
192         return it->isolate()->factory()->undefined_value();
193       case LookupIterator::INTEGER_INDEXED_EXOTIC:
194         return it->isolate()->factory()->undefined_value();
195       case LookupIterator::DATA:
196         return it->GetDataValue();
197     }
198   }
199   return it->isolate()->factory()->undefined_value();
200 }
201
202
203 bool Object::ToInt32(int32_t* value) {
204   if (IsSmi()) {
205     *value = Smi::cast(this)->value();
206     return true;
207   }
208   if (IsHeapNumber()) {
209     double num = HeapNumber::cast(this)->value();
210     if (FastI2D(FastD2I(num)) == num) {
211       *value = FastD2I(num);
212       return true;
213     }
214   }
215   return false;
216 }
217
218
219 bool Object::ToUint32(uint32_t* value) {
220   if (IsSmi()) {
221     int num = Smi::cast(this)->value();
222     if (num >= 0) {
223       *value = static_cast<uint32_t>(num);
224       return true;
225     }
226   }
227   if (IsHeapNumber()) {
228     double num = HeapNumber::cast(this)->value();
229     if (num >= 0 && FastUI2D(FastD2UI(num)) == num) {
230       *value = FastD2UI(num);
231       return true;
232     }
233   }
234   return false;
235 }
236
237
238 bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
239   if (!object->IsHeapObject()) return false;
240   return IsTemplateFor(HeapObject::cast(object)->map());
241 }
242
243
244 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
245   // There is a constraint on the object; check.
246   if (!map->IsJSObjectMap()) return false;
247   // Fetch the constructor function of the object.
248   Object* cons_obj = map->GetConstructor();
249   if (!cons_obj->IsJSFunction()) return false;
250   JSFunction* fun = JSFunction::cast(cons_obj);
251   // Iterate through the chain of inheriting function templates to
252   // see if the required one occurs.
253   for (Object* type = fun->shared()->function_data();
254        type->IsFunctionTemplateInfo();
255        type = FunctionTemplateInfo::cast(type)->parent_template()) {
256     if (type == this) return true;
257   }
258   // Didn't find the required type in the inheritance chain.
259   return false;
260 }
261
262
263 // TODO(dcarney): CallOptimization duplicates this logic, merge.
264 Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate,
265                                                     Object* receiver) {
266   // API calls are only supported with JSObject receivers.
267   if (!receiver->IsJSObject()) return isolate->heap()->null_value();
268   Object* recv_type = this->signature();
269   // No signature, return holder.
270   if (recv_type->IsUndefined()) return receiver;
271   FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
272   // Check the receiver.
273   for (PrototypeIterator iter(isolate, receiver,
274                               PrototypeIterator::START_AT_RECEIVER);
275        !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
276     if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent();
277   }
278   return isolate->heap()->null_value();
279 }
280
281
282 Handle<FixedArray> JSObject::EnsureWritableFastElements(
283     Handle<JSObject> object) {
284   DCHECK(object->HasFastSmiOrObjectElements());
285   Isolate* isolate = object->GetIsolate();
286   Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
287   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
288   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
289       elems, isolate->factory()->fixed_array_map());
290   object->set_elements(*writable_elems);
291   isolate->counters()->cow_arrays_converted()->Increment();
292   return writable_elems;
293 }
294
295
296 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
297                                                     Handle<Object> receiver,
298                                                     Handle<Name> name) {
299   Isolate* isolate = proxy->GetIsolate();
300
301   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
302   if (name->IsSymbol()) return isolate->factory()->undefined_value();
303
304   Handle<Object> args[] = { receiver, name };
305   return CallTrap(
306       proxy, "get",  isolate->derived_get_trap(), arraysize(args), args);
307 }
308
309
310 MaybeHandle<Object> Object::GetPropertyWithAccessor(
311     LookupIterator* it, LanguageMode language_mode) {
312   Isolate* isolate = it->isolate();
313   Handle<Object> structure = it->GetAccessors();
314   Handle<Object> receiver = it->GetReceiver();
315
316   // We should never get here to initialize a const with the hole value since a
317   // const declaration would conflict with the getter.
318   DCHECK(!structure->IsForeign());
319
320   // API style callbacks.
321   if (structure->IsAccessorInfo()) {
322     Handle<JSObject> holder = it->GetHolder<JSObject>();
323     Handle<Name> name = it->GetName();
324     Handle<ExecutableAccessorInfo> info =
325         Handle<ExecutableAccessorInfo>::cast(structure);
326     if (!info->IsCompatibleReceiver(*receiver)) {
327       THROW_NEW_ERROR(isolate,
328                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
329                                    name, receiver),
330                       Object);
331     }
332
333     v8::AccessorNameGetterCallback call_fun =
334         v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
335     if (call_fun == nullptr) return isolate->factory()->undefined_value();
336
337     LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
338     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
339     v8::Local<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(name));
340     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
341     if (result.IsEmpty()) {
342       return ReadAbsentProperty(isolate, receiver, name, language_mode);
343     }
344     Handle<Object> return_value = v8::Utils::OpenHandle(*result);
345     return_value->VerifyApiCallResultType();
346     // Rebox handle before return.
347     return handle(*return_value, isolate);
348   }
349
350   // Regular accessor.
351   Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
352   if (getter->IsSpecFunction()) {
353     // TODO(rossberg): nicer would be to cast to some JSCallable here...
354     return Object::GetPropertyWithDefinedGetter(
355         receiver, Handle<JSReceiver>::cast(getter));
356   }
357   // Getter is not a function.
358   return ReadAbsentProperty(isolate, receiver, it->GetName(), language_mode);
359 }
360
361
362 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
363                                            Handle<AccessorInfo> info,
364                                            Handle<Map> map) {
365   if (!info->HasExpectedReceiverType()) return true;
366   if (!map->IsJSObjectMap()) return false;
367   return FunctionTemplateInfo::cast(info->expected_receiver_type())
368       ->IsTemplateFor(*map);
369 }
370
371
372 MaybeHandle<Object> Object::SetPropertyWithAccessor(
373     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
374   Isolate* isolate = it->isolate();
375   Handle<Object> structure = it->GetAccessors();
376   Handle<Object> receiver = it->GetReceiver();
377
378   // We should never get here to initialize a const with the hole value since a
379   // const declaration would conflict with the setter.
380   DCHECK(!structure->IsForeign());
381
382   // API style callbacks.
383   if (structure->IsExecutableAccessorInfo()) {
384     Handle<JSObject> holder = it->GetHolder<JSObject>();
385     Handle<Name> name = it->GetName();
386     Handle<ExecutableAccessorInfo> info =
387         Handle<ExecutableAccessorInfo>::cast(structure);
388     if (!info->IsCompatibleReceiver(*receiver)) {
389       THROW_NEW_ERROR(isolate,
390                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
391                                    name, receiver),
392                       Object);
393     }
394
395     v8::AccessorNameSetterCallback call_fun =
396         v8::ToCData<v8::AccessorNameSetterCallback>(info->setter());
397     if (call_fun == nullptr) return value;
398
399     LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
400     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
401     args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
402     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
403     return value;
404   }
405
406   // Regular accessor.
407   Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
408   if (setter->IsSpecFunction()) {
409     // TODO(rossberg): nicer would be to cast to some JSCallable here...
410     return SetPropertyWithDefinedSetter(
411         receiver, Handle<JSReceiver>::cast(setter), value);
412   }
413
414   if (is_sloppy(language_mode)) return value;
415
416   THROW_NEW_ERROR(isolate,
417                   NewTypeError(MessageTemplate::kNoSetterInCallback,
418                                it->GetName(), it->GetHolder<JSObject>()),
419                   Object);
420 }
421
422
423 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
424     Handle<Object> receiver,
425     Handle<JSReceiver> getter) {
426   Isolate* isolate = getter->GetIsolate();
427
428   // Platforms with simulators like arm/arm64 expose a funny issue. If the
429   // simulator has a separate JS stack pointer from the C++ stack pointer, it
430   // can miss C++ stack overflows in the stack guard at the start of JavaScript
431   // functions. It would be very expensive to check the C++ stack pointer at
432   // that location. The best solution seems to be to break the impasse by
433   // adding checks at possible recursion points. What's more, we don't put
434   // this stack check behind the USE_SIMULATOR define in order to keep
435   // behavior the same between hardware and simulators.
436   StackLimitCheck check(isolate);
437   if (check.JsHasOverflowed()) {
438     isolate->StackOverflow();
439     return MaybeHandle<Object>();
440   }
441
442   Debug* debug = isolate->debug();
443   // Handle stepping into a getter if step into is active.
444   // TODO(rossberg): should this apply to getters that are function proxies?
445   if (debug->is_active()) debug->HandleStepIn(getter, false);
446
447   return Execution::Call(isolate, getter, receiver, 0, NULL, true);
448 }
449
450
451 MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
452     Handle<Object> receiver,
453     Handle<JSReceiver> setter,
454     Handle<Object> value) {
455   Isolate* isolate = setter->GetIsolate();
456
457   Debug* debug = isolate->debug();
458   // Handle stepping into a setter if step into is active.
459   // TODO(rossberg): should this apply to getters that are function proxies?
460   if (debug->is_active()) debug->HandleStepIn(setter, false);
461
462   Handle<Object> argv[] = { value };
463   RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver,
464                                                arraysize(argv), argv, true),
465                       Object);
466   return value;
467 }
468
469
470 static bool FindAllCanReadHolder(LookupIterator* it) {
471   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
472   // which have already been checked.
473   DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
474          it->state() == LookupIterator::INTERCEPTOR);
475   for (it->Next(); it->IsFound(); it->Next()) {
476     if (it->state() == LookupIterator::ACCESSOR) {
477       auto accessors = it->GetAccessors();
478       if (accessors->IsAccessorInfo()) {
479         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
480       }
481     } else if (it->state() == LookupIterator::INTERCEPTOR) {
482       if (it->GetInterceptor()->all_can_read()) return true;
483     }
484   }
485   return false;
486 }
487
488
489 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
490     LookupIterator* it) {
491   Handle<JSObject> checked = it->GetHolder<JSObject>();
492   while (FindAllCanReadHolder(it)) {
493     if (it->state() == LookupIterator::ACCESSOR) {
494       return GetPropertyWithAccessor(it, SLOPPY);
495     }
496     DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
497     bool done;
498     Handle<Object> result;
499     ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), result,
500                                GetPropertyWithInterceptor(it, &done), Object);
501     if (done) return result;
502   }
503   it->isolate()->ReportFailedAccessCheck(checked);
504   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
505   return it->factory()->undefined_value();
506 }
507
508
509 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
510     LookupIterator* it) {
511   Handle<JSObject> checked = it->GetHolder<JSObject>();
512   while (FindAllCanReadHolder(it)) {
513     if (it->state() == LookupIterator::ACCESSOR) {
514       return Just(it->property_details().attributes());
515     }
516     DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
517     auto result = GetPropertyAttributesWithInterceptor(it);
518     if (it->isolate()->has_scheduled_exception()) break;
519     if (result.IsJust() && result.FromJust() != ABSENT) return result;
520   }
521   it->isolate()->ReportFailedAccessCheck(checked);
522   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
523                                       Nothing<PropertyAttributes>());
524   return Just(ABSENT);
525 }
526
527
528 static bool FindAllCanWriteHolder(LookupIterator* it) {
529   for (; it->IsFound(); it->Next()) {
530     if (it->state() == LookupIterator::ACCESSOR) {
531       Handle<Object> accessors = it->GetAccessors();
532       if (accessors->IsAccessorInfo()) {
533         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
534       }
535     }
536   }
537   return false;
538 }
539
540
541 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
542     LookupIterator* it, Handle<Object> value) {
543   Handle<JSObject> checked = it->GetHolder<JSObject>();
544   if (FindAllCanWriteHolder(it)) {
545     // The supplied language-mode is ignored by SetPropertyWithAccessor.
546     return SetPropertyWithAccessor(it, value, SLOPPY);
547   }
548
549   it->isolate()->ReportFailedAccessCheck(checked);
550   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
551   return value;
552 }
553
554
555 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
556                                      Handle<Name> name,
557                                      Handle<Object> value,
558                                      PropertyDetails details) {
559   DCHECK(!object->HasFastProperties());
560   if (!name->IsUniqueName()) {
561     name = object->GetIsolate()->factory()->InternalizeString(
562         Handle<String>::cast(name));
563   }
564
565   if (object->IsGlobalObject()) {
566     Handle<GlobalDictionary> property_dictionary(object->global_dictionary());
567
568     int entry = property_dictionary->FindEntry(name);
569     if (entry == GlobalDictionary::kNotFound) {
570       auto cell = object->GetIsolate()->factory()->NewPropertyCell();
571       cell->set_value(*value);
572       auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
573                                             : PropertyCellType::kConstant;
574       details = details.set_cell_type(cell_type);
575       value = cell;
576       property_dictionary =
577           GlobalDictionary::Add(property_dictionary, name, value, details);
578       object->set_properties(*property_dictionary);
579     } else {
580       PropertyCell::UpdateCell(property_dictionary, entry, value, details);
581     }
582   } else {
583     Handle<NameDictionary> property_dictionary(object->property_dictionary());
584
585     int entry = property_dictionary->FindEntry(name);
586     if (entry == NameDictionary::kNotFound) {
587       property_dictionary =
588           NameDictionary::Add(property_dictionary, name, value, details);
589       object->set_properties(*property_dictionary);
590     } else {
591       PropertyDetails original_details = property_dictionary->DetailsAt(entry);
592       int enumeration_index = original_details.dictionary_index();
593       DCHECK(enumeration_index > 0);
594       details = details.set_index(enumeration_index);
595       property_dictionary->SetEntry(entry, name, value, details);
596     }
597   }
598 }
599
600
601 Map* Object::GetRootMap(Isolate* isolate) {
602   DisallowHeapAllocation no_alloc;
603   if (IsSmi()) {
604     Context* context = isolate->context()->native_context();
605     return context->number_function()->initial_map();
606   }
607
608   HeapObject* heap_object = HeapObject::cast(this);
609
610   // The object is either a number, a string, a symbol, a boolean, a SIMD value,
611   // a real JS object, or a Harmony proxy.
612   if (heap_object->IsJSReceiver()) {
613     return heap_object->map();
614   }
615   Context* context = isolate->context()->native_context();
616
617   if (heap_object->IsHeapNumber()) {
618     return context->number_function()->initial_map();
619   }
620   if (heap_object->IsString()) {
621     return context->string_function()->initial_map();
622   }
623   if (heap_object->IsSymbol()) {
624     return context->symbol_function()->initial_map();
625   }
626   if (heap_object->IsBoolean()) {
627     return context->boolean_function()->initial_map();
628   }
629   if (heap_object->IsFloat32x4()) {
630     return context->float32x4_function()->initial_map();
631   }
632   return isolate->heap()->null_value()->map();
633 }
634
635
636 Object* Object::GetHash() {
637   Object* hash = GetSimpleHash();
638   if (hash->IsSmi()) return hash;
639
640   DCHECK(IsJSReceiver());
641   return JSReceiver::cast(this)->GetIdentityHash();
642 }
643
644
645 Object* Object::GetSimpleHash() {
646   // The object is either a Smi, a HeapNumber, a name, an odd-ball,
647   // a SIMD value type, a real JS object, or a Harmony proxy.
648   if (IsSmi()) {
649     uint32_t hash = ComputeIntegerHash(Smi::cast(this)->value(), kZeroHashSeed);
650     return Smi::FromInt(hash & Smi::kMaxValue);
651   }
652   if (IsHeapNumber()) {
653     double num = HeapNumber::cast(this)->value();
654     if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
655     if (i::IsMinusZero(num)) num = 0;
656     if (IsSmiDouble(num)) {
657       return Smi::FromInt(FastD2I(num))->GetHash();
658     }
659     uint32_t hash = ComputeLongHash(double_to_uint64(num));
660     return Smi::FromInt(hash & Smi::kMaxValue);
661   }
662   if (IsName()) {
663     uint32_t hash = Name::cast(this)->Hash();
664     return Smi::FromInt(hash);
665   }
666   if (IsOddball()) {
667     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
668     return Smi::FromInt(hash);
669   }
670   if (IsFloat32x4()) {
671     Float32x4* simd = Float32x4::cast(this);
672     uint32_t seed = v8::internal::kZeroHashSeed;
673     uint32_t hash;
674     hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(0)), seed);
675     hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(1)), hash * 31);
676     hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(2)), hash * 31);
677     hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(3)), hash * 31);
678     return Smi::FromInt(hash & Smi::kMaxValue);
679   }
680   DCHECK(IsJSReceiver());
681   JSReceiver* receiver = JSReceiver::cast(this);
682   return receiver->GetHeap()->undefined_value();
683 }
684
685
686 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
687   Handle<Object> hash(object->GetSimpleHash(), isolate);
688   if (hash->IsSmi()) return Handle<Smi>::cast(hash);
689
690   DCHECK(object->IsJSReceiver());
691   return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
692 }
693
694
695 bool Object::SameValue(Object* other) {
696   if (other == this) return true;
697
698   // The object is either a number, a name, an odd-ball,
699   // a real JS object, or a Harmony proxy.
700   if (IsNumber() && other->IsNumber()) {
701     return v8::internal::SameValue(Number(), other->Number());
702   }
703   if (IsString() && other->IsString()) {
704     return String::cast(this)->Equals(String::cast(other));
705   }
706   if (IsFloat32x4() && other->IsFloat32x4()) {
707     Float32x4* x = Float32x4::cast(this);
708     Float32x4* y = Float32x4::cast(other);
709     return v8::internal::SameValue(x->get_lane(0), y->get_lane(0)) &&
710            v8::internal::SameValue(x->get_lane(1), y->get_lane(1)) &&
711            v8::internal::SameValue(x->get_lane(2), y->get_lane(2)) &&
712            v8::internal::SameValue(x->get_lane(3), y->get_lane(3));
713   }
714   return false;
715 }
716
717
718 bool Object::SameValueZero(Object* other) {
719   if (other == this) return true;
720
721   // The object is either a number, a name, an odd-ball,
722   // a real JS object, or a Harmony proxy.
723   if (IsNumber() && other->IsNumber()) {
724     return v8::internal::SameValueZero(Number(), other->Number());
725   }
726   if (IsString() && other->IsString()) {
727     return String::cast(this)->Equals(String::cast(other));
728   }
729   if (IsFloat32x4() && other->IsFloat32x4()) {
730     Float32x4* x = Float32x4::cast(this);
731     Float32x4* y = Float32x4::cast(other);
732     return v8::internal::SameValueZero(x->get_lane(0), y->get_lane(0)) &&
733            v8::internal::SameValueZero(x->get_lane(1), y->get_lane(1)) &&
734            v8::internal::SameValueZero(x->get_lane(2), y->get_lane(2)) &&
735            v8::internal::SameValueZero(x->get_lane(3), y->get_lane(3));
736   }
737   return false;
738 }
739
740
741 void Object::ShortPrint(FILE* out) {
742   OFStream os(out);
743   os << Brief(this);
744 }
745
746
747 void Object::ShortPrint(StringStream* accumulator) {
748   std::ostringstream os;
749   os << Brief(this);
750   accumulator->Add(os.str().c_str());
751 }
752
753
754 void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
755
756
757 std::ostream& operator<<(std::ostream& os, const Brief& v) {
758   if (v.value->IsSmi()) {
759     Smi::cast(v.value)->SmiPrint(os);
760   } else {
761     // TODO(svenpanne) Const-correct HeapObjectShortPrint!
762     HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
763     obj->HeapObjectShortPrint(os);
764   }
765   return os;
766 }
767
768
769 void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
770   os << value();
771 }
772
773
774 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
775 // English?  Returns false for non-ASCII or words that don't start with
776 // a capital letter.  The a/an rule follows pronunciation in English.
777 // We don't use the BBC's overcorrect "an historic occasion" though if
778 // you speak a dialect you may well say "an 'istoric occasion".
779 static bool AnWord(String* str) {
780   if (str->length() == 0) return false;  // A nothing.
781   int c0 = str->Get(0);
782   int c1 = str->length() > 1 ? str->Get(1) : 0;
783   if (c0 == 'U') {
784     if (c1 > 'Z') {
785       return true;  // An Umpire, but a UTF8String, a U.
786     }
787   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
788     return true;    // An Ape, an ABCBook.
789   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
790            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
791             c0 == 'S' || c0 == 'X')) {
792     return true;    // An MP3File, an M.
793   }
794   return false;
795 }
796
797
798 Handle<String> String::SlowFlatten(Handle<ConsString> cons,
799                                    PretenureFlag pretenure) {
800   DCHECK(AllowHeapAllocation::IsAllowed());
801   DCHECK(cons->second()->length() != 0);
802   Isolate* isolate = cons->GetIsolate();
803   int length = cons->length();
804   PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
805                                                             : TENURED;
806   Handle<SeqString> result;
807   if (cons->IsOneByteRepresentation()) {
808     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
809         length, tenure).ToHandleChecked();
810     DisallowHeapAllocation no_gc;
811     WriteToFlat(*cons, flat->GetChars(), 0, length);
812     result = flat;
813   } else {
814     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
815         length, tenure).ToHandleChecked();
816     DisallowHeapAllocation no_gc;
817     WriteToFlat(*cons, flat->GetChars(), 0, length);
818     result = flat;
819   }
820   cons->set_first(*result);
821   cons->set_second(isolate->heap()->empty_string());
822   DCHECK(result->IsFlat());
823   return result;
824 }
825
826
827
828 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
829   // Externalizing twice leaks the external resource, so it's
830   // prohibited by the API.
831   DCHECK(!this->IsExternalString());
832 #ifdef ENABLE_SLOW_DCHECKS
833   if (FLAG_enable_slow_asserts) {
834     // Assert that the resource and the string are equivalent.
835     DCHECK(static_cast<size_t>(this->length()) == resource->length());
836     ScopedVector<uc16> smart_chars(this->length());
837     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
838     DCHECK(memcmp(smart_chars.start(),
839                   resource->data(),
840                   resource->length() * sizeof(smart_chars[0])) == 0);
841   }
842 #endif  // DEBUG
843   int size = this->Size();  // Byte size of the original string.
844   // Abort if size does not allow in-place conversion.
845   if (size < ExternalString::kShortSize) return false;
846   Heap* heap = GetHeap();
847   bool is_one_byte = this->IsOneByteRepresentation();
848   bool is_internalized = this->IsInternalizedString();
849
850   // Morph the string to an external string by replacing the map and
851   // reinitializing the fields.  This won't work if the space the existing
852   // string occupies is too small for a regular  external string.
853   // Instead, we resort to a short external string instead, omitting
854   // the field caching the address of the backing store.  When we encounter
855   // short external strings in generated code, we need to bailout to runtime.
856   Map* new_map;
857   if (size < ExternalString::kSize) {
858     new_map = is_internalized
859         ? (is_one_byte
860            ? heap->short_external_internalized_string_with_one_byte_data_map()
861            : heap->short_external_internalized_string_map())
862         : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
863                        : heap->short_external_string_map());
864   } else {
865     new_map = is_internalized
866         ? (is_one_byte
867            ? heap->external_internalized_string_with_one_byte_data_map()
868            : heap->external_internalized_string_map())
869         : (is_one_byte ? heap->external_string_with_one_byte_data_map()
870                        : heap->external_string_map());
871   }
872
873   // Byte size of the external String object.
874   int new_size = this->SizeFromMap(new_map);
875   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
876
877   // We are storing the new map using release store after creating a filler for
878   // the left-over space to avoid races with the sweeper thread.
879   this->synchronized_set_map(new_map);
880
881   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
882   self->set_resource(resource);
883   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
884
885   heap->AdjustLiveBytes(this->address(), new_size - size,
886                         Heap::CONCURRENT_TO_SWEEPER);
887   return true;
888 }
889
890
891 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
892   // Externalizing twice leaks the external resource, so it's
893   // prohibited by the API.
894   DCHECK(!this->IsExternalString());
895 #ifdef ENABLE_SLOW_DCHECKS
896   if (FLAG_enable_slow_asserts) {
897     // Assert that the resource and the string are equivalent.
898     DCHECK(static_cast<size_t>(this->length()) == resource->length());
899     if (this->IsTwoByteRepresentation()) {
900       ScopedVector<uint16_t> smart_chars(this->length());
901       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
902       DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
903     }
904     ScopedVector<char> smart_chars(this->length());
905     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
906     DCHECK(memcmp(smart_chars.start(),
907                   resource->data(),
908                   resource->length() * sizeof(smart_chars[0])) == 0);
909   }
910 #endif  // DEBUG
911   int size = this->Size();  // Byte size of the original string.
912   // Abort if size does not allow in-place conversion.
913   if (size < ExternalString::kShortSize) return false;
914   Heap* heap = GetHeap();
915   bool is_internalized = this->IsInternalizedString();
916
917   // Morph the string to an external string by replacing the map and
918   // reinitializing the fields.  This won't work if the space the existing
919   // string occupies is too small for a regular  external string.
920   // Instead, we resort to a short external string instead, omitting
921   // the field caching the address of the backing store.  When we encounter
922   // short external strings in generated code, we need to bailout to runtime.
923   Map* new_map;
924   if (size < ExternalString::kSize) {
925     new_map = is_internalized
926                   ? heap->short_external_one_byte_internalized_string_map()
927                   : heap->short_external_one_byte_string_map();
928   } else {
929     new_map = is_internalized
930                   ? heap->external_one_byte_internalized_string_map()
931                   : heap->external_one_byte_string_map();
932   }
933
934   // Byte size of the external String object.
935   int new_size = this->SizeFromMap(new_map);
936   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
937
938   // We are storing the new map using release store after creating a filler for
939   // the left-over space to avoid races with the sweeper thread.
940   this->synchronized_set_map(new_map);
941
942   ExternalOneByteString* self = ExternalOneByteString::cast(this);
943   self->set_resource(resource);
944   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
945
946   heap->AdjustLiveBytes(this->address(), new_size - size,
947                         Heap::CONCURRENT_TO_SWEEPER);
948   return true;
949 }
950
951
952 void String::StringShortPrint(StringStream* accumulator) {
953   int len = length();
954   if (len > kMaxShortPrintLength) {
955     accumulator->Add("<Very long string[%u]>", len);
956     return;
957   }
958
959   if (!LooksValid()) {
960     accumulator->Add("<Invalid String>");
961     return;
962   }
963
964   StringCharacterStream stream(this);
965
966   bool truncated = false;
967   if (len > kMaxShortPrintLength) {
968     len = kMaxShortPrintLength;
969     truncated = true;
970   }
971   bool one_byte = true;
972   for (int i = 0; i < len; i++) {
973     uint16_t c = stream.GetNext();
974
975     if (c < 32 || c >= 127) {
976       one_byte = false;
977     }
978   }
979   stream.Reset(this);
980   if (one_byte) {
981     accumulator->Add("<String[%u]: ", length());
982     for (int i = 0; i < len; i++) {
983       accumulator->Put(static_cast<char>(stream.GetNext()));
984     }
985     accumulator->Put('>');
986   } else {
987     // Backslash indicates that the string contains control
988     // characters and that backslashes are therefore escaped.
989     accumulator->Add("<String[%u]\\: ", length());
990     for (int i = 0; i < len; i++) {
991       uint16_t c = stream.GetNext();
992       if (c == '\n') {
993         accumulator->Add("\\n");
994       } else if (c == '\r') {
995         accumulator->Add("\\r");
996       } else if (c == '\\') {
997         accumulator->Add("\\\\");
998       } else if (c < 32 || c > 126) {
999         accumulator->Add("\\x%02x", c);
1000       } else {
1001         accumulator->Put(static_cast<char>(c));
1002       }
1003     }
1004     if (truncated) {
1005       accumulator->Put('.');
1006       accumulator->Put('.');
1007       accumulator->Put('.');
1008     }
1009     accumulator->Put('>');
1010   }
1011   return;
1012 }
1013
1014
1015 void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
1016   if (end < 0) end = length();
1017   StringCharacterStream stream(this, start);
1018   for (int i = start; i < end && stream.HasMore(); i++) {
1019     os << AsUC16(stream.GetNext());
1020   }
1021 }
1022
1023
1024 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1025   switch (map()->instance_type()) {
1026     case JS_ARRAY_TYPE: {
1027       double length = JSArray::cast(this)->length()->IsUndefined()
1028           ? 0
1029           : JSArray::cast(this)->length()->Number();
1030       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1031       break;
1032     }
1033     case JS_WEAK_MAP_TYPE: {
1034       accumulator->Add("<JS WeakMap>");
1035       break;
1036     }
1037     case JS_WEAK_SET_TYPE: {
1038       accumulator->Add("<JS WeakSet>");
1039       break;
1040     }
1041     case JS_REGEXP_TYPE: {
1042       accumulator->Add("<JS RegExp>");
1043       break;
1044     }
1045     case JS_FUNCTION_TYPE: {
1046       JSFunction* function = JSFunction::cast(this);
1047       Object* fun_name = function->shared()->DebugName();
1048       bool printed = false;
1049       if (fun_name->IsString()) {
1050         String* str = String::cast(fun_name);
1051         if (str->length() > 0) {
1052           accumulator->Add("<JS Function ");
1053           accumulator->Put(str);
1054           printed = true;
1055         }
1056       }
1057       if (!printed) {
1058         accumulator->Add("<JS Function");
1059       }
1060       accumulator->Add(" (SharedFunctionInfo %p)",
1061                        reinterpret_cast<void*>(function->shared()));
1062       accumulator->Put('>');
1063       break;
1064     }
1065     case JS_GENERATOR_OBJECT_TYPE: {
1066       accumulator->Add("<JS Generator>");
1067       break;
1068     }
1069     case JS_MODULE_TYPE: {
1070       accumulator->Add("<JS Module>");
1071       break;
1072     }
1073     // All other JSObjects are rather similar to each other (JSObject,
1074     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1075     default: {
1076       Map* map_of_this = map();
1077       Heap* heap = GetHeap();
1078       Object* constructor = map_of_this->GetConstructor();
1079       bool printed = false;
1080       if (constructor->IsHeapObject() &&
1081           !heap->Contains(HeapObject::cast(constructor))) {
1082         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1083       } else {
1084         bool global_object = IsJSGlobalProxy();
1085         if (constructor->IsJSFunction()) {
1086           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1087             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1088           } else {
1089             Object* constructor_name =
1090                 JSFunction::cast(constructor)->shared()->name();
1091             if (constructor_name->IsString()) {
1092               String* str = String::cast(constructor_name);
1093               if (str->length() > 0) {
1094                 bool vowel = AnWord(str);
1095                 accumulator->Add("<%sa%s ",
1096                        global_object ? "Global Object: " : "",
1097                        vowel ? "n" : "");
1098                 accumulator->Put(str);
1099                 accumulator->Add(" with %smap %p",
1100                     map_of_this->is_deprecated() ? "deprecated " : "",
1101                     map_of_this);
1102                 printed = true;
1103               }
1104             }
1105           }
1106         }
1107         if (!printed) {
1108           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1109         }
1110       }
1111       if (IsJSValue()) {
1112         accumulator->Add(" value = ");
1113         JSValue::cast(this)->value()->ShortPrint(accumulator);
1114       }
1115       accumulator->Put('>');
1116       break;
1117     }
1118   }
1119 }
1120
1121
1122 void JSObject::PrintElementsTransition(
1123     FILE* file, Handle<JSObject> object,
1124     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
1125     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
1126   if (from_kind != to_kind) {
1127     OFStream os(file);
1128     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
1129        << ElementsKindToString(to_kind) << "] in ";
1130     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
1131     PrintF(file, " for ");
1132     object->ShortPrint(file);
1133     PrintF(file, " from ");
1134     from_elements->ShortPrint(file);
1135     PrintF(file, " to ");
1136     to_elements->ShortPrint(file);
1137     PrintF(file, "\n");
1138   }
1139 }
1140
1141
1142 void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
1143                                PropertyAttributes attributes) {
1144   OFStream os(file);
1145   os << "[reconfiguring ";
1146   constructor_name()->PrintOn(file);
1147   os << "] ";
1148   Name* name = instance_descriptors()->GetKey(modify_index);
1149   if (name->IsString()) {
1150     String::cast(name)->PrintOn(file);
1151   } else {
1152     os << "{symbol " << static_cast<void*>(name) << "}";
1153   }
1154   os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
1155   os << attributes << " [";
1156   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1157   os << "]\n";
1158 }
1159
1160
1161 void Map::PrintGeneralization(FILE* file,
1162                               const char* reason,
1163                               int modify_index,
1164                               int split,
1165                               int descriptors,
1166                               bool constant_to_field,
1167                               Representation old_representation,
1168                               Representation new_representation,
1169                               HeapType* old_field_type,
1170                               HeapType* new_field_type) {
1171   OFStream os(file);
1172   os << "[generalizing ";
1173   constructor_name()->PrintOn(file);
1174   os << "] ";
1175   Name* name = instance_descriptors()->GetKey(modify_index);
1176   if (name->IsString()) {
1177     String::cast(name)->PrintOn(file);
1178   } else {
1179     os << "{symbol " << static_cast<void*>(name) << "}";
1180   }
1181   os << ":";
1182   if (constant_to_field) {
1183     os << "c";
1184   } else {
1185     os << old_representation.Mnemonic() << "{";
1186     old_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1187     os << "}";
1188   }
1189   os << "->" << new_representation.Mnemonic() << "{";
1190   new_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1191   os << "} (";
1192   if (strlen(reason) > 0) {
1193     os << reason;
1194   } else {
1195     os << "+" << (descriptors - split) << " maps";
1196   }
1197   os << ") [";
1198   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1199   os << "]\n";
1200 }
1201
1202
1203 void JSObject::PrintInstanceMigration(FILE* file,
1204                                       Map* original_map,
1205                                       Map* new_map) {
1206   PrintF(file, "[migrating ");
1207   map()->constructor_name()->PrintOn(file);
1208   PrintF(file, "] ");
1209   DescriptorArray* o = original_map->instance_descriptors();
1210   DescriptorArray* n = new_map->instance_descriptors();
1211   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
1212     Representation o_r = o->GetDetails(i).representation();
1213     Representation n_r = n->GetDetails(i).representation();
1214     if (!o_r.Equals(n_r)) {
1215       String::cast(o->GetKey(i))->PrintOn(file);
1216       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
1217     } else if (o->GetDetails(i).type() == DATA_CONSTANT &&
1218                n->GetDetails(i).type() == DATA) {
1219       Name* name = o->GetKey(i);
1220       if (name->IsString()) {
1221         String::cast(name)->PrintOn(file);
1222       } else {
1223         PrintF(file, "{symbol %p}", static_cast<void*>(name));
1224       }
1225       PrintF(file, " ");
1226     }
1227   }
1228   PrintF(file, "\n");
1229 }
1230
1231
1232 void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
1233   Heap* heap = GetHeap();
1234   if (!heap->Contains(this)) {
1235     os << "!!!INVALID POINTER!!!";
1236     return;
1237   }
1238   if (!heap->Contains(map())) {
1239     os << "!!!INVALID MAP!!!";
1240     return;
1241   }
1242
1243   os << this << " ";
1244
1245   if (IsString()) {
1246     HeapStringAllocator allocator;
1247     StringStream accumulator(&allocator);
1248     String::cast(this)->StringShortPrint(&accumulator);
1249     os << accumulator.ToCString().get();
1250     return;
1251   }
1252   if (IsJSObject()) {
1253     HeapStringAllocator allocator;
1254     StringStream accumulator(&allocator);
1255     JSObject::cast(this)->JSObjectShortPrint(&accumulator);
1256     os << accumulator.ToCString().get();
1257     return;
1258   }
1259   switch (map()->instance_type()) {
1260     case MAP_TYPE:
1261       os << "<Map(" << ElementsKindToString(Map::cast(this)->elements_kind())
1262          << ")>";
1263       break;
1264     case FIXED_ARRAY_TYPE:
1265       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
1266       break;
1267     case FIXED_DOUBLE_ARRAY_TYPE:
1268       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
1269          << "]>";
1270       break;
1271     case BYTE_ARRAY_TYPE:
1272       os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
1273       break;
1274     case FREE_SPACE_TYPE:
1275       os << "<FreeSpace[" << FreeSpace::cast(this)->Size() << "]>";
1276       break;
1277 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
1278   case EXTERNAL_##TYPE##_ARRAY_TYPE:                                          \
1279     os << "<External" #Type "Array["                                          \
1280        << External##Type##Array::cast(this)->length() << "]>";                \
1281     break;                                                                    \
1282   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
1283     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
1284        << "]>";                                                               \
1285     break;
1286
1287     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1288 #undef TYPED_ARRAY_SHORT_PRINT
1289
1290     case SHARED_FUNCTION_INFO_TYPE: {
1291       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
1292       base::SmartArrayPointer<char> debug_name =
1293           shared->DebugName()->ToCString();
1294       if (debug_name[0] != 0) {
1295         os << "<SharedFunctionInfo " << debug_name.get() << ">";
1296       } else {
1297         os << "<SharedFunctionInfo>";
1298       }
1299       break;
1300     }
1301     case JS_MESSAGE_OBJECT_TYPE:
1302       os << "<JSMessageObject>";
1303       break;
1304 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1305   case NAME##_TYPE:                        \
1306     os << "<" #Name ">";                   \
1307     break;
1308   STRUCT_LIST(MAKE_STRUCT_CASE)
1309 #undef MAKE_STRUCT_CASE
1310     case CODE_TYPE: {
1311       Code* code = Code::cast(this);
1312       os << "<Code: " << Code::Kind2String(code->kind()) << ">";
1313       break;
1314     }
1315     case ODDBALL_TYPE: {
1316       if (IsUndefined()) {
1317         os << "<undefined>";
1318       } else if (IsTheHole()) {
1319         os << "<the hole>";
1320       } else if (IsNull()) {
1321         os << "<null>";
1322       } else if (IsTrue()) {
1323         os << "<true>";
1324       } else if (IsFalse()) {
1325         os << "<false>";
1326       } else {
1327         os << "<Odd Oddball>";
1328       }
1329       break;
1330     }
1331     case SYMBOL_TYPE: {
1332       Symbol* symbol = Symbol::cast(this);
1333       symbol->SymbolShortPrint(os);
1334       break;
1335     }
1336     case HEAP_NUMBER_TYPE: {
1337       os << "<Number: ";
1338       HeapNumber::cast(this)->HeapNumberPrint(os);
1339       os << ">";
1340       break;
1341     }
1342     case MUTABLE_HEAP_NUMBER_TYPE: {
1343       os << "<MutableNumber: ";
1344       HeapNumber::cast(this)->HeapNumberPrint(os);
1345       os << '>';
1346       break;
1347     }
1348     case FLOAT32X4_TYPE: {
1349       os << "<Float32x4: ";
1350       Float32x4::cast(this)->Float32x4Print(os);
1351       os << ">";
1352       break;
1353     }
1354     case JS_PROXY_TYPE:
1355       os << "<JSProxy>";
1356       break;
1357     case JS_FUNCTION_PROXY_TYPE:
1358       os << "<JSFunctionProxy>";
1359       break;
1360     case FOREIGN_TYPE:
1361       os << "<Foreign>";
1362       break;
1363     case CELL_TYPE: {
1364       os << "Cell for ";
1365       HeapStringAllocator allocator;
1366       StringStream accumulator(&allocator);
1367       Cell::cast(this)->value()->ShortPrint(&accumulator);
1368       os << accumulator.ToCString().get();
1369       break;
1370     }
1371     case PROPERTY_CELL_TYPE: {
1372       os << "PropertyCell for ";
1373       HeapStringAllocator allocator;
1374       StringStream accumulator(&allocator);
1375       PropertyCell* cell = PropertyCell::cast(this);
1376       cell->value()->ShortPrint(&accumulator);
1377       os << accumulator.ToCString().get() << " " << cell->property_details();
1378       break;
1379     }
1380     case WEAK_CELL_TYPE: {
1381       os << "WeakCell for ";
1382       HeapStringAllocator allocator;
1383       StringStream accumulator(&allocator);
1384       WeakCell::cast(this)->value()->ShortPrint(&accumulator);
1385       os << accumulator.ToCString().get();
1386       break;
1387     }
1388     default:
1389       os << "<Other heap object (" << map()->instance_type() << ")>";
1390       break;
1391   }
1392 }
1393
1394
1395 void HeapObject::Iterate(ObjectVisitor* v) {
1396   // Handle header
1397   IteratePointer(v, kMapOffset);
1398   // Handle object body
1399   Map* m = map();
1400   IterateBody(m->instance_type(), SizeFromMap(m), v);
1401 }
1402
1403
1404 void HeapObject::IterateBody(InstanceType type, int object_size,
1405                              ObjectVisitor* v) {
1406   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1407   // During GC, the map pointer field is encoded.
1408   if (type < FIRST_NONSTRING_TYPE) {
1409     switch (type & kStringRepresentationMask) {
1410       case kSeqStringTag:
1411         break;
1412       case kConsStringTag:
1413         ConsString::BodyDescriptor::IterateBody(this, v);
1414         break;
1415       case kSlicedStringTag:
1416         SlicedString::BodyDescriptor::IterateBody(this, v);
1417         break;
1418       case kExternalStringTag:
1419         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1420           reinterpret_cast<ExternalOneByteString*>(this)
1421               ->ExternalOneByteStringIterateBody(v);
1422         } else {
1423           reinterpret_cast<ExternalTwoByteString*>(this)->
1424               ExternalTwoByteStringIterateBody(v);
1425         }
1426         break;
1427     }
1428     return;
1429   }
1430
1431   switch (type) {
1432     case FIXED_ARRAY_TYPE:
1433       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1434       break;
1435     case FIXED_DOUBLE_ARRAY_TYPE:
1436       break;
1437     case JS_OBJECT_TYPE:
1438     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1439     case JS_GENERATOR_OBJECT_TYPE:
1440     case JS_MODULE_TYPE:
1441     case JS_VALUE_TYPE:
1442     case JS_DATE_TYPE:
1443     case JS_ARRAY_TYPE:
1444     case JS_ARRAY_BUFFER_TYPE:
1445     case JS_TYPED_ARRAY_TYPE:
1446     case JS_DATA_VIEW_TYPE:
1447     case JS_SET_TYPE:
1448     case JS_MAP_TYPE:
1449     case JS_SET_ITERATOR_TYPE:
1450     case JS_MAP_ITERATOR_TYPE:
1451     case JS_WEAK_MAP_TYPE:
1452     case JS_WEAK_SET_TYPE:
1453     case JS_REGEXP_TYPE:
1454     case JS_GLOBAL_PROXY_TYPE:
1455     case JS_GLOBAL_OBJECT_TYPE:
1456     case JS_BUILTINS_OBJECT_TYPE:
1457     case JS_MESSAGE_OBJECT_TYPE:
1458       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1459       break;
1460     case JS_FUNCTION_TYPE:
1461       reinterpret_cast<JSFunction*>(this)
1462           ->JSFunctionIterateBody(object_size, v);
1463       break;
1464     case ODDBALL_TYPE:
1465       Oddball::BodyDescriptor::IterateBody(this, v);
1466       break;
1467     case JS_PROXY_TYPE:
1468       JSProxy::BodyDescriptor::IterateBody(this, v);
1469       break;
1470     case JS_FUNCTION_PROXY_TYPE:
1471       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1472       break;
1473     case FOREIGN_TYPE:
1474       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1475       break;
1476     case MAP_TYPE:
1477       Map::BodyDescriptor::IterateBody(this, v);
1478       break;
1479     case CODE_TYPE:
1480       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1481       break;
1482     case CELL_TYPE:
1483       Cell::BodyDescriptor::IterateBody(this, v);
1484       break;
1485     case PROPERTY_CELL_TYPE:
1486       PropertyCell::BodyDescriptor::IterateBody(this, v);
1487       break;
1488     case WEAK_CELL_TYPE:
1489       WeakCell::BodyDescriptor::IterateBody(this, v);
1490       break;
1491     case SYMBOL_TYPE:
1492       Symbol::BodyDescriptor::IterateBody(this, v);
1493       break;
1494
1495     case HEAP_NUMBER_TYPE:
1496     case MUTABLE_HEAP_NUMBER_TYPE:
1497     case FLOAT32X4_TYPE:
1498     case FILLER_TYPE:
1499     case BYTE_ARRAY_TYPE:
1500     case FREE_SPACE_TYPE:
1501       break;
1502
1503 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
1504   case EXTERNAL_##TYPE##_ARRAY_TYPE:                    \
1505     break;                                              \
1506                                                         \
1507   case FIXED_##TYPE##_ARRAY_TYPE:                       \
1508     reinterpret_cast<FixedTypedArrayBase*>(this)        \
1509         ->FixedTypedArrayBaseIterateBody(v);            \
1510     break;
1511
1512
1513     TYPED_ARRAYS(TYPED_ARRAY_CASE)
1514 #undef TYPED_ARRAY_CASE
1515
1516     case SHARED_FUNCTION_INFO_TYPE: {
1517       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1518       break;
1519     }
1520
1521 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1522         case NAME##_TYPE:
1523       STRUCT_LIST(MAKE_STRUCT_CASE)
1524 #undef MAKE_STRUCT_CASE
1525       if (type == ALLOCATION_SITE_TYPE) {
1526         AllocationSite::BodyDescriptor::IterateBody(this, v);
1527       } else {
1528         StructBodyDescriptor::IterateBody(this, object_size, v);
1529       }
1530       break;
1531     default:
1532       PrintF("Unknown type: %d\n", type);
1533       UNREACHABLE();
1534   }
1535 }
1536
1537
1538 bool HeapNumber::HeapNumberBooleanValue() {
1539   return DoubleToBoolean(value());
1540 }
1541
1542
1543 void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
1544   os << value();
1545 }
1546
1547
1548 void Float32x4::Float32x4Print(std::ostream& os) {  // NOLINT
1549   char arr[100];
1550   Vector<char> buffer(arr, arraysize(arr));
1551   os << std::string(DoubleToCString(get_lane(0), buffer)) << ", "
1552      << std::string(DoubleToCString(get_lane(1), buffer)) << ", "
1553      << std::string(DoubleToCString(get_lane(2), buffer)) << ", "
1554      << std::string(DoubleToCString(get_lane(3), buffer));
1555 }
1556
1557
1558 String* JSReceiver::class_name() {
1559   if (IsJSFunction() || IsJSFunctionProxy()) {
1560     return GetHeap()->Function_string();
1561   }
1562   Object* maybe_constructor = map()->GetConstructor();
1563   if (maybe_constructor->IsJSFunction()) {
1564     JSFunction* constructor = JSFunction::cast(maybe_constructor);
1565     return String::cast(constructor->shared()->instance_class_name());
1566   }
1567   // If the constructor is not present, return "Object".
1568   return GetHeap()->Object_string();
1569 }
1570
1571
1572 String* Map::constructor_name() {
1573   if (is_prototype_map() && prototype_info()->IsPrototypeInfo()) {
1574     PrototypeInfo* proto_info = PrototypeInfo::cast(prototype_info());
1575     if (proto_info->constructor_name()->IsString()) {
1576       return String::cast(proto_info->constructor_name());
1577     }
1578   }
1579   Object* maybe_constructor = GetConstructor();
1580   if (maybe_constructor->IsJSFunction()) {
1581     JSFunction* constructor = JSFunction::cast(maybe_constructor);
1582     String* name = String::cast(constructor->shared()->name());
1583     if (name->length() > 0) return name;
1584     String* inferred_name = constructor->shared()->inferred_name();
1585     if (inferred_name->length() > 0) return inferred_name;
1586     Object* proto = prototype();
1587     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1588   }
1589   // TODO(rossberg): what about proxies?
1590   // If the constructor is not present, return "Object".
1591   return GetHeap()->Object_string();
1592 }
1593
1594
1595 String* JSReceiver::constructor_name() {
1596   return map()->constructor_name();
1597 }
1598
1599
1600 static Handle<Object> WrapType(Handle<HeapType> type) {
1601   if (type->IsClass()) return Map::WeakCellForMap(type->AsClass()->Map());
1602   return type;
1603 }
1604
1605
1606 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
1607                                     Handle<Name> name,
1608                                     Handle<HeapType> type,
1609                                     PropertyAttributes attributes,
1610                                     Representation representation,
1611                                     TransitionFlag flag) {
1612   DCHECK(DescriptorArray::kNotFound ==
1613          map->instance_descriptors()->Search(
1614              *name, map->NumberOfOwnDescriptors()));
1615
1616   // Ensure the descriptor array does not get too big.
1617   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1618     return MaybeHandle<Map>();
1619   }
1620
1621   Isolate* isolate = map->GetIsolate();
1622
1623   // Compute the new index for new field.
1624   int index = map->NextFreePropertyIndex();
1625
1626   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1627     representation = Representation::Tagged();
1628     type = HeapType::Any(isolate);
1629   }
1630
1631   Handle<Object> wrapped_type(WrapType(type));
1632
1633   DataDescriptor new_field_desc(name, index, wrapped_type, attributes,
1634                                 representation);
1635   Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1636   int unused_property_fields = new_map->unused_property_fields() - 1;
1637   if (unused_property_fields < 0) {
1638     unused_property_fields += JSObject::kFieldsAdded;
1639   }
1640   new_map->set_unused_property_fields(unused_property_fields);
1641   return new_map;
1642 }
1643
1644
1645 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1646                                        Handle<Name> name,
1647                                        Handle<Object> constant,
1648                                        PropertyAttributes attributes,
1649                                        TransitionFlag flag) {
1650   // Ensure the descriptor array does not get too big.
1651   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1652     return MaybeHandle<Map>();
1653   }
1654
1655   // Allocate new instance descriptors with (name, constant) added.
1656   DataConstantDescriptor new_constant_desc(name, constant, attributes);
1657   return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1658 }
1659
1660
1661 void JSObject::AddSlowProperty(Handle<JSObject> object,
1662                                Handle<Name> name,
1663                                Handle<Object> value,
1664                                PropertyAttributes attributes) {
1665   DCHECK(!object->HasFastProperties());
1666   Isolate* isolate = object->GetIsolate();
1667   if (object->IsGlobalObject()) {
1668     Handle<GlobalDictionary> dict(object->global_dictionary());
1669     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
1670     int entry = dict->FindEntry(name);
1671     // If there's a cell there, just invalidate and set the property.
1672     if (entry != GlobalDictionary::kNotFound) {
1673       PropertyCell::UpdateCell(dict, entry, value, details);
1674       // TODO(ishell): move this to UpdateCell.
1675       // Need to adjust the details.
1676       int index = dict->NextEnumerationIndex();
1677       dict->SetNextEnumerationIndex(index + 1);
1678       PropertyCell* cell = PropertyCell::cast(dict->ValueAt(entry));
1679       details = cell->property_details().set_index(index);
1680       cell->set_property_details(details);
1681
1682     } else {
1683       auto cell = isolate->factory()->NewPropertyCell();
1684       cell->set_value(*value);
1685       auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
1686                                             : PropertyCellType::kConstant;
1687       details = details.set_cell_type(cell_type);
1688       value = cell;
1689
1690       Handle<GlobalDictionary> result =
1691           GlobalDictionary::Add(dict, name, value, details);
1692       if (*dict != *result) object->set_properties(*result);
1693     }
1694   } else {
1695     Handle<NameDictionary> dict(object->property_dictionary());
1696     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
1697     Handle<NameDictionary> result =
1698         NameDictionary::Add(dict, name, value, details);
1699     if (*dict != *result) object->set_properties(*result);
1700   }
1701 }
1702
1703
1704 Context* JSObject::GetCreationContext() {
1705   Object* constructor = this->map()->GetConstructor();
1706   JSFunction* function;
1707   if (!constructor->IsJSFunction()) {
1708     // Functions have null as a constructor,
1709     // but any JSFunction knows its context immediately.
1710     function = JSFunction::cast(this);
1711   } else {
1712     function = JSFunction::cast(constructor);
1713   }
1714
1715   return function->context()->native_context();
1716 }
1717
1718
1719 MaybeHandle<Object> JSObject::EnqueueChangeRecord(Handle<JSObject> object,
1720                                                   const char* type_str,
1721                                                   Handle<Name> name,
1722                                                   Handle<Object> old_value) {
1723   DCHECK(!object->IsJSGlobalProxy());
1724   DCHECK(!object->IsJSGlobalObject());
1725   Isolate* isolate = object->GetIsolate();
1726   HandleScope scope(isolate);
1727   Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
1728   Handle<Object> args[] = { type, object, name, old_value };
1729   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
1730
1731   return Execution::Call(isolate,
1732                          Handle<JSFunction>(isolate->observers_notify_change()),
1733                          isolate->factory()->undefined_value(), argc, args);
1734 }
1735
1736
1737 const char* Representation::Mnemonic() const {
1738   switch (kind_) {
1739     case kNone: return "v";
1740     case kTagged: return "t";
1741     case kSmi: return "s";
1742     case kDouble: return "d";
1743     case kInteger32: return "i";
1744     case kHeapObject: return "h";
1745     case kExternal: return "x";
1746     default:
1747       UNREACHABLE();
1748       return NULL;
1749   }
1750 }
1751
1752
1753 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
1754                                  int target_inobject, int target_unused,
1755                                  int* old_number_of_fields) {
1756   // If fields were added (or removed), rewrite the instance.
1757   *old_number_of_fields = NumberOfFields();
1758   DCHECK(target_number_of_fields >= *old_number_of_fields);
1759   if (target_number_of_fields != *old_number_of_fields) return true;
1760
1761   // If smi descriptors were replaced by double descriptors, rewrite.
1762   DescriptorArray* old_desc = instance_descriptors();
1763   DescriptorArray* new_desc = target->instance_descriptors();
1764   int limit = NumberOfOwnDescriptors();
1765   for (int i = 0; i < limit; i++) {
1766     if (new_desc->GetDetails(i).representation().IsDouble() !=
1767         old_desc->GetDetails(i).representation().IsDouble()) {
1768       return true;
1769     }
1770   }
1771
1772   // If no fields were added, and no inobject properties were removed, setting
1773   // the map is sufficient.
1774   if (target_inobject == inobject_properties()) return false;
1775   // In-object slack tracking may have reduced the object size of the new map.
1776   // In that case, succeed if all existing fields were inobject, and they still
1777   // fit within the new inobject size.
1778   DCHECK(target_inobject < inobject_properties());
1779   if (target_number_of_fields <= target_inobject) {
1780     DCHECK(target_number_of_fields + target_unused == target_inobject);
1781     return false;
1782   }
1783   // Otherwise, properties will need to be moved to the backing store.
1784   return true;
1785 }
1786
1787
1788 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
1789                             int expected_additional_properties) {
1790   if (object->map() == *new_map) return;
1791   // If this object is a prototype (the callee will check), invalidate any
1792   // prototype chains involving it.
1793   InvalidatePrototypeChains(object->map());
1794   Handle<Map> old_map(object->map());
1795
1796   // If the map was registered with its prototype before, ensure that it
1797   // registers with its new prototype now. This preserves the invariant that
1798   // when a map on a prototype chain is registered with its prototype, then
1799   // all prototypes further up the chain are also registered with their
1800   // respective prototypes.
1801   Object* maybe_old_prototype = old_map->prototype();
1802   if (FLAG_track_prototype_users && old_map->is_prototype_map() &&
1803       maybe_old_prototype->IsJSObject()) {
1804     Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype));
1805     bool was_registered =
1806         JSObject::UnregisterPrototypeUser(old_prototype, old_map);
1807     if (was_registered) {
1808       JSObject::LazyRegisterPrototypeUser(new_map, new_map->GetIsolate());
1809     }
1810   }
1811
1812   if (object->HasFastProperties()) {
1813     if (!new_map->is_dictionary_map()) {
1814       MigrateFastToFast(object, new_map);
1815       if (old_map->is_prototype_map()) {
1816         // Clear out the old descriptor array to avoid problems to sharing
1817         // the descriptor array without using an explicit.
1818         old_map->InitializeDescriptors(
1819             old_map->GetHeap()->empty_descriptor_array(),
1820             LayoutDescriptor::FastPointerLayout());
1821         // Ensure that no transition was inserted for prototype migrations.
1822         DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
1823                          old_map->raw_transitions()));
1824         DCHECK(new_map->GetBackPointer()->IsUndefined());
1825       }
1826     } else {
1827       MigrateFastToSlow(object, new_map, expected_additional_properties);
1828     }
1829   } else {
1830     // For slow-to-fast migrations JSObject::MigrateSlowToFast()
1831     // must be used instead.
1832     CHECK(new_map->is_dictionary_map());
1833
1834     // Slow-to-slow migration is trivial.
1835     object->set_map(*new_map);
1836   }
1837
1838   // Careful: Don't allocate here!
1839   // For some callers of this method, |object| might be in an inconsistent
1840   // state now: the new map might have a new elements_kind, but the object's
1841   // elements pointer hasn't been updated yet. Callers will fix this, but in
1842   // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
1843   DisallowHeapAllocation no_object_verification;
1844
1845   if (old_map->is_prototype_map() && FLAG_track_prototype_users) {
1846     DCHECK(new_map->is_prototype_map());
1847     DCHECK(object->map() == *new_map);
1848     new_map->set_prototype_info(old_map->prototype_info());
1849     old_map->set_prototype_info(Smi::FromInt(0));
1850     if (FLAG_trace_prototype_users) {
1851       PrintF("Moving prototype_info %p from map %p to map %p.\n",
1852              reinterpret_cast<void*>(new_map->prototype_info()),
1853              reinterpret_cast<void*>(*old_map),
1854              reinterpret_cast<void*>(*new_map));
1855     }
1856   }
1857 }
1858
1859
1860 // To migrate a fast instance to a fast map:
1861 // - First check whether the instance needs to be rewritten. If not, simply
1862 //   change the map.
1863 // - Otherwise, allocate a fixed array large enough to hold all fields, in
1864 //   addition to unused space.
1865 // - Copy all existing properties in, in the following order: backing store
1866 //   properties, unused fields, inobject properties.
1867 // - If all allocation succeeded, commit the state atomically:
1868 //   * Copy inobject properties from the backing store back into the object.
1869 //   * Trim the difference in instance size of the object. This also cleanly
1870 //     frees inobject properties that moved to the backing store.
1871 //   * If there are properties left in the backing store, trim of the space used
1872 //     to temporarily store the inobject properties.
1873 //   * If there are properties left in the backing store, install the backing
1874 //     store.
1875 void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
1876   Isolate* isolate = object->GetIsolate();
1877   Handle<Map> old_map(object->map());
1878   int old_number_of_fields;
1879   int number_of_fields = new_map->NumberOfFields();
1880   int inobject = new_map->inobject_properties();
1881   int unused = new_map->unused_property_fields();
1882
1883   // Nothing to do if no functions were converted to fields and no smis were
1884   // converted to doubles.
1885   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
1886                                        unused, &old_number_of_fields)) {
1887     object->synchronized_set_map(*new_map);
1888     return;
1889   }
1890
1891   int total_size = number_of_fields + unused;
1892   int external = total_size - inobject;
1893
1894   if (number_of_fields != old_number_of_fields &&
1895       new_map->GetBackPointer() == *old_map) {
1896     PropertyDetails details = new_map->GetLastDescriptorDetails();
1897
1898     if (old_map->unused_property_fields() > 0) {
1899       if (details.representation().IsDouble()) {
1900         FieldIndex index =
1901             FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
1902         if (new_map->IsUnboxedDoubleField(index)) {
1903           object->RawFastDoublePropertyAtPut(index, 0);
1904         } else {
1905           Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1906           object->RawFastPropertyAtPut(index, *value);
1907         }
1908       }
1909       object->synchronized_set_map(*new_map);
1910       return;
1911     }
1912
1913     DCHECK(number_of_fields == old_number_of_fields + 1);
1914     // This migration is a transition from a map that has run out of property
1915     // space. Therefore it could be done by extending the backing store.
1916     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
1917     Handle<FixedArray> new_storage =
1918         FixedArray::CopySize(old_storage, external);
1919
1920     // Properly initialize newly added property.
1921     Handle<Object> value;
1922     if (details.representation().IsDouble()) {
1923       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1924     } else {
1925       value = isolate->factory()->uninitialized_value();
1926     }
1927     DCHECK(details.type() == DATA);
1928     int target_index = details.field_index() - inobject;
1929     DCHECK(target_index >= 0);  // Must be a backing store index.
1930     new_storage->set(target_index, *value);
1931
1932     // From here on we cannot fail and we shouldn't GC anymore.
1933     DisallowHeapAllocation no_allocation;
1934
1935     // Set the new property value and do the map transition.
1936     object->set_properties(*new_storage);
1937     object->synchronized_set_map(*new_map);
1938     return;
1939   }
1940   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
1941
1942   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
1943   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
1944   int old_nof = old_map->NumberOfOwnDescriptors();
1945   int new_nof = new_map->NumberOfOwnDescriptors();
1946
1947   // This method only supports generalizing instances to at least the same
1948   // number of properties.
1949   DCHECK(old_nof <= new_nof);
1950
1951   for (int i = 0; i < old_nof; i++) {
1952     PropertyDetails details = new_descriptors->GetDetails(i);
1953     if (details.type() != DATA) continue;
1954     PropertyDetails old_details = old_descriptors->GetDetails(i);
1955     Representation old_representation = old_details.representation();
1956     Representation representation = details.representation();
1957     Handle<Object> value;
1958     if (old_details.type() == ACCESSOR_CONSTANT) {
1959       // In case of kAccessor -> kData property reconfiguration, the property
1960       // must already be prepared for data or certain type.
1961       DCHECK(!details.representation().IsNone());
1962       if (details.representation().IsDouble()) {
1963         value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1964       } else {
1965         value = isolate->factory()->uninitialized_value();
1966       }
1967     } else if (old_details.type() == DATA_CONSTANT) {
1968       value = handle(old_descriptors->GetValue(i), isolate);
1969       DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
1970     } else {
1971       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
1972       if (object->IsUnboxedDoubleField(index)) {
1973         double old = object->RawFastDoublePropertyAt(index);
1974         value = isolate->factory()->NewHeapNumber(
1975             old, representation.IsDouble() ? MUTABLE : IMMUTABLE);
1976
1977       } else {
1978         value = handle(object->RawFastPropertyAt(index), isolate);
1979         if (!old_representation.IsDouble() && representation.IsDouble()) {
1980           if (old_representation.IsNone()) {
1981             value = handle(Smi::FromInt(0), isolate);
1982           }
1983           value = Object::NewStorageFor(isolate, value, representation);
1984         } else if (old_representation.IsDouble() &&
1985                    !representation.IsDouble()) {
1986           value = Object::WrapForRead(isolate, value, old_representation);
1987         }
1988       }
1989     }
1990     DCHECK(!(representation.IsDouble() && value->IsSmi()));
1991     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
1992     if (target_index < 0) target_index += total_size;
1993     array->set(target_index, *value);
1994   }
1995
1996   for (int i = old_nof; i < new_nof; i++) {
1997     PropertyDetails details = new_descriptors->GetDetails(i);
1998     if (details.type() != DATA) continue;
1999     Handle<Object> value;
2000     if (details.representation().IsDouble()) {
2001       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2002     } else {
2003       value = isolate->factory()->uninitialized_value();
2004     }
2005     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2006     if (target_index < 0) target_index += total_size;
2007     array->set(target_index, *value);
2008   }
2009
2010   // From here on we cannot fail and we shouldn't GC anymore.
2011   DisallowHeapAllocation no_allocation;
2012
2013   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2014   // avoid overwriting |one_pointer_filler_map|.
2015   int limit = Min(inobject, number_of_fields);
2016   for (int i = 0; i < limit; i++) {
2017     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
2018     Object* value = array->get(external + i);
2019     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
2020     // yet.
2021     if (new_map->IsUnboxedDoubleField(index)) {
2022       DCHECK(value->IsMutableHeapNumber());
2023       object->RawFastDoublePropertyAtPut(index,
2024                                          HeapNumber::cast(value)->value());
2025     } else {
2026       object->RawFastPropertyAtPut(index, value);
2027     }
2028   }
2029
2030   Heap* heap = isolate->heap();
2031
2032   // If there are properties in the new backing store, trim it to the correct
2033   // size and install the backing store into the object.
2034   if (external > 0) {
2035     heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, inobject);
2036     object->set_properties(*array);
2037   }
2038
2039   // Create filler object past the new instance size.
2040   int new_instance_size = new_map->instance_size();
2041   int instance_size_delta = old_map->instance_size() - new_instance_size;
2042   DCHECK(instance_size_delta >= 0);
2043
2044   if (instance_size_delta > 0) {
2045     Address address = object->address();
2046     heap->CreateFillerObjectAt(
2047         address + new_instance_size, instance_size_delta);
2048     heap->AdjustLiveBytes(address, -instance_size_delta,
2049                           Heap::CONCURRENT_TO_SWEEPER);
2050   }
2051
2052   // We are storing the new map using release store after creating a filler for
2053   // the left-over space to avoid races with the sweeper thread.
2054   object->synchronized_set_map(*new_map);
2055 }
2056
2057
2058 int Map::NumberOfFields() {
2059   DescriptorArray* descriptors = instance_descriptors();
2060   int result = 0;
2061   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2062     if (descriptors->GetDetails(i).location() == kField) result++;
2063   }
2064   return result;
2065 }
2066
2067
2068 Handle<Map> Map::CopyGeneralizeAllRepresentations(
2069     Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind,
2070     PropertyAttributes attributes, const char* reason) {
2071   Isolate* isolate = map->GetIsolate();
2072   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2073   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2074   Handle<DescriptorArray> descriptors =
2075       DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
2076
2077   for (int i = 0; i < number_of_own_descriptors; i++) {
2078     descriptors->SetRepresentation(i, Representation::Tagged());
2079     if (descriptors->GetDetails(i).type() == DATA) {
2080       descriptors->SetValue(i, HeapType::Any());
2081     }
2082   }
2083
2084   Handle<LayoutDescriptor> new_layout_descriptor(
2085       LayoutDescriptor::FastPointerLayout(), isolate);
2086   Handle<Map> new_map = CopyReplaceDescriptors(
2087       map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
2088       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
2089
2090   // Unless the instance is being migrated, ensure that modify_index is a field.
2091   if (modify_index >= 0) {
2092     PropertyDetails details = descriptors->GetDetails(modify_index);
2093     if (store_mode == FORCE_FIELD &&
2094         (details.type() != DATA || details.attributes() != attributes)) {
2095       int field_index = details.type() == DATA ? details.field_index()
2096                                                : new_map->NumberOfFields();
2097       DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
2098                        field_index, attributes, Representation::Tagged());
2099       descriptors->Replace(modify_index, &d);
2100       if (details.type() != DATA) {
2101         int unused_property_fields = new_map->unused_property_fields() - 1;
2102         if (unused_property_fields < 0) {
2103           unused_property_fields += JSObject::kFieldsAdded;
2104         }
2105         new_map->set_unused_property_fields(unused_property_fields);
2106       }
2107     } else {
2108       DCHECK(details.attributes() == attributes);
2109     }
2110
2111     if (FLAG_trace_generalization) {
2112       HeapType* field_type =
2113           (details.type() == DATA)
2114               ? map->instance_descriptors()->GetFieldType(modify_index)
2115               : NULL;
2116       map->PrintGeneralization(
2117           stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
2118           new_map->NumberOfOwnDescriptors(),
2119           details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
2120           details.representation(), Representation::Tagged(), field_type,
2121           HeapType::Any());
2122     }
2123   }
2124   return new_map;
2125 }
2126
2127
2128 void Map::DeprecateTransitionTree() {
2129   if (is_deprecated()) return;
2130   Object* transitions = raw_transitions();
2131   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
2132   for (int i = 0; i < num_transitions; ++i) {
2133     TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
2134   }
2135   deprecate();
2136   dependent_code()->DeoptimizeDependentCodeGroup(
2137       GetIsolate(), DependentCode::kTransitionGroup);
2138   NotifyLeafMapLayoutChange();
2139 }
2140
2141
2142 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
2143   if (obj1 == obj2) return true;  // Valid for both kData and kAccessor kinds.
2144   // TODO(ishell): compare AccessorPairs.
2145   return false;
2146 }
2147
2148
2149 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2150 // the current instance_descriptors to ensure proper sharing of descriptor
2151 // arrays.
2152 // Returns true if the transition target at given key was deprecated.
2153 bool Map::DeprecateTarget(PropertyKind kind, Name* key,
2154                           PropertyAttributes attributes,
2155                           DescriptorArray* new_descriptors,
2156                           LayoutDescriptor* new_layout_descriptor) {
2157   bool transition_target_deprecated = false;
2158   Map* maybe_transition =
2159       TransitionArray::SearchTransition(this, kind, key, attributes);
2160   if (maybe_transition != NULL) {
2161     maybe_transition->DeprecateTransitionTree();
2162     transition_target_deprecated = true;
2163   }
2164
2165   // Don't overwrite the empty descriptor array.
2166   if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated;
2167
2168   DescriptorArray* to_replace = instance_descriptors();
2169   Map* current = this;
2170   GetHeap()->incremental_marking()->RecordWrites(to_replace);
2171   while (current->instance_descriptors() == to_replace) {
2172     current->SetEnumLength(kInvalidEnumCacheSentinel);
2173     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
2174     Object* next = current->GetBackPointer();
2175     if (next->IsUndefined()) break;
2176     current = Map::cast(next);
2177   }
2178
2179   set_owns_descriptors(false);
2180   return transition_target_deprecated;
2181 }
2182
2183
2184 Map* Map::FindRootMap() {
2185   Map* result = this;
2186   while (true) {
2187     Object* back = result->GetBackPointer();
2188     if (back->IsUndefined()) return result;
2189     result = Map::cast(back);
2190   }
2191 }
2192
2193
2194 Map* Map::FindLastMatchMap(int verbatim,
2195                            int length,
2196                            DescriptorArray* descriptors) {
2197   DisallowHeapAllocation no_allocation;
2198
2199   // This can only be called on roots of transition trees.
2200   DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
2201
2202   Map* current = this;
2203
2204   for (int i = verbatim; i < length; i++) {
2205     Name* name = descriptors->GetKey(i);
2206     PropertyDetails details = descriptors->GetDetails(i);
2207     Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
2208                                                   details.attributes());
2209     if (next == NULL) break;
2210     DescriptorArray* next_descriptors = next->instance_descriptors();
2211
2212     PropertyDetails next_details = next_descriptors->GetDetails(i);
2213     DCHECK_EQ(details.kind(), next_details.kind());
2214     DCHECK_EQ(details.attributes(), next_details.attributes());
2215     if (details.location() != next_details.location()) break;
2216     if (!details.representation().Equals(next_details.representation())) break;
2217
2218     if (next_details.location() == kField) {
2219       HeapType* next_field_type = next_descriptors->GetFieldType(i);
2220       if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
2221         break;
2222       }
2223     } else {
2224       if (!EqualImmutableValues(descriptors->GetValue(i),
2225                                 next_descriptors->GetValue(i))) {
2226         break;
2227       }
2228     }
2229     current = next;
2230   }
2231   return current;
2232 }
2233
2234
2235 Map* Map::FindFieldOwner(int descriptor) {
2236   DisallowHeapAllocation no_allocation;
2237   DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
2238   Map* result = this;
2239   while (true) {
2240     Object* back = result->GetBackPointer();
2241     if (back->IsUndefined()) break;
2242     Map* parent = Map::cast(back);
2243     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
2244     result = parent;
2245   }
2246   return result;
2247 }
2248
2249
2250 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
2251                           Representation new_representation,
2252                           Handle<Object> new_wrapped_type) {
2253   DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
2254   DisallowHeapAllocation no_allocation;
2255   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
2256   if (details.type() != DATA) return;
2257   Object* transitions = raw_transitions();
2258   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
2259   for (int i = 0; i < num_transitions; ++i) {
2260     Map* target = TransitionArray::GetTarget(transitions, i);
2261     target->UpdateFieldType(descriptor, name, new_representation,
2262                             new_wrapped_type);
2263   }
2264   // It is allowed to change representation here only from None to something.
2265   DCHECK(details.representation().Equals(new_representation) ||
2266          details.representation().IsNone());
2267
2268   // Skip if already updated the shared descriptor.
2269   if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return;
2270   DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
2271                    new_wrapped_type, details.attributes(), new_representation);
2272   instance_descriptors()->Replace(descriptor, &d);
2273 }
2274
2275
2276 // static
2277 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
2278                                           Handle<HeapType> type2,
2279                                           Isolate* isolate) {
2280   if (type1->NowIs(type2)) return type2;
2281   if (type2->NowIs(type1)) return type1;
2282   return HeapType::Any(isolate);
2283 }
2284
2285
2286 // static
2287 void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
2288                               Representation new_representation,
2289                               Handle<HeapType> new_field_type) {
2290   Isolate* isolate = map->GetIsolate();
2291
2292   // Check if we actually need to generalize the field type at all.
2293   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
2294   Representation old_representation =
2295       old_descriptors->GetDetails(modify_index).representation();
2296   Handle<HeapType> old_field_type(old_descriptors->GetFieldType(modify_index),
2297                                   isolate);
2298
2299   if (old_representation.Equals(new_representation) &&
2300       new_field_type->NowIs(old_field_type)) {
2301     DCHECK(Map::GeneralizeFieldType(old_field_type,
2302                                     new_field_type,
2303                                     isolate)->NowIs(old_field_type));
2304     return;
2305   }
2306
2307   // Determine the field owner.
2308   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
2309   Handle<DescriptorArray> descriptors(
2310       field_owner->instance_descriptors(), isolate);
2311   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
2312   bool old_field_type_was_cleared =
2313       old_field_type->Is(HeapType::None()) && old_representation.IsHeapObject();
2314
2315   // Determine the generalized new field type. Conservatively assume type Any
2316   // for cleared field types because the cleared type could have been a
2317   // deprecated map and there still could be live instances with a non-
2318   // deprecated version of the map.
2319   new_field_type =
2320       old_field_type_was_cleared
2321           ? HeapType::Any(isolate)
2322           : Map::GeneralizeFieldType(old_field_type, new_field_type, isolate);
2323
2324   PropertyDetails details = descriptors->GetDetails(modify_index);
2325   Handle<Name> name(descriptors->GetKey(modify_index));
2326
2327   Handle<Object> wrapped_type(WrapType(new_field_type));
2328   field_owner->UpdateFieldType(modify_index, name, new_representation,
2329                                wrapped_type);
2330   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
2331       isolate, DependentCode::kFieldTypeGroup);
2332
2333   if (FLAG_trace_generalization) {
2334     map->PrintGeneralization(
2335         stdout, "field type generalization",
2336         modify_index, map->NumberOfOwnDescriptors(),
2337         map->NumberOfOwnDescriptors(), false,
2338         details.representation(), details.representation(),
2339         *old_field_type, *new_field_type);
2340   }
2341 }
2342
2343
2344 static inline Handle<HeapType> GetFieldType(Isolate* isolate,
2345                                             Handle<DescriptorArray> descriptors,
2346                                             int descriptor,
2347                                             PropertyLocation location,
2348                                             Representation representation) {
2349 #ifdef DEBUG
2350   PropertyDetails details = descriptors->GetDetails(descriptor);
2351   DCHECK_EQ(kData, details.kind());
2352   DCHECK_EQ(details.location(), location);
2353 #endif
2354   if (location == kField) {
2355     return handle(descriptors->GetFieldType(descriptor), isolate);
2356   } else {
2357     return descriptors->GetValue(descriptor)
2358         ->OptimalType(isolate, representation);
2359   }
2360 }
2361
2362
2363 // Reconfigures property at |modify_index| with |new_kind|, |new_attributes|,
2364 // |store_mode| and/or |new_representation|/|new_field_type|.
2365 // If |modify_index| is negative then no properties are reconfigured but the
2366 // map is migrated to the up-to-date non-deprecated state.
2367 //
2368 // This method rewrites or completes the transition tree to reflect the new
2369 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
2370 // on every rewrite the new type is deduced by merging the current type with
2371 // any potential new (partial) version of the type in the transition tree.
2372 // To do this, on each rewrite:
2373 // - Search the root of the transition tree using FindRootMap.
2374 // - Find |target_map|, the newest matching version of this map using the
2375 //   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
2376 //   |modify_index| is considered to be of |new_kind| and having
2377 //   |new_attributes|) to walk the transition tree.
2378 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
2379 //   descriptor array of the |target_map|.
2380 // - Generalize the |modify_index| descriptor using |new_representation| and
2381 //   |new_field_type|.
2382 // - Walk the tree again starting from the root towards |target_map|. Stop at
2383 //   |split_map|, the first map who's descriptor array does not match the merged
2384 //   descriptor array.
2385 // - If |target_map| == |split_map|, |target_map| is in the expected state.
2386 //   Return it.
2387 // - Otherwise, invalidate the outdated transition target from |target_map|, and
2388 //   replace its transition tree with a new branch for the updated descriptors.
2389 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
2390                                      PropertyKind new_kind,
2391                                      PropertyAttributes new_attributes,
2392                                      Representation new_representation,
2393                                      Handle<HeapType> new_field_type,
2394                                      StoreMode store_mode) {
2395   DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
2396   DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
2397   Isolate* isolate = old_map->GetIsolate();
2398
2399   Handle<DescriptorArray> old_descriptors(
2400       old_map->instance_descriptors(), isolate);
2401   int old_nof = old_map->NumberOfOwnDescriptors();
2402
2403   // If it's just a representation generalization case (i.e. property kind and
2404   // attributes stays unchanged) it's fine to transition from None to anything
2405   // but double without any modification to the object, because the default
2406   // uninitialized value for representation None can be overwritten by both
2407   // smi and tagged values. Doubles, however, would require a box allocation.
2408   if (modify_index >= 0 && !new_representation.IsNone() &&
2409       !new_representation.IsDouble()) {
2410     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2411     Representation old_representation = old_details.representation();
2412
2413     if (old_representation.IsNone()) {
2414       DCHECK_EQ(new_kind, old_details.kind());
2415       DCHECK_EQ(new_attributes, old_details.attributes());
2416       DCHECK_EQ(DATA, old_details.type());
2417       if (FLAG_trace_generalization) {
2418         old_map->PrintGeneralization(
2419             stdout, "uninitialized field", modify_index,
2420             old_map->NumberOfOwnDescriptors(),
2421             old_map->NumberOfOwnDescriptors(), false, old_representation,
2422             new_representation, old_descriptors->GetFieldType(modify_index),
2423             *new_field_type);
2424       }
2425       Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
2426
2427       GeneralizeFieldType(field_owner, modify_index, new_representation,
2428                           new_field_type);
2429       DCHECK(old_descriptors->GetDetails(modify_index)
2430                  .representation()
2431                  .Equals(new_representation));
2432       DCHECK(
2433           old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
2434       return old_map;
2435     }
2436   }
2437
2438   // Check the state of the root map.
2439   Handle<Map> root_map(old_map->FindRootMap(), isolate);
2440   if (!old_map->EquivalentToForTransition(*root_map)) {
2441     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2442                                             new_kind, new_attributes,
2443                                             "GenAll_NotEquivalent");
2444   }
2445
2446   ElementsKind from_kind = root_map->elements_kind();
2447   ElementsKind to_kind = old_map->elements_kind();
2448   // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
2449   if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
2450       to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
2451       !(IsTransitionableFastElementsKind(from_kind) &&
2452         IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
2453     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2454                                             new_kind, new_attributes,
2455                                             "GenAll_InvalidElementsTransition");
2456   }
2457   int root_nof = root_map->NumberOfOwnDescriptors();
2458   if (modify_index >= 0 && modify_index < root_nof) {
2459     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2460     if (old_details.kind() != new_kind ||
2461         old_details.attributes() != new_attributes) {
2462       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2463                                               new_kind, new_attributes,
2464                                               "GenAll_RootModification1");
2465     }
2466     if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
2467         (old_details.type() == DATA &&
2468          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
2469           !new_representation.fits_into(old_details.representation())))) {
2470       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2471                                               new_kind, new_attributes,
2472                                               "GenAll_RootModification2");
2473     }
2474   }
2475
2476   // From here on, use the map with correct elements kind as root map.
2477   if (from_kind != to_kind) {
2478     root_map = Map::AsElementsKind(root_map, to_kind);
2479   }
2480
2481   Handle<Map> target_map = root_map;
2482   for (int i = root_nof; i < old_nof; ++i) {
2483     PropertyDetails old_details = old_descriptors->GetDetails(i);
2484     PropertyKind next_kind;
2485     PropertyLocation next_location;
2486     PropertyAttributes next_attributes;
2487     Representation next_representation;
2488     bool property_kind_reconfiguration = false;
2489
2490     if (modify_index == i) {
2491       DCHECK_EQ(FORCE_FIELD, store_mode);
2492       property_kind_reconfiguration = old_details.kind() != new_kind;
2493
2494       next_kind = new_kind;
2495       next_location = kField;
2496       next_attributes = new_attributes;
2497       // If property kind is not reconfigured merge the result with
2498       // representation/field type from the old descriptor.
2499       next_representation = new_representation;
2500       if (!property_kind_reconfiguration) {
2501         next_representation =
2502             next_representation.generalize(old_details.representation());
2503       }
2504
2505     } else {
2506       next_kind = old_details.kind();
2507       next_location = old_details.location();
2508       next_attributes = old_details.attributes();
2509       next_representation = old_details.representation();
2510     }
2511     Map* transition = TransitionArray::SearchTransition(
2512         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
2513     if (transition == NULL) break;
2514     Handle<Map> tmp_map(transition, isolate);
2515
2516     Handle<DescriptorArray> tmp_descriptors = handle(
2517         tmp_map->instance_descriptors(), isolate);
2518
2519     // Check if target map is incompatible.
2520     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2521     DCHECK_EQ(next_kind, tmp_details.kind());
2522     DCHECK_EQ(next_attributes, tmp_details.attributes());
2523     if (next_kind == kAccessor &&
2524         !EqualImmutableValues(old_descriptors->GetValue(i),
2525                               tmp_descriptors->GetValue(i))) {
2526       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2527                                               new_kind, new_attributes,
2528                                               "GenAll_Incompatible");
2529     }
2530     if (next_location == kField && tmp_details.location() == kDescriptor) break;
2531
2532     Representation tmp_representation = tmp_details.representation();
2533     if (!next_representation.fits_into(tmp_representation)) break;
2534
2535     PropertyLocation old_location = old_details.location();
2536     PropertyLocation tmp_location = tmp_details.location();
2537     if (tmp_location == kField) {
2538       if (next_kind == kData) {
2539         Handle<HeapType> next_field_type;
2540         if (modify_index == i) {
2541           next_field_type = new_field_type;
2542           if (!property_kind_reconfiguration) {
2543             Handle<HeapType> old_field_type =
2544                 GetFieldType(isolate, old_descriptors, i,
2545                              old_details.location(), tmp_representation);
2546             next_field_type =
2547                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2548           }
2549         } else {
2550           Handle<HeapType> old_field_type =
2551               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2552                            tmp_representation);
2553           next_field_type = old_field_type;
2554         }
2555         GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
2556       }
2557     } else if (old_location == kField ||
2558                !EqualImmutableValues(old_descriptors->GetValue(i),
2559                                      tmp_descriptors->GetValue(i))) {
2560       break;
2561     }
2562     DCHECK(!tmp_map->is_deprecated());
2563     target_map = tmp_map;
2564   }
2565
2566   // Directly change the map if the target map is more general.
2567   Handle<DescriptorArray> target_descriptors(
2568       target_map->instance_descriptors(), isolate);
2569   int target_nof = target_map->NumberOfOwnDescriptors();
2570   if (target_nof == old_nof &&
2571       (store_mode != FORCE_FIELD ||
2572        (modify_index >= 0 &&
2573         target_descriptors->GetDetails(modify_index).location() == kField))) {
2574 #ifdef DEBUG
2575     if (modify_index >= 0) {
2576       PropertyDetails details = target_descriptors->GetDetails(modify_index);
2577       DCHECK_EQ(new_kind, details.kind());
2578       DCHECK_EQ(new_attributes, details.attributes());
2579       DCHECK(new_representation.fits_into(details.representation()));
2580       DCHECK(details.location() != kField ||
2581              new_field_type->NowIs(
2582                  target_descriptors->GetFieldType(modify_index)));
2583     }
2584 #endif
2585     if (*target_map != *old_map) {
2586       old_map->NotifyLeafMapLayoutChange();
2587     }
2588     return target_map;
2589   }
2590
2591   // Find the last compatible target map in the transition tree.
2592   for (int i = target_nof; i < old_nof; ++i) {
2593     PropertyDetails old_details = old_descriptors->GetDetails(i);
2594     PropertyKind next_kind;
2595     PropertyAttributes next_attributes;
2596     if (modify_index == i) {
2597       next_kind = new_kind;
2598       next_attributes = new_attributes;
2599     } else {
2600       next_kind = old_details.kind();
2601       next_attributes = old_details.attributes();
2602     }
2603     Map* transition = TransitionArray::SearchTransition(
2604         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
2605     if (transition == NULL) break;
2606     Handle<Map> tmp_map(transition, isolate);
2607     Handle<DescriptorArray> tmp_descriptors(
2608         tmp_map->instance_descriptors(), isolate);
2609
2610     // Check if target map is compatible.
2611 #ifdef DEBUG
2612     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2613     DCHECK_EQ(next_kind, tmp_details.kind());
2614     DCHECK_EQ(next_attributes, tmp_details.attributes());
2615 #endif
2616     if (next_kind == kAccessor &&
2617         !EqualImmutableValues(old_descriptors->GetValue(i),
2618                               tmp_descriptors->GetValue(i))) {
2619       return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2620                                               new_kind, new_attributes,
2621                                               "GenAll_Incompatible");
2622     }
2623     DCHECK(!tmp_map->is_deprecated());
2624     target_map = tmp_map;
2625   }
2626   target_nof = target_map->NumberOfOwnDescriptors();
2627   target_descriptors = handle(target_map->instance_descriptors(), isolate);
2628
2629   // Allocate a new descriptor array large enough to hold the required
2630   // descriptors, with minimally the exact same size as the old descriptor
2631   // array.
2632   int new_slack = Max(
2633       old_nof, old_descriptors->number_of_descriptors()) - old_nof;
2634   Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
2635       isolate, old_nof, new_slack);
2636   DCHECK(new_descriptors->length() > target_descriptors->length() ||
2637          new_descriptors->NumberOfSlackDescriptors() > 0 ||
2638          new_descriptors->number_of_descriptors() ==
2639          old_descriptors->number_of_descriptors());
2640   DCHECK(new_descriptors->number_of_descriptors() == old_nof);
2641
2642   // 0 -> |root_nof|
2643   int current_offset = 0;
2644   for (int i = 0; i < root_nof; ++i) {
2645     PropertyDetails old_details = old_descriptors->GetDetails(i);
2646     if (old_details.location() == kField) {
2647       current_offset += old_details.field_width_in_words();
2648     }
2649     Descriptor d(handle(old_descriptors->GetKey(i), isolate),
2650                  handle(old_descriptors->GetValue(i), isolate),
2651                  old_details);
2652     new_descriptors->Set(i, &d);
2653   }
2654
2655   // |root_nof| -> |target_nof|
2656   for (int i = root_nof; i < target_nof; ++i) {
2657     Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
2658     PropertyDetails old_details = old_descriptors->GetDetails(i);
2659     PropertyDetails target_details = target_descriptors->GetDetails(i);
2660
2661     PropertyKind next_kind;
2662     PropertyAttributes next_attributes;
2663     PropertyLocation next_location;
2664     Representation next_representation;
2665     bool property_kind_reconfiguration = false;
2666
2667     if (modify_index == i) {
2668       DCHECK_EQ(FORCE_FIELD, store_mode);
2669       property_kind_reconfiguration = old_details.kind() != new_kind;
2670
2671       next_kind = new_kind;
2672       next_attributes = new_attributes;
2673       next_location = kField;
2674
2675       // Merge new representation/field type with ones from the target
2676       // descriptor. If property kind is not reconfigured merge the result with
2677       // representation/field type from the old descriptor.
2678       next_representation =
2679           new_representation.generalize(target_details.representation());
2680       if (!property_kind_reconfiguration) {
2681         next_representation =
2682             next_representation.generalize(old_details.representation());
2683       }
2684     } else {
2685       // Merge old_descriptor and target_descriptor entries.
2686       DCHECK_EQ(target_details.kind(), old_details.kind());
2687       next_kind = target_details.kind();
2688       next_attributes = target_details.attributes();
2689       next_location =
2690           old_details.location() == kField ||
2691                   target_details.location() == kField ||
2692                   !EqualImmutableValues(target_descriptors->GetValue(i),
2693                                         old_descriptors->GetValue(i))
2694               ? kField
2695               : kDescriptor;
2696
2697       next_representation = old_details.representation().generalize(
2698           target_details.representation());
2699     }
2700     DCHECK_EQ(next_kind, target_details.kind());
2701     DCHECK_EQ(next_attributes, target_details.attributes());
2702
2703     if (next_location == kField) {
2704       if (next_kind == kData) {
2705         Handle<HeapType> target_field_type =
2706             GetFieldType(isolate, target_descriptors, i,
2707                          target_details.location(), next_representation);
2708
2709         Handle<HeapType> next_field_type;
2710         if (modify_index == i) {
2711           next_field_type =
2712               GeneralizeFieldType(target_field_type, new_field_type, isolate);
2713           if (!property_kind_reconfiguration) {
2714             Handle<HeapType> old_field_type =
2715                 GetFieldType(isolate, old_descriptors, i,
2716                              old_details.location(), next_representation);
2717             next_field_type =
2718                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2719           }
2720         } else {
2721           Handle<HeapType> old_field_type =
2722               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2723                            next_representation);
2724           next_field_type =
2725               GeneralizeFieldType(target_field_type, old_field_type, isolate);
2726         }
2727         Handle<Object> wrapped_type(WrapType(next_field_type));
2728         DataDescriptor d(target_key, current_offset, wrapped_type,
2729                          next_attributes, next_representation);
2730         current_offset += d.GetDetails().field_width_in_words();
2731         new_descriptors->Set(i, &d);
2732       } else {
2733         UNIMPLEMENTED();  // TODO(ishell): implement.
2734       }
2735     } else {
2736       PropertyDetails details(next_attributes, next_kind, next_location,
2737                               next_representation);
2738       Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
2739                    details);
2740       new_descriptors->Set(i, &d);
2741     }
2742   }
2743
2744   // |target_nof| -> |old_nof|
2745   for (int i = target_nof; i < old_nof; ++i) {
2746     PropertyDetails old_details = old_descriptors->GetDetails(i);
2747     Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
2748
2749     // Merge old_descriptor entry and modified details together.
2750     PropertyKind next_kind;
2751     PropertyAttributes next_attributes;
2752     PropertyLocation next_location;
2753     Representation next_representation;
2754     bool property_kind_reconfiguration = false;
2755
2756     if (modify_index == i) {
2757       DCHECK_EQ(FORCE_FIELD, store_mode);
2758       // In case of property kind reconfiguration it is not necessary to
2759       // take into account representation/field type of the old descriptor.
2760       property_kind_reconfiguration = old_details.kind() != new_kind;
2761
2762       next_kind = new_kind;
2763       next_attributes = new_attributes;
2764       next_location = kField;
2765       next_representation = new_representation;
2766       if (!property_kind_reconfiguration) {
2767         next_representation =
2768             next_representation.generalize(old_details.representation());
2769       }
2770     } else {
2771       next_kind = old_details.kind();
2772       next_attributes = old_details.attributes();
2773       next_location = old_details.location();
2774       next_representation = old_details.representation();
2775     }
2776
2777     if (next_location == kField) {
2778       if (next_kind == kData) {
2779         Handle<HeapType> next_field_type;
2780         if (modify_index == i) {
2781           next_field_type = new_field_type;
2782           if (!property_kind_reconfiguration) {
2783             Handle<HeapType> old_field_type =
2784                 GetFieldType(isolate, old_descriptors, i,
2785                              old_details.location(), next_representation);
2786             next_field_type =
2787                 GeneralizeFieldType(next_field_type, old_field_type, isolate);
2788           }
2789         } else {
2790           Handle<HeapType> old_field_type =
2791               GetFieldType(isolate, old_descriptors, i, old_details.location(),
2792                            next_representation);
2793           next_field_type = old_field_type;
2794         }
2795
2796         Handle<Object> wrapped_type(WrapType(next_field_type));
2797
2798         DataDescriptor d(old_key, current_offset, wrapped_type, next_attributes,
2799                          next_representation);
2800         current_offset += d.GetDetails().field_width_in_words();
2801         new_descriptors->Set(i, &d);
2802       } else {
2803         UNIMPLEMENTED();  // TODO(ishell): implement.
2804       }
2805     } else {
2806       PropertyDetails details(next_attributes, next_kind, next_location,
2807                               next_representation);
2808       Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
2809                    details);
2810       new_descriptors->Set(i, &d);
2811     }
2812   }
2813
2814   new_descriptors->Sort();
2815
2816   DCHECK(store_mode != FORCE_FIELD ||
2817          new_descriptors->GetDetails(modify_index).location() == kField);
2818
2819   Handle<Map> split_map(root_map->FindLastMatchMap(
2820           root_nof, old_nof, *new_descriptors), isolate);
2821   int split_nof = split_map->NumberOfOwnDescriptors();
2822   DCHECK_NE(old_nof, split_nof);
2823
2824   Handle<LayoutDescriptor> new_layout_descriptor =
2825       LayoutDescriptor::New(split_map, new_descriptors, old_nof);
2826
2827   PropertyKind split_kind;
2828   PropertyAttributes split_attributes;
2829   if (modify_index == split_nof) {
2830     split_kind = new_kind;
2831     split_attributes = new_attributes;
2832   } else {
2833     PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
2834     split_kind = split_prop_details.kind();
2835     split_attributes = split_prop_details.attributes();
2836   }
2837   bool transition_target_deprecated = split_map->DeprecateTarget(
2838       split_kind, old_descriptors->GetKey(split_nof), split_attributes,
2839       *new_descriptors, *new_layout_descriptor);
2840
2841   // If |transition_target_deprecated| is true then the transition array
2842   // already contains entry for given descriptor. This means that the transition
2843   // could be inserted regardless of whether transitions array is full or not.
2844   if (!transition_target_deprecated &&
2845       !TransitionArray::CanHaveMoreTransitions(split_map)) {
2846     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2847                                             new_kind, new_attributes,
2848                                             "GenAll_CantHaveMoreTransitions");
2849   }
2850
2851   old_map->NotifyLeafMapLayoutChange();
2852
2853   if (FLAG_trace_generalization && modify_index >= 0) {
2854     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2855     PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
2856     Handle<HeapType> old_field_type =
2857         (old_details.type() == DATA)
2858             ? handle(old_descriptors->GetFieldType(modify_index), isolate)
2859             : HeapType::Constant(
2860                   handle(old_descriptors->GetValue(modify_index), isolate),
2861                   isolate);
2862     Handle<HeapType> new_field_type =
2863         (new_details.type() == DATA)
2864             ? handle(new_descriptors->GetFieldType(modify_index), isolate)
2865             : HeapType::Constant(
2866                   handle(new_descriptors->GetValue(modify_index), isolate),
2867                   isolate);
2868     old_map->PrintGeneralization(
2869         stdout, "", modify_index, split_nof, old_nof,
2870         old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
2871         old_details.representation(), new_details.representation(),
2872         *old_field_type, *new_field_type);
2873   }
2874
2875   // Add missing transitions.
2876   Handle<Map> new_map = split_map;
2877   for (int i = split_nof; i < old_nof; ++i) {
2878     new_map = CopyInstallDescriptors(new_map, i, new_descriptors,
2879                                      new_layout_descriptor);
2880   }
2881   new_map->set_owns_descriptors(true);
2882   return new_map;
2883 }
2884
2885
2886 // Generalize the representation of all DATA descriptors.
2887 Handle<Map> Map::GeneralizeAllFieldRepresentations(
2888     Handle<Map> map) {
2889   Handle<DescriptorArray> descriptors(map->instance_descriptors());
2890   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
2891     PropertyDetails details = descriptors->GetDetails(i);
2892     if (details.type() == DATA) {
2893       map = ReconfigureProperty(map, i, kData, details.attributes(),
2894                                 Representation::Tagged(),
2895                                 HeapType::Any(map->GetIsolate()), FORCE_FIELD);
2896     }
2897   }
2898   return map;
2899 }
2900
2901
2902 // static
2903 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
2904   DisallowHeapAllocation no_allocation;
2905   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
2906
2907   if (!old_map->is_deprecated()) return old_map;
2908
2909   // Check the state of the root map.
2910   Map* root_map = old_map->FindRootMap();
2911   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
2912
2913   ElementsKind from_kind = root_map->elements_kind();
2914   ElementsKind to_kind = old_map->elements_kind();
2915   if (from_kind != to_kind) {
2916     // Try to follow existing elements kind transitions.
2917     root_map = root_map->LookupElementsTransitionMap(to_kind);
2918     if (root_map == NULL) return MaybeHandle<Map>();
2919     // From here on, use the map with correct elements kind as root map.
2920   }
2921   int root_nof = root_map->NumberOfOwnDescriptors();
2922
2923   int old_nof = old_map->NumberOfOwnDescriptors();
2924   DescriptorArray* old_descriptors = old_map->instance_descriptors();
2925
2926   Map* new_map = root_map;
2927   for (int i = root_nof; i < old_nof; ++i) {
2928     PropertyDetails old_details = old_descriptors->GetDetails(i);
2929     Map* transition = TransitionArray::SearchTransition(
2930         new_map, old_details.kind(), old_descriptors->GetKey(i),
2931         old_details.attributes());
2932     if (transition == NULL) return MaybeHandle<Map>();
2933     new_map = transition;
2934     DescriptorArray* new_descriptors = new_map->instance_descriptors();
2935
2936     PropertyDetails new_details = new_descriptors->GetDetails(i);
2937     DCHECK_EQ(old_details.kind(), new_details.kind());
2938     DCHECK_EQ(old_details.attributes(), new_details.attributes());
2939     if (!old_details.representation().fits_into(new_details.representation())) {
2940       return MaybeHandle<Map>();
2941     }
2942     switch (new_details.type()) {
2943       case DATA: {
2944         HeapType* new_type = new_descriptors->GetFieldType(i);
2945         PropertyType old_property_type = old_details.type();
2946         if (old_property_type == DATA) {
2947           HeapType* old_type = old_descriptors->GetFieldType(i);
2948           if (!old_type->NowIs(new_type)) {
2949             return MaybeHandle<Map>();
2950           }
2951         } else {
2952           DCHECK(old_property_type == DATA_CONSTANT);
2953           Object* old_value = old_descriptors->GetValue(i);
2954           if (!new_type->NowContains(old_value)) {
2955             return MaybeHandle<Map>();
2956           }
2957         }
2958         break;
2959       }
2960       case ACCESSOR: {
2961 #ifdef DEBUG
2962         HeapType* new_type = new_descriptors->GetFieldType(i);
2963         DCHECK(HeapType::Any()->Is(new_type));
2964 #endif
2965         break;
2966       }
2967
2968       case DATA_CONSTANT:
2969       case ACCESSOR_CONSTANT: {
2970         Object* old_value = old_descriptors->GetValue(i);
2971         Object* new_value = new_descriptors->GetValue(i);
2972         if (old_details.location() == kField || old_value != new_value) {
2973           return MaybeHandle<Map>();
2974         }
2975         break;
2976       }
2977     }
2978   }
2979   if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
2980   return handle(new_map);
2981 }
2982
2983
2984 // static
2985 Handle<Map> Map::Update(Handle<Map> map) {
2986   if (!map->is_deprecated()) return map;
2987   return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
2988                              HeapType::None(map->GetIsolate()),
2989                              ALLOW_IN_DESCRIPTOR);
2990 }
2991
2992
2993 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
2994                                                          Handle<Object> value) {
2995   Isolate* isolate = it->isolate();
2996   // Make sure that the top context does not change when doing callbacks or
2997   // interceptor calls.
2998   AssertNoContextChange ncc(isolate);
2999
3000   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
3001   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
3002   if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>();
3003
3004   Handle<JSObject> holder = it->GetHolder<JSObject>();
3005   v8::Local<v8::Value> result;
3006   PropertyCallbackArguments args(isolate, interceptor->data(),
3007                                  *it->GetReceiver(), *holder);
3008
3009   if (it->IsElement()) {
3010     uint32_t index = it->index();
3011     v8::IndexedPropertySetterCallback setter =
3012         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
3013     LOG(isolate,
3014         ApiIndexedPropertyAccess("interceptor-indexed-set", *holder, index));
3015     result = args.Call(setter, index, v8::Utils::ToLocal(value));
3016   } else {
3017     Handle<Name> name = it->name();
3018
3019     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
3020       return MaybeHandle<Object>();
3021     }
3022
3023     v8::GenericNamedPropertySetterCallback setter =
3024         v8::ToCData<v8::GenericNamedPropertySetterCallback>(
3025             interceptor->setter());
3026     LOG(it->isolate(),
3027         ApiNamedPropertyAccess("interceptor-named-set", *holder, *name));
3028     result =
3029         args.Call(setter, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
3030   }
3031
3032   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
3033   if (result.IsEmpty()) return MaybeHandle<Object>();
3034 #ifdef DEBUG
3035   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
3036   result_internal->VerifyApiCallResultType();
3037 #endif
3038   return value;
3039 }
3040
3041
3042 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
3043                                         Handle<Name> name, Handle<Object> value,
3044                                         LanguageMode language_mode,
3045                                         StoreFromKeyed store_mode) {
3046   LookupIterator it(object, name);
3047   return SetProperty(&it, value, language_mode, store_mode);
3048 }
3049
3050
3051 MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
3052                                                 Handle<Object> value,
3053                                                 LanguageMode language_mode,
3054                                                 StoreFromKeyed store_mode,
3055                                                 bool* found) {
3056   // Make sure that the top context does not change when doing callbacks or
3057   // interceptor calls.
3058   AssertNoContextChange ncc(it->isolate());
3059
3060   *found = true;
3061
3062   bool done = false;
3063   for (; it->IsFound(); it->Next()) {
3064     switch (it->state()) {
3065       case LookupIterator::NOT_FOUND:
3066         UNREACHABLE();
3067
3068       case LookupIterator::ACCESS_CHECK:
3069         if (it->HasAccess()) break;
3070         // Check whether it makes sense to reuse the lookup iterator. Here it
3071         // might still call into setters up the prototype chain.
3072         return JSObject::SetPropertyWithFailedAccessCheck(it, value);
3073
3074       case LookupIterator::JSPROXY:
3075         if (it->HolderIsReceiverOrHiddenPrototype()) {
3076           return JSProxy::SetPropertyWithHandler(
3077               it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(), value,
3078               language_mode);
3079         } else {
3080           // TODO(verwaest): Use the MaybeHandle to indicate result.
3081           bool has_result = false;
3082           MaybeHandle<Object> maybe_result =
3083               JSProxy::SetPropertyViaPrototypesWithHandler(
3084                   it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName(),
3085                   value, language_mode, &has_result);
3086           if (has_result) return maybe_result;
3087           done = true;
3088         }
3089         break;
3090
3091       case LookupIterator::INTERCEPTOR:
3092         if (it->HolderIsReceiverOrHiddenPrototype()) {
3093           MaybeHandle<Object> maybe_result =
3094               JSObject::SetPropertyWithInterceptor(it, value);
3095           if (!maybe_result.is_null()) return maybe_result;
3096           if (it->isolate()->has_pending_exception()) return maybe_result;
3097         } else {
3098           Maybe<PropertyAttributes> maybe_attributes =
3099               JSObject::GetPropertyAttributesWithInterceptor(it);
3100           if (!maybe_attributes.IsJust()) return MaybeHandle<Object>();
3101           done = maybe_attributes.FromJust() != ABSENT;
3102           if (done && (maybe_attributes.FromJust() & READ_ONLY) != 0) {
3103             return WriteToReadOnlyProperty(it, value, language_mode);
3104           }
3105         }
3106         break;
3107
3108       case LookupIterator::ACCESSOR: {
3109         if (it->IsReadOnly()) {
3110           return WriteToReadOnlyProperty(it, value, language_mode);
3111         }
3112         Handle<Object> accessors = it->GetAccessors();
3113         if (accessors->IsAccessorInfo() &&
3114             !it->HolderIsReceiverOrHiddenPrototype() &&
3115             AccessorInfo::cast(*accessors)->is_special_data_property()) {
3116           done = true;
3117           break;
3118         }
3119         return SetPropertyWithAccessor(it, value, language_mode);
3120       }
3121       case LookupIterator::INTEGER_INDEXED_EXOTIC:
3122         // TODO(verwaest): We should throw an exception.
3123         return value;
3124
3125       case LookupIterator::DATA:
3126         if (it->IsReadOnly()) {
3127           return WriteToReadOnlyProperty(it, value, language_mode);
3128         }
3129         if (it->HolderIsReceiverOrHiddenPrototype()) {
3130           return SetDataProperty(it, value);
3131         }
3132         done = true;
3133         break;
3134
3135       case LookupIterator::TRANSITION:
3136         done = true;
3137         break;
3138     }
3139
3140     if (done) break;
3141   }
3142
3143   // If the receiver is the JSGlobalObject, the store was contextual. In case
3144   // the property did not exist yet on the global object itself, we have to
3145   // throw a reference error in strict mode.
3146   if (it->GetReceiver()->IsJSGlobalObject() && is_strict(language_mode)) {
3147     THROW_NEW_ERROR(it->isolate(),
3148                     NewReferenceError(MessageTemplate::kNotDefined, it->name()),
3149                     Object);
3150   }
3151
3152   *found = false;
3153   return MaybeHandle<Object>();
3154 }
3155
3156
3157 MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
3158                                         Handle<Object> value,
3159                                         LanguageMode language_mode,
3160                                         StoreFromKeyed store_mode) {
3161   bool found = false;
3162   MaybeHandle<Object> result =
3163       SetPropertyInternal(it, value, language_mode, store_mode, &found);
3164   if (found) return result;
3165   return AddDataProperty(it, value, NONE, language_mode, store_mode);
3166 }
3167
3168
3169 MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
3170                                              Handle<Object> value,
3171                                              LanguageMode language_mode,
3172                                              StoreFromKeyed store_mode) {
3173   bool found = false;
3174   MaybeHandle<Object> result =
3175       SetPropertyInternal(it, value, language_mode, store_mode, &found);
3176   if (found) return result;
3177
3178   if (!it->GetReceiver()->IsJSReceiver()) {
3179     return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
3180                                    it->GetName(), value, language_mode);
3181   }
3182
3183   LookupIterator::Configuration c = LookupIterator::OWN;
3184   LookupIterator own_lookup =
3185       it->IsElement()
3186           ? LookupIterator(it->isolate(), it->GetReceiver(), it->index(), c)
3187           : LookupIterator(it->GetReceiver(), it->name(), c);
3188
3189   for (; own_lookup.IsFound(); own_lookup.Next()) {
3190     switch (own_lookup.state()) {
3191       case LookupIterator::ACCESS_CHECK:
3192         if (!own_lookup.HasAccess()) {
3193           return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value);
3194         }
3195         break;
3196
3197       case LookupIterator::INTEGER_INDEXED_EXOTIC:
3198         return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
3199                                                value, language_mode);
3200
3201       case LookupIterator::DATA: {
3202         PropertyDetails details = own_lookup.property_details();
3203         if (details.IsConfigurable() || !details.IsReadOnly()) {
3204           return JSObject::DefineOwnPropertyIgnoreAttributes(
3205               &own_lookup, value, details.attributes());
3206         }
3207         return WriteToReadOnlyProperty(&own_lookup, value, language_mode);
3208       }
3209
3210       case LookupIterator::ACCESSOR: {
3211         PropertyDetails details = own_lookup.property_details();
3212         if (details.IsConfigurable()) {
3213           return JSObject::DefineOwnPropertyIgnoreAttributes(
3214               &own_lookup, value, details.attributes());
3215         }
3216
3217         return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
3218                                                value, language_mode);
3219       }
3220
3221       case LookupIterator::INTERCEPTOR:
3222       case LookupIterator::JSPROXY: {
3223         bool found = false;
3224         MaybeHandle<Object> result = SetPropertyInternal(
3225             &own_lookup, value, language_mode, store_mode, &found);
3226         if (found) return result;
3227         break;
3228       }
3229
3230       case LookupIterator::NOT_FOUND:
3231       case LookupIterator::TRANSITION:
3232         UNREACHABLE();
3233     }
3234   }
3235
3236   return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
3237                                    store_mode);
3238 }
3239
3240
3241 MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it,
3242                                                LanguageMode language_mode) {
3243   if (is_strong(language_mode)) {
3244     THROW_NEW_ERROR(it->isolate(),
3245                     NewTypeError(MessageTemplate::kStrongPropertyAccess,
3246                                  it->GetName(), it->GetReceiver()),
3247                     Object);
3248   }
3249   return it->isolate()->factory()->undefined_value();
3250 }
3251
3252 MaybeHandle<Object> Object::ReadAbsentProperty(Isolate* isolate,
3253                                                Handle<Object> receiver,
3254                                                Handle<Object> name,
3255                                                LanguageMode language_mode) {
3256   if (is_strong(language_mode)) {
3257     THROW_NEW_ERROR(
3258         isolate,
3259         NewTypeError(MessageTemplate::kStrongPropertyAccess, name, receiver),
3260         Object);
3261   }
3262   return isolate->factory()->undefined_value();
3263 }
3264
3265
3266 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3267     LookupIterator* it, Handle<Object> value, LanguageMode language_mode) {
3268   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
3269                                  it->GetName(), value, language_mode);
3270 }
3271
3272
3273 MaybeHandle<Object> Object::WriteToReadOnlyProperty(
3274     Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
3275     Handle<Object> value, LanguageMode language_mode) {
3276   if (is_sloppy(language_mode)) return value;
3277   THROW_NEW_ERROR(
3278       isolate,
3279       NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name, receiver),
3280       Object);
3281 }
3282
3283
3284 MaybeHandle<Object> Object::RedefineNonconfigurableProperty(
3285     Isolate* isolate, Handle<Object> name, Handle<Object> value,
3286     LanguageMode language_mode) {
3287   if (is_sloppy(language_mode)) return value;
3288   THROW_NEW_ERROR(isolate,
3289                   NewTypeError(MessageTemplate::kRedefineDisallowed, name),
3290                   Object);
3291 }
3292
3293
3294 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
3295                                             Handle<Object> value) {
3296   // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3297   // have own properties.
3298   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3299
3300   // Store on the holder which may be hidden behind the receiver.
3301   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
3302
3303   // Old value for the observation change record.
3304   // Fetch before transforming the object since the encoding may become
3305   // incompatible with what's cached in |it|.
3306   bool is_observed = receiver->map()->is_observed() &&
3307                      (it->IsElement() ||
3308                       !it->isolate()->IsInternallyUsedPropertyName(it->name()));
3309   MaybeHandle<Object> maybe_old;
3310   if (is_observed) maybe_old = it->GetDataValue();
3311
3312   Handle<Object> to_assign = value;
3313   // Convert the incoming value to a number for storing into typed arrays.
3314   if (it->IsElement() && (receiver->HasExternalArrayElements() ||
3315                           receiver->HasFixedTypedArrayElements())) {
3316     if (!value->IsNumber() && !value->IsUndefined()) {
3317       ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign,
3318                                  Execution::ToNumber(it->isolate(), value),
3319                                  Object);
3320       // ToNumber above might modify the receiver, causing the cached
3321       // holder_map to mismatch the actual holder->map() after this point.
3322       // Reload the map to be in consistent state. Other cached state cannot
3323       // have been invalidated since typed array elements cannot be reconfigured
3324       // in any way.
3325       it->ReloadHolderMap();
3326     }
3327   }
3328
3329   // Possibly migrate to the most up-to-date map that will be able to store
3330   // |value| under it->name().
3331   it->PrepareForDataProperty(to_assign);
3332
3333   // Write the property value.
3334   it->WriteDataValue(to_assign);
3335
3336   // Send the change record if there are observers.
3337   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
3338     RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord(
3339                                            receiver, "update", it->GetName(),
3340                                            maybe_old.ToHandleChecked()),
3341                         Object);
3342   }
3343
3344   return value;
3345 }
3346
3347
3348 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
3349     Handle<JSArray> object) {
3350   Isolate* isolate = object->GetIsolate();
3351   HandleScope scope(isolate);
3352   Handle<Object> args[] = {object};
3353
3354   return Execution::Call(
3355       isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
3356       isolate->factory()->undefined_value(), arraysize(args), args);
3357 }
3358
3359
3360 MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
3361     Handle<JSArray> object) {
3362   Isolate* isolate = object->GetIsolate();
3363   HandleScope scope(isolate);
3364   Handle<Object> args[] = {object};
3365
3366   return Execution::Call(
3367       isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
3368       isolate->factory()->undefined_value(), arraysize(args), args);
3369 }
3370
3371
3372 MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
3373     Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
3374     uint32_t add_count) {
3375   Isolate* isolate = object->GetIsolate();
3376   HandleScope scope(isolate);
3377   Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
3378   Handle<Object> add_count_object =
3379       isolate->factory()->NewNumberFromUint(add_count);
3380
3381   Handle<Object> args[] = {object, index_object, deleted, add_count_object};
3382
3383   return Execution::Call(
3384       isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
3385       isolate->factory()->undefined_value(), arraysize(args), args);
3386 }
3387
3388
3389 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3390                                             Handle<Object> value,
3391                                             PropertyAttributes attributes,
3392                                             LanguageMode language_mode,
3393                                             StoreFromKeyed store_mode) {
3394   DCHECK(!it->GetReceiver()->IsJSProxy());
3395   if (!it->GetReceiver()->IsJSObject()) {
3396     // TODO(verwaest): Throw a TypeError with a more specific message.
3397     return WriteToReadOnlyProperty(it, value, language_mode);
3398   }
3399
3400   DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
3401
3402   Handle<JSObject> receiver = it->GetStoreTarget();
3403
3404   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3405   // instead. If the prototype is Null, the proxy is detached.
3406   if (receiver->IsJSGlobalProxy()) return value;
3407
3408   Isolate* isolate = it->isolate();
3409
3410   if (!receiver->map()->is_extensible() &&
3411       (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) {
3412     if (is_sloppy(language_mode)) return value;
3413     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kObjectNotExtensible,
3414                                           it->GetName()),
3415                     Object);
3416   }
3417
3418   if (it->IsElement()) {
3419     if (receiver->IsJSArray()) {
3420       Handle<JSArray> array = Handle<JSArray>::cast(receiver);
3421       if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
3422         if (is_sloppy(language_mode)) return value;
3423         return JSArray::ReadOnlyLengthError(array);
3424       }
3425
3426       if (FLAG_trace_external_array_abuse &&
3427           (array->HasExternalArrayElements() ||
3428            array->HasFixedTypedArrayElements())) {
3429         CheckArrayAbuse(array, "typed elements write", it->index(), true);
3430       }
3431
3432       if (FLAG_trace_js_array_abuse && !array->HasExternalArrayElements() &&
3433           !array->HasFixedTypedArrayElements()) {
3434         CheckArrayAbuse(array, "elements write", it->index(), false);
3435       }
3436     }
3437
3438     MaybeHandle<Object> result =
3439         JSObject::AddDataElement(receiver, it->index(), value, attributes);
3440     JSObject::ValidateElements(receiver);
3441     return result;
3442   } else {
3443     // Migrate to the most up-to-date map that will be able to store |value|
3444     // under it->name() with |attributes|.
3445     it->PrepareTransitionToDataProperty(value, attributes, store_mode);
3446     DCHECK_EQ(LookupIterator::TRANSITION, it->state());
3447     it->ApplyTransitionToDataProperty();
3448
3449     // TODO(verwaest): Encapsulate dictionary handling better.
3450     if (receiver->map()->is_dictionary_map()) {
3451       // TODO(verwaest): Probably should ensure this is done beforehand.
3452       it->InternalizeName();
3453       // TODO(dcarney): just populate TransitionPropertyCell here?
3454       JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3455     } else {
3456       // Write the property value.
3457       it->WriteDataValue(value);
3458     }
3459
3460     // Send the change record if there are observers.
3461     if (receiver->map()->is_observed() &&
3462         !isolate->IsInternallyUsedPropertyName(it->name())) {
3463       RETURN_ON_EXCEPTION(isolate, JSObject::EnqueueChangeRecord(
3464                                        receiver, "add", it->name(),
3465                                        it->factory()->the_hole_value()),
3466                           Object);
3467     }
3468   }
3469
3470   return value;
3471 }
3472
3473
3474 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3475   // Only supports adding slack to owned descriptors.
3476   DCHECK(map->owns_descriptors());
3477
3478   Handle<DescriptorArray> descriptors(map->instance_descriptors());
3479   int old_size = map->NumberOfOwnDescriptors();
3480   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3481
3482   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3483       descriptors, old_size, slack);
3484
3485   DisallowHeapAllocation no_allocation;
3486   // The descriptors are still the same, so keep the layout descriptor.
3487   LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
3488
3489   if (old_size == 0) {
3490     map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3491     return;
3492   }
3493
3494   // If the source descriptors had an enum cache we copy it. This ensures
3495   // that the maps to which we push the new descriptor array back can rely
3496   // on a cache always being available once it is set. If the map has more
3497   // enumerated descriptors than available in the original cache, the cache
3498   // will be lazily replaced by the extended cache when needed.
3499   if (descriptors->HasEnumCache()) {
3500     new_descriptors->CopyEnumCacheFrom(*descriptors);
3501   }
3502
3503   // Replace descriptors by new_descriptors in all maps that share it.
3504   map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
3505
3506   Map* walk_map;
3507   for (Object* current = map->GetBackPointer();
3508        !current->IsUndefined();
3509        current = walk_map->GetBackPointer()) {
3510     walk_map = Map::cast(current);
3511     if (walk_map->instance_descriptors() != *descriptors) break;
3512     walk_map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3513   }
3514
3515   map->UpdateDescriptors(*new_descriptors, layout_descriptor);
3516 }
3517
3518
3519 template<class T>
3520 static int AppendUniqueCallbacks(NeanderArray* callbacks,
3521                                  Handle<typename T::Array> array,
3522                                  int valid_descriptors) {
3523   int nof_callbacks = callbacks->length();
3524
3525   Isolate* isolate = array->GetIsolate();
3526   // Ensure the keys are unique names before writing them into the
3527   // instance descriptor. Since it may cause a GC, it has to be done before we
3528   // temporarily put the heap in an invalid state while appending descriptors.
3529   for (int i = 0; i < nof_callbacks; ++i) {
3530     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3531     if (entry->name()->IsUniqueName()) continue;
3532     Handle<String> key =
3533         isolate->factory()->InternalizeString(
3534             Handle<String>(String::cast(entry->name())));
3535     entry->set_name(*key);
3536   }
3537
3538   // Fill in new callback descriptors.  Process the callbacks from
3539   // back to front so that the last callback with a given name takes
3540   // precedence over previously added callbacks with that name.
3541   for (int i = nof_callbacks - 1; i >= 0; i--) {
3542     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3543     Handle<Name> key(Name::cast(entry->name()));
3544     // Check if a descriptor with this name already exists before writing.
3545     if (!T::Contains(key, entry, valid_descriptors, array)) {
3546       T::Insert(key, entry, valid_descriptors, array);
3547       valid_descriptors++;
3548     }
3549   }
3550
3551   return valid_descriptors;
3552 }
3553
3554 struct DescriptorArrayAppender {
3555   typedef DescriptorArray Array;
3556   static bool Contains(Handle<Name> key,
3557                        Handle<AccessorInfo> entry,
3558                        int valid_descriptors,
3559                        Handle<DescriptorArray> array) {
3560     DisallowHeapAllocation no_gc;
3561     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
3562   }
3563   static void Insert(Handle<Name> key,
3564                      Handle<AccessorInfo> entry,
3565                      int valid_descriptors,
3566                      Handle<DescriptorArray> array) {
3567     DisallowHeapAllocation no_gc;
3568     AccessorConstantDescriptor desc(key, entry, entry->property_attributes());
3569     array->Append(&desc);
3570   }
3571 };
3572
3573
3574 struct FixedArrayAppender {
3575   typedef FixedArray Array;
3576   static bool Contains(Handle<Name> key,
3577                        Handle<AccessorInfo> entry,
3578                        int valid_descriptors,
3579                        Handle<FixedArray> array) {
3580     for (int i = 0; i < valid_descriptors; i++) {
3581       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
3582     }
3583     return false;
3584   }
3585   static void Insert(Handle<Name> key,
3586                      Handle<AccessorInfo> entry,
3587                      int valid_descriptors,
3588                      Handle<FixedArray> array) {
3589     DisallowHeapAllocation no_gc;
3590     array->set(valid_descriptors, *entry);
3591   }
3592 };
3593
3594
3595 void Map::AppendCallbackDescriptors(Handle<Map> map,
3596                                     Handle<Object> descriptors) {
3597   int nof = map->NumberOfOwnDescriptors();
3598   Handle<DescriptorArray> array(map->instance_descriptors());
3599   NeanderArray callbacks(descriptors);
3600   DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
3601   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3602   map->SetNumberOfOwnDescriptors(nof);
3603 }
3604
3605
3606 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
3607                                Handle<FixedArray> array,
3608                                int valid_descriptors) {
3609   NeanderArray callbacks(descriptors);
3610   DCHECK(array->length() >= callbacks.length() + valid_descriptors);
3611   return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3612                                                    array,
3613                                                    valid_descriptors);
3614 }
3615
3616
3617 static bool ContainsMap(MapHandleList* maps, Map* map) {
3618   DCHECK_NOT_NULL(map);
3619   for (int i = 0; i < maps->length(); ++i) {
3620     if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
3621   }
3622   return false;
3623 }
3624
3625
3626 Handle<Map> Map::FindTransitionedMap(Handle<Map> map,
3627                                      MapHandleList* candidates) {
3628   ElementsKind kind = map->elements_kind();
3629   bool packed = IsFastPackedElementsKind(kind);
3630
3631   Map* transition = nullptr;
3632   if (IsTransitionableFastElementsKind(kind)) {
3633     for (Map* current = map->ElementsTransitionMap();
3634          current != nullptr && current->has_fast_elements();
3635          current = current->ElementsTransitionMap()) {
3636       if (ContainsMap(candidates, current) &&
3637           (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
3638         transition = current;
3639         packed = packed && IsFastPackedElementsKind(current->elements_kind());
3640       }
3641     }
3642   }
3643   return transition == nullptr ? Handle<Map>() : handle(transition);
3644 }
3645
3646
3647 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
3648   Map* current_map = map;
3649
3650   // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
3651   // allows to change elements from arbitrary kind to any ExternalArray
3652   // elements kind. Satisfy its requirements, checking whether we already
3653   // have the cached transition.
3654   if (IsExternalArrayElementsKind(to_kind) &&
3655       !IsFixedTypedArrayElementsKind(map->elements_kind())) {
3656     Map* next_map = map->ElementsTransitionMap();
3657     if (next_map != NULL && next_map->elements_kind() == to_kind) {
3658       return next_map;
3659     }
3660     return map;
3661   }
3662
3663   ElementsKind kind = map->elements_kind();
3664   while (kind != to_kind) {
3665     Map* next_map = current_map->ElementsTransitionMap();
3666     if (next_map == nullptr) return current_map;
3667     kind = next_map->elements_kind();
3668     current_map = next_map;
3669   }
3670
3671   DCHECK_EQ(to_kind, current_map->elements_kind());
3672   return current_map;
3673 }
3674
3675
3676 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3677   Map* to_map = FindClosestElementsTransition(this, to_kind);
3678   if (to_map->elements_kind() == to_kind) return to_map;
3679   return nullptr;
3680 }
3681
3682
3683 bool Map::IsMapInArrayPrototypeChain() {
3684   Isolate* isolate = GetIsolate();
3685   if (isolate->initial_array_prototype()->map() == this) {
3686     return true;
3687   }
3688
3689   if (isolate->initial_object_prototype()->map() == this) {
3690     return true;
3691   }
3692
3693   return false;
3694 }
3695
3696
3697 Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
3698   Isolate* isolate = map->GetIsolate();
3699   if (map->weak_cell_cache()->IsWeakCell()) {
3700     return Handle<WeakCell>(WeakCell::cast(map->weak_cell_cache()));
3701   }
3702   Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
3703   map->set_weak_cell_cache(*weak_cell);
3704   return weak_cell;
3705 }
3706
3707
3708 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
3709                                                  ElementsKind to_kind) {
3710   DCHECK(IsTransitionElementsKind(map->elements_kind()));
3711
3712   Handle<Map> current_map = map;
3713
3714   ElementsKind kind = map->elements_kind();
3715   TransitionFlag flag;
3716   if (map->is_prototype_map()) {
3717     flag = OMIT_TRANSITION;
3718   } else {
3719     flag = INSERT_TRANSITION;
3720     if (IsFastElementsKind(kind)) {
3721       while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3722         kind = GetNextTransitionElementsKind(kind);
3723         current_map = Map::CopyAsElementsKind(current_map, kind, flag);
3724       }
3725     }
3726   }
3727
3728   // In case we are exiting the fast elements kind system, just add the map in
3729   // the end.
3730   if (kind != to_kind) {
3731     current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
3732   }
3733
3734   DCHECK(current_map->elements_kind() == to_kind);
3735   return current_map;
3736 }
3737
3738
3739 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
3740                                       ElementsKind to_kind) {
3741   ElementsKind from_kind = map->elements_kind();
3742   if (from_kind == to_kind) return map;
3743
3744   Isolate* isolate = map->GetIsolate();
3745   Context* native_context = isolate->context()->native_context();
3746   if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
3747     if (*map == native_context->fast_aliased_arguments_map()) {
3748       DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
3749       return handle(native_context->slow_aliased_arguments_map());
3750     }
3751   } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
3752     if (*map == native_context->slow_aliased_arguments_map()) {
3753       DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
3754       return handle(native_context->fast_aliased_arguments_map());
3755     }
3756   } else {
3757     Object* maybe_array_maps = map->is_strong()
3758                                    ? native_context->js_array_strong_maps()
3759                                    : native_context->js_array_maps();
3760     if (maybe_array_maps->IsFixedArray()) {
3761       DisallowHeapAllocation no_gc;
3762       FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
3763       if (array_maps->get(from_kind) == *map) {
3764         Object* maybe_transitioned_map = array_maps->get(to_kind);
3765         if (maybe_transitioned_map->IsMap()) {
3766           return handle(Map::cast(maybe_transitioned_map));
3767         }
3768       }
3769     }
3770   }
3771
3772   DCHECK(!map->IsUndefined());
3773   bool allow_store_transition = IsTransitionElementsKind(from_kind);
3774   // Only store fast element maps in ascending generality.
3775   if (IsFastElementsKind(to_kind)) {
3776     allow_store_transition =
3777         allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
3778         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3779   }
3780
3781   if (!allow_store_transition) {
3782     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
3783   }
3784
3785   return Map::AsElementsKind(map, to_kind);
3786 }
3787
3788
3789 // static
3790 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
3791   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
3792
3793   if (closest_map->elements_kind() == kind) {
3794     return closest_map;
3795   }
3796
3797   return AddMissingElementsTransitions(closest_map, kind);
3798 }
3799
3800
3801 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
3802                                                ElementsKind to_kind) {
3803   Handle<Map> map(object->map());
3804   return Map::TransitionElementsTo(map, to_kind);
3805 }
3806
3807
3808 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy,
3809                                             Handle<Name> name) {
3810   Isolate* isolate = proxy->GetIsolate();
3811
3812   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3813   if (name->IsSymbol()) return Just(false);
3814
3815   Handle<Object> args[] = { name };
3816   Handle<Object> result;
3817   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3818       isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(),
3819                                 arraysize(args), args),
3820       Nothing<bool>());
3821
3822   return Just(result->BooleanValue());
3823 }
3824
3825
3826 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(
3827     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3828     Handle<Object> value, LanguageMode language_mode) {
3829   Isolate* isolate = proxy->GetIsolate();
3830
3831   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3832   if (name->IsSymbol()) return value;
3833
3834   Handle<Object> args[] = { receiver, name, value };
3835   RETURN_ON_EXCEPTION(
3836       isolate,
3837       CallTrap(proxy,
3838                "set",
3839                isolate->derived_set_trap(),
3840                arraysize(args),
3841                args),
3842       Object);
3843
3844   return value;
3845 }
3846
3847
3848 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3849     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3850     Handle<Object> value, LanguageMode language_mode, bool* done) {
3851   Isolate* isolate = proxy->GetIsolate();
3852   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy.
3853
3854   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3855   if (name->IsSymbol()) {
3856     *done = false;
3857     return isolate->factory()->the_hole_value();
3858   }
3859
3860   *done = true;  // except where redefined...
3861   Handle<Object> args[] = { name };
3862   Handle<Object> result;
3863   ASSIGN_RETURN_ON_EXCEPTION(
3864       isolate, result,
3865       CallTrap(proxy,
3866                "getPropertyDescriptor",
3867                Handle<Object>(),
3868                arraysize(args),
3869                args),
3870       Object);
3871
3872   if (result->IsUndefined()) {
3873     *done = false;
3874     return isolate->factory()->the_hole_value();
3875   }
3876
3877   // Emulate [[GetProperty]] semantics for proxies.
3878   Handle<Object> argv[] = { result };
3879   Handle<Object> desc;
3880   ASSIGN_RETURN_ON_EXCEPTION(
3881       isolate, desc,
3882       Execution::Call(isolate,
3883                       isolate->to_complete_property_descriptor(),
3884                       result,
3885                       arraysize(argv),
3886                       argv),
3887       Object);
3888
3889   // [[GetProperty]] requires to check that all properties are configurable.
3890   Handle<String> configurable_name =
3891       isolate->factory()->InternalizeOneByteString(
3892           STATIC_CHAR_VECTOR("configurable_"));
3893   Handle<Object> configurable =
3894       Object::GetProperty(desc, configurable_name).ToHandleChecked();
3895   DCHECK(configurable->IsBoolean());
3896   if (configurable->IsFalse()) {
3897     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3898         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3899     THROW_NEW_ERROR(isolate,
3900                     NewTypeError(MessageTemplate::kProxyPropNotConfigurable,
3901                                  handler, name, trap),
3902                     Object);
3903   }
3904   DCHECK(configurable->IsTrue());
3905
3906   // Check for DataDescriptor.
3907   Handle<String> hasWritable_name =
3908       isolate->factory()->InternalizeOneByteString(
3909           STATIC_CHAR_VECTOR("hasWritable_"));
3910   Handle<Object> hasWritable =
3911       Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
3912   DCHECK(hasWritable->IsBoolean());
3913   if (hasWritable->IsTrue()) {
3914     Handle<String> writable_name = isolate->factory()->InternalizeOneByteString(
3915         STATIC_CHAR_VECTOR("writable_"));
3916     Handle<Object> writable =
3917         Object::GetProperty(desc, writable_name).ToHandleChecked();
3918     DCHECK(writable->IsBoolean());
3919     *done = writable->IsFalse();
3920     if (!*done) return isolate->factory()->the_hole_value();
3921     return WriteToReadOnlyProperty(isolate, receiver, name, value,
3922                                    language_mode);
3923   }
3924
3925   // We have an AccessorDescriptor.
3926   Handle<String> set_name =
3927       isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_"));
3928   Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
3929   if (!setter->IsUndefined()) {
3930     // TODO(rossberg): nicer would be to cast to some JSCallable here...
3931     return SetPropertyWithDefinedSetter(
3932         receiver, Handle<JSReceiver>::cast(setter), value);
3933   }
3934
3935   if (is_sloppy(language_mode)) return value;
3936   THROW_NEW_ERROR(
3937       isolate, NewTypeError(MessageTemplate::kNoSetterInCallback, name, proxy),
3938       Object);
3939 }
3940
3941
3942 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
3943     Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode) {
3944   Isolate* isolate = proxy->GetIsolate();
3945
3946   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3947   if (name->IsSymbol()) return isolate->factory()->false_value();
3948
3949   Handle<Object> args[] = { name };
3950   Handle<Object> result;
3951   ASSIGN_RETURN_ON_EXCEPTION(
3952       isolate, result,
3953       CallTrap(proxy,
3954                "delete",
3955                Handle<Object>(),
3956                arraysize(args),
3957                args),
3958       Object);
3959
3960   bool result_bool = result->BooleanValue();
3961   if (is_strict(language_mode) && !result_bool) {
3962     Handle<Object> handler(proxy->handler(), isolate);
3963     THROW_NEW_ERROR(
3964         isolate,
3965         NewTypeError(MessageTemplate::kProxyHandlerDeleteFailed, handler),
3966         Object);
3967   }
3968   return isolate->factory()->ToBoolean(result_bool);
3969 }
3970
3971
3972 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
3973     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
3974   Isolate* isolate = proxy->GetIsolate();
3975   HandleScope scope(isolate);
3976
3977   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3978   if (name->IsSymbol()) return Just(ABSENT);
3979
3980   Handle<Object> args[] = { name };
3981   Handle<Object> result;
3982   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3983       isolate, result, proxy->CallTrap(proxy, "getPropertyDescriptor",
3984                                        Handle<Object>(), arraysize(args), args),
3985       Nothing<PropertyAttributes>());
3986
3987   if (result->IsUndefined()) return Just(ABSENT);
3988
3989   Handle<Object> argv[] = { result };
3990   Handle<Object> desc;
3991   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3992       isolate, desc,
3993       Execution::Call(isolate, isolate->to_complete_property_descriptor(),
3994                       result, arraysize(argv), argv),
3995       Nothing<PropertyAttributes>());
3996
3997   // Convert result to PropertyAttributes.
3998   Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3999       STATIC_CHAR_VECTOR("enumerable_"));
4000   Handle<Object> enumerable;
4001   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable,
4002                                    Object::GetProperty(desc, enum_n),
4003                                    Nothing<PropertyAttributes>());
4004   Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
4005       STATIC_CHAR_VECTOR("configurable_"));
4006   Handle<Object> configurable;
4007   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
4008                                    Object::GetProperty(desc, conf_n),
4009                                    Nothing<PropertyAttributes>());
4010   Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
4011       STATIC_CHAR_VECTOR("writable_"));
4012   Handle<Object> writable;
4013   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
4014                                    Object::GetProperty(desc, writ_n),
4015                                    Nothing<PropertyAttributes>());
4016   if (!writable->BooleanValue()) {
4017     Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
4018         STATIC_CHAR_VECTOR("set_"));
4019     Handle<Object> setter;
4020     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
4021                                      Object::GetProperty(desc, set_n),
4022                                      Nothing<PropertyAttributes>());
4023     writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
4024   }
4025
4026   if (configurable->IsFalse()) {
4027     Handle<Object> handler(proxy->handler(), isolate);
4028     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
4029         STATIC_CHAR_VECTOR("getPropertyDescriptor"));
4030     Handle<Object> error = isolate->factory()->NewTypeError(
4031         MessageTemplate::kProxyPropNotConfigurable, handler, name, trap);
4032     isolate->Throw(*error);
4033     return Nothing<PropertyAttributes>();
4034   }
4035
4036   int attributes = NONE;
4037   if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
4038   if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
4039   if (!writable->BooleanValue()) attributes |= READ_ONLY;
4040   return Just(static_cast<PropertyAttributes>(attributes));
4041 }
4042
4043
4044 void JSProxy::Fix(Handle<JSProxy> proxy) {
4045   Isolate* isolate = proxy->GetIsolate();
4046
4047   // Save identity hash.
4048   Handle<Object> hash(proxy->GetIdentityHash(), isolate);
4049
4050   if (proxy->IsJSFunctionProxy()) {
4051     isolate->factory()->BecomeJSFunction(proxy);
4052     // Code will be set on the JavaScript side.
4053   } else {
4054     isolate->factory()->BecomeJSObject(proxy);
4055   }
4056   DCHECK(proxy->IsJSObject());
4057
4058   // Inherit identity, if it was present.
4059   if (hash->IsSmi()) {
4060     JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
4061                               Handle<Smi>::cast(hash));
4062   }
4063 }
4064
4065
4066 MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
4067                                       const char* name,
4068                                       Handle<Object> derived,
4069                                       int argc,
4070                                       Handle<Object> argv[]) {
4071   Isolate* isolate = proxy->GetIsolate();
4072   Handle<Object> handler(proxy->handler(), isolate);
4073
4074   Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
4075   Handle<Object> trap;
4076   ASSIGN_RETURN_ON_EXCEPTION(
4077       isolate, trap,
4078       Object::GetPropertyOrElement(handler, trap_name),
4079       Object);
4080
4081   if (trap->IsUndefined()) {
4082     if (derived.is_null()) {
4083       THROW_NEW_ERROR(isolate,
4084                       NewTypeError(MessageTemplate::kProxyHandlerTrapMissing,
4085                                    handler, trap_name),
4086                       Object);
4087     }
4088     trap = Handle<Object>(derived);
4089   }
4090
4091   return Execution::Call(isolate, trap, handler, argc, argv);
4092 }
4093
4094
4095 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
4096   DCHECK(object->map()->inobject_properties() == map->inobject_properties());
4097   ElementsKind obj_kind = object->map()->elements_kind();
4098   ElementsKind map_kind = map->elements_kind();
4099   if (map_kind != obj_kind) {
4100     ElementsKind to_kind = map_kind;
4101     if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
4102         IsDictionaryElementsKind(obj_kind)) {
4103       to_kind = obj_kind;
4104     }
4105     if (IsDictionaryElementsKind(to_kind)) {
4106       NormalizeElements(object);
4107     } else {
4108       TransitionElementsKind(object, to_kind);
4109     }
4110     map = Map::AsElementsKind(map, to_kind);
4111   }
4112   JSObject::MigrateToMap(object, map);
4113 }
4114
4115
4116 void JSObject::MigrateInstance(Handle<JSObject> object) {
4117   Handle<Map> original_map(object->map());
4118   Handle<Map> map = Map::Update(original_map);
4119   map->set_migration_target(true);
4120   MigrateToMap(object, map);
4121   if (FLAG_trace_migration) {
4122     object->PrintInstanceMigration(stdout, *original_map, *map);
4123   }
4124 }
4125
4126
4127 // static
4128 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
4129   Isolate* isolate = object->GetIsolate();
4130   DisallowDeoptimization no_deoptimization(isolate);
4131   Handle<Map> original_map(object->map(), isolate);
4132   Handle<Map> new_map;
4133   if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
4134     return false;
4135   }
4136   JSObject::MigrateToMap(object, new_map);
4137   if (FLAG_trace_migration) {
4138     object->PrintInstanceMigration(stdout, *original_map, object->map());
4139   }
4140   return true;
4141 }
4142
4143
4144 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
4145                            Handle<Object> value,
4146                            PropertyAttributes attributes) {
4147   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
4148   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
4149 #ifdef DEBUG
4150   uint32_t index;
4151   DCHECK(!object->IsJSProxy());
4152   DCHECK(!name->AsArrayIndex(&index));
4153   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
4154   DCHECK(maybe.IsJust());
4155   DCHECK(!it.IsFound());
4156   DCHECK(object->map()->is_extensible() ||
4157          it.isolate()->IsInternallyUsedPropertyName(name));
4158 #endif
4159   AddDataProperty(&it, value, attributes, STRICT,
4160                   CERTAINLY_NOT_STORE_FROM_KEYED).Check();
4161 }
4162
4163
4164 // static
4165 void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) {
4166   Handle<Object> object = v8::FromCData(info->GetIsolate(), nullptr);
4167   info->set_setter(*object);
4168 }
4169
4170
4171 // Reconfigures a property to a data property with attributes, even if it is not
4172 // reconfigurable.
4173 // Requires a LookupIterator that does not look at the prototype chain beyond
4174 // hidden prototypes.
4175 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
4176     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
4177     ExecutableAccessorInfoHandling handling) {
4178   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
4179   bool is_observed = object->map()->is_observed() &&
4180                      (it->IsElement() ||
4181                       !it->isolate()->IsInternallyUsedPropertyName(it->name()));
4182
4183   for (; it->IsFound(); it->Next()) {
4184     switch (it->state()) {
4185       case LookupIterator::JSPROXY:
4186       case LookupIterator::NOT_FOUND:
4187       case LookupIterator::TRANSITION:
4188         UNREACHABLE();
4189
4190       case LookupIterator::ACCESS_CHECK:
4191         if (!it->HasAccess()) {
4192           return SetPropertyWithFailedAccessCheck(it, value);
4193         }
4194         break;
4195
4196       // If there's an interceptor, try to store the property with the
4197       // interceptor.
4198       // In case of success, the attributes will have been reset to the default
4199       // attributes of the interceptor, rather than the incoming attributes.
4200       //
4201       // TODO(verwaest): JSProxy afterwards verify the attributes that the
4202       // JSProxy claims it has, and verifies that they are compatible. If not,
4203       // they throw. Here we should do the same.
4204       case LookupIterator::INTERCEPTOR:
4205         if (handling == DONT_FORCE_FIELD) {
4206           MaybeHandle<Object> maybe_result =
4207               JSObject::SetPropertyWithInterceptor(it, value);
4208           if (!maybe_result.is_null()) return maybe_result;
4209           if (it->isolate()->has_pending_exception()) return maybe_result;
4210         }
4211         break;
4212
4213       case LookupIterator::ACCESSOR: {
4214         Handle<Object> accessors = it->GetAccessors();
4215
4216         // Special handling for ExecutableAccessorInfo, which behaves like a
4217         // data property.
4218         if (accessors->IsExecutableAccessorInfo() &&
4219             handling == DONT_FORCE_FIELD) {
4220           PropertyDetails details = it->property_details();
4221           // Ensure the context isn't changed after calling into accessors.
4222           AssertNoContextChange ncc(it->isolate());
4223
4224           Handle<Object> result;
4225           ASSIGN_RETURN_ON_EXCEPTION(
4226               it->isolate(), result,
4227               JSObject::SetPropertyWithAccessor(it, value, STRICT), Object);
4228           DCHECK(result->SameValue(*value));
4229
4230           if (details.attributes() == attributes) return value;
4231
4232           // Reconfigure the accessor if attributes mismatch.
4233           Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
4234               it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
4235           new_data->set_property_attributes(attributes);
4236           // By clearing the setter we don't have to introduce a lookup to
4237           // the setter, simply make it unavailable to reflect the
4238           // attributes.
4239           if (attributes & READ_ONLY) {
4240             ExecutableAccessorInfo::ClearSetter(new_data);
4241           }
4242
4243           it->TransitionToAccessorPair(new_data, attributes);
4244         } else {
4245           it->ReconfigureDataProperty(value, attributes);
4246           it->WriteDataValue(value);
4247         }
4248
4249         if (is_observed) {
4250           RETURN_ON_EXCEPTION(
4251               it->isolate(),
4252               EnqueueChangeRecord(object, "reconfigure", it->GetName(),
4253                                   it->factory()->the_hole_value()),
4254               Object);
4255         }
4256
4257         return value;
4258       }
4259       case LookupIterator::INTEGER_INDEXED_EXOTIC:
4260         return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4261                                                value, STRICT);
4262
4263       case LookupIterator::DATA: {
4264         PropertyDetails details = it->property_details();
4265         Handle<Object> old_value = it->factory()->the_hole_value();
4266         // Regular property update if the attributes match.
4267         if (details.attributes() == attributes) {
4268           return SetDataProperty(it, value);
4269         }
4270
4271         // Special case: properties of typed arrays cannot be reconfigured to
4272         // non-writable nor to non-enumerable.
4273         if (it->IsElement() && (object->HasExternalArrayElements() ||
4274                                 object->HasFixedTypedArrayElements())) {
4275           return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
4276                                                  value, STRICT);
4277         }
4278
4279         // Reconfigure the data property if the attributes mismatch.
4280         if (is_observed) old_value = it->GetDataValue();
4281
4282         it->ReconfigureDataProperty(value, attributes);
4283         it->WriteDataValue(value);
4284
4285         if (is_observed) {
4286           if (old_value->SameValue(*value)) {
4287             old_value = it->factory()->the_hole_value();
4288           }
4289           RETURN_ON_EXCEPTION(it->isolate(),
4290                               EnqueueChangeRecord(object, "reconfigure",
4291                                                   it->GetName(), old_value),
4292                               Object);
4293         }
4294         return value;
4295       }
4296     }
4297   }
4298
4299   return AddDataProperty(it, value, attributes, STRICT,
4300                          CERTAINLY_NOT_STORE_FROM_KEYED);
4301 }
4302
4303
4304 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4305     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
4306     PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4307   DCHECK(!value->IsTheHole());
4308   LookupIterator it(object, name, LookupIterator::OWN);
4309   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4310 }
4311
4312
4313 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
4314     Handle<JSObject> object, uint32_t index, Handle<Object> value,
4315     PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4316   Isolate* isolate = object->GetIsolate();
4317   LookupIterator it(isolate, object, index, LookupIterator::OWN);
4318   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4319 }
4320
4321
4322 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
4323     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
4324     PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) {
4325   Isolate* isolate = object->GetIsolate();
4326   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
4327                                                         LookupIterator::OWN);
4328   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling);
4329 }
4330
4331
4332 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
4333                                          Handle<Object> value) {
4334   DCHECK(it->GetReceiver()->IsJSObject());
4335   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(it);
4336   if (maybe.IsNothing()) return Nothing<bool>();
4337
4338   if (it->IsFound()) {
4339     if (!it->IsConfigurable()) return Just(false);
4340   } else {
4341     if (!JSObject::cast(*it->GetReceiver())->IsExtensible()) return Just(false);
4342   }
4343
4344   RETURN_ON_EXCEPTION_VALUE(
4345       it->isolate(),
4346       DefineOwnPropertyIgnoreAttributes(it, value, NONE, DONT_FORCE_FIELD),
4347       Nothing<bool>());
4348
4349   return Just(true);
4350 }
4351
4352
4353 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4354     LookupIterator* it) {
4355   Isolate* isolate = it->isolate();
4356   // Make sure that the top context does not change when doing
4357   // callbacks or interceptor calls.
4358   AssertNoContextChange ncc(isolate);
4359   HandleScope scope(isolate);
4360
4361   Handle<JSObject> holder = it->GetHolder<JSObject>();
4362   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
4363   if (!it->IsElement() && it->name()->IsSymbol() &&
4364       !interceptor->can_intercept_symbols()) {
4365     return Just(ABSENT);
4366   }
4367   PropertyCallbackArguments args(isolate, interceptor->data(),
4368                                  *it->GetReceiver(), *holder);
4369   if (!interceptor->query()->IsUndefined()) {
4370     v8::Local<v8::Integer> result;
4371     if (it->IsElement()) {
4372       uint32_t index = it->index();
4373       v8::IndexedPropertyQueryCallback query =
4374           v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4375       LOG(isolate,
4376           ApiIndexedPropertyAccess("interceptor-indexed-has", *holder, index));
4377       result = args.Call(query, index);
4378     } else {
4379       Handle<Name> name = it->name();
4380       v8::GenericNamedPropertyQueryCallback query =
4381           v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
4382               interceptor->query());
4383       LOG(isolate,
4384           ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
4385       result = args.Call(query, v8::Utils::ToLocal(name));
4386     }
4387     if (!result.IsEmpty()) {
4388       DCHECK(result->IsInt32());
4389       return Just(static_cast<PropertyAttributes>(
4390           result->Int32Value(reinterpret_cast<v8::Isolate*>(isolate)
4391                                  ->GetCurrentContext()).FromJust()));
4392     }
4393   } else if (!interceptor->getter()->IsUndefined()) {
4394     // TODO(verwaest): Use GetPropertyWithInterceptor?
4395     v8::Local<v8::Value> result;
4396     if (it->IsElement()) {
4397       uint32_t index = it->index();
4398       v8::IndexedPropertyGetterCallback getter =
4399           v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4400       LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-get-has",
4401                                             *holder, index));
4402       result = args.Call(getter, index);
4403     } else {
4404       Handle<Name> name = it->name();
4405
4406       v8::GenericNamedPropertyGetterCallback getter =
4407           v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
4408               interceptor->getter());
4409       LOG(isolate,
4410           ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
4411       result = args.Call(getter, v8::Utils::ToLocal(name));
4412     }
4413     if (!result.IsEmpty()) return Just(DONT_ENUM);
4414   }
4415
4416   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
4417   return Just(ABSENT);
4418 }
4419
4420
4421 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
4422     LookupIterator* it) {
4423   for (; it->IsFound(); it->Next()) {
4424     switch (it->state()) {
4425       case LookupIterator::NOT_FOUND:
4426       case LookupIterator::TRANSITION:
4427         UNREACHABLE();
4428       case LookupIterator::JSPROXY:
4429         return JSProxy::GetPropertyAttributesWithHandler(
4430             it->GetHolder<JSProxy>(), it->GetReceiver(), it->GetName());
4431       case LookupIterator::INTERCEPTOR: {
4432         Maybe<PropertyAttributes> result =
4433             JSObject::GetPropertyAttributesWithInterceptor(it);
4434         if (!result.IsJust()) return result;
4435         if (result.FromJust() != ABSENT) return result;
4436         break;
4437       }
4438       case LookupIterator::ACCESS_CHECK:
4439         if (it->HasAccess()) break;
4440         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
4441       case LookupIterator::INTEGER_INDEXED_EXOTIC:
4442         return Just(ABSENT);
4443       case LookupIterator::ACCESSOR:
4444       case LookupIterator::DATA:
4445         return Just(it->property_details().attributes());
4446     }
4447   }
4448   return Just(ABSENT);
4449 }
4450
4451
4452 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
4453   Handle<FixedArray> array(
4454       isolate->factory()->NewFixedArray(kEntries, TENURED));
4455   return Handle<NormalizedMapCache>::cast(array);
4456 }
4457
4458
4459 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
4460                                          PropertyNormalizationMode mode) {
4461   DisallowHeapAllocation no_gc;
4462   Object* value = FixedArray::get(GetIndex(fast_map));
4463   if (!value->IsMap() ||
4464       !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4465     return MaybeHandle<Map>();
4466   }
4467   return handle(Map::cast(value));
4468 }
4469
4470
4471 void NormalizedMapCache::Set(Handle<Map> fast_map,
4472                              Handle<Map> normalized_map) {
4473   DisallowHeapAllocation no_gc;
4474   DCHECK(normalized_map->is_dictionary_map());
4475   FixedArray::set(GetIndex(fast_map), *normalized_map);
4476 }
4477
4478
4479 void NormalizedMapCache::Clear() {
4480   int entries = length();
4481   for (int i = 0; i != entries; i++) {
4482     set_undefined(i);
4483   }
4484 }
4485
4486
4487 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
4488                                     Handle<Name> name,
4489                                     Handle<Code> code) {
4490   Handle<Map> map(object->map());
4491   Map::UpdateCodeCache(map, name, code);
4492 }
4493
4494
4495 void JSObject::NormalizeProperties(Handle<JSObject> object,
4496                                    PropertyNormalizationMode mode,
4497                                    int expected_additional_properties,
4498                                    const char* reason) {
4499   if (!object->HasFastProperties()) return;
4500
4501   Handle<Map> map(object->map());
4502   Handle<Map> new_map = Map::Normalize(map, mode, reason);
4503
4504   MigrateToMap(object, new_map, expected_additional_properties);
4505 }
4506
4507
4508 void JSObject::MigrateFastToSlow(Handle<JSObject> object,
4509                                  Handle<Map> new_map,
4510                                  int expected_additional_properties) {
4511   // The global object is always normalized.
4512   DCHECK(!object->IsGlobalObject());
4513   // JSGlobalProxy must never be normalized
4514   DCHECK(!object->IsJSGlobalProxy());
4515
4516   Isolate* isolate = object->GetIsolate();
4517   HandleScope scope(isolate);
4518   Handle<Map> map(object->map());
4519
4520   // Allocate new content.
4521   int real_size = map->NumberOfOwnDescriptors();
4522   int property_count = real_size;
4523   if (expected_additional_properties > 0) {
4524     property_count += expected_additional_properties;
4525   } else {
4526     property_count += 2;  // Make space for two more properties.
4527   }
4528   Handle<NameDictionary> dictionary =
4529       NameDictionary::New(isolate, property_count);
4530
4531   Handle<DescriptorArray> descs(map->instance_descriptors());
4532   for (int i = 0; i < real_size; i++) {
4533     PropertyDetails details = descs->GetDetails(i);
4534     Handle<Name> key(descs->GetKey(i));
4535     switch (details.type()) {
4536       case DATA_CONSTANT: {
4537         Handle<Object> value(descs->GetConstant(i), isolate);
4538         PropertyDetails d(details.attributes(), DATA, i + 1,
4539                           PropertyCellType::kNoCell);
4540         dictionary = NameDictionary::Add(dictionary, key, value, d);
4541         break;
4542       }
4543       case DATA: {
4544         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4545         Handle<Object> value;
4546         if (object->IsUnboxedDoubleField(index)) {
4547           double old_value = object->RawFastDoublePropertyAt(index);
4548           value = isolate->factory()->NewHeapNumber(old_value);
4549         } else {
4550           value = handle(object->RawFastPropertyAt(index), isolate);
4551           if (details.representation().IsDouble()) {
4552             DCHECK(value->IsMutableHeapNumber());
4553             Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
4554             value = isolate->factory()->NewHeapNumber(old->value());
4555           }
4556         }
4557         PropertyDetails d(details.attributes(), DATA, i + 1,
4558                           PropertyCellType::kNoCell);
4559         dictionary = NameDictionary::Add(dictionary, key, value, d);
4560         break;
4561       }
4562       case ACCESSOR: {
4563         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4564         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
4565         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
4566                           PropertyCellType::kNoCell);
4567         dictionary = NameDictionary::Add(dictionary, key, value, d);
4568         break;
4569       }
4570       case ACCESSOR_CONSTANT: {
4571         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4572         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
4573                           PropertyCellType::kNoCell);
4574         dictionary = NameDictionary::Add(dictionary, key, value, d);
4575         break;
4576       }
4577     }
4578   }
4579
4580   // Copy the next enumeration index from instance descriptor.
4581   dictionary->SetNextEnumerationIndex(real_size + 1);
4582
4583   // From here on we cannot fail and we shouldn't GC anymore.
4584   DisallowHeapAllocation no_allocation;
4585
4586   // Resize the object in the heap if necessary.
4587   int new_instance_size = new_map->instance_size();
4588   int instance_size_delta = map->instance_size() - new_instance_size;
4589   DCHECK(instance_size_delta >= 0);
4590
4591   if (instance_size_delta > 0) {
4592     Heap* heap = isolate->heap();
4593     heap->CreateFillerObjectAt(object->address() + new_instance_size,
4594                                instance_size_delta);
4595     heap->AdjustLiveBytes(object->address(), -instance_size_delta,
4596                           Heap::CONCURRENT_TO_SWEEPER);
4597   }
4598
4599   // We are storing the new map using release store after creating a filler for
4600   // the left-over space to avoid races with the sweeper thread.
4601   object->synchronized_set_map(*new_map);
4602
4603   object->set_properties(*dictionary);
4604
4605   // Ensure that in-object space of slow-mode object does not contain random
4606   // garbage.
4607   int inobject_properties = new_map->inobject_properties();
4608   for (int i = 0; i < inobject_properties; i++) {
4609     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
4610     object->RawFastPropertyAtPut(index, Smi::FromInt(0));
4611   }
4612
4613   isolate->counters()->props_to_dictionary()->Increment();
4614
4615 #ifdef DEBUG
4616   if (FLAG_trace_normalization) {
4617     OFStream os(stdout);
4618     os << "Object properties have been normalized:\n";
4619     object->Print(os);
4620   }
4621 #endif
4622 }
4623
4624
4625 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
4626                                  int unused_property_fields,
4627                                  const char* reason) {
4628   if (object->HasFastProperties()) return;
4629   DCHECK(!object->IsGlobalObject());
4630   Isolate* isolate = object->GetIsolate();
4631   Factory* factory = isolate->factory();
4632   Handle<NameDictionary> dictionary(object->property_dictionary());
4633
4634   // Make sure we preserve dictionary representation if there are too many
4635   // descriptors.
4636   int number_of_elements = dictionary->NumberOfElements();
4637   if (number_of_elements > kMaxNumberOfDescriptors) return;
4638
4639   Handle<FixedArray> iteration_order;
4640   if (number_of_elements != dictionary->NextEnumerationIndex()) {
4641     iteration_order =
4642         NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
4643   } else {
4644     iteration_order = NameDictionary::BuildIterationIndicesArray(dictionary);
4645   }
4646
4647   int instance_descriptor_length = iteration_order->length();
4648   int number_of_fields = 0;
4649
4650   // Compute the length of the instance descriptor.
4651   for (int i = 0; i < instance_descriptor_length; i++) {
4652     int index = Smi::cast(iteration_order->get(i))->value();
4653     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
4654
4655     Object* value = dictionary->ValueAt(index);
4656     PropertyType type = dictionary->DetailsAt(index).type();
4657     if (type == DATA && !value->IsJSFunction()) {
4658       number_of_fields += 1;
4659     }
4660   }
4661
4662   int inobject_props = object->map()->inobject_properties();
4663
4664   // Allocate new map.
4665   Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
4666   new_map->set_dictionary_map(false);
4667
4668   if (object->map()->is_prototype_map()) {
4669     DCHECK(new_map->is_prototype_map());
4670     new_map->set_prototype_info(object->map()->prototype_info());
4671     object->map()->set_prototype_info(Smi::FromInt(0));
4672     if (FLAG_trace_prototype_users) {
4673       PrintF("Moving prototype_info %p from map %p to map %p.\n",
4674              reinterpret_cast<void*>(new_map->prototype_info()),
4675              reinterpret_cast<void*>(object->map()),
4676              reinterpret_cast<void*>(*new_map));
4677     }
4678   }
4679
4680 #if TRACE_MAPS
4681   if (FLAG_trace_maps) {
4682     PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
4683            reinterpret_cast<void*>(object->map()),
4684            reinterpret_cast<void*>(*new_map), reason);
4685   }
4686 #endif
4687
4688   if (instance_descriptor_length == 0) {
4689     DisallowHeapAllocation no_gc;
4690     DCHECK_LE(unused_property_fields, inobject_props);
4691     // Transform the object.
4692     new_map->set_unused_property_fields(inobject_props);
4693     object->synchronized_set_map(*new_map);
4694     object->set_properties(isolate->heap()->empty_fixed_array());
4695     // Check that it really works.
4696     DCHECK(object->HasFastProperties());
4697     return;
4698   }
4699
4700   // Allocate the instance descriptor.
4701   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
4702       isolate, instance_descriptor_length);
4703
4704   int number_of_allocated_fields =
4705       number_of_fields + unused_property_fields - inobject_props;
4706   if (number_of_allocated_fields < 0) {
4707     // There is enough inobject space for all fields (including unused).
4708     number_of_allocated_fields = 0;
4709     unused_property_fields = inobject_props - number_of_fields;
4710   }
4711
4712   // Allocate the fixed array for the fields.
4713   Handle<FixedArray> fields = factory->NewFixedArray(
4714       number_of_allocated_fields);
4715
4716   // Fill in the instance descriptor and the fields.
4717   int current_offset = 0;
4718   for (int i = 0; i < instance_descriptor_length; i++) {
4719     int index = Smi::cast(iteration_order->get(i))->value();
4720     Object* k = dictionary->KeyAt(index);
4721     DCHECK(dictionary->IsKey(k));
4722
4723     Object* value = dictionary->ValueAt(index);
4724     Handle<Name> key;
4725     if (k->IsSymbol()) {
4726       key = handle(Symbol::cast(k));
4727     } else {
4728       // Ensure the key is a unique name before writing into the
4729       // instance descriptor.
4730       key = factory->InternalizeString(handle(String::cast(k)));
4731     }
4732
4733     PropertyDetails details = dictionary->DetailsAt(index);
4734     int enumeration_index = details.dictionary_index();
4735     PropertyType type = details.type();
4736
4737     if (value->IsJSFunction()) {
4738       DataConstantDescriptor d(key, handle(value, isolate),
4739                                details.attributes());
4740       descriptors->Set(enumeration_index - 1, &d);
4741     } else if (type == DATA) {
4742       if (current_offset < inobject_props) {
4743         object->InObjectPropertyAtPut(current_offset, value,
4744                                       UPDATE_WRITE_BARRIER);
4745       } else {
4746         int offset = current_offset - inobject_props;
4747         fields->set(offset, value);
4748       }
4749       DataDescriptor d(key, current_offset, details.attributes(),
4750                        // TODO(verwaest): value->OptimalRepresentation();
4751                        Representation::Tagged());
4752       current_offset += d.GetDetails().field_width_in_words();
4753       descriptors->Set(enumeration_index - 1, &d);
4754     } else if (type == ACCESSOR_CONSTANT) {
4755       AccessorConstantDescriptor d(key, handle(value, isolate),
4756                                    details.attributes());
4757       descriptors->Set(enumeration_index - 1, &d);
4758     } else {
4759       UNREACHABLE();
4760     }
4761   }
4762   DCHECK(current_offset == number_of_fields);
4763
4764   descriptors->Sort();
4765
4766   Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
4767       new_map, descriptors, descriptors->number_of_descriptors());
4768
4769   DisallowHeapAllocation no_gc;
4770   new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
4771   new_map->set_unused_property_fields(unused_property_fields);
4772
4773   // Transform the object.
4774   object->synchronized_set_map(*new_map);
4775
4776   object->set_properties(*fields);
4777   DCHECK(object->IsJSObject());
4778
4779   // Check that it really works.
4780   DCHECK(object->HasFastProperties());
4781 }
4782
4783
4784 void JSObject::ResetElements(Handle<JSObject> object) {
4785   Isolate* isolate = object->GetIsolate();
4786   CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
4787   if (object->map()->has_dictionary_elements()) {
4788     Handle<SeededNumberDictionary> new_elements =
4789         SeededNumberDictionary::New(isolate, 0);
4790     object->set_elements(*new_elements);
4791   } else {
4792     object->set_elements(object->map()->GetInitialElements());
4793   }
4794 }
4795
4796
4797 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4798     Handle<FixedArrayBase> array,
4799     int length,
4800     Handle<SeededNumberDictionary> dictionary) {
4801   Isolate* isolate = array->GetIsolate();
4802   Factory* factory = isolate->factory();
4803   bool has_double_elements = array->IsFixedDoubleArray();
4804   for (int i = 0; i < length; i++) {
4805     Handle<Object> value;
4806     if (has_double_elements) {
4807       Handle<FixedDoubleArray> double_array =
4808           Handle<FixedDoubleArray>::cast(array);
4809       if (double_array->is_the_hole(i)) {
4810         value = factory->the_hole_value();
4811       } else {
4812         value = factory->NewHeapNumber(double_array->get_scalar(i));
4813       }
4814     } else {
4815       value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4816     }
4817     if (!value->IsTheHole()) {
4818       PropertyDetails details = PropertyDetails::Empty();
4819       dictionary =
4820           SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4821     }
4822   }
4823   return dictionary;
4824 }
4825
4826
4827 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
4828   if (dictionary->requires_slow_elements()) return;
4829   dictionary->set_requires_slow_elements();
4830   // TODO(verwaest): Remove this hack.
4831   if (map()->is_prototype_map()) {
4832     GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
4833   }
4834 }
4835
4836
4837 Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
4838     Handle<JSObject> object, Handle<FixedArrayBase> elements) {
4839   DCHECK(!object->HasDictionaryElements());
4840   DCHECK(!object->HasSlowArgumentsElements());
4841   Isolate* isolate = object->GetIsolate();
4842   // Ensure that notifications fire if the array or object prototypes are
4843   // normalizing.
4844   isolate->UpdateArrayProtectorOnNormalizeElements(object);
4845   int length = object->IsJSArray()
4846                    ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4847                    : elements->length();
4848   int used = object->GetFastElementsUsage();
4849   Handle<SeededNumberDictionary> dictionary =
4850       SeededNumberDictionary::New(isolate, used);
4851   return CopyFastElementsToDictionary(elements, length, dictionary);
4852 }
4853
4854
4855 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4856     Handle<JSObject> object) {
4857   DCHECK(!object->HasExternalArrayElements() &&
4858          !object->HasFixedTypedArrayElements());
4859   Isolate* isolate = object->GetIsolate();
4860
4861   // Find the backing store.
4862   Handle<FixedArrayBase> elements(object->elements(), isolate);
4863   bool is_arguments = object->HasSloppyArgumentsElements();
4864   if (is_arguments) {
4865     FixedArray* parameter_map = FixedArray::cast(*elements);
4866     elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate);
4867   }
4868
4869   if (elements->IsDictionary()) {
4870     return Handle<SeededNumberDictionary>::cast(elements);
4871   }
4872
4873   DCHECK(object->HasFastSmiOrObjectElements() ||
4874          object->HasFastDoubleElements() ||
4875          object->HasFastArgumentsElements());
4876
4877   Handle<SeededNumberDictionary> dictionary =
4878       GetNormalizedElementDictionary(object, elements);
4879
4880   // Switch to using the dictionary as the backing storage for elements.
4881   ElementsKind target_kind =
4882       is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS;
4883   Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
4884   // Set the new map first to satify the elements type assert in set_elements().
4885   JSObject::MigrateToMap(object, new_map);
4886
4887   if (is_arguments) {
4888     FixedArray::cast(object->elements())->set(1, *dictionary);
4889   } else {
4890     object->set_elements(*dictionary);
4891   }
4892
4893   isolate->counters()->elements_to_dictionary()->Increment();
4894
4895 #ifdef DEBUG
4896   if (FLAG_trace_normalization) {
4897     OFStream os(stdout);
4898     os << "Object elements have been normalized:\n";
4899     object->Print(os);
4900   }
4901 #endif
4902
4903   DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
4904   return dictionary;
4905 }
4906
4907
4908 static Smi* GenerateIdentityHash(Isolate* isolate) {
4909   int hash_value;
4910   int attempts = 0;
4911   do {
4912     // Generate a random 32-bit hash value but limit range to fit
4913     // within a smi.
4914     hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4915     attempts++;
4916   } while (hash_value == 0 && attempts < 30);
4917   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
4918
4919   return Smi::FromInt(hash_value);
4920 }
4921
4922
4923 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4924   DCHECK(!object->IsJSGlobalProxy());
4925   Isolate* isolate = object->GetIsolate();
4926   Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
4927   JSObject::AddProperty(object, hash_code_symbol, hash, NONE);
4928 }
4929
4930
4931 template<typename ProxyType>
4932 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
4933   Isolate* isolate = proxy->GetIsolate();
4934
4935   Handle<Object> maybe_hash(proxy->hash(), isolate);
4936   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4937
4938   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4939   proxy->set_hash(*hash);
4940   return hash;
4941 }
4942
4943
4944 Object* JSObject::GetIdentityHash() {
4945   DisallowHeapAllocation no_gc;
4946   Isolate* isolate = GetIsolate();
4947   if (IsJSGlobalProxy()) {
4948     return JSGlobalProxy::cast(this)->hash();
4949   }
4950   Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
4951   Handle<Object> stored_value =
4952       Object::GetPropertyOrElement(Handle<Object>(this, isolate),
4953                                    hash_code_symbol).ToHandleChecked();
4954   return stored_value->IsSmi() ? *stored_value
4955                                : isolate->heap()->undefined_value();
4956 }
4957
4958
4959 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
4960   if (object->IsJSGlobalProxy()) {
4961     return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
4962   }
4963
4964   Isolate* isolate = object->GetIsolate();
4965
4966   Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
4967   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4968
4969   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4970   Handle<Name> hash_code_symbol(isolate->heap()->hash_code_symbol());
4971   JSObject::AddProperty(object, hash_code_symbol, hash, NONE);
4972   return hash;
4973 }
4974
4975
4976 Object* JSProxy::GetIdentityHash() {
4977   return this->hash();
4978 }
4979
4980
4981 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
4982   return GetOrCreateIdentityHashHelper(proxy);
4983 }
4984
4985
4986 Object* JSObject::GetHiddenProperty(Handle<Name> key) {
4987   DisallowHeapAllocation no_gc;
4988   DCHECK(key->IsUniqueName());
4989   if (IsJSGlobalProxy()) {
4990     // For a proxy, use the prototype as target object.
4991     PrototypeIterator iter(GetIsolate(), this);
4992     // If the proxy is detached, return undefined.
4993     if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
4994     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
4995     return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key);
4996   }
4997   DCHECK(!IsJSGlobalProxy());
4998   Object* inline_value = GetHiddenPropertiesHashTable();
4999
5000   if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
5001
5002   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
5003   Object* entry = hashtable->Lookup(key);
5004   return entry;
5005 }
5006
5007
5008 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
5009                                            Handle<Name> key,
5010                                            Handle<Object> value) {
5011   Isolate* isolate = object->GetIsolate();
5012
5013   DCHECK(key->IsUniqueName());
5014   if (object->IsJSGlobalProxy()) {
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   Handle<ObjectHashTable> hashtable =
5029       GetOrCreateHiddenPropertiesHashtable(object);
5030
5031   // If it was found, check if the key is already in the dictionary.
5032   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
5033                                                            value);
5034   if (*new_table != *hashtable) {
5035     // If adding the key expanded the dictionary (i.e., Add returned a new
5036     // dictionary), store it back to the object.
5037     SetHiddenPropertiesHashTable(object, new_table);
5038   }
5039
5040   // Return this to mark success.
5041   return object;
5042 }
5043
5044
5045 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
5046   Isolate* isolate = object->GetIsolate();
5047   DCHECK(key->IsUniqueName());
5048
5049   if (object->IsJSGlobalProxy()) {
5050     PrototypeIterator iter(isolate, object);
5051     if (iter.IsAtEnd()) return;
5052     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5053     return DeleteHiddenProperty(
5054         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key);
5055   }
5056
5057   Object* inline_value = object->GetHiddenPropertiesHashTable();
5058
5059   if (inline_value->IsUndefined()) return;
5060
5061   Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
5062   bool was_present = false;
5063   ObjectHashTable::Remove(hashtable, key, &was_present);
5064 }
5065
5066
5067 bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
5068   Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
5069   LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR);
5070   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
5071   // Cannot get an exception since the hidden_string isn't accessible to JS.
5072   DCHECK(maybe.IsJust());
5073   return maybe.FromJust() != ABSENT;
5074 }
5075
5076
5077 Object* JSObject::GetHiddenPropertiesHashTable() {
5078   DCHECK(!IsJSGlobalProxy());
5079   if (HasFastProperties()) {
5080     // If the object has fast properties, check whether the first slot
5081     // in the descriptor array matches the hidden string. Since the
5082     // hidden strings hash code is zero (and no other name has hash
5083     // code zero) it will always occupy the first entry if present.
5084     DescriptorArray* descriptors = this->map()->instance_descriptors();
5085     if (descriptors->number_of_descriptors() > 0) {
5086       int sorted_index = descriptors->GetSortedKeyIndex(0);
5087       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
5088           sorted_index < map()->NumberOfOwnDescriptors()) {
5089         DCHECK(descriptors->GetType(sorted_index) == DATA);
5090         DCHECK(descriptors->GetDetails(sorted_index).representation().
5091                IsCompatibleForLoad(Representation::Tagged()));
5092         FieldIndex index = FieldIndex::ForDescriptor(this->map(),
5093                                                      sorted_index);
5094         return this->RawFastPropertyAt(index);
5095       } else {
5096         return GetHeap()->undefined_value();
5097       }
5098     } else {
5099       return GetHeap()->undefined_value();
5100     }
5101   } else {
5102     Isolate* isolate = GetIsolate();
5103     LookupIterator it(handle(this), isolate->factory()->hidden_string(),
5104                       LookupIterator::OWN_SKIP_INTERCEPTOR);
5105     // Access check is always skipped for the hidden string anyways.
5106     return *GetDataProperty(&it);
5107   }
5108 }
5109
5110 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
5111     Handle<JSObject> object) {
5112   Isolate* isolate = object->GetIsolate();
5113
5114   static const int kInitialCapacity = 4;
5115   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5116   if (inline_value->IsHashTable()) {
5117     return Handle<ObjectHashTable>::cast(inline_value);
5118   }
5119
5120   Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
5121       isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
5122
5123   DCHECK(inline_value->IsUndefined());
5124   SetHiddenPropertiesHashTable(object, hashtable);
5125   return hashtable;
5126 }
5127
5128
5129 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
5130                                                       Handle<Object> value) {
5131   DCHECK(!object->IsJSGlobalProxy());
5132   Isolate* isolate = object->GetIsolate();
5133   Handle<Name> name = isolate->factory()->hidden_string();
5134   SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
5135   return object;
5136 }
5137
5138
5139 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
5140     LookupIterator* it) {
5141   Isolate* isolate = it->isolate();
5142   // Make sure that the top context does not change when doing callbacks or
5143   // interceptor calls.
5144   AssertNoContextChange ncc(isolate);
5145
5146   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
5147   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
5148   if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>();
5149
5150   Handle<JSObject> holder = it->GetHolder<JSObject>();
5151
5152   PropertyCallbackArguments args(isolate, interceptor->data(),
5153                                  *it->GetReceiver(), *holder);
5154   v8::Local<v8::Boolean> result;
5155   if (it->IsElement()) {
5156     uint32_t index = it->index();
5157     v8::IndexedPropertyDeleterCallback deleter =
5158         v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
5159     LOG(isolate,
5160         ApiIndexedPropertyAccess("interceptor-indexed-delete", *holder, index));
5161     result = args.Call(deleter, index);
5162   } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) {
5163     return MaybeHandle<Object>();
5164   } else {
5165     Handle<Name> name = it->name();
5166     v8::GenericNamedPropertyDeleterCallback deleter =
5167         v8::ToCData<v8::GenericNamedPropertyDeleterCallback>(
5168             interceptor->deleter());
5169     LOG(isolate,
5170         ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name));
5171     result = args.Call(deleter, v8::Utils::ToLocal(name));
5172   }
5173
5174   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5175   if (result.IsEmpty()) return MaybeHandle<Object>();
5176
5177   DCHECK(result->IsBoolean());
5178   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5179   result_internal->VerifyApiCallResultType();
5180   // Rebox CustomArguments::kReturnValueOffset before returning.
5181   return handle(*result_internal, isolate);
5182 }
5183
5184
5185 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
5186                                         Handle<Name> name, int entry) {
5187   DCHECK(!object->HasFastProperties());
5188   Isolate* isolate = object->GetIsolate();
5189
5190   if (object->IsGlobalObject()) {
5191     // If we have a global object, invalidate the cell and swap in a new one.
5192     Handle<GlobalDictionary> dictionary(object->global_dictionary());
5193     DCHECK_NE(GlobalDictionary::kNotFound, entry);
5194
5195     auto cell = PropertyCell::InvalidateEntry(dictionary, entry);
5196     cell->set_value(isolate->heap()->the_hole_value());
5197     // TODO(ishell): InvalidateForDelete
5198     cell->set_property_details(
5199         cell->property_details().set_cell_type(PropertyCellType::kInvalidated));
5200   } else {
5201     Handle<NameDictionary> dictionary(object->property_dictionary());
5202     DCHECK_NE(NameDictionary::kNotFound, entry);
5203
5204     NameDictionary::DeleteProperty(dictionary, entry);
5205     Handle<NameDictionary> new_properties =
5206         NameDictionary::Shrink(dictionary, name);
5207     object->set_properties(*new_properties);
5208   }
5209 }
5210
5211
5212 // ECMA-262, 3rd, 8.6.2.5
5213 MaybeHandle<Object> JSReceiver::DeleteProperty(LookupIterator* it,
5214                                                LanguageMode language_mode) {
5215   Isolate* isolate = it->isolate();
5216   if (it->state() == LookupIterator::JSPROXY) {
5217     return JSProxy::DeletePropertyWithHandler(it->GetHolder<JSProxy>(),
5218                                               it->GetName(), language_mode);
5219   }
5220
5221   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
5222
5223   bool is_observed =
5224       receiver->map()->is_observed() &&
5225       (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()));
5226
5227   Handle<Object> old_value = it->factory()->the_hole_value();
5228
5229   for (; it->IsFound(); it->Next()) {
5230     switch (it->state()) {
5231       case LookupIterator::JSPROXY:
5232       case LookupIterator::NOT_FOUND:
5233       case LookupIterator::TRANSITION:
5234         UNREACHABLE();
5235       case LookupIterator::ACCESS_CHECK:
5236         if (it->HasAccess()) break;
5237         isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
5238         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5239         return it->factory()->false_value();
5240       case LookupIterator::INTERCEPTOR: {
5241         MaybeHandle<Object> maybe_result =
5242             JSObject::DeletePropertyWithInterceptor(it);
5243         // Delete with interceptor succeeded. Return result.
5244         if (!maybe_result.is_null()) return maybe_result;
5245         // An exception was thrown in the interceptor. Propagate.
5246         if (isolate->has_pending_exception()) return maybe_result;
5247         break;
5248       }
5249       case LookupIterator::INTEGER_INDEXED_EXOTIC:
5250         return it->factory()->true_value();
5251       case LookupIterator::DATA:
5252         if (is_observed) {
5253           old_value = it->GetDataValue();
5254         }
5255       // Fall through.
5256       case LookupIterator::ACCESSOR: {
5257         if (!it->IsConfigurable() || receiver->map()->is_strong()) {
5258           // Fail if the property is not configurable, or on a strong object.
5259           if (is_strict(language_mode)) {
5260             MessageTemplate::Template templ =
5261                 receiver->map()->is_strong()
5262                     ? MessageTemplate::kStrongDeleteProperty
5263                     : MessageTemplate::kStrictDeleteProperty;
5264             THROW_NEW_ERROR(
5265                 isolate, NewTypeError(templ, it->GetName(), receiver), Object);
5266           }
5267           return it->factory()->false_value();
5268         }
5269
5270         it->Delete();
5271
5272         if (is_observed) {
5273           RETURN_ON_EXCEPTION(isolate,
5274                               JSObject::EnqueueChangeRecord(
5275                                   receiver, "delete", it->GetName(), old_value),
5276                               Object);
5277         }
5278
5279         return it->factory()->true_value();
5280       }
5281     }
5282   }
5283
5284   return it->factory()->true_value();
5285 }
5286
5287
5288 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
5289                                               uint32_t index,
5290                                               LanguageMode language_mode) {
5291   LookupIterator it(object->GetIsolate(), object, index,
5292                     LookupIterator::HIDDEN);
5293   return DeleteProperty(&it, language_mode);
5294 }
5295
5296
5297 MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
5298                                                Handle<Name> name,
5299                                                LanguageMode language_mode) {
5300   LookupIterator it(object, name, LookupIterator::HIDDEN);
5301   return JSObject::DeleteProperty(&it, language_mode);
5302 }
5303
5304
5305 MaybeHandle<Object> JSReceiver::DeletePropertyOrElement(
5306     Handle<JSReceiver> object, Handle<Name> name, LanguageMode language_mode) {
5307   LookupIterator it = LookupIterator::PropertyOrElement(
5308       name->GetIsolate(), object, name, LookupIterator::HIDDEN);
5309   return JSObject::DeleteProperty(&it, language_mode);
5310 }
5311
5312
5313 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
5314                                             ElementsKind kind,
5315                                             Object* object) {
5316   DCHECK(IsFastObjectElementsKind(kind) ||
5317          kind == DICTIONARY_ELEMENTS);
5318   if (IsFastObjectElementsKind(kind)) {
5319     int length = IsJSArray()
5320         ? Smi::cast(JSArray::cast(this)->length())->value()
5321         : elements->length();
5322     for (int i = 0; i < length; ++i) {
5323       Object* element = elements->get(i);
5324       if (!element->IsTheHole() && element == object) return true;
5325     }
5326   } else {
5327     Object* key =
5328         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5329     if (!key->IsUndefined()) return true;
5330   }
5331   return false;
5332 }
5333
5334
5335 // Check whether this object references another object.
5336 bool JSObject::ReferencesObject(Object* obj) {
5337   Map* map_of_this = map();
5338   Heap* heap = GetHeap();
5339   DisallowHeapAllocation no_allocation;
5340
5341   // Is the object the constructor for this object?
5342   if (map_of_this->GetConstructor() == obj) {
5343     return true;
5344   }
5345
5346   // Is the object the prototype for this object?
5347   if (map_of_this->prototype() == obj) {
5348     return true;
5349   }
5350
5351   // Check if the object is among the named properties.
5352   Object* key = SlowReverseLookup(obj);
5353   if (!key->IsUndefined()) {
5354     return true;
5355   }
5356
5357   // Check if the object is among the indexed properties.
5358   ElementsKind kind = GetElementsKind();
5359   switch (kind) {
5360     // Raw pixels and external arrays do not reference other
5361     // objects.
5362 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5363     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
5364     case TYPE##_ELEMENTS:                                                      \
5365       break;
5366
5367     TYPED_ARRAYS(TYPED_ARRAY_CASE)
5368 #undef TYPED_ARRAY_CASE
5369
5370     case FAST_DOUBLE_ELEMENTS:
5371     case FAST_HOLEY_DOUBLE_ELEMENTS:
5372       break;
5373     case FAST_SMI_ELEMENTS:
5374     case FAST_HOLEY_SMI_ELEMENTS:
5375       break;
5376     case FAST_ELEMENTS:
5377     case FAST_HOLEY_ELEMENTS:
5378     case DICTIONARY_ELEMENTS: {
5379       FixedArray* elements = FixedArray::cast(this->elements());
5380       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5381       break;
5382     }
5383     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
5384     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
5385       FixedArray* parameter_map = FixedArray::cast(elements());
5386       // Check the mapped parameters.
5387       int length = parameter_map->length();
5388       for (int i = 2; i < length; ++i) {
5389         Object* value = parameter_map->get(i);
5390         if (!value->IsTheHole() && value == obj) return true;
5391       }
5392       // Check the arguments.
5393       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5394       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5395           FAST_HOLEY_ELEMENTS;
5396       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5397       break;
5398     }
5399   }
5400
5401   // For functions check the context.
5402   if (IsJSFunction()) {
5403     // Get the constructor function for arguments array.
5404     Map* arguments_map =
5405         heap->isolate()->context()->native_context()->sloppy_arguments_map();
5406     JSFunction* arguments_function =
5407         JSFunction::cast(arguments_map->GetConstructor());
5408
5409     // Get the context and don't check if it is the native context.
5410     JSFunction* f = JSFunction::cast(this);
5411     Context* context = f->context();
5412     if (context->IsNativeContext()) {
5413       return false;
5414     }
5415
5416     // Check the non-special context slots.
5417     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5418       // Only check JS objects.
5419       if (context->get(i)->IsJSObject()) {
5420         JSObject* ctxobj = JSObject::cast(context->get(i));
5421         // If it is an arguments array check the content.
5422         if (ctxobj->map()->GetConstructor() == arguments_function) {
5423           if (ctxobj->ReferencesObject(obj)) {
5424             return true;
5425           }
5426         } else if (ctxobj == obj) {
5427           return true;
5428         }
5429       }
5430     }
5431
5432     // Check the context extension (if any) if it can have references.
5433     if (context->has_extension() && !context->IsCatchContext()) {
5434       // With harmony scoping, a JSFunction may have a global context.
5435       // TODO(mvstanton): walk into the ScopeInfo.
5436       if (context->IsScriptContext()) {
5437         return false;
5438       }
5439
5440       return JSObject::cast(context->extension())->ReferencesObject(obj);
5441     }
5442   }
5443
5444   // No references to object.
5445   return false;
5446 }
5447
5448
5449 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5450   if (!object->map()->is_extensible()) return object;
5451
5452   if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) {
5453     return PreventExtensionsWithTransition<NONE>(object);
5454   }
5455
5456   Isolate* isolate = object->GetIsolate();
5457
5458   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
5459     isolate->ReportFailedAccessCheck(object);
5460     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5461     return isolate->factory()->false_value();
5462   }
5463
5464   if (object->IsJSGlobalProxy()) {
5465     PrototypeIterator iter(isolate, object);
5466     if (iter.IsAtEnd()) return object;
5467     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5468     return PreventExtensions(
5469         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5470   }
5471
5472   // It's not possible to seal objects with external array elements
5473   if (object->HasExternalArrayElements() ||
5474       object->HasFixedTypedArrayElements()) {
5475     THROW_NEW_ERROR(
5476         isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray),
5477         Object);
5478   }
5479
5480   // If there are fast elements we normalize.
5481   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5482   DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
5483
5484   // Make sure that we never go back to fast case.
5485   object->RequireSlowElements(*dictionary);
5486
5487   // Do a map transition, other objects with this map may still
5488   // be extensible.
5489   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5490   Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
5491
5492   new_map->set_is_extensible(false);
5493   JSObject::MigrateToMap(object, new_map);
5494   DCHECK(!object->map()->is_extensible());
5495
5496   if (object->map()->is_observed()) {
5497     RETURN_ON_EXCEPTION(
5498         isolate,
5499         EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5500                             isolate->factory()->the_hole_value()),
5501         Object);
5502   }
5503   return object;
5504 }
5505
5506
5507 bool JSObject::IsExtensible() {
5508   if (IsJSGlobalProxy()) {
5509     PrototypeIterator iter(GetIsolate(), this);
5510     if (iter.IsAtEnd()) return false;
5511     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
5512     return JSObject::cast(iter.GetCurrent())->map()->is_extensible();
5513   }
5514   return map()->is_extensible();
5515 }
5516
5517
5518 template <typename Dictionary>
5519 static void ApplyAttributesToDictionary(Dictionary* dictionary,
5520                                         const PropertyAttributes attributes) {
5521   int capacity = dictionary->Capacity();
5522   for (int i = 0; i < capacity; i++) {
5523     Object* k = dictionary->KeyAt(i);
5524     if (dictionary->IsKey(k) &&
5525         !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
5526       PropertyDetails details = dictionary->DetailsAt(i);
5527       int attrs = attributes;
5528       // READ_ONLY is an invalid attribute for JS setters/getters.
5529       if ((attributes & READ_ONLY) && details.type() == ACCESSOR_CONSTANT) {
5530         Object* v = dictionary->ValueAt(i);
5531         if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
5532         if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
5533       }
5534       details = details.CopyAddAttributes(
5535           static_cast<PropertyAttributes>(attrs));
5536       dictionary->DetailsAtPut(i, details);
5537     }
5538   }
5539 }
5540
5541
5542 template <PropertyAttributes attrs>
5543 MaybeHandle<Object> JSObject::PreventExtensionsWithTransition(
5544     Handle<JSObject> object) {
5545   STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
5546
5547   // Sealing/freezing sloppy arguments should be handled elsewhere.
5548   DCHECK(!object->HasSloppyArgumentsElements());
5549   DCHECK(!object->map()->is_observed());
5550
5551   Isolate* isolate = object->GetIsolate();
5552   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
5553     isolate->ReportFailedAccessCheck(object);
5554     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5555     return isolate->factory()->false_value();
5556   }
5557
5558   if (object->IsJSGlobalProxy()) {
5559     PrototypeIterator iter(isolate, object);
5560     if (iter.IsAtEnd()) return object;
5561     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5562     return PreventExtensionsWithTransition<attrs>(
5563         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5564   }
5565
5566   // It's not possible to seal or freeze objects with external array elements
5567   if (object->HasExternalArrayElements() ||
5568       object->HasFixedTypedArrayElements()) {
5569     THROW_NEW_ERROR(
5570         isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray),
5571         Object);
5572   }
5573
5574   Handle<SeededNumberDictionary> new_element_dictionary;
5575   if (!object->HasDictionaryElements()) {
5576     int length =
5577         object->IsJSArray()
5578             ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5579             : object->elements()->length();
5580     new_element_dictionary =
5581         length == 0 ? isolate->factory()->empty_slow_element_dictionary()
5582                     : GetNormalizedElementDictionary(
5583                           object, handle(object->elements()));
5584   }
5585
5586   Handle<Symbol> transition_marker;
5587   if (attrs == NONE) {
5588     transition_marker = isolate->factory()->nonextensible_symbol();
5589   } else if (attrs == SEALED) {
5590     transition_marker = isolate->factory()->sealed_symbol();
5591   } else {
5592     DCHECK(attrs == FROZEN);
5593     transition_marker = isolate->factory()->frozen_symbol();
5594   }
5595
5596   Handle<Map> old_map(object->map(), isolate);
5597   Map* transition =
5598       TransitionArray::SearchSpecial(*old_map, *transition_marker);
5599   if (transition != NULL) {
5600     Handle<Map> transition_map(transition, isolate);
5601     DCHECK(transition_map->has_dictionary_elements());
5602     DCHECK(!transition_map->is_extensible());
5603     JSObject::MigrateToMap(object, transition_map);
5604   } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
5605     // Create a new descriptor array with the appropriate property attributes
5606     Handle<Map> new_map = Map::CopyForPreventExtensions(
5607         old_map, attrs, transition_marker, "CopyForPreventExtensions");
5608     JSObject::MigrateToMap(object, new_map);
5609   } else {
5610     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5611     // Slow path: need to normalize properties for safety
5612     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
5613                         "SlowPreventExtensions");
5614
5615     // Create a new map, since other objects with this map may be extensible.
5616     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5617     Handle<Map> new_map =
5618         Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
5619     new_map->set_is_extensible(false);
5620     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5621     JSObject::MigrateToMap(object, new_map);
5622
5623     if (attrs != NONE) {
5624       if (object->IsGlobalObject()) {
5625         ApplyAttributesToDictionary(object->global_dictionary(), attrs);
5626       } else {
5627         ApplyAttributesToDictionary(object->property_dictionary(), attrs);
5628       }
5629     }
5630   }
5631
5632   DCHECK(object->map()->has_dictionary_elements());
5633   if (!new_element_dictionary.is_null()) {
5634     object->set_elements(*new_element_dictionary);
5635   }
5636
5637   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5638     SeededNumberDictionary* dictionary = object->element_dictionary();
5639     // Make sure we never go back to the fast case
5640     object->RequireSlowElements(dictionary);
5641     if (attrs != NONE) {
5642       ApplyAttributesToDictionary(dictionary, attrs);
5643     }
5644   }
5645
5646   return object;
5647 }
5648
5649
5650 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
5651   return PreventExtensionsWithTransition<FROZEN>(object);
5652 }
5653
5654
5655 MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) {
5656   return PreventExtensionsWithTransition<SEALED>(object);
5657 }
5658
5659
5660 void JSObject::SetObserved(Handle<JSObject> object) {
5661   DCHECK(!object->IsJSGlobalProxy());
5662   DCHECK(!object->IsJSGlobalObject());
5663   Isolate* isolate = object->GetIsolate();
5664   Handle<Map> new_map;
5665   Handle<Map> old_map(object->map(), isolate);
5666   DCHECK(!old_map->is_observed());
5667   Map* transition = TransitionArray::SearchSpecial(
5668       *old_map, isolate->heap()->observed_symbol());
5669   if (transition != NULL) {
5670     new_map = handle(transition, isolate);
5671     DCHECK(new_map->is_observed());
5672   } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
5673     new_map = Map::CopyForObserved(old_map);
5674   } else {
5675     new_map = Map::Copy(old_map, "SlowObserved");
5676     new_map->set_is_observed();
5677   }
5678   JSObject::MigrateToMap(object, new_map);
5679 }
5680
5681
5682 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
5683                                         Representation representation,
5684                                         FieldIndex index) {
5685   Isolate* isolate = object->GetIsolate();
5686   if (object->IsUnboxedDoubleField(index)) {
5687     double value = object->RawFastDoublePropertyAt(index);
5688     return isolate->factory()->NewHeapNumber(value);
5689   }
5690   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
5691   return Object::WrapForRead(isolate, raw_value, representation);
5692 }
5693
5694
5695 template<class ContextObject>
5696 class JSObjectWalkVisitor {
5697  public:
5698   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5699                       JSObject::DeepCopyHints hints)
5700     : site_context_(site_context),
5701       copying_(copying),
5702       hints_(hints) {}
5703
5704   MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
5705
5706  protected:
5707   MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
5708       Handle<JSObject> object,
5709       Handle<JSObject> value) {
5710     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5711     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
5712     site_context()->ExitScope(current_site, value);
5713     return copy_of_value;
5714   }
5715
5716   inline ContextObject* site_context() { return site_context_; }
5717   inline Isolate* isolate() { return site_context()->isolate(); }
5718
5719   inline bool copying() const { return copying_; }
5720
5721  private:
5722   ContextObject* site_context_;
5723   const bool copying_;
5724   const JSObject::DeepCopyHints hints_;
5725 };
5726
5727
5728 template <class ContextObject>
5729 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
5730     Handle<JSObject> object) {
5731   Isolate* isolate = this->isolate();
5732   bool copying = this->copying();
5733   bool shallow = hints_ == JSObject::kObjectIsShallow;
5734
5735   if (!shallow) {
5736     StackLimitCheck check(isolate);
5737
5738     if (check.HasOverflowed()) {
5739       isolate->StackOverflow();
5740       return MaybeHandle<JSObject>();
5741     }
5742   }
5743
5744   if (object->map()->is_deprecated()) {
5745     JSObject::MigrateInstance(object);
5746   }
5747
5748   Handle<JSObject> copy;
5749   if (copying) {
5750     Handle<AllocationSite> site_to_pass;
5751     if (site_context()->ShouldCreateMemento(object)) {
5752       site_to_pass = site_context()->current();
5753     }
5754     copy = isolate->factory()->CopyJSObjectWithAllocationSite(
5755         object, site_to_pass);
5756   } else {
5757     copy = object;
5758   }
5759
5760   DCHECK(copying || copy.is_identical_to(object));
5761
5762   ElementsKind kind = copy->GetElementsKind();
5763   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5764       FixedArray::cast(copy->elements())->map() ==
5765         isolate->heap()->fixed_cow_array_map()) {
5766     isolate->counters()->cow_arrays_created_runtime()->Increment();
5767   }
5768
5769   if (!shallow) {
5770     HandleScope scope(isolate);
5771
5772     // Deep copy own properties.
5773     if (copy->HasFastProperties()) {
5774       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5775       int limit = copy->map()->NumberOfOwnDescriptors();
5776       for (int i = 0; i < limit; i++) {
5777         PropertyDetails details = descriptors->GetDetails(i);
5778         if (details.type() != DATA) continue;
5779         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
5780         if (object->IsUnboxedDoubleField(index)) {
5781           if (copying) {
5782             double value = object->RawFastDoublePropertyAt(index);
5783             copy->RawFastDoublePropertyAtPut(index, value);
5784           }
5785         } else {
5786           Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5787           if (value->IsJSObject()) {
5788             ASSIGN_RETURN_ON_EXCEPTION(
5789                 isolate, value,
5790                 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5791                 JSObject);
5792             if (copying) {
5793               copy->FastPropertyAtPut(index, *value);
5794             }
5795           } else {
5796             if (copying) {
5797               Representation representation = details.representation();
5798               value = Object::NewStorageFor(isolate, value, representation);
5799               copy->FastPropertyAtPut(index, *value);
5800             }
5801           }
5802         }
5803       }
5804     } else {
5805       Handle<FixedArray> names =
5806           isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
5807       copy->GetOwnPropertyNames(*names, 0);
5808       for (int i = 0; i < names->length(); i++) {
5809         DCHECK(names->get(i)->IsString());
5810         Handle<String> key_string(String::cast(names->get(i)));
5811         Maybe<PropertyAttributes> maybe =
5812             JSReceiver::GetOwnPropertyAttributes(copy, key_string);
5813         DCHECK(maybe.IsJust());
5814         PropertyAttributes attributes = maybe.FromJust();
5815         // Only deep copy fields from the object literal expression.
5816         // In particular, don't try to copy the length attribute of
5817         // an array.
5818         if (attributes != NONE) continue;
5819         Handle<Object> value =
5820             Object::GetProperty(copy, key_string).ToHandleChecked();
5821         if (value->IsJSObject()) {
5822           Handle<JSObject> result;
5823           ASSIGN_RETURN_ON_EXCEPTION(
5824               isolate, result,
5825               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5826               JSObject);
5827           if (copying) {
5828             // Creating object copy for literals. No strict mode needed.
5829             JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert();
5830           }
5831         }
5832       }
5833     }
5834
5835     // Deep copy own elements.
5836     // Pixel elements cannot be created using an object literal.
5837     DCHECK(!copy->HasExternalArrayElements());
5838     switch (kind) {
5839       case FAST_SMI_ELEMENTS:
5840       case FAST_ELEMENTS:
5841       case FAST_HOLEY_SMI_ELEMENTS:
5842       case FAST_HOLEY_ELEMENTS: {
5843         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5844         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5845 #ifdef DEBUG
5846           for (int i = 0; i < elements->length(); i++) {
5847             DCHECK(!elements->get(i)->IsJSObject());
5848           }
5849 #endif
5850         } else {
5851           for (int i = 0; i < elements->length(); i++) {
5852             Handle<Object> value(elements->get(i), isolate);
5853             DCHECK(value->IsSmi() ||
5854                    value->IsTheHole() ||
5855                    (IsFastObjectElementsKind(copy->GetElementsKind())));
5856             if (value->IsJSObject()) {
5857               Handle<JSObject> result;
5858               ASSIGN_RETURN_ON_EXCEPTION(
5859                   isolate, result,
5860                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5861                   JSObject);
5862               if (copying) {
5863                 elements->set(i, *result);
5864               }
5865             }
5866           }
5867         }
5868         break;
5869       }
5870       case DICTIONARY_ELEMENTS: {
5871         Handle<SeededNumberDictionary> element_dictionary(
5872             copy->element_dictionary());
5873         int capacity = element_dictionary->Capacity();
5874         for (int i = 0; i < capacity; i++) {
5875           Object* k = element_dictionary->KeyAt(i);
5876           if (element_dictionary->IsKey(k)) {
5877             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
5878             if (value->IsJSObject()) {
5879               Handle<JSObject> result;
5880               ASSIGN_RETURN_ON_EXCEPTION(
5881                   isolate, result,
5882                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5883                   JSObject);
5884               if (copying) {
5885                 element_dictionary->ValueAtPut(i, *result);
5886               }
5887             }
5888           }
5889         }
5890         break;
5891       }
5892       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
5893       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
5894         UNIMPLEMENTED();
5895         break;
5896
5897
5898 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5899       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
5900       case TYPE##_ELEMENTS:                                                    \
5901
5902       TYPED_ARRAYS(TYPED_ARRAY_CASE)
5903 #undef TYPED_ARRAY_CASE
5904
5905       case FAST_DOUBLE_ELEMENTS:
5906       case FAST_HOLEY_DOUBLE_ELEMENTS:
5907         // No contained objects, nothing to do.
5908         break;
5909     }
5910   }
5911
5912   return copy;
5913 }
5914
5915
5916 MaybeHandle<JSObject> JSObject::DeepWalk(
5917     Handle<JSObject> object,
5918     AllocationSiteCreationContext* site_context) {
5919   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
5920                                                        kNoHints);
5921   MaybeHandle<JSObject> result = v.StructureWalk(object);
5922   Handle<JSObject> for_assert;
5923   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
5924   return result;
5925 }
5926
5927
5928 MaybeHandle<JSObject> JSObject::DeepCopy(
5929     Handle<JSObject> object,
5930     AllocationSiteUsageContext* site_context,
5931     DeepCopyHints hints) {
5932   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
5933   MaybeHandle<JSObject> copy = v.StructureWalk(object);
5934   Handle<JSObject> for_assert;
5935   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
5936   return copy;
5937 }
5938
5939
5940 // Tests for the fast common case for property enumeration:
5941 // - This object and all prototypes has an enum cache (which means that
5942 //   it is no proxy, has no interceptors and needs no access checks).
5943 // - This object has no elements.
5944 // - No prototype has enumerable properties/elements.
5945 bool JSReceiver::IsSimpleEnum() {
5946   for (PrototypeIterator iter(GetIsolate(), this,
5947                               PrototypeIterator::START_AT_RECEIVER);
5948        !iter.IsAtEnd(); iter.Advance()) {
5949     if (!iter.GetCurrent()->IsJSObject()) return false;
5950     JSObject* curr = JSObject::cast(iter.GetCurrent());
5951     int enum_length = curr->map()->EnumLength();
5952     if (enum_length == kInvalidEnumCacheSentinel) return false;
5953     if (curr->IsAccessCheckNeeded()) return false;
5954     DCHECK(!curr->HasNamedInterceptor());
5955     DCHECK(!curr->HasIndexedInterceptor());
5956     if (curr->NumberOfEnumElements() > 0) return false;
5957     if (curr != this && enum_length != 0) return false;
5958   }
5959   return true;
5960 }
5961
5962
5963 static bool FilterKey(Object* key, PropertyAttributes filter) {
5964   if ((filter & SYMBOLIC) && key->IsSymbol()) {
5965     return true;
5966   }
5967
5968   if ((filter & PRIVATE_SYMBOL) &&
5969       key->IsSymbol() && Symbol::cast(key)->is_private()) {
5970     return true;
5971   }
5972
5973   if ((filter & STRING) && !key->IsSymbol()) {
5974     return true;
5975   }
5976
5977   return false;
5978 }
5979
5980
5981 int Map::NumberOfDescribedProperties(DescriptorFlag which,
5982                                      PropertyAttributes filter) {
5983   int result = 0;
5984   DescriptorArray* descs = instance_descriptors();
5985   int limit = which == ALL_DESCRIPTORS
5986       ? descs->number_of_descriptors()
5987       : NumberOfOwnDescriptors();
5988   for (int i = 0; i < limit; i++) {
5989     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
5990         !FilterKey(descs->GetKey(i), filter)) {
5991       result++;
5992     }
5993   }
5994   return result;
5995 }
5996
5997
5998 int Map::NextFreePropertyIndex() {
5999   int free_index = 0;
6000   int number_of_own_descriptors = NumberOfOwnDescriptors();
6001   DescriptorArray* descs = instance_descriptors();
6002   for (int i = 0; i < number_of_own_descriptors; i++) {
6003     PropertyDetails details = descs->GetDetails(i);
6004     if (details.location() == kField) {
6005       int candidate = details.field_index() + details.field_width_in_words();
6006       if (candidate > free_index) free_index = candidate;
6007     }
6008   }
6009   return free_index;
6010 }
6011
6012
6013 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
6014   int len = array->length();
6015   for (int i = 0; i < len; i++) {
6016     Object* e = array->get(i);
6017     if (!(e->IsName() || e->IsNumber())) return false;
6018   }
6019   return true;
6020 }
6021
6022
6023 static Handle<FixedArray> ReduceFixedArrayTo(
6024     Handle<FixedArray> array, int length) {
6025   DCHECK(array->length() >= length);
6026   if (array->length() == length) return array;
6027
6028   Handle<FixedArray> new_array =
6029       array->GetIsolate()->factory()->NewFixedArray(length);
6030   for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
6031   return new_array;
6032 }
6033
6034
6035 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
6036                                                  bool cache_result) {
6037   Isolate* isolate = object->GetIsolate();
6038   if (object->HasFastProperties()) {
6039     int own_property_count = object->map()->EnumLength();
6040     // If the enum length of the given map is set to kInvalidEnumCache, this
6041     // means that the map itself has never used the present enum cache. The
6042     // first step to using the cache is to set the enum length of the map by
6043     // counting the number of own descriptors that are not DONT_ENUM or
6044     // SYMBOLIC.
6045     if (own_property_count == kInvalidEnumCacheSentinel) {
6046       own_property_count = object->map()->NumberOfDescribedProperties(
6047           OWN_DESCRIPTORS, DONT_SHOW);
6048     } else {
6049       DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
6050           OWN_DESCRIPTORS, DONT_SHOW));
6051     }
6052
6053     if (object->map()->instance_descriptors()->HasEnumCache()) {
6054       DescriptorArray* desc = object->map()->instance_descriptors();
6055       Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
6056
6057       // In case the number of properties required in the enum are actually
6058       // present, we can reuse the enum cache. Otherwise, this means that the
6059       // enum cache was generated for a previous (smaller) version of the
6060       // Descriptor Array. In that case we regenerate the enum cache.
6061       if (own_property_count <= keys->length()) {
6062         if (cache_result) object->map()->SetEnumLength(own_property_count);
6063         isolate->counters()->enum_cache_hits()->Increment();
6064         return ReduceFixedArrayTo(keys, own_property_count);
6065       }
6066     }
6067
6068     Handle<Map> map(object->map());
6069
6070     if (map->instance_descriptors()->IsEmpty()) {
6071       isolate->counters()->enum_cache_hits()->Increment();
6072       if (cache_result) map->SetEnumLength(0);
6073       return isolate->factory()->empty_fixed_array();
6074     }
6075
6076     isolate->counters()->enum_cache_misses()->Increment();
6077
6078     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
6079         own_property_count);
6080     Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
6081         own_property_count);
6082
6083     Handle<DescriptorArray> descs =
6084         Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
6085
6086     int size = map->NumberOfOwnDescriptors();
6087     int index = 0;
6088
6089     for (int i = 0; i < size; i++) {
6090       PropertyDetails details = descs->GetDetails(i);
6091       Object* key = descs->GetKey(i);
6092       if (!(details.IsDontEnum() || key->IsSymbol())) {
6093         storage->set(index, key);
6094         if (!indices.is_null()) {
6095           if (details.type() != DATA) {
6096             indices = Handle<FixedArray>();
6097           } else {
6098             FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
6099             int load_by_field_index = field_index.GetLoadByFieldIndex();
6100             indices->set(index, Smi::FromInt(load_by_field_index));
6101           }
6102         }
6103         index++;
6104       }
6105     }
6106     DCHECK(index == storage->length());
6107
6108     Handle<FixedArray> bridge_storage =
6109         isolate->factory()->NewFixedArray(
6110             DescriptorArray::kEnumCacheBridgeLength);
6111     DescriptorArray* desc = object->map()->instance_descriptors();
6112     desc->SetEnumCache(*bridge_storage,
6113                        *storage,
6114                        indices.is_null() ? Object::cast(Smi::FromInt(0))
6115                                          : Object::cast(*indices));
6116     if (cache_result) {
6117       object->map()->SetEnumLength(own_property_count);
6118     }
6119     return storage;
6120   } else if (object->IsGlobalObject()) {
6121     Handle<GlobalDictionary> dictionary(object->global_dictionary());
6122     int length = dictionary->NumberOfEnumElements();
6123     if (length == 0) {
6124       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6125     }
6126     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6127     dictionary->CopyEnumKeysTo(*storage);
6128     return storage;
6129   } else {
6130     Handle<NameDictionary> dictionary(object->property_dictionary());
6131     int length = dictionary->NumberOfEnumElements();
6132     if (length == 0) {
6133       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6134     }
6135     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6136     dictionary->CopyEnumKeysTo(*storage);
6137     return storage;
6138   }
6139 }
6140
6141
6142 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6143                                             KeyCollectionType type) {
6144   USE(ContainsOnlyValidKeys);
6145   Isolate* isolate = object->GetIsolate();
6146   Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
6147   Handle<JSFunction> arguments_function(
6148       JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
6149
6150   // Only collect keys if access is permitted.
6151   for (PrototypeIterator iter(isolate, object,
6152                               PrototypeIterator::START_AT_RECEIVER);
6153        !iter.IsAtEnd(); iter.Advance()) {
6154     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6155       Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
6156                             isolate);
6157       Handle<Object> args[] = { proxy };
6158       Handle<Object> names;
6159       ASSIGN_RETURN_ON_EXCEPTION(
6160           isolate, names,
6161           Execution::Call(isolate,
6162                           isolate->proxy_enumerate(),
6163                           object,
6164                           arraysize(args),
6165                           args),
6166           FixedArray);
6167       ASSIGN_RETURN_ON_EXCEPTION(
6168           isolate, content,
6169           FixedArray::AddKeysFromArrayLike(
6170               content, Handle<JSObject>::cast(names)),
6171           FixedArray);
6172       break;
6173     }
6174
6175     Handle<JSObject> current =
6176         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
6177
6178     // Check access rights if required.
6179     if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) {
6180       isolate->ReportFailedAccessCheck(current);
6181       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6182       break;
6183     }
6184
6185     // Compute the element keys.
6186     Handle<FixedArray> element_keys =
6187         isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6188     current->GetEnumElementKeys(*element_keys);
6189     ASSIGN_RETURN_ON_EXCEPTION(
6190         isolate, content,
6191         FixedArray::UnionOfKeys(content, element_keys),
6192         FixedArray);
6193     DCHECK(ContainsOnlyValidKeys(content));
6194
6195     // Add the element keys from the interceptor.
6196     if (current->HasIndexedInterceptor()) {
6197       Handle<JSObject> result;
6198       if (JSObject::GetKeysForIndexedInterceptor(
6199               current, object).ToHandle(&result)) {
6200         ASSIGN_RETURN_ON_EXCEPTION(
6201             isolate, content,
6202             FixedArray::AddKeysFromArrayLike(content, result),
6203             FixedArray);
6204       }
6205       DCHECK(ContainsOnlyValidKeys(content));
6206     }
6207
6208     // We can cache the computed property keys if access checks are
6209     // not needed and no interceptors are involved.
6210     //
6211     // We do not use the cache if the object has elements and
6212     // therefore it does not make sense to cache the property names
6213     // for arguments objects.  Arguments objects will always have
6214     // elements.
6215     // Wrapped strings have elements, but don't have an elements
6216     // array or dictionary.  So the fast inline test for whether to
6217     // use the cache says yes, so we should not create a cache.
6218     bool cache_enum_keys =
6219         ((current->map()->GetConstructor() != *arguments_function) &&
6220          !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
6221          !current->HasNamedInterceptor() && !current->HasIndexedInterceptor());
6222     // Compute the property keys and cache them if possible.
6223     ASSIGN_RETURN_ON_EXCEPTION(
6224         isolate, content,
6225         FixedArray::UnionOfKeys(
6226             content, JSObject::GetEnumPropertyKeys(current, cache_enum_keys)),
6227         FixedArray);
6228     DCHECK(ContainsOnlyValidKeys(content));
6229
6230     // Add the non-symbol property keys from the interceptor.
6231     if (current->HasNamedInterceptor()) {
6232       Handle<JSObject> result;
6233       if (JSObject::GetKeysForNamedInterceptor(
6234               current, object).ToHandle(&result)) {
6235         ASSIGN_RETURN_ON_EXCEPTION(
6236             isolate, content, FixedArray::AddKeysFromArrayLike(
6237                                   content, result, FixedArray::NON_SYMBOL_KEYS),
6238             FixedArray);
6239       }
6240       DCHECK(ContainsOnlyValidKeys(content));
6241     }
6242
6243     // If we only want own properties we bail out after the first
6244     // iteration.
6245     if (type == OWN_ONLY) break;
6246   }
6247   return content;
6248 }
6249
6250
6251 bool Map::DictionaryElementsInPrototypeChainOnly() {
6252   if (IsDictionaryElementsKind(elements_kind())) {
6253     return false;
6254   }
6255
6256   for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
6257     // Be conservative, don't walk into proxies.
6258     if (iter.GetCurrent()->IsJSProxy()) return true;
6259     // String wrappers have non-configurable, non-writable elements.
6260     if (iter.GetCurrent()->IsStringWrapper()) return true;
6261     JSObject* current = JSObject::cast(iter.GetCurrent());
6262
6263     if (current->HasDictionaryElements() &&
6264         current->element_dictionary()->requires_slow_elements()) {
6265       return true;
6266     }
6267
6268     if (current->HasSlowArgumentsElements()) {
6269       FixedArray* parameter_map = FixedArray::cast(current->elements());
6270       Object* arguments = parameter_map->get(1);
6271       if (SeededNumberDictionary::cast(arguments)->requires_slow_elements()) {
6272         return true;
6273       }
6274     }
6275   }
6276
6277   return false;
6278 }
6279
6280
6281 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
6282                                              Handle<Name> name,
6283                                              Handle<Object> getter,
6284                                              Handle<Object> setter,
6285                                              PropertyAttributes attributes) {
6286   Isolate* isolate = object->GetIsolate();
6287
6288   LookupIterator it = LookupIterator::PropertyOrElement(
6289       isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6290
6291   if (it.state() == LookupIterator::ACCESS_CHECK) {
6292     if (!it.HasAccess()) {
6293       isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
6294       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6295       return isolate->factory()->undefined_value();
6296     }
6297     it.Next();
6298   }
6299
6300   // Ignore accessors on typed arrays.
6301   if (it.IsElement() && (object->HasFixedTypedArrayElements() ||
6302                          object->HasExternalArrayElements())) {
6303     return it.factory()->undefined_value();
6304   }
6305
6306   Handle<Object> old_value = isolate->factory()->the_hole_value();
6307   bool is_observed = object->map()->is_observed() &&
6308                      !isolate->IsInternallyUsedPropertyName(name);
6309   bool preexists = false;
6310   if (is_observed) {
6311     CHECK(GetPropertyAttributes(&it).IsJust());
6312     preexists = it.IsFound();
6313     if (preexists && (it.state() == LookupIterator::DATA ||
6314                       it.GetAccessors()->IsAccessorInfo())) {
6315       old_value = GetProperty(&it).ToHandleChecked();
6316     }
6317   }
6318
6319   DCHECK(getter->IsSpecFunction() || getter->IsUndefined() || getter->IsNull());
6320   DCHECK(setter->IsSpecFunction() || setter->IsUndefined() || setter->IsNull());
6321   // At least one of the accessors needs to be a new value.
6322   DCHECK(!getter->IsNull() || !setter->IsNull());
6323   if (!getter->IsNull()) {
6324     it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
6325   }
6326   if (!setter->IsNull()) {
6327     it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
6328   }
6329
6330   if (is_observed) {
6331     // Make sure the top context isn't changed.
6332     AssertNoContextChange ncc(isolate);
6333     const char* type = preexists ? "reconfigure" : "add";
6334     RETURN_ON_EXCEPTION(
6335         isolate, EnqueueChangeRecord(object, type, name, old_value), Object);
6336   }
6337
6338   return isolate->factory()->undefined_value();
6339 }
6340
6341
6342 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6343                                           Handle<AccessorInfo> info) {
6344   Isolate* isolate = object->GetIsolate();
6345   Handle<Name> name(Name::cast(info->name()), isolate);
6346
6347   LookupIterator it = LookupIterator::PropertyOrElement(
6348       isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6349
6350   // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
6351   // the FailedAccessCheckCallbackFunction doesn't throw an exception.
6352   //
6353   // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
6354   // remove reliance on default return values.
6355   if (it.state() == LookupIterator::ACCESS_CHECK) {
6356     if (!it.HasAccess()) {
6357       isolate->ReportFailedAccessCheck(object);
6358       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6359       return it.factory()->undefined_value();
6360     }
6361     it.Next();
6362   }
6363
6364   // Ignore accessors on typed arrays.
6365   if (it.IsElement() && (object->HasFixedTypedArrayElements() ||
6366                          object->HasExternalArrayElements())) {
6367     return it.factory()->undefined_value();
6368   }
6369
6370   CHECK(GetPropertyAttributes(&it).IsJust());
6371
6372   // ES5 forbids turning a property into an accessor if it's not
6373   // configurable. See 8.6.1 (Table 5).
6374   if (it.IsFound() && !it.IsConfigurable()) {
6375     return it.factory()->undefined_value();
6376   }
6377
6378   it.TransitionToAccessorPair(info, info->property_attributes());
6379
6380   return object;
6381 }
6382
6383
6384 MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
6385                                           Handle<Name> name,
6386                                           AccessorComponent component) {
6387   Isolate* isolate = object->GetIsolate();
6388
6389   // Make sure that the top context does not change when doing callbacks or
6390   // interceptor calls.
6391   AssertNoContextChange ncc(isolate);
6392
6393   LookupIterator it = LookupIterator::PropertyOrElement(
6394       isolate, object, name, LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
6395
6396   for (; it.IsFound(); it.Next()) {
6397     switch (it.state()) {
6398       case LookupIterator::INTERCEPTOR:
6399       case LookupIterator::NOT_FOUND:
6400       case LookupIterator::TRANSITION:
6401         UNREACHABLE();
6402
6403       case LookupIterator::ACCESS_CHECK:
6404         if (it.HasAccess()) continue;
6405         isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
6406         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6407         return isolate->factory()->undefined_value();
6408
6409       case LookupIterator::JSPROXY:
6410         return isolate->factory()->undefined_value();
6411
6412       case LookupIterator::INTEGER_INDEXED_EXOTIC:
6413         return isolate->factory()->undefined_value();
6414       case LookupIterator::DATA:
6415         continue;
6416       case LookupIterator::ACCESSOR: {
6417         Handle<Object> maybe_pair = it.GetAccessors();
6418         if (maybe_pair->IsAccessorPair()) {
6419           return handle(
6420               AccessorPair::cast(*maybe_pair)->GetComponent(component),
6421               isolate);
6422         }
6423       }
6424     }
6425   }
6426
6427   return isolate->factory()->undefined_value();
6428 }
6429
6430
6431 Object* JSObject::SlowReverseLookup(Object* value) {
6432   if (HasFastProperties()) {
6433     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
6434     DescriptorArray* descs = map()->instance_descriptors();
6435     bool value_is_number = value->IsNumber();
6436     for (int i = 0; i < number_of_own_descriptors; i++) {
6437       if (descs->GetType(i) == DATA) {
6438         FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
6439         if (IsUnboxedDoubleField(field_index)) {
6440           if (value_is_number) {
6441             double property = RawFastDoublePropertyAt(field_index);
6442             if (property == value->Number()) {
6443               return descs->GetKey(i);
6444             }
6445           }
6446         } else {
6447           Object* property = RawFastPropertyAt(field_index);
6448           if (field_index.is_double()) {
6449             DCHECK(property->IsMutableHeapNumber());
6450             if (value_is_number && property->Number() == value->Number()) {
6451               return descs->GetKey(i);
6452             }
6453           } else if (property == value) {
6454             return descs->GetKey(i);
6455           }
6456         }
6457       } else if (descs->GetType(i) == DATA_CONSTANT) {
6458         if (descs->GetConstant(i) == value) {
6459           return descs->GetKey(i);
6460         }
6461       }
6462     }
6463     return GetHeap()->undefined_value();
6464   } else if (IsGlobalObject()) {
6465     return global_dictionary()->SlowReverseLookup(value);
6466   } else {
6467     return property_dictionary()->SlowReverseLookup(value);
6468   }
6469 }
6470
6471
6472 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
6473   Isolate* isolate = map->GetIsolate();
6474   Handle<Map> result =
6475       isolate->factory()->NewMap(map->instance_type(), instance_size);
6476   Handle<Object> prototype(map->prototype(), isolate);
6477   Map::SetPrototype(result, prototype);
6478   result->set_constructor_or_backpointer(map->GetConstructor());
6479   result->set_bit_field(map->bit_field());
6480   result->set_bit_field2(map->bit_field2());
6481   int new_bit_field3 = map->bit_field3();
6482   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6483   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6484   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6485                                           kInvalidEnumCacheSentinel);
6486   new_bit_field3 = Deprecated::update(new_bit_field3, false);
6487   if (!map->is_dictionary_map()) {
6488     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
6489   }
6490   new_bit_field3 = Counter::update(new_bit_field3, kRetainingCounterStart);
6491   result->set_bit_field3(new_bit_field3);
6492   return result;
6493 }
6494
6495
6496 Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode,
6497                            const char* reason) {
6498   DCHECK(!fast_map->is_dictionary_map());
6499
6500   Isolate* isolate = fast_map->GetIsolate();
6501   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
6502                              isolate);
6503   bool use_cache = !fast_map->is_prototype_map() && !maybe_cache->IsUndefined();
6504   Handle<NormalizedMapCache> cache;
6505   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
6506
6507   Handle<Map> new_map;
6508   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
6509 #ifdef VERIFY_HEAP
6510     if (FLAG_verify_heap) new_map->DictionaryMapVerify();
6511 #endif
6512 #ifdef ENABLE_SLOW_DCHECKS
6513     if (FLAG_enable_slow_asserts) {
6514       // The cached map should match newly created normalized map bit-by-bit,
6515       // except for the code cache, which can contain some ics which can be
6516       // applied to the shared map, dependent code and weak cell cache.
6517       Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
6518
6519       if (new_map->is_prototype_map()) {
6520         // For prototype maps, the PrototypeInfo is not copied.
6521         DCHECK(memcmp(fresh->address(), new_map->address(),
6522                       kTransitionsOrPrototypeInfoOffset) == 0);
6523         DCHECK(fresh->raw_transitions() == Smi::FromInt(0));
6524         STATIC_ASSERT(kDescriptorsOffset ==
6525                       kTransitionsOrPrototypeInfoOffset + kPointerSize);
6526         DCHECK(memcmp(HeapObject::RawField(*fresh, kDescriptorsOffset),
6527                       HeapObject::RawField(*new_map, kDescriptorsOffset),
6528                       kCodeCacheOffset - kDescriptorsOffset) == 0);
6529       } else {
6530         DCHECK(memcmp(fresh->address(), new_map->address(),
6531                       Map::kCodeCacheOffset) == 0);
6532       }
6533       STATIC_ASSERT(Map::kDependentCodeOffset ==
6534                     Map::kCodeCacheOffset + kPointerSize);
6535       STATIC_ASSERT(Map::kWeakCellCacheOffset ==
6536                     Map::kDependentCodeOffset + kPointerSize);
6537       int offset = Map::kWeakCellCacheOffset + kPointerSize;
6538       DCHECK(memcmp(fresh->address() + offset,
6539                     new_map->address() + offset,
6540                     Map::kSize - offset) == 0);
6541     }
6542 #endif
6543   } else {
6544     new_map = Map::CopyNormalized(fast_map, mode);
6545     if (use_cache) {
6546       cache->Set(fast_map, new_map);
6547       isolate->counters()->normalized_maps()->Increment();
6548     }
6549 #if TRACE_MAPS
6550     if (FLAG_trace_maps) {
6551       PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n",
6552              reinterpret_cast<void*>(*fast_map),
6553              reinterpret_cast<void*>(*new_map), reason);
6554     }
6555 #endif
6556   }
6557   fast_map->NotifyLeafMapLayoutChange();
6558   return new_map;
6559 }
6560
6561
6562 Handle<Map> Map::CopyNormalized(Handle<Map> map,
6563                                 PropertyNormalizationMode mode) {
6564   int new_instance_size = map->instance_size();
6565   if (mode == CLEAR_INOBJECT_PROPERTIES) {
6566     new_instance_size -= map->inobject_properties() * kPointerSize;
6567   }
6568
6569   Handle<Map> result = RawCopy(map, new_instance_size);
6570
6571   if (mode != CLEAR_INOBJECT_PROPERTIES) {
6572     result->set_inobject_properties(map->inobject_properties());
6573   }
6574
6575   result->set_dictionary_map(true);
6576   result->set_migration_target(false);
6577
6578 #ifdef VERIFY_HEAP
6579   if (FLAG_verify_heap) result->DictionaryMapVerify();
6580 #endif
6581
6582   return result;
6583 }
6584
6585
6586 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
6587   Handle<Map> result = RawCopy(map, map->instance_size());
6588
6589   // Please note instance_type and instance_size are set when allocated.
6590   result->set_inobject_properties(map->inobject_properties());
6591   result->set_unused_property_fields(map->unused_property_fields());
6592
6593   result->ClearCodeCache(map->GetHeap());
6594   map->NotifyLeafMapLayoutChange();
6595   return result;
6596 }
6597
6598
6599 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
6600                                  Handle<DescriptorArray> descriptors,
6601                                  Descriptor* descriptor) {
6602   // Sanity check. This path is only to be taken if the map owns its descriptor
6603   // array, implying that its NumberOfOwnDescriptors equals the number of
6604   // descriptors in the descriptor array.
6605   DCHECK(map->NumberOfOwnDescriptors() ==
6606          map->instance_descriptors()->number_of_descriptors());
6607
6608   Handle<Map> result = CopyDropDescriptors(map);
6609   Handle<Name> name = descriptor->GetKey();
6610
6611   // Ensure there's space for the new descriptor in the shared descriptor array.
6612   if (descriptors->NumberOfSlackDescriptors() == 0) {
6613     int old_size = descriptors->number_of_descriptors();
6614     if (old_size == 0) {
6615       descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
6616     } else {
6617       int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
6618       EnsureDescriptorSlack(map, slack);
6619       descriptors = handle(map->instance_descriptors());
6620     }
6621   }
6622
6623   Handle<LayoutDescriptor> layout_descriptor =
6624       FLAG_unbox_double_fields
6625           ? LayoutDescriptor::ShareAppend(map, descriptor->GetDetails())
6626           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
6627
6628   {
6629     DisallowHeapAllocation no_gc;
6630     descriptors->Append(descriptor);
6631     result->InitializeDescriptors(*descriptors, *layout_descriptor);
6632   }
6633
6634   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
6635   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
6636
6637   return result;
6638 }
6639
6640
6641 #if TRACE_MAPS
6642
6643 // static
6644 void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) {
6645   if (FLAG_trace_maps) {
6646     PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
6647            reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
6648     name->NameShortPrint();
6649     PrintF(" ]\n");
6650   }
6651 }
6652
6653
6654 // static
6655 void Map::TraceAllTransitions(Map* map) {
6656   Object* transitions = map->raw_transitions();
6657   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
6658   for (int i = -0; i < num_transitions; ++i) {
6659     Map* target = TransitionArray::GetTarget(transitions, i);
6660     Name* key = TransitionArray::GetKey(transitions, i);
6661     Map::TraceTransition("Transition", map, target, key);
6662     Map::TraceAllTransitions(target);
6663   }
6664 }
6665
6666 #endif  // TRACE_MAPS
6667
6668
6669 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
6670                             Handle<Name> name, SimpleTransitionFlag flag) {
6671   parent->set_owns_descriptors(false);
6672   if (parent->is_prototype_map()) {
6673     DCHECK(child->is_prototype_map());
6674 #if TRACE_MAPS
6675     Map::TraceTransition("NoTransition", *parent, *child, *name);
6676 #endif
6677   } else {
6678     TransitionArray::Insert(parent, name, child, flag);
6679 #if TRACE_MAPS
6680     Map::TraceTransition("Transition", *parent, *child, *name);
6681 #endif
6682   }
6683 }
6684
6685
6686 Handle<Map> Map::CopyReplaceDescriptors(
6687     Handle<Map> map, Handle<DescriptorArray> descriptors,
6688     Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
6689     MaybeHandle<Name> maybe_name, const char* reason,
6690     SimpleTransitionFlag simple_flag) {
6691   DCHECK(descriptors->IsSortedNoDuplicates());
6692
6693   Handle<Map> result = CopyDropDescriptors(map);
6694
6695   if (!map->is_prototype_map()) {
6696     if (flag == INSERT_TRANSITION &&
6697         TransitionArray::CanHaveMoreTransitions(map)) {
6698       result->InitializeDescriptors(*descriptors, *layout_descriptor);
6699
6700       Handle<Name> name;
6701       CHECK(maybe_name.ToHandle(&name));
6702       ConnectTransition(map, result, name, simple_flag);
6703     } else {
6704       int length = descriptors->number_of_descriptors();
6705       for (int i = 0; i < length; i++) {
6706         descriptors->SetRepresentation(i, Representation::Tagged());
6707         if (descriptors->GetDetails(i).type() == DATA) {
6708           descriptors->SetValue(i, HeapType::Any());
6709         }
6710       }
6711       result->InitializeDescriptors(*descriptors,
6712                                     LayoutDescriptor::FastPointerLayout());
6713     }
6714   } else {
6715     result->InitializeDescriptors(*descriptors, *layout_descriptor);
6716   }
6717 #if TRACE_MAPS
6718   if (FLAG_trace_maps &&
6719       // Mirror conditions above that did not call ConnectTransition().
6720       (map->is_prototype_map() ||
6721        !(flag == INSERT_TRANSITION &&
6722          TransitionArray::CanHaveMoreTransitions(map)))) {
6723     PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
6724            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
6725            reason);
6726   }
6727 #endif
6728
6729   return result;
6730 }
6731
6732
6733 // Since this method is used to rewrite an existing transition tree, it can
6734 // always insert transitions without checking.
6735 Handle<Map> Map::CopyInstallDescriptors(
6736     Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors,
6737     Handle<LayoutDescriptor> full_layout_descriptor) {
6738   DCHECK(descriptors->IsSortedNoDuplicates());
6739
6740   Handle<Map> result = CopyDropDescriptors(map);
6741
6742   result->set_instance_descriptors(*descriptors);
6743   result->SetNumberOfOwnDescriptors(new_descriptor + 1);
6744
6745   int unused_property_fields = map->unused_property_fields();
6746   PropertyDetails details = descriptors->GetDetails(new_descriptor);
6747   if (details.location() == kField) {
6748     unused_property_fields = map->unused_property_fields() - 1;
6749     if (unused_property_fields < 0) {
6750       unused_property_fields += JSObject::kFieldsAdded;
6751     }
6752   }
6753   result->set_unused_property_fields(unused_property_fields);
6754
6755   if (FLAG_unbox_double_fields) {
6756     Handle<LayoutDescriptor> layout_descriptor =
6757         LayoutDescriptor::AppendIfFastOrUseFull(map, details,
6758                                                 full_layout_descriptor);
6759     result->set_layout_descriptor(*layout_descriptor);
6760 #ifdef VERIFY_HEAP
6761     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
6762     if (FLAG_verify_heap) {
6763       CHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
6764     }
6765 #else
6766     SLOW_DCHECK(result->layout_descriptor()->IsConsistentWithMap(*result));
6767 #endif
6768     result->set_visitor_id(StaticVisitorBase::GetVisitorId(*result));
6769   }
6770
6771   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
6772   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
6773
6774   return result;
6775 }
6776
6777
6778 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
6779                                     TransitionFlag flag) {
6780   Map* maybe_elements_transition_map = NULL;
6781   if (flag == INSERT_TRANSITION) {
6782     maybe_elements_transition_map = map->ElementsTransitionMap();
6783     DCHECK(
6784         maybe_elements_transition_map == NULL ||
6785         ((maybe_elements_transition_map->elements_kind() ==
6786               DICTIONARY_ELEMENTS ||
6787           IsExternalArrayElementsKind(
6788               maybe_elements_transition_map->elements_kind())) &&
6789          (kind == DICTIONARY_ELEMENTS || IsExternalArrayElementsKind(kind))));
6790     DCHECK(!IsFastElementsKind(kind) ||
6791            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
6792     DCHECK(kind != map->elements_kind());
6793   }
6794
6795   bool insert_transition = flag == INSERT_TRANSITION &&
6796                            TransitionArray::CanHaveMoreTransitions(map) &&
6797                            maybe_elements_transition_map == NULL;
6798
6799   if (insert_transition) {
6800     Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
6801     new_map->set_elements_kind(kind);
6802
6803     Isolate* isolate = map->GetIsolate();
6804     Handle<Name> name = isolate->factory()->elements_transition_symbol();
6805     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
6806     return new_map;
6807   }
6808
6809   // Create a new free-floating map only if we are not allowed to store it.
6810   Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
6811   new_map->set_elements_kind(kind);
6812   return new_map;
6813 }
6814
6815
6816 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
6817   DCHECK(!map->is_observed());
6818
6819   Isolate* isolate = map->GetIsolate();
6820
6821   bool insert_transition =
6822       TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map();
6823
6824   if (insert_transition) {
6825     Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
6826     new_map->set_is_observed();
6827
6828     Handle<Name> name = isolate->factory()->observed_symbol();
6829     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
6830     return new_map;
6831   }
6832
6833   // Create a new free-floating map only if we are not allowed to store it.
6834   Handle<Map> new_map = Map::Copy(map, "CopyForObserved");
6835   new_map->set_is_observed();
6836   return new_map;
6837 }
6838
6839
6840 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
6841   DCHECK(!map->is_prototype_map());
6842   Handle<Map> new_map = CopyDropDescriptors(map);
6843
6844   if (map->owns_descriptors()) {
6845     // In case the map owned its own descriptors, share the descriptors and
6846     // transfer ownership to the new map.
6847     // The properties did not change, so reuse descriptors.
6848     new_map->InitializeDescriptors(map->instance_descriptors(),
6849                                    map->GetLayoutDescriptor());
6850   } else {
6851     // In case the map did not own its own descriptors, a split is forced by
6852     // copying the map; creating a new descriptor array cell.
6853     Handle<DescriptorArray> descriptors(map->instance_descriptors());
6854     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
6855     Handle<DescriptorArray> new_descriptors =
6856         DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
6857     Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
6858                                                    map->GetIsolate());
6859     new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
6860   }
6861
6862 #if TRACE_MAPS
6863   if (FLAG_trace_maps) {
6864     PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
6865            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
6866            reason);
6867   }
6868 #endif
6869
6870   return new_map;
6871 }
6872
6873
6874 Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
6875   Handle<DescriptorArray> descriptors(map->instance_descriptors());
6876   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
6877   Handle<DescriptorArray> new_descriptors =
6878       DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
6879   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
6880                                                  map->GetIsolate());
6881   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
6882                                 OMIT_TRANSITION, MaybeHandle<Name>(), reason,
6883                                 SPECIAL_TRANSITION);
6884 }
6885
6886
6887 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
6888   Handle<Map> copy =
6889       Copy(handle(isolate->object_function()->initial_map()), "MapCreate");
6890
6891   // Check that we do not overflow the instance size when adding the extra
6892   // inobject properties. If the instance size overflows, we allocate as many
6893   // properties as we can as inobject properties.
6894   int max_extra_properties =
6895       (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
6896
6897   if (inobject_properties > max_extra_properties) {
6898     inobject_properties = max_extra_properties;
6899   }
6900
6901   int new_instance_size =
6902       JSObject::kHeaderSize + kPointerSize * inobject_properties;
6903
6904   // Adjust the map with the extra inobject properties.
6905   copy->set_inobject_properties(inobject_properties);
6906   copy->set_unused_property_fields(inobject_properties);
6907   copy->set_instance_size(new_instance_size);
6908   copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
6909   return copy;
6910 }
6911
6912
6913 Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
6914                                           PropertyAttributes attrs_to_add,
6915                                           Handle<Symbol> transition_marker,
6916                                           const char* reason) {
6917   int num_descriptors = map->NumberOfOwnDescriptors();
6918   Isolate* isolate = map->GetIsolate();
6919   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
6920       handle(map->instance_descriptors(), isolate), num_descriptors,
6921       attrs_to_add);
6922   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
6923                                                  isolate);
6924   Handle<Map> new_map = CopyReplaceDescriptors(
6925       map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
6926       transition_marker, reason, SPECIAL_TRANSITION);
6927   new_map->set_is_extensible(false);
6928   new_map->set_elements_kind(DICTIONARY_ELEMENTS);
6929   return new_map;
6930 }
6931
6932
6933 Handle<Map> Map::FixProxy(Handle<Map> map, InstanceType type, int size) {
6934   DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE);
6935   DCHECK(map->IsJSProxyMap());
6936
6937   Isolate* isolate = map->GetIsolate();
6938
6939   // Allocate fresh map.
6940   // TODO(rossberg): Once we optimize proxies, cache these maps.
6941   Handle<Map> new_map = isolate->factory()->NewMap(type, size);
6942
6943   Handle<Object> prototype(map->prototype(), isolate);
6944   Map::SetPrototype(new_map, prototype);
6945
6946   map->NotifyLeafMapLayoutChange();
6947
6948   return new_map;
6949 }
6950
6951
6952 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
6953   PropertyDetails details = GetDetails(descriptor);
6954   switch (details.type()) {
6955     case DATA:
6956       return value->FitsRepresentation(details.representation()) &&
6957              GetFieldType(descriptor)->NowContains(value);
6958
6959     case DATA_CONSTANT:
6960       DCHECK(GetConstant(descriptor) != value ||
6961              value->FitsRepresentation(details.representation()));
6962       return GetConstant(descriptor) == value;
6963
6964     case ACCESSOR:
6965     case ACCESSOR_CONSTANT:
6966       return false;
6967   }
6968
6969   UNREACHABLE();
6970   return false;
6971 }
6972
6973
6974 // static
6975 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
6976                                         Handle<Object> value) {
6977   // Dictionaries can store any property value.
6978   if (map->is_dictionary_map()) return map;
6979
6980   // Migrate to the newest map before storing the property.
6981   map = Update(map);
6982
6983   Handle<DescriptorArray> descriptors(map->instance_descriptors());
6984
6985   if (descriptors->CanHoldValue(descriptor, *value)) return map;
6986
6987   Isolate* isolate = map->GetIsolate();
6988   PropertyAttributes attributes =
6989       descriptors->GetDetails(descriptor).attributes();
6990   Representation representation = value->OptimalRepresentation();
6991   Handle<HeapType> type = value->OptimalType(isolate, representation);
6992
6993   return ReconfigureProperty(map, descriptor, kData, attributes, representation,
6994                              type, FORCE_FIELD);
6995 }
6996
6997
6998 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
6999                                           Handle<Object> value,
7000                                           PropertyAttributes attributes,
7001                                           StoreFromKeyed store_mode) {
7002   // Dictionary maps can always have additional data properties.
7003   if (map->is_dictionary_map()) return map;
7004
7005   // Migrate to the newest map before storing the property.
7006   map = Update(map);
7007
7008   Map* maybe_transition =
7009       TransitionArray::SearchTransition(*map, kData, *name, attributes);
7010   if (maybe_transition != NULL) {
7011     Handle<Map> transition(maybe_transition);
7012     int descriptor = transition->LastAdded();
7013
7014     DCHECK_EQ(attributes, transition->instance_descriptors()
7015                               ->GetDetails(descriptor)
7016                               .attributes());
7017
7018     return Map::PrepareForDataProperty(transition, descriptor, value);
7019   }
7020
7021   TransitionFlag flag = INSERT_TRANSITION;
7022   MaybeHandle<Map> maybe_map;
7023   if (value->IsJSFunction()) {
7024     maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
7025   } else if (!map->TooManyFastProperties(store_mode)) {
7026     Isolate* isolate = name->GetIsolate();
7027     Representation representation = value->OptimalRepresentation();
7028     Handle<HeapType> type = value->OptimalType(isolate, representation);
7029     maybe_map =
7030         Map::CopyWithField(map, name, type, attributes, representation, flag);
7031   }
7032
7033   Handle<Map> result;
7034   if (!maybe_map.ToHandle(&result)) {
7035 #if TRACE_MAPS
7036     if (FLAG_trace_maps) {
7037       Vector<char> name_buffer = Vector<char>::New(100);
7038       name->NameShortPrint(name_buffer);
7039       Vector<char> buffer = Vector<char>::New(128);
7040       SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
7041       return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start());
7042     }
7043 #endif
7044     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
7045                           "TooManyFastProperties");
7046   }
7047
7048   return result;
7049 }
7050
7051
7052 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
7053                                              PropertyKind kind,
7054                                              PropertyAttributes attributes) {
7055   // Dictionaries have to be reconfigured in-place.
7056   DCHECK(!map->is_dictionary_map());
7057
7058   if (!map->GetBackPointer()->IsMap()) {
7059     // There is no benefit from reconstructing transition tree for maps without
7060     // back pointers.
7061     return CopyGeneralizeAllRepresentations(
7062         map, descriptor, FORCE_FIELD, kind, attributes,
7063         "GenAll_AttributesMismatchProtoMap");
7064   }
7065
7066   if (FLAG_trace_generalization) {
7067     map->PrintReconfiguration(stdout, descriptor, kind, attributes);
7068   }
7069
7070   Isolate* isolate = map->GetIsolate();
7071   Handle<Map> new_map = ReconfigureProperty(
7072       map, descriptor, kind, attributes, Representation::None(),
7073       HeapType::None(isolate), FORCE_FIELD);
7074   return new_map;
7075 }
7076
7077
7078 Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
7079                                               Handle<Name> name,
7080                                               AccessorComponent component,
7081                                               Handle<Object> accessor,
7082                                               PropertyAttributes attributes) {
7083   Isolate* isolate = name->GetIsolate();
7084
7085   // Dictionary maps can always have additional data properties.
7086   if (map->is_dictionary_map()) return map;
7087
7088   // Migrate to the newest map before transitioning to the new property.
7089   map = Update(map);
7090
7091   PropertyNormalizationMode mode = map->is_prototype_map()
7092                                        ? KEEP_INOBJECT_PROPERTIES
7093                                        : CLEAR_INOBJECT_PROPERTIES;
7094
7095   Map* maybe_transition =
7096       TransitionArray::SearchTransition(*map, kAccessor, *name, attributes);
7097   if (maybe_transition != NULL) {
7098     Handle<Map> transition(maybe_transition, isolate);
7099     DescriptorArray* descriptors = transition->instance_descriptors();
7100     int descriptor = transition->LastAdded();
7101     DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
7102
7103     DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
7104     DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
7105
7106     Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
7107     if (!maybe_pair->IsAccessorPair()) {
7108       return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
7109     }
7110
7111     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
7112     if (pair->get(component) != *accessor) {
7113       return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
7114     }
7115
7116     return transition;
7117   }
7118
7119   Handle<AccessorPair> pair;
7120   DescriptorArray* old_descriptors = map->instance_descriptors();
7121   int descriptor = old_descriptors->SearchWithCache(*name, *map);
7122   if (descriptor != DescriptorArray::kNotFound) {
7123     if (descriptor != map->LastAdded()) {
7124       return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
7125     }
7126     PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
7127     if (old_details.type() != ACCESSOR_CONSTANT) {
7128       return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
7129     }
7130
7131     if (old_details.attributes() != attributes) {
7132       return Map::Normalize(map, mode, "AccessorsWithAttributes");
7133     }
7134
7135     Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
7136     if (!maybe_pair->IsAccessorPair()) {
7137       return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
7138     }
7139
7140     Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component);
7141     if (current == *accessor) return map;
7142
7143     if (!current->IsTheHole()) {
7144       return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
7145     }
7146
7147     pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
7148   } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
7149              map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
7150     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors");
7151   } else {
7152     pair = isolate->factory()->NewAccessorPair();
7153   }
7154
7155   pair->set(component, *accessor);
7156   TransitionFlag flag = INSERT_TRANSITION;
7157   AccessorConstantDescriptor new_desc(name, pair, attributes);
7158   return Map::CopyInsertDescriptor(map, &new_desc, flag);
7159 }
7160
7161
7162 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7163                                    Descriptor* descriptor,
7164                                    TransitionFlag flag) {
7165   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7166
7167   // Ensure the key is unique.
7168   descriptor->KeyToUniqueName();
7169
7170   if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
7171       TransitionArray::CanHaveMoreTransitions(map)) {
7172     return ShareDescriptor(map, descriptors, descriptor);
7173   }
7174
7175   int nof = map->NumberOfOwnDescriptors();
7176   Handle<DescriptorArray> new_descriptors =
7177       DescriptorArray::CopyUpTo(descriptors, nof, 1);
7178   new_descriptors->Append(descriptor);
7179
7180   Handle<LayoutDescriptor> new_layout_descriptor =
7181       FLAG_unbox_double_fields
7182           ? LayoutDescriptor::New(map, new_descriptors, nof + 1)
7183           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
7184
7185   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7186                                 flag, descriptor->GetKey(), "CopyAddDescriptor",
7187                                 SIMPLE_PROPERTY_TRANSITION);
7188 }
7189
7190
7191 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
7192                                       Descriptor* descriptor,
7193                                       TransitionFlag flag) {
7194   Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
7195
7196   // Ensure the key is unique.
7197   descriptor->KeyToUniqueName();
7198
7199   // We replace the key if it is already present.
7200   int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
7201   if (index != DescriptorArray::kNotFound) {
7202     return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
7203   }
7204   return CopyAddDescriptor(map, descriptor, flag);
7205 }
7206
7207
7208 Handle<DescriptorArray> DescriptorArray::CopyUpTo(
7209     Handle<DescriptorArray> desc,
7210     int enumeration_index,
7211     int slack) {
7212   return DescriptorArray::CopyUpToAddAttributes(
7213       desc, enumeration_index, NONE, slack);
7214 }
7215
7216
7217 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
7218     Handle<DescriptorArray> desc,
7219     int enumeration_index,
7220     PropertyAttributes attributes,
7221     int slack) {
7222   if (enumeration_index + slack == 0) {
7223     return desc->GetIsolate()->factory()->empty_descriptor_array();
7224   }
7225
7226   int size = enumeration_index;
7227
7228   Handle<DescriptorArray> descriptors =
7229       DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
7230   DescriptorArray::WhitenessWitness witness(*descriptors);
7231
7232   if (attributes != NONE) {
7233     for (int i = 0; i < size; ++i) {
7234       Object* value = desc->GetValue(i);
7235       Name* key = desc->GetKey(i);
7236       PropertyDetails details = desc->GetDetails(i);
7237       // Bulk attribute changes never affect private properties.
7238       if (!key->IsSymbol() || !Symbol::cast(key)->is_private()) {
7239         int mask = DONT_DELETE | DONT_ENUM;
7240         // READ_ONLY is an invalid attribute for JS setters/getters.
7241         if (details.type() != ACCESSOR_CONSTANT || !value->IsAccessorPair()) {
7242           mask |= READ_ONLY;
7243         }
7244         details = details.CopyAddAttributes(
7245             static_cast<PropertyAttributes>(attributes & mask));
7246       }
7247       Descriptor inner_desc(
7248           handle(key), handle(value, desc->GetIsolate()), details);
7249       descriptors->Set(i, &inner_desc, witness);
7250     }
7251   } else {
7252     for (int i = 0; i < size; ++i) {
7253       descriptors->CopyFrom(i, *desc, witness);
7254     }
7255   }
7256
7257   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
7258
7259   return descriptors;
7260 }
7261
7262
7263 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
7264                                        Handle<DescriptorArray> descriptors,
7265                                        Descriptor* descriptor,
7266                                        int insertion_index,
7267                                        TransitionFlag flag) {
7268   // Ensure the key is unique.
7269   descriptor->KeyToUniqueName();
7270
7271   Handle<Name> key = descriptor->GetKey();
7272   DCHECK(*key == descriptors->GetKey(insertion_index));
7273
7274   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7275       descriptors, map->NumberOfOwnDescriptors());
7276
7277   new_descriptors->Replace(insertion_index, descriptor);
7278   Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
7279       map, new_descriptors, new_descriptors->number_of_descriptors());
7280
7281   SimpleTransitionFlag simple_flag =
7282       (insertion_index == descriptors->number_of_descriptors() - 1)
7283           ? SIMPLE_PROPERTY_TRANSITION
7284           : PROPERTY_TRANSITION;
7285   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
7286                                 flag, key, "CopyReplaceDescriptor",
7287                                 simple_flag);
7288 }
7289
7290
7291 void Map::UpdateCodeCache(Handle<Map> map,
7292                           Handle<Name> name,
7293                           Handle<Code> code) {
7294   Isolate* isolate = map->GetIsolate();
7295   HandleScope scope(isolate);
7296   // Allocate the code cache if not present.
7297   if (map->code_cache()->IsFixedArray()) {
7298     Handle<Object> result = isolate->factory()->NewCodeCache();
7299     map->set_code_cache(*result);
7300   }
7301
7302   // Update the code cache.
7303   Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
7304   CodeCache::Update(code_cache, name, code);
7305 }
7306
7307
7308 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
7309   // Do a lookup if a code cache exists.
7310   if (!code_cache()->IsFixedArray()) {
7311     return CodeCache::cast(code_cache())->Lookup(name, flags);
7312   } else {
7313     return GetHeap()->undefined_value();
7314   }
7315 }
7316
7317
7318 int Map::IndexInCodeCache(Object* name, Code* code) {
7319   // Get the internal index if a code cache exists.
7320   if (!code_cache()->IsFixedArray()) {
7321     return CodeCache::cast(code_cache())->GetIndex(name, code);
7322   }
7323   return -1;
7324 }
7325
7326
7327 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7328   // No GC is supposed to happen between a call to IndexInCodeCache and
7329   // RemoveFromCodeCache so the code cache must be there.
7330   DCHECK(!code_cache()->IsFixedArray());
7331   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7332 }
7333
7334
7335 void CodeCache::Update(
7336     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7337   // The number of monomorphic stubs for normal load/store/call IC's can grow to
7338   // a large number and therefore they need to go into a hash table. They are
7339   // used to load global properties from cells.
7340   if (code->type() == Code::NORMAL) {
7341     // Make sure that a hash table is allocated for the normal load code cache.
7342     if (code_cache->normal_type_cache()->IsUndefined()) {
7343       Handle<Object> result =
7344           CodeCacheHashTable::New(code_cache->GetIsolate(),
7345                                   CodeCacheHashTable::kInitialSize);
7346       code_cache->set_normal_type_cache(*result);
7347     }
7348     UpdateNormalTypeCache(code_cache, name, code);
7349   } else {
7350     DCHECK(code_cache->default_cache()->IsFixedArray());
7351     UpdateDefaultCache(code_cache, name, code);
7352   }
7353 }
7354
7355
7356 void CodeCache::UpdateDefaultCache(
7357     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7358   // When updating the default code cache we disregard the type encoded in the
7359   // flags. This allows call constant stubs to overwrite call field
7360   // stubs, etc.
7361   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7362
7363   // First check whether we can update existing code cache without
7364   // extending it.
7365   Handle<FixedArray> cache = handle(code_cache->default_cache());
7366   int length = cache->length();
7367   {
7368     DisallowHeapAllocation no_alloc;
7369     int deleted_index = -1;
7370     for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7371       Object* key = cache->get(i);
7372       if (key->IsNull()) {
7373         if (deleted_index < 0) deleted_index = i;
7374         continue;
7375       }
7376       if (key->IsUndefined()) {
7377         if (deleted_index >= 0) i = deleted_index;
7378         cache->set(i + kCodeCacheEntryNameOffset, *name);
7379         cache->set(i + kCodeCacheEntryCodeOffset, *code);
7380         return;
7381       }
7382       if (name->Equals(Name::cast(key))) {
7383         Code::Flags found =
7384             Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7385         if (Code::RemoveTypeFromFlags(found) == flags) {
7386           cache->set(i + kCodeCacheEntryCodeOffset, *code);
7387           return;
7388         }
7389       }
7390     }
7391
7392     // Reached the end of the code cache.  If there were deleted
7393     // elements, reuse the space for the first of them.
7394     if (deleted_index >= 0) {
7395       cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
7396       cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
7397       return;
7398     }
7399   }
7400
7401   // Extend the code cache with some new entries (at least one). Must be a
7402   // multiple of the entry size.
7403   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7404   new_length = new_length - new_length % kCodeCacheEntrySize;
7405   DCHECK((new_length % kCodeCacheEntrySize) == 0);
7406   cache = FixedArray::CopySize(cache, new_length);
7407
7408   // Add the (name, code) pair to the new cache.
7409   cache->set(length + kCodeCacheEntryNameOffset, *name);
7410   cache->set(length + kCodeCacheEntryCodeOffset, *code);
7411   code_cache->set_default_cache(*cache);
7412 }
7413
7414
7415 void CodeCache::UpdateNormalTypeCache(
7416     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7417   // Adding a new entry can cause a new cache to be allocated.
7418   Handle<CodeCacheHashTable> cache(
7419       CodeCacheHashTable::cast(code_cache->normal_type_cache()));
7420   Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
7421   code_cache->set_normal_type_cache(*new_cache);
7422 }
7423
7424
7425 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
7426   Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7427   if (result->IsCode()) {
7428     if (Code::cast(result)->flags() == flags) return result;
7429     return GetHeap()->undefined_value();
7430   }
7431   return LookupNormalTypeCache(name, flags);
7432 }
7433
7434
7435 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
7436   FixedArray* cache = default_cache();
7437   int length = cache->length();
7438   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7439     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7440     // Skip deleted elements.
7441     if (key->IsNull()) continue;
7442     if (key->IsUndefined()) return key;
7443     if (name->Equals(Name::cast(key))) {
7444       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
7445       if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
7446         return code;
7447       }
7448     }
7449   }
7450   return GetHeap()->undefined_value();
7451 }
7452
7453
7454 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
7455   if (!normal_type_cache()->IsUndefined()) {
7456     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7457     return cache->Lookup(name, flags);
7458   } else {
7459     return GetHeap()->undefined_value();
7460   }
7461 }
7462
7463
7464 int CodeCache::GetIndex(Object* name, Code* code) {
7465   if (code->type() == Code::NORMAL) {
7466     if (normal_type_cache()->IsUndefined()) return -1;
7467     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7468     return cache->GetIndex(Name::cast(name), code->flags());
7469   }
7470
7471   FixedArray* array = default_cache();
7472   int len = array->length();
7473   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
7474     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
7475   }
7476   return -1;
7477 }
7478
7479
7480 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
7481   if (code->type() == Code::NORMAL) {
7482     DCHECK(!normal_type_cache()->IsUndefined());
7483     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7484     DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
7485     cache->RemoveByIndex(index);
7486   } else {
7487     FixedArray* array = default_cache();
7488     DCHECK(array->length() >= index && array->get(index)->IsCode());
7489     // Use null instead of undefined for deleted elements to distinguish
7490     // deleted elements from unused elements.  This distinction is used
7491     // when looking up in the cache and when updating the cache.
7492     DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
7493     array->set_null(index - 1);  // Name.
7494     array->set_null(index);  // Code.
7495   }
7496 }
7497
7498
7499 // The key in the code cache hash table consists of the property name and the
7500 // code object. The actual match is on the name and the code flags. If a key
7501 // is created using the flags and not a code object it can only be used for
7502 // lookup not to create a new entry.
7503 class CodeCacheHashTableKey : public HashTableKey {
7504  public:
7505   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
7506       : name_(name), flags_(flags), code_() { }
7507
7508   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
7509       : name_(name), flags_(code->flags()), code_(code) { }
7510
7511   bool IsMatch(Object* other) override {
7512     if (!other->IsFixedArray()) return false;
7513     FixedArray* pair = FixedArray::cast(other);
7514     Name* name = Name::cast(pair->get(0));
7515     Code::Flags flags = Code::cast(pair->get(1))->flags();
7516     if (flags != flags_) {
7517       return false;
7518     }
7519     return name_->Equals(name);
7520   }
7521
7522   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
7523     return name->Hash() ^ flags;
7524   }
7525
7526   uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); }
7527
7528   uint32_t HashForObject(Object* obj) override {
7529     FixedArray* pair = FixedArray::cast(obj);
7530     Name* name = Name::cast(pair->get(0));
7531     Code* code = Code::cast(pair->get(1));
7532     return NameFlagsHashHelper(name, code->flags());
7533   }
7534
7535   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
7536     Handle<Code> code = code_.ToHandleChecked();
7537     Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
7538     pair->set(0, *name_);
7539     pair->set(1, *code);
7540     return pair;
7541   }
7542
7543  private:
7544   Handle<Name> name_;
7545   Code::Flags flags_;
7546   // TODO(jkummerow): We should be able to get by without this.
7547   MaybeHandle<Code> code_;
7548 };
7549
7550
7551 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
7552   DisallowHeapAllocation no_alloc;
7553   CodeCacheHashTableKey key(handle(name), flags);
7554   int entry = FindEntry(&key);
7555   if (entry == kNotFound) return GetHeap()->undefined_value();
7556   return get(EntryToIndex(entry) + 1);
7557 }
7558
7559
7560 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
7561     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
7562   CodeCacheHashTableKey key(name, code);
7563
7564   Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
7565
7566   int entry = new_cache->FindInsertionEntry(key.Hash());
7567   Handle<Object> k = key.AsHandle(cache->GetIsolate());
7568
7569   new_cache->set(EntryToIndex(entry), *k);
7570   new_cache->set(EntryToIndex(entry) + 1, *code);
7571   new_cache->ElementAdded();
7572   return new_cache;
7573 }
7574
7575
7576 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
7577   DisallowHeapAllocation no_alloc;
7578   CodeCacheHashTableKey key(handle(name), flags);
7579   int entry = FindEntry(&key);
7580   return (entry == kNotFound) ? -1 : entry;
7581 }
7582
7583
7584 void CodeCacheHashTable::RemoveByIndex(int index) {
7585   DCHECK(index >= 0);
7586   Heap* heap = GetHeap();
7587   set(EntryToIndex(index), heap->the_hole_value());
7588   set(EntryToIndex(index) + 1, heap->the_hole_value());
7589   ElementRemoved();
7590 }
7591
7592
7593 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
7594                                   MapHandleList* maps,
7595                                   Code::Flags flags,
7596                                   Handle<Code> code) {
7597   Isolate* isolate = code_cache->GetIsolate();
7598   if (code_cache->cache()->IsUndefined()) {
7599     Handle<PolymorphicCodeCacheHashTable> result =
7600         PolymorphicCodeCacheHashTable::New(
7601             isolate,
7602             PolymorphicCodeCacheHashTable::kInitialSize);
7603     code_cache->set_cache(*result);
7604   } else {
7605     // This entry shouldn't be contained in the cache yet.
7606     DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
7607                ->Lookup(maps, flags)->IsUndefined());
7608   }
7609   Handle<PolymorphicCodeCacheHashTable> hash_table =
7610       handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
7611   Handle<PolymorphicCodeCacheHashTable> new_cache =
7612       PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
7613   code_cache->set_cache(*new_cache);
7614 }
7615
7616
7617 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
7618                                             Code::Flags flags) {
7619   if (!cache()->IsUndefined()) {
7620     PolymorphicCodeCacheHashTable* hash_table =
7621         PolymorphicCodeCacheHashTable::cast(cache());
7622     return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
7623   } else {
7624     return GetIsolate()->factory()->undefined_value();
7625   }
7626 }
7627
7628
7629 // Despite their name, object of this class are not stored in the actual
7630 // hash table; instead they're temporarily used for lookups. It is therefore
7631 // safe to have a weak (non-owning) pointer to a MapList as a member field.
7632 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
7633  public:
7634   // Callers must ensure that |maps| outlives the newly constructed object.
7635   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
7636       : maps_(maps),
7637         code_flags_(code_flags) {}
7638
7639   bool IsMatch(Object* other) override {
7640     MapHandleList other_maps(kDefaultListAllocationSize);
7641     int other_flags;
7642     FromObject(other, &other_flags, &other_maps);
7643     if (code_flags_ != other_flags) return false;
7644     if (maps_->length() != other_maps.length()) return false;
7645     // Compare just the hashes first because it's faster.
7646     int this_hash = MapsHashHelper(maps_, code_flags_);
7647     int other_hash = MapsHashHelper(&other_maps, other_flags);
7648     if (this_hash != other_hash) return false;
7649
7650     // Full comparison: for each map in maps_, look for an equivalent map in
7651     // other_maps. This implementation is slow, but probably good enough for
7652     // now because the lists are short (<= 4 elements currently).
7653     for (int i = 0; i < maps_->length(); ++i) {
7654       bool match_found = false;
7655       for (int j = 0; j < other_maps.length(); ++j) {
7656         if (*(maps_->at(i)) == *(other_maps.at(j))) {
7657           match_found = true;
7658           break;
7659         }
7660       }
7661       if (!match_found) return false;
7662     }
7663     return true;
7664   }
7665
7666   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
7667     uint32_t hash = code_flags;
7668     for (int i = 0; i < maps->length(); ++i) {
7669       hash ^= maps->at(i)->Hash();
7670     }
7671     return hash;
7672   }
7673
7674   uint32_t Hash() override { return MapsHashHelper(maps_, code_flags_); }
7675
7676   uint32_t HashForObject(Object* obj) override {
7677     MapHandleList other_maps(kDefaultListAllocationSize);
7678     int other_flags;
7679     FromObject(obj, &other_flags, &other_maps);
7680     return MapsHashHelper(&other_maps, other_flags);
7681   }
7682
7683   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
7684     // The maps in |maps_| must be copied to a newly allocated FixedArray,
7685     // both because the referenced MapList is short-lived, and because C++
7686     // objects can't be stored in the heap anyway.
7687     Handle<FixedArray> list =
7688         isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
7689     list->set(0, Smi::FromInt(code_flags_));
7690     for (int i = 0; i < maps_->length(); ++i) {
7691       list->set(i + 1, *maps_->at(i));
7692     }
7693     return list;
7694   }
7695
7696  private:
7697   static MapHandleList* FromObject(Object* obj,
7698                                    int* code_flags,
7699                                    MapHandleList* maps) {
7700     FixedArray* list = FixedArray::cast(obj);
7701     maps->Rewind(0);
7702     *code_flags = Smi::cast(list->get(0))->value();
7703     for (int i = 1; i < list->length(); ++i) {
7704       maps->Add(Handle<Map>(Map::cast(list->get(i))));
7705     }
7706     return maps;
7707   }
7708
7709   MapHandleList* maps_;  // weak.
7710   int code_flags_;
7711   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
7712 };
7713
7714
7715 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
7716                                               int code_kind) {
7717   DisallowHeapAllocation no_alloc;
7718   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7719   int entry = FindEntry(&key);
7720   if (entry == kNotFound) return GetHeap()->undefined_value();
7721   return get(EntryToIndex(entry) + 1);
7722 }
7723
7724
7725 Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
7726       Handle<PolymorphicCodeCacheHashTable> hash_table,
7727       MapHandleList* maps,
7728       int code_kind,
7729       Handle<Code> code) {
7730   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7731   Handle<PolymorphicCodeCacheHashTable> cache =
7732       EnsureCapacity(hash_table, 1, &key);
7733   int entry = cache->FindInsertionEntry(key.Hash());
7734
7735   Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
7736   cache->set(EntryToIndex(entry), *obj);
7737   cache->set(EntryToIndex(entry) + 1, *code);
7738   cache->ElementAdded();
7739   return cache;
7740 }
7741
7742
7743 void FixedArray::Shrink(int new_length) {
7744   DCHECK(0 <= new_length && new_length <= length());
7745   if (new_length < length()) {
7746     GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
7747         this, length() - new_length);
7748   }
7749 }
7750
7751
7752 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
7753     Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) {
7754   DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
7755   ElementsAccessor* accessor = array->GetElementsAccessor();
7756   Handle<FixedArray> result =
7757       accessor->AddElementsToFixedArray(array, content, filter);
7758
7759 #ifdef ENABLE_SLOW_DCHECKS
7760   if (FLAG_enable_slow_asserts) {
7761     DisallowHeapAllocation no_allocation;
7762     for (int i = 0; i < result->length(); i++) {
7763       Object* current = result->get(i);
7764       DCHECK(current->IsNumber() || current->IsName());
7765     }
7766   }
7767 #endif
7768   return result;
7769 }
7770
7771
7772 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
7773                                                 Handle<FixedArray> second) {
7774   if (second->length() == 0) return first;
7775   if (first->length() == 0) return second;
7776   Isolate* isolate = first->GetIsolate();
7777   Handle<FixedArray> result =
7778       isolate->factory()->NewFixedArray(first->length() + second->length());
7779   for (int i = 0; i < first->length(); i++) {
7780     result->set(i, first->get(i));
7781   }
7782   int pos = first->length();
7783   for (int j = 0; j < second->length(); j++) {
7784     Object* current = second->get(j);
7785     int i;
7786     for (i = 0; i < first->length(); i++) {
7787       if (current->KeyEquals(first->get(i))) break;
7788     }
7789     if (i == first->length()) {
7790       result->set(pos++, current);
7791     }
7792   }
7793
7794   result->Shrink(pos);
7795   return result;
7796 }
7797
7798
7799 Handle<FixedArray> FixedArray::CopySize(
7800     Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
7801   Isolate* isolate = array->GetIsolate();
7802   if (new_length == 0) return isolate->factory()->empty_fixed_array();
7803   Handle<FixedArray> result =
7804       isolate->factory()->NewFixedArray(new_length, pretenure);
7805   // Copy the content
7806   DisallowHeapAllocation no_gc;
7807   int len = array->length();
7808   if (new_length < len) len = new_length;
7809   // We are taking the map from the old fixed array so the map is sure to
7810   // be an immortal immutable object.
7811   result->set_map_no_write_barrier(array->map());
7812   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
7813   for (int i = 0; i < len; i++) {
7814     result->set(i, array->get(i), mode);
7815   }
7816   return result;
7817 }
7818
7819
7820 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
7821   DisallowHeapAllocation no_gc;
7822   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
7823   for (int index = 0; index < len; index++) {
7824     dest->set(dest_pos+index, get(pos+index), mode);
7825   }
7826 }
7827
7828
7829 #ifdef DEBUG
7830 bool FixedArray::IsEqualTo(FixedArray* other) {
7831   if (length() != other->length()) return false;
7832   for (int i = 0 ; i < length(); ++i) {
7833     if (get(i) != other->get(i)) return false;
7834   }
7835   return true;
7836 }
7837 #endif
7838
7839
7840 // static
7841 void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
7842                          Handle<HeapObject> value) {
7843   DCHECK(array->IsEmptySlot(index));  // Don't overwrite anything.
7844   Handle<WeakCell> cell =
7845       value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
7846                      : array->GetIsolate()->factory()->NewWeakCell(value);
7847   Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
7848   if (FLAG_trace_weak_arrays) {
7849     PrintF("[WeakFixedArray: storing at index %d ]\n", index);
7850   }
7851   array->set_last_used_index(index);
7852 }
7853
7854
7855 // static
7856 Handle<WeakFixedArray> WeakFixedArray::Add(
7857     Handle<Object> maybe_array, Handle<HeapObject> value,
7858     SearchForDuplicates search_for_duplicates, bool* was_present) {
7859   Handle<WeakFixedArray> array =
7860       (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
7861           ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
7862           : Handle<WeakFixedArray>::cast(maybe_array);
7863   if (was_present != NULL) *was_present = false;
7864   if (search_for_duplicates == kAddIfNotFound) {
7865     for (int i = 0; i < array->Length(); ++i) {
7866       if (array->Get(i) == *value) {
7867         if (was_present != NULL) *was_present = true;
7868         return array;
7869       }
7870     }
7871 #if 0  // Enable this if you want to check your search_for_duplicates flags.
7872   } else {
7873     for (int i = 0; i < array->Length(); ++i) {
7874       DCHECK_NE(*value, array->Get(i));
7875     }
7876 #endif
7877   }
7878
7879   // Try to store the new entry if there's room. Optimize for consecutive
7880   // accesses.
7881   int first_index = array->last_used_index();
7882   if (array->Length() > 0) {
7883     for (int i = first_index;;) {
7884       if (array->IsEmptySlot((i))) {
7885         WeakFixedArray::Set(array, i, value);
7886         return array;
7887       }
7888       if (FLAG_trace_weak_arrays) {
7889         PrintF("[WeakFixedArray: searching for free slot]\n");
7890       }
7891       i = (i + 1) % array->Length();
7892       if (i == first_index) break;
7893     }
7894   }
7895
7896   // No usable slot found, grow the array.
7897   int new_length =
7898       array->Length() == 0 ? 1 : array->Length() + (array->Length() >> 1) + 4;
7899   Handle<WeakFixedArray> new_array =
7900       Allocate(array->GetIsolate(), new_length, array);
7901   if (FLAG_trace_weak_arrays) {
7902     PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
7903   }
7904   WeakFixedArray::Set(new_array, array->Length(), value);
7905   return new_array;
7906 }
7907
7908
7909 void WeakFixedArray::Compact() {
7910   FixedArray* array = FixedArray::cast(this);
7911   int new_length = kFirstIndex;
7912   for (int i = kFirstIndex; i < array->length(); i++) {
7913     Object* element = array->get(i);
7914     if (element->IsSmi()) continue;
7915     if (WeakCell::cast(element)->cleared()) continue;
7916     array->set(new_length++, element);
7917   }
7918   array->Shrink(new_length);
7919   set_last_used_index(0);
7920 }
7921
7922
7923 bool WeakFixedArray::Remove(Handle<HeapObject> value) {
7924   if (Length() == 0) return false;
7925   // Optimize for the most recently added element to be removed again.
7926   int first_index = last_used_index();
7927   for (int i = first_index;;) {
7928     if (Get(i) == *value) {
7929       Clear(i);
7930       // Users of WeakFixedArray should make sure that there are no duplicates,
7931       // they can use Add(..., kAddIfNotFound) if necessary.
7932       return true;
7933     }
7934     i = (i + 1) % Length();
7935     if (i == first_index) return false;
7936   }
7937   UNREACHABLE();
7938 }
7939
7940
7941 // static
7942 Handle<WeakFixedArray> WeakFixedArray::Allocate(
7943     Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
7944   DCHECK(0 <= size);
7945   Handle<FixedArray> result =
7946       isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
7947   Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result);
7948   if (initialize_from.is_null()) {
7949     for (int i = 0; i < result->length(); ++i) {
7950       result->set(i, Smi::FromInt(0));
7951     }
7952   } else {
7953     DCHECK(initialize_from->Length() <= size);
7954     Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
7955     int target_index = kFirstIndex;
7956     for (int source_index = kFirstIndex; source_index < raw_source->length();
7957          ++source_index) {
7958       // The act of allocating might have caused entries in the source array
7959       // to be cleared. Copy only what's needed.
7960       if (initialize_from->IsEmptySlot(source_index - kFirstIndex)) continue;
7961       result->set(target_index++, raw_source->get(source_index));
7962     }
7963     casted_result->set_last_used_index(target_index - 1 - kFirstIndex);
7964     for (; target_index < result->length(); ++target_index) {
7965       result->set(target_index, Smi::FromInt(0));
7966     }
7967   }
7968   return casted_result;
7969 }
7970
7971
7972 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj,
7973                                  AddMode mode) {
7974   int length = array->Length();
7975   array = EnsureSpace(array, length + 1);
7976   if (mode == kReloadLengthAfterAllocation) {
7977     DCHECK(array->Length() <= length);
7978     length = array->Length();
7979   }
7980   array->Set(length, *obj);
7981   array->SetLength(length + 1);
7982   return array;
7983 }
7984
7985
7986 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1,
7987                                  Handle<Object> obj2, AddMode mode) {
7988   int length = array->Length();
7989   array = EnsureSpace(array, length + 2);
7990   if (mode == kReloadLengthAfterAllocation) {
7991     length = array->Length();
7992   }
7993   array->Set(length, *obj1);
7994   array->Set(length + 1, *obj2);
7995   array->SetLength(length + 2);
7996   return array;
7997 }
7998
7999
8000 Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
8001   int capacity = array->length();
8002   bool empty = (capacity == 0);
8003   if (capacity < kFirstIndex + length) {
8004     capacity = kFirstIndex + length;
8005     capacity = capacity + Max(capacity / 2, 2);
8006     array = Handle<ArrayList>::cast(FixedArray::CopySize(array, capacity));
8007     if (empty) array->SetLength(0);
8008   }
8009   return array;
8010 }
8011
8012
8013 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
8014                                                   int number_of_descriptors,
8015                                                   int slack) {
8016   DCHECK(0 <= number_of_descriptors);
8017   Factory* factory = isolate->factory();
8018   // Do not use DescriptorArray::cast on incomplete object.
8019   int size = number_of_descriptors + slack;
8020   if (size == 0) return factory->empty_descriptor_array();
8021   // Allocate the array of keys.
8022   Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
8023
8024   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
8025   result->set(kEnumCacheIndex, Smi::FromInt(0));
8026   return Handle<DescriptorArray>::cast(result);
8027 }
8028
8029
8030 void DescriptorArray::ClearEnumCache() {
8031   set(kEnumCacheIndex, Smi::FromInt(0));
8032 }
8033
8034
8035 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
8036   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
8037   Set(index, descriptor);
8038 }
8039
8040
8041 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
8042                                    FixedArray* new_cache,
8043                                    Object* new_index_cache) {
8044   DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
8045   DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
8046   DCHECK(!IsEmpty());
8047   DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
8048   FixedArray::cast(bridge_storage)->
8049     set(kEnumCacheBridgeCacheIndex, new_cache);
8050   FixedArray::cast(bridge_storage)->
8051     set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
8052   set(kEnumCacheIndex, bridge_storage);
8053 }
8054
8055
8056 void DescriptorArray::CopyFrom(int index, DescriptorArray* src,
8057                                const WhitenessWitness& witness) {
8058   Object* value = src->GetValue(index);
8059   PropertyDetails details = src->GetDetails(index);
8060   Descriptor desc(handle(src->GetKey(index)),
8061                   handle(value, src->GetIsolate()),
8062                   details);
8063   Set(index, &desc, witness);
8064 }
8065
8066
8067 // We need the whiteness witness since sort will reshuffle the entries in the
8068 // descriptor array. If the descriptor array were to be black, the shuffling
8069 // would move a slot that was already recorded as pointing into an evacuation
8070 // candidate. This would result in missing updates upon evacuation.
8071 void DescriptorArray::Sort() {
8072   // In-place heap sort.
8073   int len = number_of_descriptors();
8074   // Reset sorting since the descriptor array might contain invalid pointers.
8075   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
8076   // Bottom-up max-heap construction.
8077   // Index of the last node with children
8078   const int max_parent_index = (len / 2) - 1;
8079   for (int i = max_parent_index; i >= 0; --i) {
8080     int parent_index = i;
8081     const uint32_t parent_hash = GetSortedKey(i)->Hash();
8082     while (parent_index <= max_parent_index) {
8083       int child_index = 2 * parent_index + 1;
8084       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8085       if (child_index + 1 < len) {
8086         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8087         if (right_child_hash > child_hash) {
8088           child_index++;
8089           child_hash = right_child_hash;
8090         }
8091       }
8092       if (child_hash <= parent_hash) break;
8093       SwapSortedKeys(parent_index, child_index);
8094       // Now element at child_index could be < its children.
8095       parent_index = child_index;  // parent_hash remains correct.
8096     }
8097   }
8098
8099   // Extract elements and create sorted array.
8100   for (int i = len - 1; i > 0; --i) {
8101     // Put max element at the back of the array.
8102     SwapSortedKeys(0, i);
8103     // Shift down the new top element.
8104     int parent_index = 0;
8105     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
8106     const int max_parent_index = (i / 2) - 1;
8107     while (parent_index <= max_parent_index) {
8108       int child_index = parent_index * 2 + 1;
8109       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8110       if (child_index + 1 < i) {
8111         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8112         if (right_child_hash > child_hash) {
8113           child_index++;
8114           child_hash = right_child_hash;
8115         }
8116       }
8117       if (child_hash <= parent_hash) break;
8118       SwapSortedKeys(parent_index, child_index);
8119       parent_index = child_index;
8120     }
8121   }
8122   DCHECK(IsSortedNoDuplicates());
8123 }
8124
8125
8126 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
8127   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
8128   copy->set_getter(pair->getter());
8129   copy->set_setter(pair->setter());
8130   return copy;
8131 }
8132
8133
8134 Object* AccessorPair::GetComponent(AccessorComponent component) {
8135   Object* accessor = get(component);
8136   return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
8137 }
8138
8139
8140 Handle<DeoptimizationInputData> DeoptimizationInputData::New(
8141     Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
8142   return Handle<DeoptimizationInputData>::cast(
8143       isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
8144                                         pretenure));
8145 }
8146
8147
8148 Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
8149     Isolate* isolate,
8150     int number_of_deopt_points,
8151     PretenureFlag pretenure) {
8152   Handle<FixedArray> result;
8153   if (number_of_deopt_points == 0) {
8154     result = isolate->factory()->empty_fixed_array();
8155   } else {
8156     result = isolate->factory()->NewFixedArray(
8157         LengthOfFixedArray(number_of_deopt_points), pretenure);
8158   }
8159   return Handle<DeoptimizationOutputData>::cast(result);
8160 }
8161
8162
8163 int HandlerTable::LookupRange(int pc_offset, int* stack_depth_out,
8164                               CatchPrediction* prediction_out) {
8165   int innermost_handler = -1, innermost_start = -1;
8166   for (int i = 0; i < length(); i += kRangeEntrySize) {
8167     int start_offset = Smi::cast(get(i + kRangeStartIndex))->value();
8168     int end_offset = Smi::cast(get(i + kRangeEndIndex))->value();
8169     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
8170     int handler_offset = HandlerOffsetField::decode(handler_field);
8171     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
8172     int stack_depth = Smi::cast(get(i + kRangeDepthIndex))->value();
8173     if (pc_offset > start_offset && pc_offset <= end_offset) {
8174       DCHECK_NE(start_offset, innermost_start);
8175       if (start_offset < innermost_start) continue;
8176       innermost_handler = handler_offset;
8177       innermost_start = start_offset;
8178       *stack_depth_out = stack_depth;
8179       if (prediction_out) *prediction_out = prediction;
8180     }
8181   }
8182   return innermost_handler;
8183 }
8184
8185
8186 // TODO(turbofan): Make sure table is sorted and use binary search.
8187 int HandlerTable::LookupReturn(int pc_offset, CatchPrediction* prediction_out) {
8188   for (int i = 0; i < length(); i += kReturnEntrySize) {
8189     int return_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
8190     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
8191     if (pc_offset == return_offset) {
8192       if (prediction_out) {
8193         *prediction_out = HandlerPredictionField::decode(handler_field);
8194       }
8195       return HandlerOffsetField::decode(handler_field);
8196     }
8197   }
8198   return -1;
8199 }
8200
8201
8202 #ifdef DEBUG
8203 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
8204   if (IsEmpty()) return other->IsEmpty();
8205   if (other->IsEmpty()) return false;
8206   if (length() != other->length()) return false;
8207   for (int i = 0; i < length(); ++i) {
8208     if (get(i) != other->get(i)) return false;
8209   }
8210   return true;
8211 }
8212 #endif
8213
8214
8215 bool String::LooksValid() {
8216   if (!GetIsolate()->heap()->Contains(this)) return false;
8217   return true;
8218 }
8219
8220
8221 String::FlatContent String::GetFlatContent() {
8222   DCHECK(!AllowHeapAllocation::IsAllowed());
8223   int length = this->length();
8224   StringShape shape(this);
8225   String* string = this;
8226   int offset = 0;
8227   if (shape.representation_tag() == kConsStringTag) {
8228     ConsString* cons = ConsString::cast(string);
8229     if (cons->second()->length() != 0) {
8230       return FlatContent();
8231     }
8232     string = cons->first();
8233     shape = StringShape(string);
8234   }
8235   if (shape.representation_tag() == kSlicedStringTag) {
8236     SlicedString* slice = SlicedString::cast(string);
8237     offset = slice->offset();
8238     string = slice->parent();
8239     shape = StringShape(string);
8240     DCHECK(shape.representation_tag() != kConsStringTag &&
8241            shape.representation_tag() != kSlicedStringTag);
8242   }
8243   if (shape.encoding_tag() == kOneByteStringTag) {
8244     const uint8_t* start;
8245     if (shape.representation_tag() == kSeqStringTag) {
8246       start = SeqOneByteString::cast(string)->GetChars();
8247     } else {
8248       start = ExternalOneByteString::cast(string)->GetChars();
8249     }
8250     return FlatContent(start + offset, length);
8251   } else {
8252     DCHECK(shape.encoding_tag() == kTwoByteStringTag);
8253     const uc16* start;
8254     if (shape.representation_tag() == kSeqStringTag) {
8255       start = SeqTwoByteString::cast(string)->GetChars();
8256     } else {
8257       start = ExternalTwoByteString::cast(string)->GetChars();
8258     }
8259     return FlatContent(start + offset, length);
8260   }
8261 }
8262
8263
8264 base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8265                                                 RobustnessFlag robust_flag,
8266                                                 int offset, int length,
8267                                                 int* length_return) {
8268   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8269     return base::SmartArrayPointer<char>(NULL);
8270   }
8271   // Negative length means the to the end of the string.
8272   if (length < 0) length = kMaxInt - offset;
8273
8274   // Compute the size of the UTF-8 string. Start at the specified offset.
8275   StringCharacterStream stream(this, offset);
8276   int character_position = offset;
8277   int utf8_bytes = 0;
8278   int last = unibrow::Utf16::kNoPreviousCharacter;
8279   while (stream.HasMore() && character_position++ < offset + length) {
8280     uint16_t character = stream.GetNext();
8281     utf8_bytes += unibrow::Utf8::Length(character, last);
8282     last = character;
8283   }
8284
8285   if (length_return) {
8286     *length_return = utf8_bytes;
8287   }
8288
8289   char* result = NewArray<char>(utf8_bytes + 1);
8290
8291   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8292   stream.Reset(this, offset);
8293   character_position = offset;
8294   int utf8_byte_position = 0;
8295   last = unibrow::Utf16::kNoPreviousCharacter;
8296   while (stream.HasMore() && character_position++ < offset + length) {
8297     uint16_t character = stream.GetNext();
8298     if (allow_nulls == DISALLOW_NULLS && character == 0) {
8299       character = ' ';
8300     }
8301     utf8_byte_position +=
8302         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8303     last = character;
8304   }
8305   result[utf8_byte_position] = 0;
8306   return base::SmartArrayPointer<char>(result);
8307 }
8308
8309
8310 base::SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8311                                                 RobustnessFlag robust_flag,
8312                                                 int* length_return) {
8313   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8314 }
8315
8316
8317 const uc16* String::GetTwoByteData(unsigned start) {
8318   DCHECK(!IsOneByteRepresentationUnderneath());
8319   switch (StringShape(this).representation_tag()) {
8320     case kSeqStringTag:
8321       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8322     case kExternalStringTag:
8323       return ExternalTwoByteString::cast(this)->
8324         ExternalTwoByteStringGetData(start);
8325     case kSlicedStringTag: {
8326       SlicedString* slice = SlicedString::cast(this);
8327       return slice->parent()->GetTwoByteData(start + slice->offset());
8328     }
8329     case kConsStringTag:
8330       UNREACHABLE();
8331       return NULL;
8332   }
8333   UNREACHABLE();
8334   return NULL;
8335 }
8336
8337
8338 base::SmartArrayPointer<uc16> String::ToWideCString(
8339     RobustnessFlag robust_flag) {
8340   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8341     return base::SmartArrayPointer<uc16>();
8342   }
8343   StringCharacterStream stream(this);
8344
8345   uc16* result = NewArray<uc16>(length() + 1);
8346
8347   int i = 0;
8348   while (stream.HasMore()) {
8349     uint16_t character = stream.GetNext();
8350     result[i++] = character;
8351   }
8352   result[i] = 0;
8353   return base::SmartArrayPointer<uc16>(result);
8354 }
8355
8356
8357 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
8358   return reinterpret_cast<uc16*>(
8359       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8360 }
8361
8362
8363 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8364   Relocatable* current = isolate->relocatable_top();
8365   while (current != NULL) {
8366     current->PostGarbageCollection();
8367     current = current->prev_;
8368   }
8369 }
8370
8371
8372 // Reserve space for statics needing saving and restoring.
8373 int Relocatable::ArchiveSpacePerThread() {
8374   return sizeof(Relocatable*);  // NOLINT
8375 }
8376
8377
8378 // Archive statics that are thread-local.
8379 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8380   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8381   isolate->set_relocatable_top(NULL);
8382   return to + ArchiveSpacePerThread();
8383 }
8384
8385
8386 // Restore statics that are thread-local.
8387 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8388   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8389   return from + ArchiveSpacePerThread();
8390 }
8391
8392
8393 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8394   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8395   Iterate(v, top);
8396   return thread_storage + ArchiveSpacePerThread();
8397 }
8398
8399
8400 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8401   Iterate(v, isolate->relocatable_top());
8402 }
8403
8404
8405 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8406   Relocatable* current = top;
8407   while (current != NULL) {
8408     current->IterateInstance(v);
8409     current = current->prev_;
8410   }
8411 }
8412
8413
8414 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
8415     : Relocatable(isolate),
8416       str_(str.location()),
8417       length_(str->length()) {
8418   PostGarbageCollection();
8419 }
8420
8421
8422 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
8423     : Relocatable(isolate),
8424       str_(0),
8425       is_one_byte_(true),
8426       length_(input.length()),
8427       start_(input.start()) {}
8428
8429
8430 void FlatStringReader::PostGarbageCollection() {
8431   if (str_ == NULL) return;
8432   Handle<String> str(str_);
8433   DCHECK(str->IsFlat());
8434   DisallowHeapAllocation no_gc;
8435   // This does not actually prevent the vector from being relocated later.
8436   String::FlatContent content = str->GetFlatContent();
8437   DCHECK(content.IsFlat());
8438   is_one_byte_ = content.IsOneByte();
8439   if (is_one_byte_) {
8440     start_ = content.ToOneByteVector().start();
8441   } else {
8442     start_ = content.ToUC16Vector().start();
8443   }
8444 }
8445
8446
8447 void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
8448   DCHECK(cons_string != NULL);
8449   root_ = cons_string;
8450   consumed_ = offset;
8451   // Force stack blown condition to trigger restart.
8452   depth_ = 1;
8453   maximum_depth_ = kStackSize + depth_;
8454   DCHECK(StackBlown());
8455 }
8456
8457
8458 String* ConsStringIterator::Continue(int* offset_out) {
8459   DCHECK(depth_ != 0);
8460   DCHECK_EQ(0, *offset_out);
8461   bool blew_stack = StackBlown();
8462   String* string = NULL;
8463   // Get the next leaf if there is one.
8464   if (!blew_stack) string = NextLeaf(&blew_stack);
8465   // Restart search from root.
8466   if (blew_stack) {
8467     DCHECK(string == NULL);
8468     string = Search(offset_out);
8469   }
8470   // Ensure future calls return null immediately.
8471   if (string == NULL) Reset(NULL);
8472   return string;
8473 }
8474
8475
8476 String* ConsStringIterator::Search(int* offset_out) {
8477   ConsString* cons_string = root_;
8478   // Reset the stack, pushing the root string.
8479   depth_ = 1;
8480   maximum_depth_ = 1;
8481   frames_[0] = cons_string;
8482   const int consumed = consumed_;
8483   int offset = 0;
8484   while (true) {
8485     // Loop until the string is found which contains the target offset.
8486     String* string = cons_string->first();
8487     int length = string->length();
8488     int32_t type;
8489     if (consumed < offset + length) {
8490       // Target offset is in the left branch.
8491       // Keep going if we're still in a ConString.
8492       type = string->map()->instance_type();
8493       if ((type & kStringRepresentationMask) == kConsStringTag) {
8494         cons_string = ConsString::cast(string);
8495         PushLeft(cons_string);
8496         continue;
8497       }
8498       // Tell the stack we're done descending.
8499       AdjustMaximumDepth();
8500     } else {
8501       // Descend right.
8502       // Update progress through the string.
8503       offset += length;
8504       // Keep going if we're still in a ConString.
8505       string = cons_string->second();
8506       type = string->map()->instance_type();
8507       if ((type & kStringRepresentationMask) == kConsStringTag) {
8508         cons_string = ConsString::cast(string);
8509         PushRight(cons_string);
8510         continue;
8511       }
8512       // Need this to be updated for the current string.
8513       length = string->length();
8514       // Account for the possibility of an empty right leaf.
8515       // This happens only if we have asked for an offset outside the string.
8516       if (length == 0) {
8517         // Reset so future operations will return null immediately.
8518         Reset(NULL);
8519         return NULL;
8520       }
8521       // Tell the stack we're done descending.
8522       AdjustMaximumDepth();
8523       // Pop stack so next iteration is in correct place.
8524       Pop();
8525     }
8526     DCHECK(length != 0);
8527     // Adjust return values and exit.
8528     consumed_ = offset + length;
8529     *offset_out = consumed - offset;
8530     return string;
8531   }
8532   UNREACHABLE();
8533   return NULL;
8534 }
8535
8536
8537 String* ConsStringIterator::NextLeaf(bool* blew_stack) {
8538   while (true) {
8539     // Tree traversal complete.
8540     if (depth_ == 0) {
8541       *blew_stack = false;
8542       return NULL;
8543     }
8544     // We've lost track of higher nodes.
8545     if (StackBlown()) {
8546       *blew_stack = true;
8547       return NULL;
8548     }
8549     // Go right.
8550     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
8551     String* string = cons_string->second();
8552     int32_t type = string->map()->instance_type();
8553     if ((type & kStringRepresentationMask) != kConsStringTag) {
8554       // Pop stack so next iteration is in correct place.
8555       Pop();
8556       int length = string->length();
8557       // Could be a flattened ConsString.
8558       if (length == 0) continue;
8559       consumed_ += length;
8560       return string;
8561     }
8562     cons_string = ConsString::cast(string);
8563     PushRight(cons_string);
8564     // Need to traverse all the way left.
8565     while (true) {
8566       // Continue left.
8567       string = cons_string->first();
8568       type = string->map()->instance_type();
8569       if ((type & kStringRepresentationMask) != kConsStringTag) {
8570         AdjustMaximumDepth();
8571         int length = string->length();
8572         DCHECK(length != 0);
8573         consumed_ += length;
8574         return string;
8575       }
8576       cons_string = ConsString::cast(string);
8577       PushLeft(cons_string);
8578     }
8579   }
8580   UNREACHABLE();
8581   return NULL;
8582 }
8583
8584
8585 uint16_t ConsString::ConsStringGet(int index) {
8586   DCHECK(index >= 0 && index < this->length());
8587
8588   // Check for a flattened cons string
8589   if (second()->length() == 0) {
8590     String* left = first();
8591     return left->Get(index);
8592   }
8593
8594   String* string = String::cast(this);
8595
8596   while (true) {
8597     if (StringShape(string).IsCons()) {
8598       ConsString* cons_string = ConsString::cast(string);
8599       String* left = cons_string->first();
8600       if (left->length() > index) {
8601         string = left;
8602       } else {
8603         index -= left->length();
8604         string = cons_string->second();
8605       }
8606     } else {
8607       return string->Get(index);
8608     }
8609   }
8610
8611   UNREACHABLE();
8612   return 0;
8613 }
8614
8615
8616 uint16_t SlicedString::SlicedStringGet(int index) {
8617   return parent()->Get(offset() + index);
8618 }
8619
8620
8621 template <typename sinkchar>
8622 void String::WriteToFlat(String* src,
8623                          sinkchar* sink,
8624                          int f,
8625                          int t) {
8626   String* source = src;
8627   int from = f;
8628   int to = t;
8629   while (true) {
8630     DCHECK(0 <= from && from <= to && to <= source->length());
8631     switch (StringShape(source).full_representation_tag()) {
8632       case kOneByteStringTag | kExternalStringTag: {
8633         CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
8634                   to - from);
8635         return;
8636       }
8637       case kTwoByteStringTag | kExternalStringTag: {
8638         const uc16* data =
8639             ExternalTwoByteString::cast(source)->GetChars();
8640         CopyChars(sink,
8641                   data + from,
8642                   to - from);
8643         return;
8644       }
8645       case kOneByteStringTag | kSeqStringTag: {
8646         CopyChars(sink,
8647                   SeqOneByteString::cast(source)->GetChars() + from,
8648                   to - from);
8649         return;
8650       }
8651       case kTwoByteStringTag | kSeqStringTag: {
8652         CopyChars(sink,
8653                   SeqTwoByteString::cast(source)->GetChars() + from,
8654                   to - from);
8655         return;
8656       }
8657       case kOneByteStringTag | kConsStringTag:
8658       case kTwoByteStringTag | kConsStringTag: {
8659         ConsString* cons_string = ConsString::cast(source);
8660         String* first = cons_string->first();
8661         int boundary = first->length();
8662         if (to - boundary >= boundary - from) {
8663           // Right hand side is longer.  Recurse over left.
8664           if (from < boundary) {
8665             WriteToFlat(first, sink, from, boundary);
8666             sink += boundary - from;
8667             from = 0;
8668           } else {
8669             from -= boundary;
8670           }
8671           to -= boundary;
8672           source = cons_string->second();
8673         } else {
8674           // Left hand side is longer.  Recurse over right.
8675           if (to > boundary) {
8676             String* second = cons_string->second();
8677             // When repeatedly appending to a string, we get a cons string that
8678             // is unbalanced to the left, a list, essentially.  We inline the
8679             // common case of sequential one-byte right child.
8680             if (to - boundary == 1) {
8681               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
8682             } else if (second->IsSeqOneByteString()) {
8683               CopyChars(sink + boundary - from,
8684                         SeqOneByteString::cast(second)->GetChars(),
8685                         to - boundary);
8686             } else {
8687               WriteToFlat(second,
8688                           sink + boundary - from,
8689                           0,
8690                           to - boundary);
8691             }
8692             to = boundary;
8693           }
8694           source = first;
8695         }
8696         break;
8697       }
8698       case kOneByteStringTag | kSlicedStringTag:
8699       case kTwoByteStringTag | kSlicedStringTag: {
8700         SlicedString* slice = SlicedString::cast(source);
8701         unsigned offset = slice->offset();
8702         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
8703         return;
8704       }
8705     }
8706   }
8707 }
8708
8709
8710
8711 template <typename SourceChar>
8712 static void CalculateLineEndsImpl(Isolate* isolate,
8713                                   List<int>* line_ends,
8714                                   Vector<const SourceChar> src,
8715                                   bool include_ending_line) {
8716   const int src_len = src.length();
8717   UnicodeCache* cache = isolate->unicode_cache();
8718   for (int i = 0; i < src_len - 1; i++) {
8719     SourceChar current = src[i];
8720     SourceChar next = src[i + 1];
8721     if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i);
8722   }
8723
8724   if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
8725     line_ends->Add(src_len - 1);
8726   } else if (include_ending_line) {
8727     // Even if the last line misses a line end, it is counted.
8728     line_ends->Add(src_len);
8729   }
8730 }
8731
8732
8733 Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
8734                                              bool include_ending_line) {
8735   src = Flatten(src);
8736   // Rough estimate of line count based on a roughly estimated average
8737   // length of (unpacked) code.
8738   int line_count_estimate = src->length() >> 4;
8739   List<int> line_ends(line_count_estimate);
8740   Isolate* isolate = src->GetIsolate();
8741   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
8742     // Dispatch on type of strings.
8743     String::FlatContent content = src->GetFlatContent();
8744     DCHECK(content.IsFlat());
8745     if (content.IsOneByte()) {
8746       CalculateLineEndsImpl(isolate,
8747                             &line_ends,
8748                             content.ToOneByteVector(),
8749                             include_ending_line);
8750     } else {
8751       CalculateLineEndsImpl(isolate,
8752                             &line_ends,
8753                             content.ToUC16Vector(),
8754                             include_ending_line);
8755     }
8756   }
8757   int line_count = line_ends.length();
8758   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
8759   for (int i = 0; i < line_count; i++) {
8760     array->set(i, Smi::FromInt(line_ends[i]));
8761   }
8762   return array;
8763 }
8764
8765
8766 // Compares the contents of two strings by reading and comparing
8767 // int-sized blocks of characters.
8768 template <typename Char>
8769 static inline bool CompareRawStringContents(const Char* const a,
8770                                             const Char* const b,
8771                                             int length) {
8772   return CompareChars(a, b, length) == 0;
8773 }
8774
8775
8776 template<typename Chars1, typename Chars2>
8777 class RawStringComparator : public AllStatic {
8778  public:
8779   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
8780     DCHECK(sizeof(Chars1) != sizeof(Chars2));
8781     for (int i = 0; i < len; i++) {
8782       if (a[i] != b[i]) {
8783         return false;
8784       }
8785     }
8786     return true;
8787   }
8788 };
8789
8790
8791 template<>
8792 class RawStringComparator<uint16_t, uint16_t> {
8793  public:
8794   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
8795     return CompareRawStringContents(a, b, len);
8796   }
8797 };
8798
8799
8800 template<>
8801 class RawStringComparator<uint8_t, uint8_t> {
8802  public:
8803   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
8804     return CompareRawStringContents(a, b, len);
8805   }
8806 };
8807
8808
8809 class StringComparator {
8810   class State {
8811    public:
8812     State() : is_one_byte_(true), length_(0), buffer8_(NULL) {}
8813
8814     void Init(String* string) {
8815       ConsString* cons_string = String::VisitFlat(this, string);
8816       iter_.Reset(cons_string);
8817       if (cons_string != NULL) {
8818         int offset;
8819         string = iter_.Next(&offset);
8820         String::VisitFlat(this, string, offset);
8821       }
8822     }
8823
8824     inline void VisitOneByteString(const uint8_t* chars, int length) {
8825       is_one_byte_ = true;
8826       buffer8_ = chars;
8827       length_ = length;
8828     }
8829
8830     inline void VisitTwoByteString(const uint16_t* chars, int length) {
8831       is_one_byte_ = false;
8832       buffer16_ = chars;
8833       length_ = length;
8834     }
8835
8836     void Advance(int consumed) {
8837       DCHECK(consumed <= length_);
8838       // Still in buffer.
8839       if (length_ != consumed) {
8840         if (is_one_byte_) {
8841           buffer8_ += consumed;
8842         } else {
8843           buffer16_ += consumed;
8844         }
8845         length_ -= consumed;
8846         return;
8847       }
8848       // Advance state.
8849       int offset;
8850       String* next = iter_.Next(&offset);
8851       DCHECK_EQ(0, offset);
8852       DCHECK(next != NULL);
8853       String::VisitFlat(this, next);
8854     }
8855
8856     ConsStringIterator iter_;
8857     bool is_one_byte_;
8858     int length_;
8859     union {
8860       const uint8_t* buffer8_;
8861       const uint16_t* buffer16_;
8862     };
8863
8864    private:
8865     DISALLOW_COPY_AND_ASSIGN(State);
8866   };
8867
8868  public:
8869   inline StringComparator() {}
8870
8871   template<typename Chars1, typename Chars2>
8872   static inline bool Equals(State* state_1, State* state_2, int to_check) {
8873     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
8874     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
8875     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
8876   }
8877
8878   bool Equals(String* string_1, String* string_2) {
8879     int length = string_1->length();
8880     state_1_.Init(string_1);
8881     state_2_.Init(string_2);
8882     while (true) {
8883       int to_check = Min(state_1_.length_, state_2_.length_);
8884       DCHECK(to_check > 0 && to_check <= length);
8885       bool is_equal;
8886       if (state_1_.is_one_byte_) {
8887         if (state_2_.is_one_byte_) {
8888           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
8889         } else {
8890           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
8891         }
8892       } else {
8893         if (state_2_.is_one_byte_) {
8894           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
8895         } else {
8896           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
8897         }
8898       }
8899       // Looping done.
8900       if (!is_equal) return false;
8901       length -= to_check;
8902       // Exit condition. Strings are equal.
8903       if (length == 0) return true;
8904       state_1_.Advance(to_check);
8905       state_2_.Advance(to_check);
8906     }
8907   }
8908
8909  private:
8910   State state_1_;
8911   State state_2_;
8912
8913   DISALLOW_COPY_AND_ASSIGN(StringComparator);
8914 };
8915
8916
8917 bool String::SlowEquals(String* other) {
8918   DisallowHeapAllocation no_gc;
8919   // Fast check: negative check with lengths.
8920   int len = length();
8921   if (len != other->length()) return false;
8922   if (len == 0) return true;
8923
8924   // Fast check: if hash code is computed for both strings
8925   // a fast negative check can be performed.
8926   if (HasHashCode() && other->HasHashCode()) {
8927 #ifdef ENABLE_SLOW_DCHECKS
8928     if (FLAG_enable_slow_asserts) {
8929       if (Hash() != other->Hash()) {
8930         bool found_difference = false;
8931         for (int i = 0; i < len; i++) {
8932           if (Get(i) != other->Get(i)) {
8933             found_difference = true;
8934             break;
8935           }
8936         }
8937         DCHECK(found_difference);
8938       }
8939     }
8940 #endif
8941     if (Hash() != other->Hash()) return false;
8942   }
8943
8944   // We know the strings are both non-empty. Compare the first chars
8945   // before we try to flatten the strings.
8946   if (this->Get(0) != other->Get(0)) return false;
8947
8948   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
8949     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
8950     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
8951     return CompareRawStringContents(str1, str2, len);
8952   }
8953
8954   StringComparator comparator;
8955   return comparator.Equals(this, other);
8956 }
8957
8958
8959 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
8960   // Fast check: negative check with lengths.
8961   int one_length = one->length();
8962   if (one_length != two->length()) return false;
8963   if (one_length == 0) return true;
8964
8965   // Fast check: if hash code is computed for both strings
8966   // a fast negative check can be performed.
8967   if (one->HasHashCode() && two->HasHashCode()) {
8968 #ifdef ENABLE_SLOW_DCHECKS
8969     if (FLAG_enable_slow_asserts) {
8970       if (one->Hash() != two->Hash()) {
8971         bool found_difference = false;
8972         for (int i = 0; i < one_length; i++) {
8973           if (one->Get(i) != two->Get(i)) {
8974             found_difference = true;
8975             break;
8976           }
8977         }
8978         DCHECK(found_difference);
8979       }
8980     }
8981 #endif
8982     if (one->Hash() != two->Hash()) return false;
8983   }
8984
8985   // We know the strings are both non-empty. Compare the first chars
8986   // before we try to flatten the strings.
8987   if (one->Get(0) != two->Get(0)) return false;
8988
8989   one = String::Flatten(one);
8990   two = String::Flatten(two);
8991
8992   DisallowHeapAllocation no_gc;
8993   String::FlatContent flat1 = one->GetFlatContent();
8994   String::FlatContent flat2 = two->GetFlatContent();
8995
8996   if (flat1.IsOneByte() && flat2.IsOneByte()) {
8997       return CompareRawStringContents(flat1.ToOneByteVector().start(),
8998                                       flat2.ToOneByteVector().start(),
8999                                       one_length);
9000   } else {
9001     for (int i = 0; i < one_length; i++) {
9002       if (flat1.Get(i) != flat2.Get(i)) return false;
9003     }
9004     return true;
9005   }
9006 }
9007
9008
9009 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
9010   int slen = length();
9011   // Can't check exact length equality, but we can check bounds.
9012   int str_len = str.length();
9013   if (!allow_prefix_match &&
9014       (str_len < slen ||
9015           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
9016     return false;
9017   }
9018   int i;
9019   size_t remaining_in_str = static_cast<size_t>(str_len);
9020   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
9021   for (i = 0; i < slen && remaining_in_str > 0; i++) {
9022     size_t cursor = 0;
9023     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
9024     DCHECK(cursor > 0 && cursor <= remaining_in_str);
9025     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
9026       if (i > slen - 1) return false;
9027       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
9028       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
9029     } else {
9030       if (Get(i) != r) return false;
9031     }
9032     utf8_data += cursor;
9033     remaining_in_str -= cursor;
9034   }
9035   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
9036 }
9037
9038
9039 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
9040   int slen = length();
9041   if (str.length() != slen) return false;
9042   DisallowHeapAllocation no_gc;
9043   FlatContent content = GetFlatContent();
9044   if (content.IsOneByte()) {
9045     return CompareChars(content.ToOneByteVector().start(),
9046                         str.start(), slen) == 0;
9047   }
9048   for (int i = 0; i < slen; i++) {
9049     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
9050   }
9051   return true;
9052 }
9053
9054
9055 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
9056   int slen = length();
9057   if (str.length() != slen) return false;
9058   DisallowHeapAllocation no_gc;
9059   FlatContent content = GetFlatContent();
9060   if (content.IsTwoByte()) {
9061     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
9062   }
9063   for (int i = 0; i < slen; i++) {
9064     if (Get(i) != str[i]) return false;
9065   }
9066   return true;
9067 }
9068
9069
9070 uint32_t String::ComputeAndSetHash() {
9071   // Should only be called if hash code has not yet been computed.
9072   DCHECK(!HasHashCode());
9073
9074   // Store the hash code in the object.
9075   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
9076   set_hash_field(field);
9077
9078   // Check the hash code is there.
9079   DCHECK(HasHashCode());
9080   uint32_t result = field >> kHashShift;
9081   DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
9082   return result;
9083 }
9084
9085
9086 bool String::ComputeArrayIndex(uint32_t* index) {
9087   int length = this->length();
9088   if (length == 0 || length > kMaxArrayIndexSize) return false;
9089   StringCharacterStream stream(this);
9090   return StringToArrayIndex(&stream, index);
9091 }
9092
9093
9094 bool String::SlowAsArrayIndex(uint32_t* index) {
9095   if (length() <= kMaxCachedArrayIndexLength) {
9096     Hash();  // force computation of hash code
9097     uint32_t field = hash_field();
9098     if ((field & kIsNotArrayIndexMask) != 0) return false;
9099     // Isolate the array index form the full hash field.
9100     *index = ArrayIndexValueBits::decode(field);
9101     return true;
9102   } else {
9103     return ComputeArrayIndex(index);
9104   }
9105 }
9106
9107
9108 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
9109   int new_size, old_size;
9110   int old_length = string->length();
9111   if (old_length <= new_length) return string;
9112
9113   if (string->IsSeqOneByteString()) {
9114     old_size = SeqOneByteString::SizeFor(old_length);
9115     new_size = SeqOneByteString::SizeFor(new_length);
9116   } else {
9117     DCHECK(string->IsSeqTwoByteString());
9118     old_size = SeqTwoByteString::SizeFor(old_length);
9119     new_size = SeqTwoByteString::SizeFor(new_length);
9120   }
9121
9122   int delta = old_size - new_size;
9123
9124   Address start_of_string = string->address();
9125   DCHECK_OBJECT_ALIGNED(start_of_string);
9126   DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
9127
9128   Heap* heap = string->GetHeap();
9129   NewSpace* newspace = heap->new_space();
9130   if (newspace->Contains(start_of_string) &&
9131       newspace->top() == start_of_string + old_size) {
9132     // Last allocated object in new space.  Simply lower allocation top.
9133     newspace->set_top(start_of_string + new_size);
9134   } else {
9135     // Sizes are pointer size aligned, so that we can use filler objects
9136     // that are a multiple of pointer size.
9137     heap->CreateFillerObjectAt(start_of_string + new_size, delta);
9138   }
9139   heap->AdjustLiveBytes(start_of_string, -delta, Heap::CONCURRENT_TO_SWEEPER);
9140
9141   // We are storing the new length using release store after creating a filler
9142   // for the left-over space to avoid races with the sweeper thread.
9143   string->synchronized_set_length(new_length);
9144
9145   if (new_length == 0) return heap->isolate()->factory()->empty_string();
9146   return string;
9147 }
9148
9149
9150 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
9151   // For array indexes mix the length into the hash as an array index could
9152   // be zero.
9153   DCHECK(length > 0);
9154   DCHECK(length <= String::kMaxArrayIndexSize);
9155   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
9156          (1 << String::kArrayIndexValueBits));
9157
9158   value <<= String::ArrayIndexValueBits::kShift;
9159   value |= length << String::ArrayIndexLengthBits::kShift;
9160
9161   DCHECK((value & String::kIsNotArrayIndexMask) == 0);
9162   DCHECK((length > String::kMaxCachedArrayIndexLength) ||
9163          (value & String::kContainsCachedArrayIndexMask) == 0);
9164   return value;
9165 }
9166
9167
9168 uint32_t StringHasher::GetHashField() {
9169   if (length_ <= String::kMaxHashCalcLength) {
9170     if (is_array_index_) {
9171       return MakeArrayIndexHash(array_index_, length_);
9172     }
9173     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
9174            String::kIsNotArrayIndexMask;
9175   } else {
9176     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
9177   }
9178 }
9179
9180
9181 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
9182                                        uint32_t seed,
9183                                        int* utf16_length_out) {
9184   int vector_length = chars.length();
9185   // Handle some edge cases
9186   if (vector_length <= 1) {
9187     DCHECK(vector_length == 0 ||
9188            static_cast<uint8_t>(chars.start()[0]) <=
9189                unibrow::Utf8::kMaxOneByteChar);
9190     *utf16_length_out = vector_length;
9191     return HashSequentialString(chars.start(), vector_length, seed);
9192   }
9193   // Start with a fake length which won't affect computation.
9194   // It will be updated later.
9195   StringHasher hasher(String::kMaxArrayIndexSize, seed);
9196   size_t remaining = static_cast<size_t>(vector_length);
9197   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
9198   int utf16_length = 0;
9199   bool is_index = true;
9200   DCHECK(hasher.is_array_index_);
9201   while (remaining > 0) {
9202     size_t consumed = 0;
9203     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
9204     DCHECK(consumed > 0 && consumed <= remaining);
9205     stream += consumed;
9206     remaining -= consumed;
9207     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
9208     utf16_length += is_two_characters ? 2 : 1;
9209     // No need to keep hashing. But we do need to calculate utf16_length.
9210     if (utf16_length > String::kMaxHashCalcLength) continue;
9211     if (is_two_characters) {
9212       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
9213       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
9214       hasher.AddCharacter(c1);
9215       hasher.AddCharacter(c2);
9216       if (is_index) is_index = hasher.UpdateIndex(c1);
9217       if (is_index) is_index = hasher.UpdateIndex(c2);
9218     } else {
9219       hasher.AddCharacter(c);
9220       if (is_index) is_index = hasher.UpdateIndex(c);
9221     }
9222   }
9223   *utf16_length_out = static_cast<int>(utf16_length);
9224   // Must set length here so that hash computation is correct.
9225   hasher.length_ = utf16_length;
9226   return hasher.GetHashField();
9227 }
9228
9229
9230 void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
9231   // Run small ConsStrings through ConsStringIterator.
9232   if (cons_string->length() < 64) {
9233     ConsStringIterator iter(cons_string);
9234     int offset;
9235     String* string;
9236     while (nullptr != (string = iter.Next(&offset))) {
9237       DCHECK_EQ(0, offset);
9238       String::VisitFlat(this, string, 0);
9239     }
9240     return;
9241   }
9242   // Slow case.
9243   const int max_length = String::kMaxHashCalcLength;
9244   int length = std::min(cons_string->length(), max_length);
9245   if (cons_string->HasOnlyOneByteChars()) {
9246     uint8_t* buffer = new uint8_t[length];
9247     String::WriteToFlat(cons_string, buffer, 0, length);
9248     AddCharacters(buffer, length);
9249     delete[] buffer;
9250   } else {
9251     uint16_t* buffer = new uint16_t[length];
9252     String::WriteToFlat(cons_string, buffer, 0, length);
9253     AddCharacters(buffer, length);
9254     delete[] buffer;
9255   }
9256 }
9257
9258
9259 void String::PrintOn(FILE* file) {
9260   int length = this->length();
9261   for (int i = 0; i < length; i++) {
9262     PrintF(file, "%c", Get(i));
9263   }
9264 }
9265
9266
9267 inline static uint32_t ObjectAddressForHashing(Object* object) {
9268   uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
9269   return value & MemoryChunk::kAlignmentMask;
9270 }
9271
9272
9273 int Map::Hash() {
9274   // For performance reasons we only hash the 3 most variable fields of a map:
9275   // constructor, prototype and bit_field2. For predictability reasons we
9276   // use objects' offsets in respective pages for hashing instead of raw
9277   // addresses.
9278
9279   // Shift away the tag.
9280   int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
9281
9282   // XOR-ing the prototype and constructor directly yields too many zero bits
9283   // when the two pointers are close (which is fairly common).
9284   // To avoid this we shift the prototype bits relatively to the constructor.
9285   hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
9286
9287   return hash ^ (hash >> 16) ^ bit_field2();
9288 }
9289
9290
9291 static bool CheckEquivalent(Map* first, Map* second) {
9292   return first->GetConstructor() == second->GetConstructor() &&
9293          first->prototype() == second->prototype() &&
9294          first->instance_type() == second->instance_type() &&
9295          first->bit_field() == second->bit_field() &&
9296          first->is_extensible() == second->is_extensible() &&
9297          first->is_strong() == second->is_strong() &&
9298          first->has_instance_call_handler() ==
9299              second->has_instance_call_handler();
9300 }
9301
9302
9303 bool Map::EquivalentToForTransition(Map* other) {
9304   return CheckEquivalent(this, other);
9305 }
9306
9307
9308 bool Map::EquivalentToForNormalization(Map* other,
9309                                        PropertyNormalizationMode mode) {
9310   int properties = mode == CLEAR_INOBJECT_PROPERTIES
9311       ? 0 : other->inobject_properties();
9312   return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
9313          inobject_properties() == properties;
9314 }
9315
9316
9317 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
9318   // Iterate over all fields in the body but take care in dealing with
9319   // the code entry.
9320   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
9321   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9322   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9323 }
9324
9325
9326 void JSFunction::MarkForOptimization() {
9327   Isolate* isolate = GetIsolate();
9328   DCHECK(!IsOptimized());
9329   DCHECK(shared()->allows_lazy_compilation() ||
9330          !shared()->optimization_disabled());
9331   set_code_no_write_barrier(
9332       isolate->builtins()->builtin(Builtins::kCompileOptimized));
9333   // No write barrier required, since the builtin is part of the root set.
9334 }
9335
9336
9337 void JSFunction::AttemptConcurrentOptimization() {
9338   Isolate* isolate = GetIsolate();
9339   if (!isolate->concurrent_recompilation_enabled() ||
9340       isolate->bootstrapper()->IsActive()) {
9341     MarkForOptimization();
9342     return;
9343   }
9344   if (isolate->concurrent_osr_enabled() &&
9345       isolate->optimizing_compile_dispatcher()->IsQueuedForOSR(this)) {
9346     // Do not attempt regular recompilation if we already queued this for OSR.
9347     // TODO(yangguo): This is necessary so that we don't install optimized
9348     // code on a function that is already optimized, since OSR and regular
9349     // recompilation race.  This goes away as soon as OSR becomes one-shot.
9350     return;
9351   }
9352   DCHECK(!IsInOptimizationQueue());
9353   DCHECK(!IsOptimized());
9354   DCHECK(shared()->allows_lazy_compilation() ||
9355          !shared()->optimization_disabled());
9356   DCHECK(isolate->concurrent_recompilation_enabled());
9357   if (FLAG_trace_concurrent_recompilation) {
9358     PrintF("  ** Marking ");
9359     ShortPrint();
9360     PrintF(" for concurrent recompilation.\n");
9361   }
9362   set_code_no_write_barrier(
9363       isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9364   // No write barrier required, since the builtin is part of the root set.
9365 }
9366
9367
9368 Handle<JSFunction> JSFunction::CloneClosure(Handle<JSFunction> function) {
9369   Isolate* isolate = function->GetIsolate();
9370   Handle<Map> map(function->map());
9371   Handle<SharedFunctionInfo> shared(function->shared());
9372   Handle<Context> context(function->context());
9373   Handle<JSFunction> clone =
9374       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
9375
9376   if (shared->bound()) {
9377     clone->set_function_bindings(function->function_bindings());
9378   }
9379
9380   // In typical case, __proto__ of ``function`` is the default Function
9381   // prototype, which means that SetPrototype below is a no-op.
9382   // In rare cases when that is not true, we mutate the clone's __proto__.
9383   Handle<Object> original_prototype(map->prototype(), isolate);
9384   if (*original_prototype != clone->map()->prototype()) {
9385     JSObject::SetPrototype(clone, original_prototype, false).Assert();
9386   }
9387
9388   return clone;
9389 }
9390
9391
9392 void SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(
9393     Handle<SharedFunctionInfo> shared, Handle<Code> code) {
9394   Isolate* isolate = shared->GetIsolate();
9395   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9396   Handle<Object> value(shared->optimized_code_map(), isolate);
9397   if (value->IsSmi()) return;  // Empty code maps are unsupported.
9398   Handle<FixedArray> code_map = Handle<FixedArray>::cast(value);
9399   code_map->set(kSharedCodeIndex, *code);
9400 }
9401
9402
9403 void SharedFunctionInfo::AddToOptimizedCodeMap(
9404     Handle<SharedFunctionInfo> shared,
9405     Handle<Context> native_context,
9406     Handle<Code> code,
9407     Handle<FixedArray> literals,
9408     BailoutId osr_ast_id) {
9409   Isolate* isolate = shared->GetIsolate();
9410   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9411   DCHECK(native_context->IsNativeContext());
9412   STATIC_ASSERT(kEntryLength == 4);
9413   Handle<FixedArray> new_code_map;
9414   Handle<Object> value(shared->optimized_code_map(), isolate);
9415   int old_length;
9416   if (value->IsSmi()) {
9417     // No optimized code map.
9418     DCHECK_EQ(0, Smi::cast(*value)->value());
9419     new_code_map = isolate->factory()->NewFixedArray(kInitialLength);
9420     old_length = kEntriesStart;
9421   } else {
9422     // Copy old map and append one new entry.
9423     Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value);
9424     DCHECK(!shared->SearchOptimizedCodeMap(*native_context, osr_ast_id).code);
9425     old_length = old_code_map->length();
9426     new_code_map = FixedArray::CopySize(
9427         old_code_map, old_length + kEntryLength);
9428     // Zap the old map for the sake of the heap verifier.
9429     if (Heap::ShouldZapGarbage()) {
9430       Object** data = old_code_map->data_start();
9431       MemsetPointer(data, isolate->heap()->the_hole_value(), old_length);
9432     }
9433   }
9434   new_code_map->set(old_length + kContextOffset, *native_context);
9435   new_code_map->set(old_length + kCachedCodeOffset, *code);
9436   new_code_map->set(old_length + kLiteralsOffset, *literals);
9437   new_code_map->set(old_length + kOsrAstIdOffset,
9438                     Smi::FromInt(osr_ast_id.ToInt()));
9439
9440 #ifdef DEBUG
9441   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9442     DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext());
9443     DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9444     DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9445            Code::OPTIMIZED_FUNCTION);
9446     DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9447     DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9448   }
9449 #endif
9450   shared->set_optimized_code_map(*new_code_map);
9451 }
9452
9453
9454 void SharedFunctionInfo::ClearOptimizedCodeMap() {
9455   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9456
9457   // If the next map link slot is already used then the function was
9458   // enqueued with code flushing and we remove it now.
9459   if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9460     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
9461     flusher->EvictOptimizedCodeMap(this);
9462   }
9463
9464   DCHECK(code_map->get(kNextMapIndex)->IsUndefined());
9465   set_optimized_code_map(Smi::FromInt(0));
9466 }
9467
9468
9469 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
9470                                                    const char* reason) {
9471   DisallowHeapAllocation no_gc;
9472   if (optimized_code_map()->IsSmi()) return;
9473
9474   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9475   int dst = kEntriesStart;
9476   int length = code_map->length();
9477   for (int src = kEntriesStart; src < length; src += kEntryLength) {
9478     DCHECK(code_map->get(src)->IsNativeContext());
9479     if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9480       // Evict the src entry by not copying it to the dst entry.
9481       if (FLAG_trace_opt) {
9482         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9483         ShortPrint();
9484         BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9485         if (osr.IsNone()) {
9486           PrintF("]\n");
9487         } else {
9488           PrintF(" (osr ast id %d)]\n", osr.ToInt());
9489         }
9490       }
9491     } else {
9492       // Keep the src entry by copying it to the dst entry.
9493       if (dst != src) {
9494         code_map->set(dst + kContextOffset,
9495                       code_map->get(src + kContextOffset));
9496         code_map->set(dst + kCachedCodeOffset,
9497                       code_map->get(src + kCachedCodeOffset));
9498         code_map->set(dst + kLiteralsOffset,
9499                       code_map->get(src + kLiteralsOffset));
9500         code_map->set(dst + kOsrAstIdOffset,
9501                       code_map->get(src + kOsrAstIdOffset));
9502       }
9503       dst += kEntryLength;
9504     }
9505   }
9506   if (code_map->get(kSharedCodeIndex) == optimized_code) {
9507     // Evict context-independent code as well.
9508     code_map->set_undefined(kSharedCodeIndex);
9509     if (FLAG_trace_opt) {
9510       PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9511       ShortPrint();
9512       PrintF(" (context-independent code)]\n");
9513     }
9514   }
9515   if (dst != length) {
9516     // Always trim even when array is cleared because of heap verifier.
9517     GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map,
9518                                                                 length - dst);
9519     if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap();
9520   }
9521 }
9522
9523
9524 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
9525   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9526   DCHECK(shrink_by % kEntryLength == 0);
9527   DCHECK(shrink_by <= code_map->length() - kEntriesStart);
9528   // Always trim even when array is cleared because of heap verifier.
9529   GetHeap()->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(code_map,
9530                                                               shrink_by);
9531   if (code_map->length() == kEntriesStart) {
9532     ClearOptimizedCodeMap();
9533   }
9534 }
9535
9536
9537 static void GetMinInobjectSlack(Map* map, void* data) {
9538   int slack = map->unused_property_fields();
9539   if (*reinterpret_cast<int*>(data) > slack) {
9540     *reinterpret_cast<int*>(data) = slack;
9541   }
9542 }
9543
9544
9545 static void ShrinkInstanceSize(Map* map, void* data) {
9546   int slack = *reinterpret_cast<int*>(data);
9547   map->set_inobject_properties(map->inobject_properties() - slack);
9548   map->set_unused_property_fields(map->unused_property_fields() - slack);
9549   map->set_instance_size(map->instance_size() - slack * kPointerSize);
9550
9551   // Visitor id might depend on the instance size, recalculate it.
9552   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
9553 }
9554
9555
9556 void JSFunction::CompleteInobjectSlackTracking() {
9557   DCHECK(has_initial_map());
9558   Map* map = initial_map();
9559
9560   DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1);
9561   map->set_counter(Map::kRetainingCounterStart);
9562
9563   int slack = map->unused_property_fields();
9564   TransitionArray::TraverseTransitionTree(map, &GetMinInobjectSlack, &slack);
9565   if (slack != 0) {
9566     // Resize the initial map and all maps in its transition tree.
9567     TransitionArray::TraverseTransitionTree(map, &ShrinkInstanceSize, &slack);
9568   }
9569 }
9570
9571
9572 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
9573   DisallowHeapAllocation no_gc;
9574   if (!object->HasFastProperties()) return false;
9575   Map* map = object->map();
9576   if (map->is_prototype_map()) return false;
9577   DescriptorArray* descriptors = map->instance_descriptors();
9578   for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
9579     PropertyDetails details = descriptors->GetDetails(i);
9580     if (details.location() == kDescriptor) continue;
9581     if (details.representation().IsHeapObject() ||
9582         details.representation().IsTagged()) {
9583       FieldIndex index = FieldIndex::ForDescriptor(map, i);
9584       if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
9585     }
9586   }
9587   return false;
9588 }
9589
9590
9591 // static
9592 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
9593                                    PrototypeOptimizationMode mode) {
9594   if (object->IsGlobalObject()) return;
9595   if (object->IsJSGlobalProxy()) return;
9596   if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
9597     // First normalize to ensure all JSFunctions are DATA_CONSTANT.
9598     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
9599                                   "NormalizeAsPrototype");
9600   }
9601   Handle<Map> previous_map(object->map());
9602   if (!object->HasFastProperties()) {
9603     JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
9604   }
9605   if (!object->map()->is_prototype_map()) {
9606     if (object->map() == *previous_map) {
9607       Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
9608       JSObject::MigrateToMap(object, new_map);
9609     }
9610     object->map()->set_is_prototype_map(true);
9611
9612     // Replace the pointer to the exact constructor with the Object function
9613     // from the same context if undetectable from JS. This is to avoid keeping
9614     // memory alive unnecessarily.
9615     Object* maybe_constructor = object->map()->GetConstructor();
9616     if (maybe_constructor->IsJSFunction()) {
9617       JSFunction* constructor = JSFunction::cast(maybe_constructor);
9618       Isolate* isolate = object->GetIsolate();
9619       if (!constructor->shared()->IsApiFunction() &&
9620           object->class_name() == isolate->heap()->Object_string()) {
9621         Handle<String> constructor_name(object->constructor_name(), isolate);
9622         Context* context = constructor->context()->native_context();
9623         JSFunction* object_function = context->object_function();
9624         object->map()->SetConstructor(object_function);
9625         Handle<PrototypeInfo> proto_info =
9626             Map::GetOrCreatePrototypeInfo(object, isolate);
9627         proto_info->set_constructor_name(*constructor_name);
9628       }
9629     }
9630   }
9631 }
9632
9633
9634 // static
9635 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9636   if (!object->map()->is_prototype_map()) return;
9637   OptimizeAsPrototype(object, FAST_PROTOTYPE);
9638 }
9639
9640
9641 // static
9642 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
9643   DCHECK(FLAG_track_prototype_users);
9644   // Contract: In line with InvalidatePrototypeChains()'s requirements,
9645   // leaf maps don't need to register as users, only prototypes do.
9646   DCHECK(user->is_prototype_map());
9647
9648   Handle<Map> current_user = user;
9649   for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) {
9650     Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
9651     if (maybe_proto->IsJSGlobalProxy()) continue;
9652     // Proxies on the prototype chain are not supported.
9653     if (maybe_proto->IsJSProxy()) return;
9654     Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
9655     bool just_registered =
9656         RegisterPrototypeUserIfNotRegistered(proto, current_user, isolate);
9657     // Walk up the prototype chain as far as links haven't been registered yet.
9658     if (!just_registered) break;
9659     current_user = handle(proto->map(), isolate);
9660   }
9661 }
9662
9663
9664 // Returns true if the user was not yet registered.
9665 // static
9666 bool JSObject::RegisterPrototypeUserIfNotRegistered(Handle<JSObject> prototype,
9667                                                     Handle<HeapObject> user,
9668                                                     Isolate* isolate) {
9669   Handle<PrototypeInfo> proto_info =
9670       Map::GetOrCreatePrototypeInfo(prototype, isolate);
9671   Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
9672   bool was_present = false;
9673   Handle<WeakFixedArray> new_array = WeakFixedArray::Add(
9674       maybe_registry, user, WeakFixedArray::kAddIfNotFound, &was_present);
9675   if (!maybe_registry.is_identical_to(new_array)) {
9676     proto_info->set_prototype_users(*new_array);
9677   }
9678   if (FLAG_trace_prototype_users && !was_present) {
9679     PrintF("Registering %p as a user of prototype %p (map=%p).\n",
9680            reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype),
9681            reinterpret_cast<void*>(prototype->map()));
9682   }
9683   return !was_present;
9684 }
9685
9686
9687 // Can be called regardless of whether |user| was actually registered with
9688 // |prototype|. Returns true when there was a registration.
9689 // static
9690 bool JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
9691                                        Handle<HeapObject> user) {
9692   Isolate* isolate = prototype->GetIsolate();
9693   if (prototype->IsJSGlobalProxy()) {
9694     PrototypeIterator iter(isolate, prototype);
9695     prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
9696   }
9697   DCHECK(prototype->map()->is_prototype_map());
9698   Object* maybe_proto_info = prototype->map()->prototype_info();
9699   if (!maybe_proto_info->IsPrototypeInfo()) return false;
9700   Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
9701                                    isolate);
9702   Object* maybe_registry = proto_info->prototype_users();
9703   if (!maybe_registry->IsWeakFixedArray()) return false;
9704   bool result = WeakFixedArray::cast(maybe_registry)->Remove(user);
9705   if (FLAG_trace_prototype_users && result) {
9706     PrintF("Unregistering %p as a user of prototype %p.\n",
9707            reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
9708   }
9709   return result;
9710 }
9711
9712
9713 static void InvalidatePrototypeChainsInternal(Map* map) {
9714   if (!map->is_prototype_map()) return;
9715   if (FLAG_trace_prototype_users) {
9716     PrintF("Invalidating prototype map %p 's cell\n",
9717            reinterpret_cast<void*>(map));
9718   }
9719   Object* maybe_proto_info = map->prototype_info();
9720   if (!maybe_proto_info->IsPrototypeInfo()) return;
9721   PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
9722   Object* maybe_cell = proto_info->validity_cell();
9723   if (maybe_cell->IsCell()) {
9724     // Just set the value; the cell will be replaced lazily.
9725     Cell* cell = Cell::cast(maybe_cell);
9726     cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
9727   }
9728
9729   Object* maybe_array = proto_info->prototype_users();
9730   if (!maybe_array->IsWeakFixedArray()) return;
9731
9732   WeakFixedArray* users = WeakFixedArray::cast(maybe_array);
9733   for (int i = 0; i < users->Length(); ++i) {
9734     Object* maybe_user = users->Get(i);
9735     if (maybe_user->IsSmi()) continue;
9736
9737     // For now, only maps register themselves as users.
9738     Map* user = Map::cast(maybe_user);
9739     // Walk the prototype chain (backwards, towards leaf objects) if necessary.
9740     InvalidatePrototypeChainsInternal(user);
9741   }
9742 }
9743
9744
9745 // static
9746 void JSObject::InvalidatePrototypeChains(Map* map) {
9747   if (!FLAG_eliminate_prototype_chain_checks) return;
9748   DisallowHeapAllocation no_gc;
9749   if (map->IsJSGlobalProxyMap()) {
9750     PrototypeIterator iter(map);
9751     map = JSObject::cast(iter.GetCurrent())->map();
9752   }
9753   InvalidatePrototypeChainsInternal(map);
9754 }
9755
9756
9757 // static
9758 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
9759                                                     Isolate* isolate) {
9760   Object* maybe_proto_info = prototype->map()->prototype_info();
9761   if (maybe_proto_info->IsPrototypeInfo()) {
9762     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
9763   }
9764   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
9765   prototype->map()->set_prototype_info(*proto_info);
9766   return proto_info;
9767 }
9768
9769
9770 // static
9771 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
9772                                                         Isolate* isolate) {
9773   Handle<Object> maybe_prototype(map->prototype(), isolate);
9774   if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
9775   Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
9776   if (prototype->IsJSGlobalProxy()) {
9777     PrototypeIterator iter(isolate, prototype);
9778     prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
9779   }
9780   // Ensure the prototype is registered with its own prototypes so its cell
9781   // will be invalidated when necessary.
9782   JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
9783                                       isolate);
9784   Handle<PrototypeInfo> proto_info =
9785       GetOrCreatePrototypeInfo(prototype, isolate);
9786   Object* maybe_cell = proto_info->validity_cell();
9787   // Return existing cell if it's still valid.
9788   if (maybe_cell->IsCell()) {
9789     Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
9790     if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
9791       return cell;
9792     }
9793   }
9794   // Otherwise create a new cell.
9795   Handle<Cell> cell = isolate->factory()->NewCell(
9796       handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
9797   proto_info->set_validity_cell(*cell);
9798   return cell;
9799 }
9800
9801
9802 // static
9803 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
9804                        PrototypeOptimizationMode proto_mode) {
9805   if (prototype->IsJSObject()) {
9806     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
9807     JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
9808   }
9809   WriteBarrierMode wb_mode =
9810       prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
9811   map->set_prototype(*prototype, wb_mode);
9812 }
9813
9814
9815 Handle<Object> CacheInitialJSArrayMaps(
9816     Handle<Context> native_context, Handle<Map> initial_map) {
9817   // Replace all of the cached initial array maps in the native context with
9818   // the appropriate transitioned elements kind maps.
9819   Factory* factory = native_context->GetIsolate()->factory();
9820   Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9821       kElementsKindCount, TENURED);
9822
9823   Handle<Map> current_map = initial_map;
9824   ElementsKind kind = current_map->elements_kind();
9825   DCHECK(kind == GetInitialFastElementsKind());
9826   maps->set(kind, *current_map);
9827   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
9828        i < kFastElementsKindCount; ++i) {
9829     Handle<Map> new_map;
9830     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
9831     Map* maybe_elements_transition = current_map->ElementsTransitionMap();
9832     if (maybe_elements_transition != NULL) {
9833       new_map = handle(maybe_elements_transition);
9834       DCHECK(new_map->elements_kind() == next_kind);
9835     } else {
9836       new_map = Map::CopyAsElementsKind(
9837           current_map, next_kind, INSERT_TRANSITION);
9838     }
9839     maps->set(next_kind, *new_map);
9840     current_map = new_map;
9841   }
9842   if (initial_map->is_strong())
9843     native_context->set_js_array_strong_maps(*maps);
9844   else
9845     native_context->set_js_array_maps(*maps);
9846   return initial_map;
9847 }
9848
9849
9850 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
9851                                       Handle<Object> value) {
9852   Isolate* isolate = function->GetIsolate();
9853
9854   DCHECK(value->IsJSReceiver());
9855
9856   // Now some logic for the maps of the objects that are created by using this
9857   // function as a constructor.
9858   if (function->has_initial_map()) {
9859     // If the function has allocated the initial map replace it with a
9860     // copy containing the new prototype.  Also complete any in-object
9861     // slack tracking that is in progress at this point because it is
9862     // still tracking the old copy.
9863     if (function->IsInobjectSlackTrackingInProgress()) {
9864       function->CompleteInobjectSlackTracking();
9865     }
9866
9867     Handle<Map> initial_map(function->initial_map(), isolate);
9868
9869     if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
9870         initial_map->instance_type() == JS_OBJECT_TYPE) {
9871       // Put the value in the initial map field until an initial map is needed.
9872       // At that point, a new initial map is created and the prototype is put
9873       // into the initial map where it belongs.
9874       function->set_prototype_or_initial_map(*value);
9875     } else {
9876       Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype");
9877       JSFunction::SetInitialMap(function, new_map, value);
9878
9879       // If the function is used as the global Array function, cache the
9880       // updated initial maps (and transitioned versions) in the native context.
9881       Handle<Context> native_context(function->context()->native_context(),
9882                                      isolate);
9883       Handle<Object> array_function(
9884           native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
9885       if (array_function->IsJSFunction() &&
9886           *function == JSFunction::cast(*array_function)) {
9887         CacheInitialJSArrayMaps(native_context, new_map);
9888         Handle<Map> new_strong_map = Map::Copy(new_map, "SetInstancePrototype");
9889         new_strong_map->set_is_strong();
9890         CacheInitialJSArrayMaps(native_context, new_strong_map);
9891       }
9892     }
9893
9894     // Deoptimize all code that embeds the previous initial map.
9895     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
9896         isolate, DependentCode::kInitialMapChangedGroup);
9897   } else {
9898     // Put the value in the initial map field until an initial map is
9899     // needed.  At that point, a new initial map is created and the
9900     // prototype is put into the initial map where it belongs.
9901     function->set_prototype_or_initial_map(*value);
9902     if (value->IsJSObject()) {
9903       // Optimize as prototype to detach it from its transition tree.
9904       JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value),
9905                                     FAST_PROTOTYPE);
9906     }
9907   }
9908   isolate->heap()->ClearInstanceofCache();
9909 }
9910
9911
9912 void JSFunction::SetPrototype(Handle<JSFunction> function,
9913                               Handle<Object> value) {
9914   DCHECK(function->should_have_prototype());
9915   Handle<Object> construct_prototype = value;
9916
9917   // If the value is not a JSReceiver, store the value in the map's
9918   // constructor field so it can be accessed.  Also, set the prototype
9919   // used for constructing objects to the original object prototype.
9920   // See ECMA-262 13.2.2.
9921   if (!value->IsJSReceiver()) {
9922     // Copy the map so this does not affect unrelated functions.
9923     // Remove map transitions because they point to maps with a
9924     // different prototype.
9925     Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype");
9926
9927     JSObject::MigrateToMap(function, new_map);
9928     new_map->SetConstructor(*value);
9929     new_map->set_non_instance_prototype(true);
9930     Isolate* isolate = new_map->GetIsolate();
9931     construct_prototype = handle(
9932         isolate->context()->native_context()->initial_object_prototype(),
9933         isolate);
9934   } else {
9935     function->map()->set_non_instance_prototype(false);
9936   }
9937
9938   return SetInstancePrototype(function, construct_prototype);
9939 }
9940
9941
9942 bool JSFunction::RemovePrototype() {
9943   Context* native_context = context()->native_context();
9944   Map* no_prototype_map =
9945       is_strict(shared()->language_mode())
9946           ? native_context->strict_function_without_prototype_map()
9947           : native_context->sloppy_function_without_prototype_map();
9948
9949   if (map() == no_prototype_map) return true;
9950
9951 #ifdef DEBUG
9952   if (map() != (is_strict(shared()->language_mode())
9953                     ? native_context->strict_function_map()
9954                     : native_context->sloppy_function_map())) {
9955     return false;
9956   }
9957 #endif
9958
9959   set_map(no_prototype_map);
9960   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9961   return true;
9962 }
9963
9964
9965 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
9966                                Handle<Object> prototype) {
9967   if (map->prototype() != *prototype) {
9968     Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
9969   }
9970   function->set_prototype_or_initial_map(*map);
9971   map->SetConstructor(*function);
9972 #if TRACE_MAPS
9973   if (FLAG_trace_maps) {
9974     PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
9975            reinterpret_cast<void*>(*map), function->shared()->unique_id(),
9976            function->shared()->DebugName()->ToCString().get());
9977   }
9978 #endif
9979 }
9980
9981
9982 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
9983   if (function->has_initial_map()) return;
9984   Isolate* isolate = function->GetIsolate();
9985
9986   // First create a new map with the size and number of in-object properties
9987   // suggested by the function.
9988   InstanceType instance_type;
9989   int instance_size;
9990   int in_object_properties;
9991   if (function->shared()->is_generator()) {
9992     instance_type = JS_GENERATOR_OBJECT_TYPE;
9993     instance_size = JSGeneratorObject::kSize;
9994     in_object_properties = 0;
9995   } else {
9996     instance_type = JS_OBJECT_TYPE;
9997     instance_size = function->shared()->CalculateInstanceSize();
9998     in_object_properties = function->shared()->CalculateInObjectProperties();
9999   }
10000   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
10001
10002   // Fetch or allocate prototype.
10003   Handle<Object> prototype;
10004   if (function->has_instance_prototype()) {
10005     prototype = handle(function->instance_prototype(), isolate);
10006   } else {
10007     prototype = isolate->factory()->NewFunctionPrototype(function);
10008   }
10009   map->set_inobject_properties(in_object_properties);
10010   map->set_unused_property_fields(in_object_properties);
10011   DCHECK(map->has_fast_object_elements());
10012
10013   // Finally link initial map and constructor function.
10014   JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
10015
10016   if (!function->shared()->is_generator()) {
10017     function->StartInobjectSlackTracking();
10018   }
10019 }
10020
10021
10022 void JSFunction::SetInstanceClassName(String* name) {
10023   shared()->set_instance_class_name(name);
10024 }
10025
10026
10027 void JSFunction::PrintName(FILE* out) {
10028   base::SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
10029   PrintF(out, "%s", name.get());
10030 }
10031
10032
10033 // The filter is a pattern that matches function names in this way:
10034 //   "*"      all; the default
10035 //   "-"      all but the top-level function
10036 //   "-name"  all but the function "name"
10037 //   ""       only the top-level function
10038 //   "name"   only the function "name"
10039 //   "name*"  only functions starting with "name"
10040 //   "~"      none; the tilde is not an identifier
10041 bool JSFunction::PassesFilter(const char* raw_filter) {
10042   if (*raw_filter == '*') return true;
10043   String* name = shared()->DebugName();
10044   Vector<const char> filter = CStrVector(raw_filter);
10045   if (filter.length() == 0) return name->length() == 0;
10046   if (filter[0] == '-') {
10047     // Negative filter.
10048     if (filter.length() == 1) {
10049       return (name->length() != 0);
10050     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
10051       return false;
10052     }
10053     if (filter[filter.length() - 1] == '*' &&
10054         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
10055       return false;
10056     }
10057     return true;
10058
10059   } else if (name->IsUtf8EqualTo(filter)) {
10060     return true;
10061   }
10062   if (filter[filter.length() - 1] == '*' &&
10063       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
10064     return true;
10065   }
10066   return false;
10067 }
10068
10069
10070 Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
10071   Isolate* isolate = function->GetIsolate();
10072   Handle<Object> name =
10073       JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
10074   if (name->IsString()) return Handle<String>::cast(name);
10075   return handle(function->shared()->DebugName(), isolate);
10076 }
10077
10078
10079 void Oddball::Initialize(Isolate* isolate,
10080                          Handle<Oddball> oddball,
10081                          const char* to_string,
10082                          Handle<Object> to_number,
10083                          byte kind) {
10084   Handle<String> internalized_to_string =
10085       isolate->factory()->InternalizeUtf8String(to_string);
10086   oddball->set_to_string(*internalized_to_string);
10087   oddball->set_to_number(*to_number);
10088   oddball->set_kind(kind);
10089 }
10090
10091
10092 void Script::InitLineEnds(Handle<Script> script) {
10093   if (!script->line_ends()->IsUndefined()) return;
10094
10095   Isolate* isolate = script->GetIsolate();
10096
10097   if (!script->source()->IsString()) {
10098     DCHECK(script->source()->IsUndefined());
10099     Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
10100     script->set_line_ends(*empty);
10101     DCHECK(script->line_ends()->IsFixedArray());
10102     return;
10103   }
10104
10105   Handle<String> src(String::cast(script->source()), isolate);
10106
10107   Handle<FixedArray> array = String::CalculateLineEnds(src, true);
10108
10109   if (*array != isolate->heap()->empty_fixed_array()) {
10110     array->set_map(isolate->heap()->fixed_cow_array_map());
10111   }
10112
10113   script->set_line_ends(*array);
10114   DCHECK(script->line_ends()->IsFixedArray());
10115 }
10116
10117
10118 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
10119   int line_number = GetLineNumber(script, code_pos);
10120   if (line_number == -1) return -1;
10121
10122   DisallowHeapAllocation no_allocation;
10123   FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
10124   line_number = line_number - script->line_offset()->value();
10125   if (line_number == 0) return code_pos + script->column_offset()->value();
10126   int prev_line_end_pos =
10127       Smi::cast(line_ends_array->get(line_number - 1))->value();
10128   return code_pos - (prev_line_end_pos + 1);
10129 }
10130
10131
10132 int Script::GetLineNumberWithArray(int code_pos) {
10133   DisallowHeapAllocation no_allocation;
10134   DCHECK(line_ends()->IsFixedArray());
10135   FixedArray* line_ends_array = FixedArray::cast(line_ends());
10136   int line_ends_len = line_ends_array->length();
10137   if (line_ends_len == 0) return -1;
10138
10139   if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
10140     return line_offset()->value();
10141   }
10142
10143   int left = 0;
10144   int right = line_ends_len;
10145   while (int half = (right - left) / 2) {
10146     if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
10147       right -= half;
10148     } else {
10149       left += half;
10150     }
10151   }
10152   return right + line_offset()->value();
10153 }
10154
10155
10156 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
10157   InitLineEnds(script);
10158   return script->GetLineNumberWithArray(code_pos);
10159 }
10160
10161
10162 int Script::GetLineNumber(int code_pos) {
10163   DisallowHeapAllocation no_allocation;
10164   if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
10165
10166   // Slow mode: we do not have line_ends. We have to iterate through source.
10167   if (!source()->IsString()) return -1;
10168
10169   String* source_string = String::cast(source());
10170   int line = 0;
10171   int len = source_string->length();
10172   for (int pos = 0; pos < len; pos++) {
10173     if (pos == code_pos) break;
10174     if (source_string->Get(pos) == '\n') line++;
10175   }
10176   return line;
10177 }
10178
10179
10180 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
10181   Isolate* isolate = script->GetIsolate();
10182   Handle<String> name_or_source_url_key =
10183       isolate->factory()->InternalizeOneByteString(
10184           STATIC_CHAR_VECTOR("nameOrSourceURL"));
10185   Handle<JSObject> script_wrapper = Script::GetWrapper(script);
10186   Handle<Object> property = Object::GetProperty(
10187       script_wrapper, name_or_source_url_key).ToHandleChecked();
10188   DCHECK(property->IsJSFunction());
10189   Handle<JSFunction> method = Handle<JSFunction>::cast(property);
10190   Handle<Object> result;
10191   // Do not check against pending exception, since this function may be called
10192   // when an exception has already been pending.
10193   if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
10194     return isolate->factory()->undefined_value();
10195   }
10196   return result;
10197 }
10198
10199
10200 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
10201   Isolate* isolate = script->GetIsolate();
10202   if (!script->wrapper()->IsUndefined()) {
10203     DCHECK(script->wrapper()->IsWeakCell());
10204     Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
10205     if (!cell->cleared()) {
10206       // Return a handle for the existing script wrapper from the cache.
10207       return handle(JSObject::cast(cell->value()));
10208     }
10209     // If we found an empty WeakCell, that means the script wrapper was
10210     // GCed.  We are not notified directly of that, so we decrement here
10211     // so that we at least don't count double for any given script.
10212     isolate->counters()->script_wrappers()->Decrement();
10213   }
10214   // Construct a new script wrapper.
10215   isolate->counters()->script_wrappers()->Increment();
10216   Handle<JSFunction> constructor = isolate->script_function();
10217   Handle<JSValue> result =
10218       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
10219   result->set_value(*script);
10220   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
10221   script->set_wrapper(*cell);
10222   return result;
10223 }
10224
10225
10226 MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
10227     FunctionLiteral* fun) {
10228   if (shared_function_infos()->IsWeakFixedArray()) {
10229     WeakFixedArray* array = WeakFixedArray::cast(shared_function_infos());
10230     for (int i = 0; i < array->Length(); i++) {
10231       Object* obj = array->Get(i);
10232       if (!obj->IsSharedFunctionInfo()) continue;
10233       SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
10234       if (fun->function_token_position() == shared->function_token_position() &&
10235           fun->start_position() == shared->start_position()) {
10236         return Handle<SharedFunctionInfo>(shared);
10237       }
10238     }
10239   }
10240   return MaybeHandle<SharedFunctionInfo>();
10241 }
10242
10243
10244 void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
10245                                    Handle<Object> script_object) {
10246   if (shared->script() == *script_object) return;
10247   // Remove shared function info from old script's list.
10248   if (shared->script()->IsScript()) {
10249     Script* old_script = Script::cast(shared->script());
10250     if (old_script->shared_function_infos()->IsWeakFixedArray()) {
10251       WeakFixedArray* list =
10252           WeakFixedArray::cast(old_script->shared_function_infos());
10253       list->Remove(shared);
10254     }
10255   }
10256   // Add shared function info to new script's list.
10257   if (script_object->IsScript()) {
10258     Handle<Script> script = Handle<Script>::cast(script_object);
10259     Handle<Object> list(script->shared_function_infos(), shared->GetIsolate());
10260 #ifdef DEBUG
10261     bool found = false;
10262     list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAddIfNotFound,
10263                                &found);
10264     CHECK(!found);
10265 #else
10266     list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAlwaysAdd);
10267 #endif  // DEBUG
10268     script->set_shared_function_infos(*list);
10269   }
10270   // Finally set new script.
10271   shared->set_script(*script_object);
10272 }
10273
10274
10275 String* SharedFunctionInfo::DebugName() {
10276   Object* n = name();
10277   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
10278   return String::cast(n);
10279 }
10280
10281
10282 bool SharedFunctionInfo::HasSourceCode() const {
10283   return !script()->IsUndefined() &&
10284          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
10285 }
10286
10287
10288 Handle<Object> SharedFunctionInfo::GetSourceCode() {
10289   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
10290   Handle<String> source(String::cast(Script::cast(script())->source()));
10291   return GetIsolate()->factory()->NewSubString(
10292       source, start_position(), end_position());
10293 }
10294
10295
10296 bool SharedFunctionInfo::IsInlineable() {
10297   // Check that the function has a script associated with it.
10298   if (!script()->IsScript()) return false;
10299   return !optimization_disabled();
10300 }
10301
10302
10303 int SharedFunctionInfo::SourceSize() {
10304   return end_position() - start_position();
10305 }
10306
10307
10308 int SharedFunctionInfo::CalculateInstanceSize() {
10309   int instance_size =
10310       JSObject::kHeaderSize +
10311       expected_nof_properties() * kPointerSize;
10312   if (instance_size > JSObject::kMaxInstanceSize) {
10313     instance_size = JSObject::kMaxInstanceSize;
10314   }
10315   return instance_size;
10316 }
10317
10318
10319 int SharedFunctionInfo::CalculateInObjectProperties() {
10320   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
10321 }
10322
10323
10324 // Output the source code without any allocation in the heap.
10325 std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
10326   const SharedFunctionInfo* s = v.value;
10327   // For some native functions there is no source.
10328   if (!s->HasSourceCode()) return os << "<No Source>";
10329
10330   // Get the source for the script which this function came from.
10331   // Don't use String::cast because we don't want more assertion errors while
10332   // we are already creating a stack dump.
10333   String* script_source =
10334       reinterpret_cast<String*>(Script::cast(s->script())->source());
10335
10336   if (!script_source->LooksValid()) return os << "<Invalid Source>";
10337
10338   if (!s->is_toplevel()) {
10339     os << "function ";
10340     Object* name = s->name();
10341     if (name->IsString() && String::cast(name)->length() > 0) {
10342       String::cast(name)->PrintUC16(os);
10343     }
10344   }
10345
10346   int len = s->end_position() - s->start_position();
10347   if (len <= v.max_length || v.max_length < 0) {
10348     script_source->PrintUC16(os, s->start_position(), s->end_position());
10349     return os;
10350   } else {
10351     script_source->PrintUC16(os, s->start_position(),
10352                              s->start_position() + v.max_length);
10353     return os << "...\n";
10354   }
10355 }
10356
10357
10358 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
10359   if (code->instruction_size() != recompiled->instruction_size()) return false;
10360   ByteArray* code_relocation = code->relocation_info();
10361   ByteArray* recompiled_relocation = recompiled->relocation_info();
10362   int length = code_relocation->length();
10363   if (length != recompiled_relocation->length()) return false;
10364   int compare = memcmp(code_relocation->GetDataStartAddress(),
10365                        recompiled_relocation->GetDataStartAddress(),
10366                        length);
10367   return compare == 0;
10368 }
10369
10370
10371 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
10372   DCHECK(!has_deoptimization_support());
10373   DisallowHeapAllocation no_allocation;
10374   Code* code = this->code();
10375   if (IsCodeEquivalent(code, recompiled)) {
10376     // Copy the deoptimization data from the recompiled code.
10377     code->set_deoptimization_data(recompiled->deoptimization_data());
10378     code->set_has_deoptimization_support(true);
10379   } else {
10380     // TODO(3025757): In case the recompiled isn't equivalent to the
10381     // old code, we have to replace it. We should try to avoid this
10382     // altogether because it flushes valuable type feedback by
10383     // effectively resetting all IC state.
10384     ReplaceCode(recompiled);
10385   }
10386   DCHECK(has_deoptimization_support());
10387 }
10388
10389
10390 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
10391   // Disable optimization for the shared function info and mark the
10392   // code as non-optimizable. The marker on the shared function info
10393   // is there because we flush non-optimized code thereby loosing the
10394   // non-optimizable information for the code. When the code is
10395   // regenerated and set on the shared function info it is marked as
10396   // non-optimizable if optimization is disabled for the shared
10397   // function info.
10398   DCHECK(reason != kNoReason);
10399   set_optimization_disabled(true);
10400   set_disable_optimization_reason(reason);
10401   // Code should be the lazy compilation stub or else unoptimized.
10402   DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
10403   PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
10404   if (FLAG_trace_opt) {
10405     PrintF("[disabled optimization for ");
10406     ShortPrint();
10407     PrintF(", reason: %s]\n", GetBailoutReason(reason));
10408   }
10409 }
10410
10411
10412 void SharedFunctionInfo::InitFromFunctionLiteral(
10413     Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
10414   shared_info->set_length(lit->scope()->default_function_length());
10415   shared_info->set_internal_formal_parameter_count(lit->parameter_count());
10416   shared_info->set_function_token_position(lit->function_token_position());
10417   shared_info->set_start_position(lit->start_position());
10418   shared_info->set_end_position(lit->end_position());
10419   shared_info->set_is_expression(lit->is_expression());
10420   shared_info->set_is_anonymous(lit->is_anonymous());
10421   shared_info->set_inferred_name(*lit->inferred_name());
10422   shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
10423   shared_info->set_allows_lazy_compilation_without_context(
10424       lit->AllowsLazyCompilationWithoutContext());
10425   shared_info->set_language_mode(lit->language_mode());
10426   shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
10427   shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
10428   shared_info->set_ast_node_count(lit->ast_node_count());
10429   shared_info->set_is_function(lit->is_function());
10430   if (lit->dont_optimize_reason() != kNoReason) {
10431     shared_info->DisableOptimization(lit->dont_optimize_reason());
10432   }
10433   shared_info->set_dont_crankshaft(lit->flags() &
10434                                    AstProperties::kDontCrankshaft);
10435   shared_info->set_kind(lit->kind());
10436   shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
10437   shared_info->set_asm_function(lit->scope()->asm_function());
10438 }
10439
10440
10441 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
10442   DCHECK(!id.IsNone());
10443   Code* unoptimized = code();
10444   DeoptimizationOutputData* data =
10445       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
10446   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
10447   USE(ignore);
10448   return true;  // Return true if there was no DCHECK.
10449 }
10450
10451
10452 void JSFunction::StartInobjectSlackTracking() {
10453   DCHECK(has_initial_map() && !IsInobjectSlackTrackingInProgress());
10454
10455   Map* map = initial_map();
10456
10457   // No tracking during the snapshot construction phase.
10458   Isolate* isolate = GetIsolate();
10459   if (isolate->serializer_enabled()) return;
10460
10461   if (map->unused_property_fields() == 0) return;
10462
10463   map->set_counter(Map::kSlackTrackingCounterStart);
10464 }
10465
10466
10467 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
10468   code()->ClearInlineCaches();
10469   // If we clear ICs, we need to clear the type feedback vector too, since
10470   // CallICs are synced with a feedback vector slot.
10471   ClearTypeFeedbackInfo();
10472   set_ic_age(new_ic_age);
10473   if (code()->kind() == Code::FUNCTION) {
10474     code()->set_profiler_ticks(0);
10475     if (optimization_disabled() &&
10476         opt_count() >= FLAG_max_opt_count) {
10477       // Re-enable optimizations if they were disabled due to opt_count limit.
10478       set_optimization_disabled(false);
10479     }
10480     set_opt_count(0);
10481     set_deopt_count(0);
10482   }
10483 }
10484
10485
10486 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap(
10487     Context* native_context, BailoutId osr_ast_id) {
10488   DisallowHeapAllocation no_gc;
10489   DCHECK(native_context->IsNativeContext());
10490   Object* value = optimized_code_map();
10491   if (!value->IsSmi()) {
10492     FixedArray* optimized_code_map = FixedArray::cast(value);
10493     int length = optimized_code_map->length();
10494     Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
10495     for (int i = kEntriesStart; i < length; i += kEntryLength) {
10496       if (optimized_code_map->get(i + kContextOffset) == native_context &&
10497           optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
10498         return {Code::cast(optimized_code_map->get(i + kCachedCodeOffset)),
10499                 FixedArray::cast(optimized_code_map->get(i + kLiteralsOffset))};
10500       }
10501     }
10502     Object* shared_code = optimized_code_map->get(kSharedCodeIndex);
10503     if (shared_code->IsCode() && osr_ast_id.IsNone()) {
10504       return {Code::cast(shared_code), nullptr};
10505     }
10506     if (FLAG_trace_opt) {
10507       PrintF("[didn't find optimized code in optimized code map for ");
10508       ShortPrint();
10509       PrintF("]\n");
10510     }
10511   }
10512   return {nullptr, nullptr};
10513 }
10514
10515
10516 #define DECLARE_TAG(ignore1, name, ignore2) name,
10517 const char* const VisitorSynchronization::kTags[
10518     VisitorSynchronization::kNumberOfSyncTags] = {
10519   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10520 };
10521 #undef DECLARE_TAG
10522
10523
10524 #define DECLARE_TAG(ignore1, ignore2, name) name,
10525 const char* const VisitorSynchronization::kTagNames[
10526     VisitorSynchronization::kNumberOfSyncTags] = {
10527   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10528 };
10529 #undef DECLARE_TAG
10530
10531
10532 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10533   DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
10534   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10535   Object* old_target = target;
10536   VisitPointer(&target);
10537   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10538 }
10539
10540
10541 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10542   DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10543   Object* stub = rinfo->code_age_stub();
10544   if (stub) {
10545     VisitPointer(&stub);
10546   }
10547 }
10548
10549
10550 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10551   Object* code = Code::GetObjectFromEntryAddress(entry_address);
10552   Object* old_code = code;
10553   VisitPointer(&code);
10554   if (code != old_code) {
10555     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10556   }
10557 }
10558
10559
10560 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10561   DCHECK(rinfo->rmode() == RelocInfo::CELL);
10562   Object* cell = rinfo->target_cell();
10563   Object* old_cell = cell;
10564   VisitPointer(&cell);
10565   if (cell != old_cell) {
10566     rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10567   }
10568 }
10569
10570
10571 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10572   DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10573          rinfo->IsPatchedDebugBreakSlotSequence());
10574   Object* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
10575   Object* old_target = target;
10576   VisitPointer(&target);
10577   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10578 }
10579
10580
10581 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10582   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10583   Object* p = rinfo->target_object();
10584   VisitPointer(&p);
10585 }
10586
10587
10588 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10589   Address p = rinfo->target_external_reference();
10590   VisitExternalReference(&p);
10591 }
10592
10593
10594 void Code::InvalidateRelocation() {
10595   InvalidateEmbeddedObjects();
10596   set_relocation_info(GetHeap()->empty_byte_array());
10597 }
10598
10599
10600 void Code::InvalidateEmbeddedObjects() {
10601   Object* undefined = GetHeap()->undefined_value();
10602   Cell* undefined_cell = GetHeap()->undefined_cell();
10603   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10604                   RelocInfo::ModeMask(RelocInfo::CELL);
10605   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10606     RelocInfo::Mode mode = it.rinfo()->rmode();
10607     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10608       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10609     } else if (mode == RelocInfo::CELL) {
10610       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10611     }
10612   }
10613 }
10614
10615
10616 void Code::Relocate(intptr_t delta) {
10617   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10618     it.rinfo()->apply(delta);
10619   }
10620   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10621 }
10622
10623
10624 void Code::CopyFrom(const CodeDesc& desc) {
10625   DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT);
10626
10627   // copy code
10628   CopyBytes(instruction_start(), desc.buffer,
10629             static_cast<size_t>(desc.instr_size));
10630
10631   // copy reloc info
10632   CopyBytes(relocation_start(),
10633             desc.buffer + desc.buffer_size - desc.reloc_size,
10634             static_cast<size_t>(desc.reloc_size));
10635
10636   // unbox handles and relocate
10637   intptr_t delta = instruction_start() - desc.buffer;
10638   int mode_mask = RelocInfo::kCodeTargetMask |
10639                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10640                   RelocInfo::ModeMask(RelocInfo::CELL) |
10641                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
10642                   RelocInfo::kApplyMask;
10643   // Needed to find target_object and runtime_entry on X64
10644   Assembler* origin = desc.origin;
10645   AllowDeferredHandleDereference embedding_raw_address;
10646   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10647     RelocInfo::Mode mode = it.rinfo()->rmode();
10648     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10649       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10650       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10651     } else if (mode == RelocInfo::CELL) {
10652       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
10653       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10654     } else if (RelocInfo::IsCodeTarget(mode)) {
10655       // rewrite code handles in inline cache targets to direct
10656       // pointers to the first instruction in the code object
10657       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10658       Code* code = Code::cast(*p);
10659       it.rinfo()->set_target_address(code->instruction_start(),
10660                                      SKIP_WRITE_BARRIER,
10661                                      SKIP_ICACHE_FLUSH);
10662     } else if (RelocInfo::IsRuntimeEntry(mode)) {
10663       Address p = it.rinfo()->target_runtime_entry(origin);
10664       it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
10665                                            SKIP_ICACHE_FLUSH);
10666     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10667       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10668       Code* code = Code::cast(*p);
10669       it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
10670     } else {
10671       it.rinfo()->apply(delta);
10672     }
10673   }
10674   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10675 }
10676
10677
10678 // Locate the source position which is closest to the address in the code. This
10679 // is using the source position information embedded in the relocation info.
10680 // The position returned is relative to the beginning of the script where the
10681 // source for this function is found.
10682 int Code::SourcePosition(Address pc) {
10683   int distance = kMaxInt;
10684   int position = RelocInfo::kNoPosition;  // Initially no position found.
10685   // Run through all the relocation info to find the best matching source
10686   // position. All the code needs to be considered as the sequence of the
10687   // instructions in the code does not necessarily follow the same order as the
10688   // source.
10689   RelocIterator it(this, RelocInfo::kPositionMask);
10690   while (!it.done()) {
10691     // Only look at positions after the current pc.
10692     if (it.rinfo()->pc() < pc) {
10693       // Get position and distance.
10694
10695       int dist = static_cast<int>(pc - it.rinfo()->pc());
10696       int pos = static_cast<int>(it.rinfo()->data());
10697       // If this position is closer than the current candidate or if it has the
10698       // same distance as the current candidate and the position is higher then
10699       // this position is the new candidate.
10700       if ((dist < distance) ||
10701           (dist == distance && pos > position)) {
10702         position = pos;
10703         distance = dist;
10704       }
10705     }
10706     it.next();
10707   }
10708   return position;
10709 }
10710
10711
10712 // Same as Code::SourcePosition above except it only looks for statement
10713 // positions.
10714 int Code::SourceStatementPosition(Address pc) {
10715   // First find the position as close as possible using all position
10716   // information.
10717   int position = SourcePosition(pc);
10718   // Now find the closest statement position before the position.
10719   int statement_position = 0;
10720   RelocIterator it(this, RelocInfo::kPositionMask);
10721   while (!it.done()) {
10722     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
10723       int p = static_cast<int>(it.rinfo()->data());
10724       if (statement_position < p && p <= position) {
10725         statement_position = p;
10726       }
10727     }
10728     it.next();
10729   }
10730   return statement_position;
10731 }
10732
10733
10734 SafepointEntry Code::GetSafepointEntry(Address pc) {
10735   SafepointTable table(this);
10736   return table.FindEntry(pc);
10737 }
10738
10739
10740 Object* Code::FindNthObject(int n, Map* match_map) {
10741   DCHECK(is_inline_cache_stub());
10742   DisallowHeapAllocation no_allocation;
10743   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10744   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10745     RelocInfo* info = it.rinfo();
10746     Object* object = info->target_object();
10747     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10748     if (object->IsHeapObject()) {
10749       if (HeapObject::cast(object)->map() == match_map) {
10750         if (--n == 0) return object;
10751       }
10752     }
10753   }
10754   return NULL;
10755 }
10756
10757
10758 AllocationSite* Code::FindFirstAllocationSite() {
10759   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
10760   return (result != NULL) ? AllocationSite::cast(result) : NULL;
10761 }
10762
10763
10764 Map* Code::FindFirstMap() {
10765   Object* result = FindNthObject(1, GetHeap()->meta_map());
10766   return (result != NULL) ? Map::cast(result) : NULL;
10767 }
10768
10769
10770 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
10771   DCHECK(is_inline_cache_stub() || is_handler());
10772   DisallowHeapAllocation no_allocation;
10773   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10774   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
10775   int current_pattern = 0;
10776   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10777     RelocInfo* info = it.rinfo();
10778     Object* object = info->target_object();
10779     if (object->IsHeapObject()) {
10780       if (object->IsWeakCell()) {
10781         object = HeapObject::cast(WeakCell::cast(object)->value());
10782       }
10783       Map* map = HeapObject::cast(object)->map();
10784       if (map == *pattern.find_[current_pattern]) {
10785         info->set_target_object(*pattern.replace_[current_pattern]);
10786         if (++current_pattern == pattern.count_) return;
10787       }
10788     }
10789   }
10790   UNREACHABLE();
10791 }
10792
10793
10794 void Code::FindAllMaps(MapHandleList* maps) {
10795   DCHECK(is_inline_cache_stub());
10796   DisallowHeapAllocation no_allocation;
10797   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10798   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10799     RelocInfo* info = it.rinfo();
10800     Object* object = info->target_object();
10801     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10802     if (object->IsMap()) maps->Add(handle(Map::cast(object)));
10803   }
10804 }
10805
10806
10807 Code* Code::FindFirstHandler() {
10808   DCHECK(is_inline_cache_stub());
10809   DisallowHeapAllocation no_allocation;
10810   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10811              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10812   bool skip_next_handler = false;
10813   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10814     RelocInfo* info = it.rinfo();
10815     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10816       Object* obj = info->target_object();
10817       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
10818     } else {
10819       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10820       if (code->kind() == Code::HANDLER) {
10821         if (!skip_next_handler) return code;
10822         skip_next_handler = false;
10823       }
10824     }
10825   }
10826   return NULL;
10827 }
10828
10829
10830 bool Code::FindHandlers(CodeHandleList* code_list, int length) {
10831   DCHECK(is_inline_cache_stub());
10832   DisallowHeapAllocation no_allocation;
10833   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10834              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10835   bool skip_next_handler = false;
10836   int i = 0;
10837   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10838     if (i == length) return true;
10839     RelocInfo* info = it.rinfo();
10840     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10841       Object* obj = info->target_object();
10842       skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
10843     } else {
10844       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10845       // IC stubs with handlers never contain non-handler code objects before
10846       // handler targets.
10847       if (code->kind() != Code::HANDLER) break;
10848       if (!skip_next_handler) {
10849         code_list->Add(Handle<Code>(code));
10850         i++;
10851       }
10852       skip_next_handler = false;
10853     }
10854   }
10855   return i == length;
10856 }
10857
10858
10859 MaybeHandle<Code> Code::FindHandlerForMap(Map* map) {
10860   DCHECK(is_inline_cache_stub());
10861   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10862              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10863   bool return_next = false;
10864   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10865     RelocInfo* info = it.rinfo();
10866     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10867       Object* object = info->target_object();
10868       if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
10869       if (object == map) return_next = true;
10870     } else if (return_next) {
10871       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10872       DCHECK(code->kind() == Code::HANDLER);
10873       return handle(code);
10874     }
10875   }
10876   return MaybeHandle<Code>();
10877 }
10878
10879
10880 Name* Code::FindFirstName() {
10881   DCHECK(is_inline_cache_stub());
10882   DisallowHeapAllocation no_allocation;
10883   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10884   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10885     RelocInfo* info = it.rinfo();
10886     Object* object = info->target_object();
10887     if (object->IsName()) return Name::cast(object);
10888   }
10889   return NULL;
10890 }
10891
10892
10893 void Code::ClearInlineCaches() {
10894   ClearInlineCaches(NULL);
10895 }
10896
10897
10898 void Code::ClearInlineCaches(Code::Kind kind) {
10899   ClearInlineCaches(&kind);
10900 }
10901
10902
10903 void Code::ClearInlineCaches(Code::Kind* kind) {
10904   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10905              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
10906              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
10907   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10908     RelocInfo* info = it.rinfo();
10909     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10910     if (target->is_inline_cache_stub()) {
10911       if (kind == NULL || *kind == target->kind()) {
10912         IC::Clear(this->GetIsolate(), info->pc(),
10913                   info->host()->constant_pool());
10914       }
10915     }
10916   }
10917 }
10918
10919
10920 void SharedFunctionInfo::ClearTypeFeedbackInfo() {
10921   feedback_vector()->ClearSlots(this);
10922   feedback_vector()->ClearICSlots(this);
10923 }
10924
10925
10926 void SharedFunctionInfo::ClearTypeFeedbackInfoAtGCTime() {
10927   feedback_vector()->ClearSlotsAtGCTime(this);
10928   feedback_vector()->ClearICSlotsAtGCTime(this);
10929 }
10930
10931
10932 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
10933   DisallowHeapAllocation no_gc;
10934   DCHECK(kind() == FUNCTION);
10935   BackEdgeTable back_edges(this, &no_gc);
10936   for (uint32_t i = 0; i < back_edges.length(); i++) {
10937     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
10938   }
10939   return BailoutId::None();
10940 }
10941
10942
10943 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
10944   DisallowHeapAllocation no_gc;
10945   DCHECK(kind() == FUNCTION);
10946   BackEdgeTable back_edges(this, &no_gc);
10947   for (uint32_t i = 0; i < back_edges.length(); i++) {
10948     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
10949   }
10950   UNREACHABLE();  // We expect to find the back edge.
10951   return 0;
10952 }
10953
10954
10955 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
10956   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
10957 }
10958
10959
10960 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
10961   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
10962       NO_MARKING_PARITY);
10963 }
10964
10965
10966 // NextAge defines the Code::Age state transitions during a GC cycle.
10967 static Code::Age NextAge(Code::Age age) {
10968   switch (age) {
10969     case Code::kNotExecutedCodeAge:  // Keep, until we've been executed.
10970     case Code::kToBeExecutedOnceCodeAge:  // Keep, until we've been executed.
10971     case Code::kLastCodeAge:  // Clamp at last Code::Age value.
10972       return age;
10973     case Code::kExecutedOnceCodeAge:
10974       // Pre-age code that has only been executed once.
10975       return static_cast<Code::Age>(Code::kPreAgedCodeAge + 1);
10976     default:
10977       return static_cast<Code::Age>(age + 1);  // Default case: Increase age.
10978   }
10979 }
10980
10981
10982 // IsOldAge defines the collection criteria for a Code object.
10983 static bool IsOldAge(Code::Age age) {
10984   return age >= Code::kIsOldCodeAge || age == Code::kNotExecutedCodeAge;
10985 }
10986
10987
10988 void Code::MakeYoung(Isolate* isolate) {
10989   byte* sequence = FindCodeAgeSequence();
10990   if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, isolate);
10991 }
10992
10993
10994 void Code::MarkToBeExecutedOnce(Isolate* isolate) {
10995   byte* sequence = FindCodeAgeSequence();
10996   if (sequence != NULL) {
10997     PatchPlatformCodeAge(isolate, sequence, kToBeExecutedOnceCodeAge,
10998                          NO_MARKING_PARITY);
10999   }
11000 }
11001
11002
11003 void Code::MakeOlder(MarkingParity current_parity) {
11004   byte* sequence = FindCodeAgeSequence();
11005   if (sequence != NULL) {
11006     Age age;
11007     MarkingParity code_parity;
11008     Isolate* isolate = GetIsolate();
11009     GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
11010     Age next_age = NextAge(age);
11011     if (age != next_age && code_parity != current_parity) {
11012       PatchPlatformCodeAge(isolate, sequence, next_age, current_parity);
11013     }
11014   }
11015 }
11016
11017
11018 bool Code::IsOld() {
11019   return IsOldAge(GetAge());
11020 }
11021
11022
11023 byte* Code::FindCodeAgeSequence() {
11024   return FLAG_age_code &&
11025       prologue_offset() != Code::kPrologueOffsetNotSet &&
11026       (kind() == OPTIMIZED_FUNCTION ||
11027        (kind() == FUNCTION && !has_debug_break_slots()))
11028       ? instruction_start() + prologue_offset()
11029       : NULL;
11030 }
11031
11032
11033 Code::Age Code::GetAge() {
11034   byte* sequence = FindCodeAgeSequence();
11035   if (sequence == NULL) {
11036     return kNoAgeCodeAge;
11037   }
11038   Age age;
11039   MarkingParity parity;
11040   GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
11041   return age;
11042 }
11043
11044
11045 void Code::GetCodeAgeAndParity(Code* code, Age* age,
11046                                MarkingParity* parity) {
11047   Isolate* isolate = code->GetIsolate();
11048   Builtins* builtins = isolate->builtins();
11049   Code* stub = NULL;
11050 #define HANDLE_CODE_AGE(AGE)                                            \
11051   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
11052   if (code == stub) {                                                   \
11053     *age = k##AGE##CodeAge;                                             \
11054     *parity = EVEN_MARKING_PARITY;                                      \
11055     return;                                                             \
11056   }                                                                     \
11057   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
11058   if (code == stub) {                                                   \
11059     *age = k##AGE##CodeAge;                                             \
11060     *parity = ODD_MARKING_PARITY;                                       \
11061     return;                                                             \
11062   }
11063   CODE_AGE_LIST(HANDLE_CODE_AGE)
11064 #undef HANDLE_CODE_AGE
11065   stub = *builtins->MarkCodeAsExecutedOnce();
11066   if (code == stub) {
11067     *age = kNotExecutedCodeAge;
11068     *parity = NO_MARKING_PARITY;
11069     return;
11070   }
11071   stub = *builtins->MarkCodeAsExecutedTwice();
11072   if (code == stub) {
11073     *age = kExecutedOnceCodeAge;
11074     *parity = NO_MARKING_PARITY;
11075     return;
11076   }
11077   stub = *builtins->MarkCodeAsToBeExecutedOnce();
11078   if (code == stub) {
11079     *age = kToBeExecutedOnceCodeAge;
11080     *parity = NO_MARKING_PARITY;
11081     return;
11082   }
11083   UNREACHABLE();
11084 }
11085
11086
11087 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
11088   Builtins* builtins = isolate->builtins();
11089   switch (age) {
11090 #define HANDLE_CODE_AGE(AGE)                                            \
11091     case k##AGE##CodeAge: {                                             \
11092       Code* stub = parity == EVEN_MARKING_PARITY                        \
11093           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
11094           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
11095       return stub;                                                      \
11096     }
11097     CODE_AGE_LIST(HANDLE_CODE_AGE)
11098 #undef HANDLE_CODE_AGE
11099     case kNotExecutedCodeAge: {
11100       DCHECK(parity == NO_MARKING_PARITY);
11101       return *builtins->MarkCodeAsExecutedOnce();
11102     }
11103     case kExecutedOnceCodeAge: {
11104       DCHECK(parity == NO_MARKING_PARITY);
11105       return *builtins->MarkCodeAsExecutedTwice();
11106     }
11107     case kToBeExecutedOnceCodeAge: {
11108       DCHECK(parity == NO_MARKING_PARITY);
11109       return *builtins->MarkCodeAsToBeExecutedOnce();
11110     }
11111     default:
11112       UNREACHABLE();
11113       break;
11114   }
11115   return NULL;
11116 }
11117
11118
11119 void Code::PrintDeoptLocation(FILE* out, Address pc) {
11120   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
11121   class SourcePosition pos = info.position;
11122   if (info.deopt_reason != Deoptimizer::kNoReason || !pos.IsUnknown()) {
11123     if (FLAG_hydrogen_track_positions) {
11124       PrintF(out, "            ;;; deoptimize at %d_%d: %s\n",
11125              pos.inlining_id(), pos.position(),
11126              Deoptimizer::GetDeoptReason(info.deopt_reason));
11127     } else {
11128       PrintF(out, "            ;;; deoptimize at %d: %s\n", pos.raw(),
11129              Deoptimizer::GetDeoptReason(info.deopt_reason));
11130     }
11131   }
11132 }
11133
11134
11135 bool Code::CanDeoptAt(Address pc) {
11136   DeoptimizationInputData* deopt_data =
11137       DeoptimizationInputData::cast(deoptimization_data());
11138   Address code_start_address = instruction_start();
11139   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
11140     if (deopt_data->Pc(i)->value() == -1) continue;
11141     Address address = code_start_address + deopt_data->Pc(i)->value();
11142     if (address == pc) return true;
11143   }
11144   return false;
11145 }
11146
11147
11148 // Identify kind of code.
11149 const char* Code::Kind2String(Kind kind) {
11150   switch (kind) {
11151 #define CASE(name) case name: return #name;
11152     CODE_KIND_LIST(CASE)
11153 #undef CASE
11154     case NUMBER_OF_KINDS: break;
11155   }
11156   UNREACHABLE();
11157   return NULL;
11158 }
11159
11160
11161 Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
11162   DCHECK(code->kind() == OPTIMIZED_FUNCTION);
11163   WeakCell* raw_cell = code->CachedWeakCell();
11164   if (raw_cell != NULL) return Handle<WeakCell>(raw_cell);
11165   Handle<WeakCell> cell = code->GetIsolate()->factory()->NewWeakCell(code);
11166   DeoptimizationInputData::cast(code->deoptimization_data())
11167       ->SetWeakCellCache(*cell);
11168   return cell;
11169 }
11170
11171
11172 WeakCell* Code::CachedWeakCell() {
11173   DCHECK(kind() == OPTIMIZED_FUNCTION);
11174   Object* weak_cell_cache =
11175       DeoptimizationInputData::cast(deoptimization_data())->WeakCellCache();
11176   if (weak_cell_cache->IsWeakCell()) {
11177     DCHECK(this == WeakCell::cast(weak_cell_cache)->value());
11178     return WeakCell::cast(weak_cell_cache);
11179   }
11180   return NULL;
11181 }
11182
11183
11184 #ifdef ENABLE_DISASSEMBLER
11185
11186 void DeoptimizationInputData::DeoptimizationInputDataPrint(
11187     std::ostream& os) {  // NOLINT
11188   disasm::NameConverter converter;
11189   int const inlined_function_count = InlinedFunctionCount()->value();
11190   os << "Inlined functions (count = " << inlined_function_count << ")\n";
11191   for (int id = 0; id < inlined_function_count; ++id) {
11192     Object* info = LiteralArray()->get(id);
11193     os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
11194   }
11195   os << "\n";
11196   int deopt_count = DeoptCount();
11197   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
11198   if (0 != deopt_count) {
11199     os << " index  ast id    argc     pc";
11200     if (FLAG_print_code_verbose) os << "  commands";
11201     os << "\n";
11202   }
11203   for (int i = 0; i < deopt_count; i++) {
11204     os << std::setw(6) << i << "  " << std::setw(6) << AstId(i).ToInt() << "  "
11205        << std::setw(6) << ArgumentsStackHeight(i)->value() << " "
11206        << std::setw(6) << Pc(i)->value();
11207
11208     if (!FLAG_print_code_verbose) {
11209       os << "\n";
11210       continue;
11211     }
11212     // Print details of the frame translation.
11213     int translation_index = TranslationIndex(i)->value();
11214     TranslationIterator iterator(TranslationByteArray(), translation_index);
11215     Translation::Opcode opcode =
11216         static_cast<Translation::Opcode>(iterator.Next());
11217     DCHECK(Translation::BEGIN == opcode);
11218     int frame_count = iterator.Next();
11219     int jsframe_count = iterator.Next();
11220     os << "  " << Translation::StringFor(opcode)
11221        << " {frame count=" << frame_count
11222        << ", js frame count=" << jsframe_count << "}\n";
11223
11224     while (iterator.HasNext() &&
11225            Translation::BEGIN !=
11226            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
11227       os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
11228
11229       switch (opcode) {
11230         case Translation::BEGIN:
11231           UNREACHABLE();
11232           break;
11233
11234         case Translation::JS_FRAME: {
11235           int ast_id = iterator.Next();
11236           int shared_info_id = iterator.Next();
11237           unsigned height = iterator.Next();
11238           Object* shared_info = LiteralArray()->get(shared_info_id);
11239           os << "{ast_id=" << ast_id << ", function="
11240              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
11241              << ", height=" << height << "}";
11242           break;
11243         }
11244
11245         case Translation::JS_FRAME_FUNCTION: {
11246           os << "{function}";
11247           break;
11248         }
11249
11250         case Translation::COMPILED_STUB_FRAME: {
11251           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
11252           os << "{kind=" << stub_kind << "}";
11253           break;
11254         }
11255
11256         case Translation::ARGUMENTS_ADAPTOR_FRAME:
11257         case Translation::CONSTRUCT_STUB_FRAME: {
11258           int shared_info_id = iterator.Next();
11259           Object* shared_info = LiteralArray()->get(shared_info_id);
11260           unsigned height = iterator.Next();
11261           os << "{function="
11262              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
11263              << ", height=" << height << "}";
11264           break;
11265         }
11266
11267         case Translation::GETTER_STUB_FRAME:
11268         case Translation::SETTER_STUB_FRAME: {
11269           int shared_info_id = iterator.Next();
11270           Object* shared_info = LiteralArray()->get(shared_info_id);
11271           os << "{function=" << Brief(SharedFunctionInfo::cast(shared_info)
11272                                           ->DebugName()) << "}";
11273           break;
11274         }
11275
11276         case Translation::REGISTER: {
11277           int reg_code = iterator.Next();
11278           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11279           break;
11280         }
11281
11282         case Translation::INT32_REGISTER: {
11283           int reg_code = iterator.Next();
11284           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11285           break;
11286         }
11287
11288         case Translation::UINT32_REGISTER: {
11289           int reg_code = iterator.Next();
11290           os << "{input=" << converter.NameOfCPURegister(reg_code)
11291              << " (unsigned)}";
11292           break;
11293         }
11294
11295         case Translation::BOOL_REGISTER: {
11296           int reg_code = iterator.Next();
11297           os << "{input=" << converter.NameOfCPURegister(reg_code)
11298              << " (bool)}";
11299           break;
11300         }
11301
11302         case Translation::DOUBLE_REGISTER: {
11303           int reg_code = iterator.Next();
11304           os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
11305              << "}";
11306           break;
11307         }
11308
11309         case Translation::STACK_SLOT: {
11310           int input_slot_index = iterator.Next();
11311           os << "{input=" << input_slot_index << "}";
11312           break;
11313         }
11314
11315         case Translation::INT32_STACK_SLOT: {
11316           int input_slot_index = iterator.Next();
11317           os << "{input=" << input_slot_index << "}";
11318           break;
11319         }
11320
11321         case Translation::UINT32_STACK_SLOT: {
11322           int input_slot_index = iterator.Next();
11323           os << "{input=" << input_slot_index << " (unsigned)}";
11324           break;
11325         }
11326
11327         case Translation::BOOL_STACK_SLOT: {
11328           int input_slot_index = iterator.Next();
11329           os << "{input=" << input_slot_index << " (bool)}";
11330           break;
11331         }
11332
11333         case Translation::DOUBLE_STACK_SLOT: {
11334           int input_slot_index = iterator.Next();
11335           os << "{input=" << input_slot_index << "}";
11336           break;
11337         }
11338
11339         case Translation::LITERAL: {
11340           unsigned literal_index = iterator.Next();
11341           os << "{literal_id=" << literal_index << "}";
11342           break;
11343         }
11344
11345         case Translation::DUPLICATED_OBJECT: {
11346           int object_index = iterator.Next();
11347           os << "{object_index=" << object_index << "}";
11348           break;
11349         }
11350
11351         case Translation::ARGUMENTS_OBJECT:
11352         case Translation::CAPTURED_OBJECT: {
11353           int args_length = iterator.Next();
11354           os << "{length=" << args_length << "}";
11355           break;
11356         }
11357       }
11358       os << "\n";
11359     }
11360   }
11361 }
11362
11363
11364 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
11365     std::ostream& os) {  // NOLINT
11366   os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
11367      << ")\n";
11368   if (this->DeoptPoints() == 0) return;
11369
11370   os << "ast id        pc  state\n";
11371   for (int i = 0; i < this->DeoptPoints(); i++) {
11372     int pc_and_state = this->PcAndState(i)->value();
11373     os << std::setw(6) << this->AstId(i).ToInt() << "  " << std::setw(8)
11374        << FullCodeGenerator::PcField::decode(pc_and_state) << "  "
11375        << FullCodeGenerator::State2String(
11376               FullCodeGenerator::StateField::decode(pc_and_state)) << "\n";
11377   }
11378 }
11379
11380
11381 void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
11382   os << "   from   to       hdlr\n";
11383   for (int i = 0; i < length(); i += kRangeEntrySize) {
11384     int pc_start = Smi::cast(get(i + kRangeStartIndex))->value();
11385     int pc_end = Smi::cast(get(i + kRangeEndIndex))->value();
11386     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
11387     int handler_offset = HandlerOffsetField::decode(handler_field);
11388     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
11389     int depth = Smi::cast(get(i + kRangeDepthIndex))->value();
11390     os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
11391        << ")  ->  " << std::setw(4) << handler_offset
11392        << " (prediction=" << prediction << ", depth=" << depth << ")\n";
11393   }
11394 }
11395
11396
11397 void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
11398   os << "   off      hdlr (c)\n";
11399   for (int i = 0; i < length(); i += kReturnEntrySize) {
11400     int pc_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
11401     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
11402     int handler_offset = HandlerOffsetField::decode(handler_field);
11403     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
11404     os << "  " << std::setw(4) << pc_offset << "  ->  " << std::setw(4)
11405        << handler_offset << " (prediction=" << prediction << ")\n";
11406   }
11407 }
11408
11409
11410 const char* Code::ICState2String(InlineCacheState state) {
11411   switch (state) {
11412     case UNINITIALIZED: return "UNINITIALIZED";
11413     case PREMONOMORPHIC: return "PREMONOMORPHIC";
11414     case MONOMORPHIC: return "MONOMORPHIC";
11415     case PROTOTYPE_FAILURE:
11416       return "PROTOTYPE_FAILURE";
11417     case POLYMORPHIC: return "POLYMORPHIC";
11418     case MEGAMORPHIC: return "MEGAMORPHIC";
11419     case GENERIC: return "GENERIC";
11420     case DEBUG_STUB: return "DEBUG_STUB";
11421     case DEFAULT:
11422       return "DEFAULT";
11423   }
11424   UNREACHABLE();
11425   return NULL;
11426 }
11427
11428
11429 const char* Code::StubType2String(StubType type) {
11430   switch (type) {
11431     case NORMAL: return "NORMAL";
11432     case FAST: return "FAST";
11433   }
11434   UNREACHABLE();  // keep the compiler happy
11435   return NULL;
11436 }
11437
11438
11439 void Code::PrintExtraICState(std::ostream& os,  // NOLINT
11440                              Kind kind, ExtraICState extra) {
11441   os << "extra_ic_state = ";
11442   if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
11443       is_strict(static_cast<LanguageMode>(extra))) {
11444     os << "STRICT\n";
11445   } else {
11446     os << extra << "\n";
11447   }
11448 }
11449
11450
11451 void Code::Disassemble(const char* name, std::ostream& os) {  // NOLINT
11452   os << "kind = " << Kind2String(kind()) << "\n";
11453   if (IsCodeStubOrIC()) {
11454     const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true);
11455     os << "major_key = " << (n == NULL ? "null" : n) << "\n";
11456   }
11457   if (is_inline_cache_stub()) {
11458     os << "ic_state = " << ICState2String(ic_state()) << "\n";
11459     PrintExtraICState(os, kind(), extra_ic_state());
11460     if (ic_state() == MONOMORPHIC) {
11461       os << "type = " << StubType2String(type()) << "\n";
11462     }
11463     if (is_compare_ic_stub()) {
11464       DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
11465       CompareICStub stub(stub_key(), GetIsolate());
11466       os << "compare_state = " << CompareICState::GetStateName(stub.left())
11467          << "*" << CompareICState::GetStateName(stub.right()) << " -> "
11468          << CompareICState::GetStateName(stub.state()) << "\n";
11469       os << "compare_operation = " << Token::Name(stub.op()) << "\n";
11470     }
11471   }
11472   if ((name != NULL) && (name[0] != '\0')) {
11473     os << "name = " << name << "\n";
11474   }
11475   if (kind() == OPTIMIZED_FUNCTION) {
11476     os << "stack_slots = " << stack_slots() << "\n";
11477   }
11478   os << "compiler = " << (is_turbofanned()
11479                               ? "turbofan"
11480                               : is_crankshafted() ? "crankshaft"
11481                                                   : kind() == Code::FUNCTION
11482                                                         ? "full-codegen"
11483                                                         : "unknown") << "\n";
11484
11485   os << "Instructions (size = " << instruction_size() << ")\n";
11486   {
11487     Isolate* isolate = GetIsolate();
11488     int size = instruction_size();
11489     int safepoint_offset =
11490         is_crankshafted() ? static_cast<int>(safepoint_table_offset()) : size;
11491     int back_edge_offset = (kind() == Code::FUNCTION)
11492                                ? static_cast<int>(back_edge_table_offset())
11493                                : size;
11494     int constant_pool_offset = FLAG_enable_embedded_constant_pool
11495                                    ? this->constant_pool_offset()
11496                                    : size;
11497
11498     // Stop before reaching any embedded tables
11499     int code_size = Min(safepoint_offset, back_edge_offset);
11500     code_size = Min(code_size, constant_pool_offset);
11501     byte* begin = instruction_start();
11502     byte* end = begin + code_size;
11503     Disassembler::Decode(isolate, &os, begin, end, this);
11504
11505     if (constant_pool_offset < size) {
11506       int constant_pool_size = size - constant_pool_offset;
11507       DCHECK((constant_pool_size & kPointerAlignmentMask) == 0);
11508       os << "\nConstant Pool (size = " << constant_pool_size << ")\n";
11509       Vector<char> buf = Vector<char>::New(50);
11510       intptr_t* ptr = reinterpret_cast<intptr_t*>(begin + constant_pool_offset);
11511       for (int i = 0; i < constant_pool_size; i += kPointerSize, ptr++) {
11512         SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
11513         os << static_cast<const void*>(ptr) << "  " << buf.start() << "\n";
11514       }
11515     }
11516   }
11517   os << "\n";
11518
11519   if (kind() == FUNCTION) {
11520     DeoptimizationOutputData* data =
11521         DeoptimizationOutputData::cast(this->deoptimization_data());
11522     data->DeoptimizationOutputDataPrint(os);
11523   } else if (kind() == OPTIMIZED_FUNCTION) {
11524     DeoptimizationInputData* data =
11525         DeoptimizationInputData::cast(this->deoptimization_data());
11526     data->DeoptimizationInputDataPrint(os);
11527   }
11528   os << "\n";
11529
11530   if (is_crankshafted()) {
11531     SafepointTable table(this);
11532     os << "Safepoints (size = " << table.size() << ")\n";
11533     for (unsigned i = 0; i < table.length(); i++) {
11534       unsigned pc_offset = table.GetPcOffset(i);
11535       os << static_cast<const void*>(instruction_start() + pc_offset) << "  ";
11536       os << std::setw(4) << pc_offset << "  ";
11537       table.PrintEntry(i, os);
11538       os << " (sp -> fp)  ";
11539       SafepointEntry entry = table.GetEntry(i);
11540       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
11541         os << std::setw(6) << entry.deoptimization_index();
11542       } else {
11543         os << "<none>";
11544       }
11545       if (entry.argument_count() > 0) {
11546         os << " argc: " << entry.argument_count();
11547       }
11548       os << "\n";
11549     }
11550     os << "\n";
11551   } else if (kind() == FUNCTION) {
11552     unsigned offset = back_edge_table_offset();
11553     // If there is no back edge table, the "table start" will be at or after
11554     // (due to alignment) the end of the instruction stream.
11555     if (static_cast<int>(offset) < instruction_size()) {
11556       DisallowHeapAllocation no_gc;
11557       BackEdgeTable back_edges(this, &no_gc);
11558
11559       os << "Back edges (size = " << back_edges.length() << ")\n";
11560       os << "ast_id  pc_offset  loop_depth\n";
11561
11562       for (uint32_t i = 0; i < back_edges.length(); i++) {
11563         os << std::setw(6) << back_edges.ast_id(i).ToInt() << "  "
11564            << std::setw(9) << back_edges.pc_offset(i) << "  " << std::setw(10)
11565            << back_edges.loop_depth(i) << "\n";
11566       }
11567
11568       os << "\n";
11569     }
11570 #ifdef OBJECT_PRINT
11571     if (!type_feedback_info()->IsUndefined()) {
11572       OFStream os(stdout);
11573       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
11574       os << "\n";
11575     }
11576 #endif
11577   }
11578
11579   if (handler_table()->length() > 0) {
11580     os << "Handler Table (size = " << handler_table()->Size() << ")\n";
11581     if (kind() == FUNCTION) {
11582       HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
11583     } else if (kind() == OPTIMIZED_FUNCTION) {
11584       HandlerTable::cast(handler_table())->HandlerTableReturnPrint(os);
11585     }
11586     os << "\n";
11587   }
11588
11589   os << "RelocInfo (size = " << relocation_size() << ")\n";
11590   for (RelocIterator it(this); !it.done(); it.next()) {
11591     it.rinfo()->Print(GetIsolate(), os);
11592   }
11593   os << "\n";
11594 }
11595 #endif  // ENABLE_DISASSEMBLER
11596
11597
11598 // static
11599 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11600   DCHECK(capacity >= 0);
11601   array->GetIsolate()->factory()->NewJSArrayStorage(
11602       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11603 }
11604
11605
11606 // Returns false if the passed-in index is marked non-configurable, which will
11607 // cause the truncation operation to halt, and thus no further old values need
11608 // be collected.
11609 static bool GetOldValue(Isolate* isolate,
11610                         Handle<JSObject> object,
11611                         uint32_t index,
11612                         List<Handle<Object> >* old_values,
11613                         List<uint32_t>* indices) {
11614   LookupIterator it(isolate, object, index, LookupIterator::HIDDEN);
11615   CHECK(JSReceiver::GetPropertyAttributes(&it).IsJust());
11616   DCHECK(it.IsFound());
11617   if (!it.IsConfigurable()) return false;
11618   Handle<Object> value =
11619       it.state() == LookupIterator::ACCESSOR
11620           ? Handle<Object>::cast(isolate->factory()->the_hole_value())
11621           : JSReceiver::GetDataProperty(&it);
11622   old_values->Add(value);
11623   indices->Add(index);
11624   return true;
11625 }
11626
11627
11628 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
11629   // We should never end in here with a pixel or external array.
11630   DCHECK(array->AllowsSetLength());
11631   if (array->SetLengthWouldNormalize(new_length)) {
11632     JSObject::NormalizeElements(array);
11633   }
11634   array->GetElementsAccessor()->SetLength(array, new_length);
11635 }
11636
11637
11638 MaybeHandle<Object> JSArray::ObservableSetLength(Handle<JSArray> array,
11639                                                  uint32_t new_length) {
11640   if (!array->map()->is_observed()) {
11641     SetLength(array, new_length);
11642     return array;
11643   }
11644
11645   Isolate* isolate = array->GetIsolate();
11646   List<uint32_t> indices;
11647   List<Handle<Object> > old_values;
11648   Handle<Object> old_length_handle(array->length(), isolate);
11649   uint32_t old_length = 0;
11650   CHECK(old_length_handle->ToArrayLength(&old_length));
11651
11652   static const PropertyAttributes kNoAttrFilter = NONE;
11653   int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
11654   if (num_elements > 0) {
11655     if (old_length == static_cast<uint32_t>(num_elements)) {
11656       // Simple case for arrays without holes.
11657       for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
11658         if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
11659       }
11660     } else {
11661       // For sparse arrays, only iterate over existing elements.
11662       // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
11663       // the to-be-removed indices twice.
11664       Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
11665       array->GetOwnElementKeys(*keys, kNoAttrFilter);
11666       while (num_elements-- > 0) {
11667         uint32_t index = NumberToUint32(keys->get(num_elements));
11668         if (index < new_length) break;
11669         if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
11670       }
11671     }
11672   }
11673
11674   SetLength(array, new_length);
11675
11676   CHECK(array->length()->ToArrayLength(&new_length));
11677   if (old_length == new_length) return array;
11678
11679   RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
11680
11681   for (int i = 0; i < indices.length(); ++i) {
11682     // For deletions where the property was an accessor, old_values[i]
11683     // will be the hole, which instructs EnqueueChangeRecord to elide
11684     // the "oldValue" property.
11685     RETURN_ON_EXCEPTION(
11686         isolate,
11687         JSObject::EnqueueChangeRecord(
11688             array, "delete", isolate->factory()->Uint32ToString(indices[i]),
11689             old_values[i]),
11690         Object);
11691   }
11692
11693   RETURN_ON_EXCEPTION(isolate,
11694                       JSObject::EnqueueChangeRecord(
11695                           array, "update", isolate->factory()->length_string(),
11696                           old_length_handle),
11697                       Object);
11698
11699   RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
11700
11701   uint32_t index = Min(old_length, new_length);
11702   uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11703   uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11704   Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11705   if (delete_count > 0) {
11706     for (int i = indices.length() - 1; i >= 0; i--) {
11707       // Skip deletions where the property was an accessor, leaving holes
11708       // in the array of old values.
11709       if (old_values[i]->IsTheHole()) continue;
11710       JSObject::AddDataElement(deleted, indices[i] - index, old_values[i], NONE)
11711           .Assert();
11712     }
11713
11714     JSArray::SetLength(deleted, delete_count);
11715   }
11716
11717   RETURN_ON_EXCEPTION(
11718       isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
11719
11720   return array;
11721 }
11722
11723
11724 // static
11725 void Map::AddDependentCode(Handle<Map> map,
11726                            DependentCode::DependencyGroup group,
11727                            Handle<Code> code) {
11728   Handle<WeakCell> cell = Code::WeakCellFor(code);
11729   Handle<DependentCode> codes = DependentCode::InsertWeakCode(
11730       Handle<DependentCode>(map->dependent_code()), group, cell);
11731   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11732 }
11733
11734
11735 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
11736   Recompute(entries);
11737 }
11738
11739
11740 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
11741   start_indexes_[0] = 0;
11742   for (int g = 1; g <= kGroupCount; g++) {
11743     int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
11744     start_indexes_[g] = start_indexes_[g - 1] + count;
11745   }
11746 }
11747
11748
11749 Handle<DependentCode> DependentCode::InsertCompilationDependencies(
11750     Handle<DependentCode> entries, DependencyGroup group,
11751     Handle<Foreign> info) {
11752   return Insert(entries, group, info);
11753 }
11754
11755
11756 Handle<DependentCode> DependentCode::InsertWeakCode(
11757     Handle<DependentCode> entries, DependencyGroup group,
11758     Handle<WeakCell> code_cell) {
11759   return Insert(entries, group, code_cell);
11760 }
11761
11762
11763 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
11764                                             DependencyGroup group,
11765                                             Handle<Object> object) {
11766   GroupStartIndexes starts(*entries);
11767   int start = starts.at(group);
11768   int end = starts.at(group + 1);
11769   int number_of_entries = starts.number_of_entries();
11770   // Check for existing entry to avoid duplicates.
11771   for (int i = start; i < end; i++) {
11772     if (entries->object_at(i) == *object) return entries;
11773   }
11774   if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
11775     entries = EnsureSpace(entries);
11776     // The number of codes can change after Compact and GC.
11777     starts.Recompute(*entries);
11778     start = starts.at(group);
11779     end = starts.at(group + 1);
11780   }
11781
11782   entries->ExtendGroup(group);
11783   entries->set_object_at(end, *object);
11784   entries->set_number_of_entries(group, end + 1 - start);
11785   return entries;
11786 }
11787
11788
11789 Handle<DependentCode> DependentCode::EnsureSpace(
11790     Handle<DependentCode> entries) {
11791   if (entries->length() == 0) {
11792     entries = Handle<DependentCode>::cast(
11793         FixedArray::CopySize(entries, kCodesStartIndex + 1, TENURED));
11794     for (int g = 0; g < kGroupCount; g++) {
11795       entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
11796     }
11797     return entries;
11798   }
11799   if (entries->Compact()) return entries;
11800   GroupStartIndexes starts(*entries);
11801   int capacity =
11802       kCodesStartIndex + DependentCode::Grow(starts.number_of_entries());
11803   return Handle<DependentCode>::cast(
11804       FixedArray::CopySize(entries, capacity, TENURED));
11805 }
11806
11807
11808 bool DependentCode::Compact() {
11809   GroupStartIndexes starts(this);
11810   int n = 0;
11811   for (int g = 0; g < kGroupCount; g++) {
11812     int start = starts.at(g);
11813     int end = starts.at(g + 1);
11814     int count = 0;
11815     DCHECK(start >= n);
11816     for (int i = start; i < end; i++) {
11817       Object* obj = object_at(i);
11818       if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) {
11819         if (i != n + count) {
11820           copy(i, n + count);
11821         }
11822         count++;
11823       }
11824     }
11825     if (count != end - start) {
11826       set_number_of_entries(static_cast<DependencyGroup>(g), count);
11827     }
11828     n += count;
11829   }
11830   return n < starts.number_of_entries();
11831 }
11832
11833
11834 void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
11835                                          WeakCell* code_cell) {
11836   DisallowHeapAllocation no_gc;
11837   GroupStartIndexes starts(this);
11838   int start = starts.at(group);
11839   int end = starts.at(group + 1);
11840   for (int i = start; i < end; i++) {
11841     if (object_at(i) == info) {
11842       set_object_at(i, code_cell);
11843       break;
11844     }
11845   }
11846
11847 #ifdef DEBUG
11848   for (int i = start; i < end; i++) {
11849     DCHECK(object_at(i) != info);
11850   }
11851 #endif
11852 }
11853
11854
11855 void DependentCode::RemoveCompilationDependencies(
11856     DependentCode::DependencyGroup group, Foreign* info) {
11857   DisallowHeapAllocation no_allocation;
11858   GroupStartIndexes starts(this);
11859   int start = starts.at(group);
11860   int end = starts.at(group + 1);
11861   // Find compilation info wrapper.
11862   int info_pos = -1;
11863   for (int i = start; i < end; i++) {
11864     if (object_at(i) == info) {
11865       info_pos = i;
11866       break;
11867     }
11868   }
11869   if (info_pos == -1) return;  // Not found.
11870   int gap = info_pos;
11871   // Use the last of each group to fill the gap in the previous group.
11872   for (int i = group; i < kGroupCount; i++) {
11873     int last_of_group = starts.at(i + 1) - 1;
11874     DCHECK(last_of_group >= gap);
11875     if (last_of_group == gap) continue;
11876     copy(last_of_group, gap);
11877     gap = last_of_group;
11878   }
11879   DCHECK(gap == starts.number_of_entries() - 1);
11880   clear_at(gap);  // Clear last gap.
11881   set_number_of_entries(group, end - start - 1);
11882
11883 #ifdef DEBUG
11884   for (int i = start; i < end - 1; i++) {
11885     DCHECK(object_at(i) != info);
11886   }
11887 #endif
11888 }
11889
11890
11891 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) {
11892   GroupStartIndexes starts(this);
11893   int start = starts.at(group);
11894   int end = starts.at(group + 1);
11895   for (int i = start; i < end; i++) {
11896     if (object_at(i) == code_cell) return true;
11897   }
11898   return false;
11899 }
11900
11901
11902 bool DependentCode::MarkCodeForDeoptimization(
11903     Isolate* isolate,
11904     DependentCode::DependencyGroup group) {
11905   DisallowHeapAllocation no_allocation_scope;
11906   DependentCode::GroupStartIndexes starts(this);
11907   int start = starts.at(group);
11908   int end = starts.at(group + 1);
11909   int code_entries = starts.number_of_entries();
11910   if (start == end) return false;
11911
11912   // Mark all the code that needs to be deoptimized.
11913   bool marked = false;
11914   bool invalidate_embedded_objects = group == kWeakCodeGroup;
11915   for (int i = start; i < end; i++) {
11916     Object* obj = object_at(i);
11917     if (obj->IsWeakCell()) {
11918       WeakCell* cell = WeakCell::cast(obj);
11919       if (cell->cleared()) continue;
11920       Code* code = Code::cast(cell->value());
11921       if (!code->marked_for_deoptimization()) {
11922         SetMarkedForDeoptimization(code, group);
11923         if (invalidate_embedded_objects) {
11924           code->InvalidateEmbeddedObjects();
11925         }
11926         marked = true;
11927       }
11928     } else {
11929       DCHECK(obj->IsForeign());
11930       CompilationDependencies* info =
11931           reinterpret_cast<CompilationDependencies*>(
11932               Foreign::cast(obj)->foreign_address());
11933       info->Abort();
11934     }
11935   }
11936   // Compact the array by moving all subsequent groups to fill in the new holes.
11937   for (int src = end, dst = start; src < code_entries; src++, dst++) {
11938     copy(src, dst);
11939   }
11940   // Now the holes are at the end of the array, zap them for heap-verifier.
11941   int removed = end - start;
11942   for (int i = code_entries - removed; i < code_entries; i++) {
11943     clear_at(i);
11944   }
11945   set_number_of_entries(group, 0);
11946   return marked;
11947 }
11948
11949
11950 void DependentCode::DeoptimizeDependentCodeGroup(
11951     Isolate* isolate,
11952     DependentCode::DependencyGroup group) {
11953   DCHECK(AllowCodeDependencyChange::IsAllowed());
11954   DisallowHeapAllocation no_allocation_scope;
11955   bool marked = MarkCodeForDeoptimization(isolate, group);
11956   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
11957 }
11958
11959
11960 void DependentCode::SetMarkedForDeoptimization(Code* code,
11961                                                DependencyGroup group) {
11962   code->set_marked_for_deoptimization(true);
11963   if (FLAG_trace_deopt &&
11964       (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
11965     DeoptimizationInputData* deopt_data =
11966         DeoptimizationInputData::cast(code->deoptimization_data());
11967     CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
11968     PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
11969                          " (opt #%d) for deoptimization, reason: %s]\n",
11970            reinterpret_cast<intptr_t>(code),
11971            deopt_data->OptimizationId()->value(), DependencyGroupName(group));
11972   }
11973 }
11974
11975
11976 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
11977   switch (group) {
11978     case kWeakCodeGroup:
11979       return "weak-code";
11980     case kTransitionGroup:
11981       return "transition";
11982     case kPrototypeCheckGroup:
11983       return "prototype-check";
11984     case kPropertyCellChangedGroup:
11985       return "property-cell-changed";
11986     case kFieldTypeGroup:
11987       return "field-type";
11988     case kInitialMapChangedGroup:
11989       return "initial-map-changed";
11990     case kAllocationSiteTenuringChangedGroup:
11991       return "allocation-site-tenuring-changed";
11992     case kAllocationSiteTransitionChangedGroup:
11993       return "allocation-site-transition-changed";
11994   }
11995   UNREACHABLE();
11996   return "?";
11997 }
11998
11999
12000 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
12001                                        Handle<Object> prototype,
12002                                        PrototypeOptimizationMode mode) {
12003   Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
12004   if (new_map.is_null()) {
12005     new_map = Copy(map, "TransitionToPrototype");
12006     TransitionArray::PutPrototypeTransition(map, prototype, new_map);
12007     Map::SetPrototype(new_map, prototype, mode);
12008   }
12009   return new_map;
12010 }
12011
12012
12013 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12014                                            Handle<Object> value,
12015                                            bool from_javascript) {
12016 #ifdef DEBUG
12017   int size = object->Size();
12018 #endif
12019
12020   Isolate* isolate = object->GetIsolate();
12021   // Strong objects may not have their prototype set via __proto__ or
12022   // setPrototypeOf.
12023   if (from_javascript && object->map()->is_strong()) {
12024     THROW_NEW_ERROR(isolate,
12025                     NewTypeError(MessageTemplate::kStrongSetProto, object),
12026                     Object);
12027   }
12028   Heap* heap = isolate->heap();
12029   // Silently ignore the change if value is not a JSObject or null.
12030   // SpiderMonkey behaves this way.
12031   if (!value->IsJSReceiver() && !value->IsNull()) return value;
12032
12033   // From 8.6.2 Object Internal Methods
12034   // ...
12035   // In addition, if [[Extensible]] is false the value of the [[Class]] and
12036   // [[Prototype]] internal properties of the object may not be modified.
12037   // ...
12038   // Implementation specific extensions that modify [[Class]], [[Prototype]]
12039   // or [[Extensible]] must not violate the invariants defined in the preceding
12040   // paragraph.
12041   if (!object->map()->is_extensible()) {
12042     THROW_NEW_ERROR(isolate,
12043                     NewTypeError(MessageTemplate::kNonExtensibleProto, object),
12044                     Object);
12045   }
12046
12047   // Before we can set the prototype we need to be sure
12048   // prototype cycles are prevented.
12049   // It is sufficient to validate that the receiver is not in the new prototype
12050   // chain.
12051   for (PrototypeIterator iter(isolate, *value,
12052                               PrototypeIterator::START_AT_RECEIVER);
12053        !iter.IsAtEnd(); iter.Advance()) {
12054     if (JSReceiver::cast(iter.GetCurrent()) == *object) {
12055       // Cycle detected.
12056       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCyclicProto),
12057                       Object);
12058     }
12059   }
12060
12061   bool dictionary_elements_in_chain =
12062       object->map()->DictionaryElementsInPrototypeChainOnly();
12063   Handle<JSObject> real_receiver = object;
12064
12065   if (from_javascript) {
12066     // Find the first object in the chain whose prototype object is not
12067     // hidden and set the new prototype on that object.
12068     PrototypeIterator iter(isolate, real_receiver);
12069     while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
12070       real_receiver =
12071           Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
12072       iter.Advance();
12073       if (!real_receiver->map()->is_extensible()) {
12074         THROW_NEW_ERROR(
12075             isolate, NewTypeError(MessageTemplate::kNonExtensibleProto, object),
12076             Object);
12077       }
12078     }
12079   }
12080
12081   // Set the new prototype of the object.
12082   Handle<Map> map(real_receiver->map());
12083
12084   // Nothing to do if prototype is already set.
12085   if (map->prototype() == *value) return value;
12086
12087   isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
12088
12089   PrototypeOptimizationMode mode =
12090       from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
12091   Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
12092   DCHECK(new_map->prototype() == *value);
12093   JSObject::MigrateToMap(real_receiver, new_map);
12094
12095   if (from_javascript && !dictionary_elements_in_chain &&
12096       new_map->DictionaryElementsInPrototypeChainOnly()) {
12097     // If the prototype chain didn't previously have element callbacks, then
12098     // KeyedStoreICs need to be cleared to ensure any that involve this
12099     // map go generic.
12100     object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
12101   }
12102
12103   heap->ClearInstanceofCache();
12104   DCHECK(size == object->Size());
12105   return value;
12106 }
12107
12108
12109 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
12110                                         Arguments* args,
12111                                         uint32_t first_arg,
12112                                         uint32_t arg_count,
12113                                         EnsureElementsMode mode) {
12114   // Elements in |Arguments| are ordered backwards (because they're on the
12115   // stack), but the method that's called here iterates over them in forward
12116   // direction.
12117   return EnsureCanContainElements(
12118       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
12119 }
12120
12121
12122 ElementsAccessor* JSObject::GetElementsAccessor() {
12123   return ElementsAccessor::ForKind(GetElementsKind());
12124 }
12125
12126
12127 void JSObject::ValidateElements(Handle<JSObject> object) {
12128 #ifdef ENABLE_SLOW_DCHECKS
12129   if (FLAG_enable_slow_asserts) {
12130     ElementsAccessor* accessor = object->GetElementsAccessor();
12131     accessor->Validate(object);
12132   }
12133 #endif
12134 }
12135
12136
12137 static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
12138                                         uint32_t index,
12139                                         uint32_t* new_capacity) {
12140   STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
12141                 JSObject::kMaxUncheckedFastElementsLength);
12142   if (index < capacity) {
12143     *new_capacity = capacity;
12144     return false;
12145   }
12146   if (index - capacity >= JSObject::kMaxGap) return true;
12147   *new_capacity = JSObject::NewElementsCapacity(index + 1);
12148   DCHECK_LT(index, *new_capacity);
12149   if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
12150       (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
12151        object->GetHeap()->InNewSpace(object))) {
12152     return false;
12153   }
12154   // If the fast-case backing storage takes up roughly three times as
12155   // much space (in machine words) as a dictionary backing storage
12156   // would, the object should have slow elements.
12157   int used_elements = object->GetFastElementsUsage();
12158   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
12159                         SeededNumberDictionary::kEntrySize;
12160   return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
12161 }
12162
12163
12164 bool JSObject::WouldConvertToSlowElements(uint32_t index) {
12165   if (HasFastElements()) {
12166     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
12167     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12168     uint32_t new_capacity;
12169     return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
12170   }
12171   return false;
12172 }
12173
12174
12175 static ElementsKind BestFittingFastElementsKind(JSObject* object) {
12176   if (object->HasSloppyArgumentsElements()) {
12177     return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
12178   }
12179   DCHECK(object->HasDictionaryElements());
12180   SeededNumberDictionary* dictionary = object->element_dictionary();
12181   ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
12182   for (int i = 0; i < dictionary->Capacity(); i++) {
12183     Object* key = dictionary->KeyAt(i);
12184     if (key->IsNumber()) {
12185       Object* value = dictionary->ValueAt(i);
12186       if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
12187       if (!value->IsSmi()) {
12188         if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
12189         kind = FAST_HOLEY_DOUBLE_ELEMENTS;
12190       }
12191     }
12192   }
12193   return kind;
12194 }
12195
12196
12197 static bool ShouldConvertToFastElements(JSObject* object,
12198                                         SeededNumberDictionary* dictionary,
12199                                         uint32_t index,
12200                                         uint32_t* new_capacity) {
12201   // If properties with non-standard attributes or accessors were added, we
12202   // cannot go back to fast elements.
12203   if (dictionary->requires_slow_elements()) return false;
12204
12205   // Adding a property with this index will require slow elements.
12206   if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
12207
12208   if (object->IsJSArray()) {
12209     Object* length = JSArray::cast(object)->length();
12210     if (!length->IsSmi()) return false;
12211     *new_capacity = static_cast<uint32_t>(Smi::cast(length)->value());
12212   } else {
12213     *new_capacity = dictionary->max_number_key() + 1;
12214   }
12215   *new_capacity = Max(index + 1, *new_capacity);
12216
12217   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
12218                              SeededNumberDictionary::kEntrySize;
12219   return 2 * dictionary_size >= *new_capacity;
12220 }
12221
12222
12223 // static
12224 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
12225                                              uint32_t index,
12226                                              Handle<Object> value,
12227                                              PropertyAttributes attributes) {
12228   DCHECK(object->map()->is_extensible());
12229
12230   Isolate* isolate = object->GetIsolate();
12231
12232   uint32_t old_length = 0;
12233   uint32_t new_capacity = 0;
12234
12235   Handle<Object> old_length_handle;
12236   if (object->IsJSArray()) {
12237     CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
12238     if (object->map()->is_observed()) {
12239       old_length_handle = handle(JSArray::cast(*object)->length(), isolate);
12240     }
12241   }
12242
12243   ElementsKind kind = object->GetElementsKind();
12244   FixedArrayBase* elements = object->elements();
12245   ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
12246   if (IsSloppyArgumentsElements(kind)) {
12247     elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
12248     dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
12249   }
12250
12251   if (attributes != NONE) {
12252     kind = dictionary_kind;
12253   } else if (elements->IsSeededNumberDictionary()) {
12254     kind = ShouldConvertToFastElements(*object,
12255                                        SeededNumberDictionary::cast(elements),
12256                                        index, &new_capacity)
12257                ? BestFittingFastElementsKind(*object)
12258                : dictionary_kind;  // Overwrite in case of arguments.
12259   } else if (ShouldConvertToSlowElements(
12260                  *object, static_cast<uint32_t>(elements->length()), index,
12261                  &new_capacity)) {
12262     kind = dictionary_kind;
12263   }
12264
12265   ElementsKind to = value->OptimalElementsKind();
12266   if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
12267     to = GetHoleyElementsKind(to);
12268     kind = GetHoleyElementsKind(kind);
12269   }
12270   to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind;
12271   ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
12272   accessor->Add(object, index, value, attributes, new_capacity);
12273
12274   uint32_t new_length = old_length;
12275   Handle<Object> new_length_handle;
12276   if (object->IsJSArray() && index >= old_length) {
12277     new_length = index + 1;
12278     new_length_handle = isolate->factory()->NewNumberFromUint(new_length);
12279     JSArray::cast(*object)->set_length(*new_length_handle);
12280   }
12281
12282   if (!old_length_handle.is_null() && new_length != old_length) {
12283     // |old_length_handle| is kept null above unless the object is observed.
12284     DCHECK(object->map()->is_observed());
12285     Handle<JSArray> array = Handle<JSArray>::cast(object);
12286     Handle<String> name = isolate->factory()->Uint32ToString(index);
12287
12288     RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
12289     RETURN_ON_EXCEPTION(
12290         isolate, EnqueueChangeRecord(array, "add", name,
12291                                      isolate->factory()->the_hole_value()),
12292         Object);
12293     RETURN_ON_EXCEPTION(isolate,
12294                         EnqueueChangeRecord(array, "update",
12295                                             isolate->factory()->length_string(),
12296                                             old_length_handle),
12297                         Object);
12298     RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
12299     Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12300     RETURN_ON_EXCEPTION(isolate, EnqueueSpliceRecord(array, old_length, deleted,
12301                                                      new_length - old_length),
12302                         Object);
12303   } else if (object->map()->is_observed()) {
12304     Handle<String> name = isolate->factory()->Uint32ToString(index);
12305     RETURN_ON_EXCEPTION(
12306         isolate, EnqueueChangeRecord(object, "add", name,
12307                                      isolate->factory()->the_hole_value()),
12308         Object);
12309   }
12310
12311   return value;
12312 }
12313
12314
12315 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
12316   if (!HasFastElements()) return false;
12317   uint32_t capacity = static_cast<uint32_t>(elements()->length());
12318   uint32_t new_capacity;
12319   return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
12320          ShouldConvertToSlowElements(this, capacity, new_length - 1,
12321                                      &new_capacity);
12322 }
12323
12324
12325 const double AllocationSite::kPretenureRatio = 0.85;
12326
12327
12328 void AllocationSite::ResetPretenureDecision() {
12329   set_pretenure_decision(kUndecided);
12330   set_memento_found_count(0);
12331   set_memento_create_count(0);
12332 }
12333
12334
12335 PretenureFlag AllocationSite::GetPretenureMode() {
12336   PretenureDecision mode = pretenure_decision();
12337   // Zombie objects "decide" to be untenured.
12338   return mode == kTenure ? TENURED : NOT_TENURED;
12339 }
12340
12341
12342 bool AllocationSite::IsNestedSite() {
12343   DCHECK(FLAG_trace_track_allocation_sites);
12344   Object* current = GetHeap()->allocation_sites_list();
12345   while (current->IsAllocationSite()) {
12346     AllocationSite* current_site = AllocationSite::cast(current);
12347     if (current_site->nested_site() == this) {
12348       return true;
12349     }
12350     current = current_site->weak_next();
12351   }
12352   return false;
12353 }
12354
12355
12356 void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
12357                                               ElementsKind to_kind) {
12358   Isolate* isolate = site->GetIsolate();
12359
12360   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
12361     Handle<JSArray> transition_info =
12362         handle(JSArray::cast(site->transition_info()));
12363     ElementsKind kind = transition_info->GetElementsKind();
12364     // if kind is holey ensure that to_kind is as well.
12365     if (IsHoleyElementsKind(kind)) {
12366       to_kind = GetHoleyElementsKind(to_kind);
12367     }
12368     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12369       // If the array is huge, it's not likely to be defined in a local
12370       // function, so we shouldn't make new instances of it very often.
12371       uint32_t length = 0;
12372       CHECK(transition_info->length()->ToArrayLength(&length));
12373       if (length <= kMaximumArrayBytesToPretransition) {
12374         if (FLAG_trace_track_allocation_sites) {
12375           bool is_nested = site->IsNestedSite();
12376           PrintF(
12377               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
12378               reinterpret_cast<void*>(*site),
12379               is_nested ? "(nested)" : "",
12380               ElementsKindToString(kind),
12381               ElementsKindToString(to_kind));
12382         }
12383         JSObject::TransitionElementsKind(transition_info, to_kind);
12384         site->dependent_code()->DeoptimizeDependentCodeGroup(
12385             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12386       }
12387     }
12388   } else {
12389     ElementsKind kind = site->GetElementsKind();
12390     // if kind is holey ensure that to_kind is as well.
12391     if (IsHoleyElementsKind(kind)) {
12392       to_kind = GetHoleyElementsKind(to_kind);
12393     }
12394     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12395       if (FLAG_trace_track_allocation_sites) {
12396         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
12397                reinterpret_cast<void*>(*site),
12398                ElementsKindToString(kind),
12399                ElementsKindToString(to_kind));
12400       }
12401       site->SetElementsKind(to_kind);
12402       site->dependent_code()->DeoptimizeDependentCodeGroup(
12403           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12404     }
12405   }
12406 }
12407
12408
12409 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
12410   switch (decision) {
12411     case kUndecided: return "undecided";
12412     case kDontTenure: return "don't tenure";
12413     case kMaybeTenure: return "maybe tenure";
12414     case kTenure: return "tenure";
12415     case kZombie: return "zombie";
12416     default: UNREACHABLE();
12417   }
12418   return NULL;
12419 }
12420
12421
12422 void JSObject::UpdateAllocationSite(Handle<JSObject> object,
12423                                     ElementsKind to_kind) {
12424   if (!object->IsJSArray()) return;
12425
12426   Heap* heap = object->GetHeap();
12427   if (!heap->InNewSpace(*object)) return;
12428
12429   Handle<AllocationSite> site;
12430   {
12431     DisallowHeapAllocation no_allocation;
12432
12433     AllocationMemento* memento = heap->FindAllocationMemento(*object);
12434     if (memento == NULL) return;
12435
12436     // Walk through to the Allocation Site
12437     site = handle(memento->GetAllocationSite());
12438   }
12439   AllocationSite::DigestTransitionFeedback(site, to_kind);
12440 }
12441
12442
12443 void JSObject::TransitionElementsKind(Handle<JSObject> object,
12444                                       ElementsKind to_kind) {
12445   ElementsKind from_kind = object->GetElementsKind();
12446
12447   if (IsFastHoleyElementsKind(from_kind)) {
12448     to_kind = GetHoleyElementsKind(to_kind);
12449   }
12450
12451   if (from_kind == to_kind) return;
12452
12453   // This method should never be called for any other case.
12454   DCHECK(IsFastElementsKind(from_kind));
12455   DCHECK(IsFastElementsKind(to_kind));
12456   DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
12457
12458   UpdateAllocationSite(object, to_kind);
12459   if (object->elements() == object->GetHeap()->empty_fixed_array() ||
12460       IsFastDoubleElementsKind(from_kind) ==
12461           IsFastDoubleElementsKind(to_kind)) {
12462     // No change is needed to the elements() buffer, the transition
12463     // only requires a map change.
12464     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
12465     MigrateToMap(object, new_map);
12466     if (FLAG_trace_elements_transitions) {
12467       Handle<FixedArrayBase> elms(object->elements());
12468       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
12469     }
12470   } else {
12471     DCHECK((IsFastSmiElementsKind(from_kind) &&
12472             IsFastDoubleElementsKind(to_kind)) ||
12473            (IsFastDoubleElementsKind(from_kind) &&
12474             IsFastObjectElementsKind(to_kind)));
12475     uint32_t c = static_cast<uint32_t>(object->elements()->length());
12476     ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
12477   }
12478 }
12479
12480
12481 // static
12482 bool Map::IsValidElementsTransition(ElementsKind from_kind,
12483                                     ElementsKind to_kind) {
12484   // Transitions can't go backwards.
12485   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
12486     return false;
12487   }
12488
12489   // Transitions from HOLEY -> PACKED are not allowed.
12490   return !IsFastHoleyElementsKind(from_kind) ||
12491       IsFastHoleyElementsKind(to_kind);
12492 }
12493
12494
12495 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
12496   LookupIterator it(array, array->GetIsolate()->factory()->length_string(),
12497                     LookupIterator::OWN_SKIP_INTERCEPTOR);
12498   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
12499   CHECK(it.IsFound());
12500   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
12501   return it.IsReadOnly();
12502 }
12503
12504
12505 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
12506                                         uint32_t index) {
12507   uint32_t length = 0;
12508   CHECK(array->length()->ToArrayLength(&length));
12509   if (length <= index) return HasReadOnlyLength(array);
12510   return false;
12511 }
12512
12513
12514 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
12515   Isolate* isolate = array->GetIsolate();
12516   Handle<Name> length = isolate->factory()->length_string();
12517   THROW_NEW_ERROR(
12518       isolate,
12519       NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, array),
12520       Object);
12521 }
12522
12523
12524 template <typename BackingStore>
12525 static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) {
12526   int limit = object->IsJSArray()
12527                   ? Smi::cast(JSArray::cast(object)->length())->value()
12528                   : store->length();
12529   int used = 0;
12530   for (int i = 0; i < limit; ++i) {
12531     if (!store->is_the_hole(i)) ++used;
12532   }
12533   return used;
12534 }
12535
12536
12537 int JSObject::GetFastElementsUsage() {
12538   FixedArrayBase* store = elements();
12539   switch (GetElementsKind()) {
12540     case FAST_SMI_ELEMENTS:
12541     case FAST_DOUBLE_ELEMENTS:
12542     case FAST_ELEMENTS:
12543       // Only JSArray have packed elements.
12544       return Smi::cast(JSArray::cast(this)->length())->value();
12545     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
12546       store = FixedArray::cast(FixedArray::cast(store)->get(1));
12547     // Fall through.
12548     case FAST_HOLEY_SMI_ELEMENTS:
12549     case FAST_HOLEY_ELEMENTS:
12550       return FastHoleyElementsUsage(this, FixedArray::cast(store));
12551     case FAST_HOLEY_DOUBLE_ELEMENTS:
12552       if (elements()->length() == 0) return 0;
12553       return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
12554
12555     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
12556     case DICTIONARY_ELEMENTS:
12557 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
12558     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
12559     case TYPE##_ELEMENTS:                                                    \
12560
12561     TYPED_ARRAYS(TYPED_ARRAY_CASE)
12562 #undef TYPED_ARRAY_CASE
12563     UNREACHABLE();
12564   }
12565   return 0;
12566 }
12567
12568
12569 // Certain compilers request function template instantiation when they
12570 // see the definition of the other template functions in the
12571 // class. This requires us to have the template functions put
12572 // together, so even though this function belongs in objects-debug.cc,
12573 // we keep it here instead to satisfy certain compilers.
12574 #ifdef OBJECT_PRINT
12575 template <typename Derived, typename Shape, typename Key>
12576 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
12577   int capacity = this->Capacity();
12578   for (int i = 0; i < capacity; i++) {
12579     Object* k = this->KeyAt(i);
12580     if (this->IsKey(k)) {
12581       os << " ";
12582       if (k->IsString()) {
12583         String::cast(k)->StringPrint(os);
12584       } else {
12585         os << Brief(k);
12586       }
12587       os << ": " << Brief(this->ValueAt(i)) << " " << this->DetailsAt(i)
12588          << "\n";
12589     }
12590   }
12591 }
12592 #endif
12593
12594
12595 template<typename Derived, typename Shape, typename Key>
12596 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
12597   int pos = 0;
12598   int capacity = this->Capacity();
12599   DisallowHeapAllocation no_gc;
12600   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
12601   for (int i = 0; i < capacity; i++) {
12602     Object* k = this->KeyAt(i);
12603     if (this->IsKey(k)) {
12604       elements->set(pos++, this->ValueAt(i), mode);
12605     }
12606   }
12607   DCHECK(pos == elements->length());
12608 }
12609
12610
12611 InterceptorInfo* JSObject::GetNamedInterceptor() {
12612   DCHECK(map()->has_named_interceptor());
12613   JSFunction* constructor = JSFunction::cast(map()->GetConstructor());
12614   DCHECK(constructor->shared()->IsApiFunction());
12615   Object* result =
12616       constructor->shared()->get_api_func_data()->named_property_handler();
12617   return InterceptorInfo::cast(result);
12618 }
12619
12620
12621 InterceptorInfo* JSObject::GetIndexedInterceptor() {
12622   DCHECK(map()->has_indexed_interceptor());
12623   JSFunction* constructor = JSFunction::cast(map()->GetConstructor());
12624   DCHECK(constructor->shared()->IsApiFunction());
12625   Object* result =
12626       constructor->shared()->get_api_func_data()->indexed_property_handler();
12627   return InterceptorInfo::cast(result);
12628 }
12629
12630
12631 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
12632                                                          bool* done) {
12633   *done = false;
12634   Isolate* isolate = it->isolate();
12635   // Make sure that the top context does not change when doing callbacks or
12636   // interceptor calls.
12637   AssertNoContextChange ncc(isolate);
12638
12639   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
12640   Handle<InterceptorInfo> interceptor = it->GetInterceptor();
12641   if (interceptor->getter()->IsUndefined()) {
12642     return isolate->factory()->undefined_value();
12643   }
12644
12645   Handle<JSObject> holder = it->GetHolder<JSObject>();
12646   v8::Local<v8::Value> result;
12647   PropertyCallbackArguments args(isolate, interceptor->data(),
12648                                  *it->GetReceiver(), *holder);
12649
12650   if (it->IsElement()) {
12651     uint32_t index = it->index();
12652     v8::IndexedPropertyGetterCallback getter =
12653         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
12654     LOG(isolate,
12655         ApiIndexedPropertyAccess("interceptor-indexed-get", *holder, index));
12656     result = args.Call(getter, index);
12657   } else {
12658     Handle<Name> name = it->name();
12659
12660     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
12661       return isolate->factory()->undefined_value();
12662     }
12663
12664     v8::GenericNamedPropertyGetterCallback getter =
12665         v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
12666             interceptor->getter());
12667     LOG(isolate,
12668         ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
12669     result = args.Call(getter, v8::Utils::ToLocal(name));
12670   }
12671
12672   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12673   if (result.IsEmpty()) return isolate->factory()->undefined_value();
12674   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12675   result_internal->VerifyApiCallResultType();
12676   *done = true;
12677   // Rebox handle before return
12678   return handle(*result_internal, isolate);
12679 }
12680
12681
12682 // Compute the property keys from the interceptor.
12683 MaybeHandle<JSObject> JSObject::GetKeysForNamedInterceptor(
12684     Handle<JSObject> object, Handle<JSReceiver> receiver) {
12685   Isolate* isolate = receiver->GetIsolate();
12686   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
12687   PropertyCallbackArguments
12688       args(isolate, interceptor->data(), *receiver, *object);
12689   v8::Local<v8::Object> result;
12690   if (!interceptor->enumerator()->IsUndefined()) {
12691     v8::GenericNamedPropertyEnumeratorCallback enum_fun =
12692         v8::ToCData<v8::GenericNamedPropertyEnumeratorCallback>(
12693             interceptor->enumerator());
12694     LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
12695     result = args.Call(enum_fun);
12696   }
12697   if (result.IsEmpty()) return MaybeHandle<JSObject>();
12698   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
12699          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
12700   // Rebox before returning.
12701   return handle(*v8::Utils::OpenHandle(*result), isolate);
12702 }
12703
12704
12705 // Compute the element keys from the interceptor.
12706 MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor(
12707     Handle<JSObject> object, Handle<JSReceiver> receiver) {
12708   Isolate* isolate = receiver->GetIsolate();
12709   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
12710   PropertyCallbackArguments
12711       args(isolate, interceptor->data(), *receiver, *object);
12712   v8::Local<v8::Object> result;
12713   if (!interceptor->enumerator()->IsUndefined()) {
12714     v8::IndexedPropertyEnumeratorCallback enum_fun =
12715         v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
12716             interceptor->enumerator());
12717     LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
12718     result = args.Call(enum_fun);
12719   }
12720   if (result.IsEmpty()) return MaybeHandle<JSObject>();
12721   DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
12722          v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
12723   // Rebox before returning.
12724   return handle(*v8::Utils::OpenHandle(*result), isolate);
12725 }
12726
12727
12728 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
12729                                            Handle<Name> name) {
12730   LookupIterator it = LookupIterator::PropertyOrElement(
12731       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
12732   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
12733   if (!maybe_result.IsJust()) return Nothing<bool>();
12734   return Just(it.IsFound());
12735 }
12736
12737
12738 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
12739                                              uint32_t index) {
12740   Isolate* isolate = object->GetIsolate();
12741   LookupIterator it(isolate, object, index,
12742                     LookupIterator::OWN_SKIP_INTERCEPTOR);
12743   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
12744   if (!maybe_result.IsJust()) return Nothing<bool>();
12745   return Just(it.IsFound());
12746 }
12747
12748
12749 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
12750                                                    Handle<Name> name) {
12751   LookupIterator it = LookupIterator::PropertyOrElement(
12752       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
12753   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
12754   return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
12755                                : Nothing<bool>();
12756 }
12757
12758
12759 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) {
12760   if (HasFastProperties()) {
12761     Map* map = this->map();
12762     if (filter == NONE) return map->NumberOfOwnDescriptors();
12763     if (filter & DONT_ENUM) {
12764       int result = map->EnumLength();
12765       if (result != kInvalidEnumCacheSentinel) return result;
12766     }
12767     return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
12768   } else if (IsGlobalObject()) {
12769     return global_dictionary()->NumberOfElementsFilterAttributes(filter);
12770   } else {
12771     return property_dictionary()->NumberOfElementsFilterAttributes(filter);
12772   }
12773 }
12774
12775
12776 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
12777   Object* temp = get(i);
12778   set(i, get(j));
12779   set(j, temp);
12780   if (this != numbers) {
12781     temp = numbers->get(i);
12782     numbers->set(i, Smi::cast(numbers->get(j)));
12783     numbers->set(j, Smi::cast(temp));
12784   }
12785 }
12786
12787
12788 static void InsertionSortPairs(FixedArray* content,
12789                                FixedArray* numbers,
12790                                int len) {
12791   for (int i = 1; i < len; i++) {
12792     int j = i;
12793     while (j > 0 &&
12794            (NumberToUint32(numbers->get(j - 1)) >
12795             NumberToUint32(numbers->get(j)))) {
12796       content->SwapPairs(numbers, j - 1, j);
12797       j--;
12798     }
12799   }
12800 }
12801
12802
12803 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
12804   // In-place heap sort.
12805   DCHECK(content->length() == numbers->length());
12806
12807   // Bottom-up max-heap construction.
12808   for (int i = 1; i < len; ++i) {
12809     int child_index = i;
12810     while (child_index > 0) {
12811       int parent_index = ((child_index + 1) >> 1) - 1;
12812       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
12813       uint32_t child_value = NumberToUint32(numbers->get(child_index));
12814       if (parent_value < child_value) {
12815         content->SwapPairs(numbers, parent_index, child_index);
12816       } else {
12817         break;
12818       }
12819       child_index = parent_index;
12820     }
12821   }
12822
12823   // Extract elements and create sorted array.
12824   for (int i = len - 1; i > 0; --i) {
12825     // Put max element at the back of the array.
12826     content->SwapPairs(numbers, 0, i);
12827     // Sift down the new top element.
12828     int parent_index = 0;
12829     while (true) {
12830       int child_index = ((parent_index + 1) << 1) - 1;
12831       if (child_index >= i) break;
12832       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
12833       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
12834       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
12835       if (child_index + 1 >= i || child1_value > child2_value) {
12836         if (parent_value > child1_value) break;
12837         content->SwapPairs(numbers, parent_index, child_index);
12838         parent_index = child_index;
12839       } else {
12840         if (parent_value > child2_value) break;
12841         content->SwapPairs(numbers, parent_index, child_index + 1);
12842         parent_index = child_index + 1;
12843       }
12844     }
12845   }
12846 }
12847
12848
12849 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
12850 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
12851   DCHECK(this->length() == numbers->length());
12852   // For small arrays, simply use insertion sort.
12853   if (len <= 10) {
12854     InsertionSortPairs(this, numbers, len);
12855     return;
12856   }
12857   // Check the range of indices.
12858   uint32_t min_index = NumberToUint32(numbers->get(0));
12859   uint32_t max_index = min_index;
12860   uint32_t i;
12861   for (i = 1; i < len; i++) {
12862     if (NumberToUint32(numbers->get(i)) < min_index) {
12863       min_index = NumberToUint32(numbers->get(i));
12864     } else if (NumberToUint32(numbers->get(i)) > max_index) {
12865       max_index = NumberToUint32(numbers->get(i));
12866     }
12867   }
12868   if (max_index - min_index + 1 == len) {
12869     // Indices form a contiguous range, unless there are duplicates.
12870     // Do an in-place linear time sort assuming distinct numbers, but
12871     // avoid hanging in case they are not.
12872     for (i = 0; i < len; i++) {
12873       uint32_t p;
12874       uint32_t j = 0;
12875       // While the current element at i is not at its correct position p,
12876       // swap the elements at these two positions.
12877       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
12878              j++ < len) {
12879         SwapPairs(numbers, i, p);
12880       }
12881     }
12882   } else {
12883     HeapSortPairs(this, numbers, len);
12884     return;
12885   }
12886 }
12887
12888
12889 // Fill in the names of own properties into the supplied storage. The main
12890 // purpose of this function is to provide reflection information for the object
12891 // mirrors.
12892 void JSObject::GetOwnPropertyNames(
12893     FixedArray* storage, int index, PropertyAttributes filter) {
12894   DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index));
12895   if (HasFastProperties()) {
12896     int real_size = map()->NumberOfOwnDescriptors();
12897     DescriptorArray* descs = map()->instance_descriptors();
12898     for (int i = 0; i < real_size; i++) {
12899       if ((descs->GetDetails(i).attributes() & filter) == 0 &&
12900           !FilterKey(descs->GetKey(i), filter)) {
12901         storage->set(index++, descs->GetKey(i));
12902       }
12903     }
12904   } else if (IsGlobalObject()) {
12905     global_dictionary()->CopyKeysTo(storage, index, filter,
12906                                     GlobalDictionary::UNSORTED);
12907   } else {
12908     property_dictionary()->CopyKeysTo(storage, index, filter,
12909                                       NameDictionary::UNSORTED);
12910   }
12911 }
12912
12913
12914 int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
12915   return GetOwnElementKeys(NULL, filter);
12916 }
12917
12918
12919 int JSObject::NumberOfEnumElements() {
12920   // Fast case for objects with no elements.
12921   if (!IsJSValue() && HasFastObjectElements()) {
12922     uint32_t length = IsJSArray() ?
12923         static_cast<uint32_t>(
12924             Smi::cast(JSArray::cast(this)->length())->value()) :
12925         static_cast<uint32_t>(FixedArray::cast(elements())->length());
12926     if (length == 0) return 0;
12927   }
12928   // Compute the number of enumerable elements.
12929   return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
12930 }
12931
12932
12933 int JSObject::GetOwnElementKeys(FixedArray* storage,
12934                                 PropertyAttributes filter) {
12935   int counter = 0;
12936
12937   // If this is a String wrapper, add the string indices first,
12938   // as they're guaranteed to preced the elements in numerical order
12939   // and ascending order is required by ECMA-262, 6th, 9.1.12.
12940   if (IsJSValue()) {
12941     Object* val = JSValue::cast(this)->value();
12942     if (val->IsString()) {
12943       String* str = String::cast(val);
12944       if (storage) {
12945         for (int i = 0; i < str->length(); i++) {
12946           storage->set(counter + i, Smi::FromInt(i));
12947         }
12948       }
12949       counter += str->length();
12950     }
12951   }
12952
12953   switch (GetElementsKind()) {
12954     case FAST_SMI_ELEMENTS:
12955     case FAST_ELEMENTS:
12956     case FAST_HOLEY_SMI_ELEMENTS:
12957     case FAST_HOLEY_ELEMENTS: {
12958       int length = IsJSArray() ?
12959           Smi::cast(JSArray::cast(this)->length())->value() :
12960           FixedArray::cast(elements())->length();
12961       for (int i = 0; i < length; i++) {
12962         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
12963           if (storage != NULL) {
12964             storage->set(counter, Smi::FromInt(i));
12965           }
12966           counter++;
12967         }
12968       }
12969       DCHECK(!storage || storage->length() >= counter);
12970       break;
12971     }
12972     case FAST_DOUBLE_ELEMENTS:
12973     case FAST_HOLEY_DOUBLE_ELEMENTS: {
12974       int length = IsJSArray() ?
12975           Smi::cast(JSArray::cast(this)->length())->value() :
12976           FixedArrayBase::cast(elements())->length();
12977       for (int i = 0; i < length; i++) {
12978         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
12979           if (storage != NULL) {
12980             storage->set(counter, Smi::FromInt(i));
12981           }
12982           counter++;
12983         }
12984       }
12985       DCHECK(!storage || storage->length() >= counter);
12986       break;
12987     }
12988
12989 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
12990     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
12991     case TYPE##_ELEMENTS:                                                    \
12992
12993     TYPED_ARRAYS(TYPED_ARRAY_CASE)
12994 #undef TYPED_ARRAY_CASE
12995     {
12996       int length = FixedArrayBase::cast(elements())->length();
12997       while (counter < length) {
12998         if (storage != NULL) {
12999           storage->set(counter, Smi::FromInt(counter));
13000         }
13001         counter++;
13002       }
13003       DCHECK(!storage || storage->length() >= counter);
13004       break;
13005     }
13006
13007     case DICTIONARY_ELEMENTS: {
13008       if (storage != NULL) {
13009         element_dictionary()->CopyKeysTo(storage, filter,
13010                                          SeededNumberDictionary::SORTED);
13011       }
13012       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
13013       break;
13014     }
13015     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
13016     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
13017       FixedArray* parameter_map = FixedArray::cast(elements());
13018       int mapped_length = parameter_map->length() - 2;
13019       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
13020       if (arguments->IsDictionary()) {
13021         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
13022         // will insert in storage starting at index 0.
13023         SeededNumberDictionary* dictionary =
13024             SeededNumberDictionary::cast(arguments);
13025         if (storage != NULL) {
13026           dictionary->CopyKeysTo(storage, filter,
13027                                  SeededNumberDictionary::UNSORTED);
13028         }
13029         counter += dictionary->NumberOfElementsFilterAttributes(filter);
13030         for (int i = 0; i < mapped_length; ++i) {
13031           if (!parameter_map->get(i + 2)->IsTheHole()) {
13032             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13033             ++counter;
13034           }
13035         }
13036         if (storage != NULL) storage->SortPairs(storage, counter);
13037
13038       } else {
13039         int backing_length = arguments->length();
13040         int i = 0;
13041         for (; i < mapped_length; ++i) {
13042           if (!parameter_map->get(i + 2)->IsTheHole()) {
13043             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13044             ++counter;
13045           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
13046             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13047             ++counter;
13048           }
13049         }
13050         for (; i < backing_length; ++i) {
13051           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13052           ++counter;
13053         }
13054       }
13055       break;
13056     }
13057   }
13058
13059   DCHECK(!storage || storage->length() == counter);
13060   return counter;
13061 }
13062
13063
13064 int JSObject::GetEnumElementKeys(FixedArray* storage) {
13065   return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
13066 }
13067
13068
13069 const char* Symbol::PrivateSymbolToName() const {
13070   Heap* heap = GetIsolate()->heap();
13071 #define SYMBOL_CHECK_AND_PRINT(name) \
13072   if (this == heap->name()) return #name;
13073   PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
13074 #undef SYMBOL_CHECK_AND_PRINT
13075   return "UNKNOWN";
13076 }
13077
13078
13079 void Symbol::SymbolShortPrint(std::ostream& os) {
13080   os << "<Symbol: " << Hash();
13081   if (!name()->IsUndefined()) {
13082     os << " ";
13083     HeapStringAllocator allocator;
13084     StringStream accumulator(&allocator);
13085     String::cast(name())->StringShortPrint(&accumulator);
13086     os << accumulator.ToCString().get();
13087   } else {
13088     os << " (" << PrivateSymbolToName() << ")";
13089   }
13090   os << ">";
13091 }
13092
13093
13094 // StringSharedKeys are used as keys in the eval cache.
13095 class StringSharedKey : public HashTableKey {
13096  public:
13097   StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
13098                   LanguageMode language_mode, int scope_position)
13099       : source_(source),
13100         shared_(shared),
13101         language_mode_(language_mode),
13102         scope_position_(scope_position) {}
13103
13104   bool IsMatch(Object* other) override {
13105     DisallowHeapAllocation no_allocation;
13106     if (!other->IsFixedArray()) {
13107       if (!other->IsNumber()) return false;
13108       uint32_t other_hash = static_cast<uint32_t>(other->Number());
13109       return Hash() == other_hash;
13110     }
13111     FixedArray* other_array = FixedArray::cast(other);
13112     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13113     if (shared != *shared_) return false;
13114     int language_unchecked = Smi::cast(other_array->get(2))->value();
13115     DCHECK(is_valid_language_mode(language_unchecked));
13116     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
13117     if (language_mode != language_mode_) return false;
13118     int scope_position = Smi::cast(other_array->get(3))->value();
13119     if (scope_position != scope_position_) return false;
13120     String* source = String::cast(other_array->get(1));
13121     return source->Equals(*source_);
13122   }
13123
13124   static uint32_t StringSharedHashHelper(String* source,
13125                                          SharedFunctionInfo* shared,
13126                                          LanguageMode language_mode,
13127                                          int scope_position) {
13128     uint32_t hash = source->Hash();
13129     if (shared->HasSourceCode()) {
13130       // Instead of using the SharedFunctionInfo pointer in the hash
13131       // code computation, we use a combination of the hash of the
13132       // script source code and the start position of the calling scope.
13133       // We do this to ensure that the cache entries can survive garbage
13134       // collection.
13135       Script* script(Script::cast(shared->script()));
13136       hash ^= String::cast(script->source())->Hash();
13137       STATIC_ASSERT(LANGUAGE_END == 3);
13138       if (is_strict(language_mode)) hash ^= 0x8000;
13139       if (is_strong(language_mode)) hash ^= 0x10000;
13140       hash += scope_position;
13141     }
13142     return hash;
13143   }
13144
13145   uint32_t Hash() override {
13146     return StringSharedHashHelper(*source_, *shared_, language_mode_,
13147                                   scope_position_);
13148   }
13149
13150   uint32_t HashForObject(Object* obj) override {
13151     DisallowHeapAllocation no_allocation;
13152     if (obj->IsNumber()) {
13153       return static_cast<uint32_t>(obj->Number());
13154     }
13155     FixedArray* other_array = FixedArray::cast(obj);
13156     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13157     String* source = String::cast(other_array->get(1));
13158     int language_unchecked = Smi::cast(other_array->get(2))->value();
13159     DCHECK(is_valid_language_mode(language_unchecked));
13160     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
13161     int scope_position = Smi::cast(other_array->get(3))->value();
13162     return StringSharedHashHelper(source, shared, language_mode,
13163                                   scope_position);
13164   }
13165
13166
13167   Handle<Object> AsHandle(Isolate* isolate) override {
13168     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
13169     array->set(0, *shared_);
13170     array->set(1, *source_);
13171     array->set(2, Smi::FromInt(language_mode_));
13172     array->set(3, Smi::FromInt(scope_position_));
13173     return array;
13174   }
13175
13176  private:
13177   Handle<String> source_;
13178   Handle<SharedFunctionInfo> shared_;
13179   LanguageMode language_mode_;
13180   int scope_position_;
13181 };
13182
13183
13184 // RegExpKey carries the source and flags of a regular expression as key.
13185 class RegExpKey : public HashTableKey {
13186  public:
13187   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
13188       : string_(string),
13189         flags_(Smi::FromInt(flags.value())) { }
13190
13191   // Rather than storing the key in the hash table, a pointer to the
13192   // stored value is stored where the key should be.  IsMatch then
13193   // compares the search key to the found object, rather than comparing
13194   // a key to a key.
13195   bool IsMatch(Object* obj) override {
13196     FixedArray* val = FixedArray::cast(obj);
13197     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
13198         && (flags_ == val->get(JSRegExp::kFlagsIndex));
13199   }
13200
13201   uint32_t Hash() override { return RegExpHash(*string_, flags_); }
13202
13203   Handle<Object> AsHandle(Isolate* isolate) override {
13204     // Plain hash maps, which is where regexp keys are used, don't
13205     // use this function.
13206     UNREACHABLE();
13207     return MaybeHandle<Object>().ToHandleChecked();
13208   }
13209
13210   uint32_t HashForObject(Object* obj) override {
13211     FixedArray* val = FixedArray::cast(obj);
13212     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
13213                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
13214   }
13215
13216   static uint32_t RegExpHash(String* string, Smi* flags) {
13217     return string->Hash() + flags->value();
13218   }
13219
13220   Handle<String> string_;
13221   Smi* flags_;
13222 };
13223
13224
13225 Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
13226   if (hash_field_ == 0) Hash();
13227   return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
13228 }
13229
13230
13231 Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
13232   if (hash_field_ == 0) Hash();
13233   return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
13234 }
13235
13236
13237 Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
13238   if (hash_field_ == 0) Hash();
13239   return isolate->factory()->NewOneByteInternalizedSubString(
13240       string_, from_, length_, hash_field_);
13241 }
13242
13243
13244 bool SeqOneByteSubStringKey::IsMatch(Object* string) {
13245   Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
13246   return String::cast(string)->IsOneByteEqualTo(chars);
13247 }
13248
13249
13250 // InternalizedStringKey carries a string/internalized-string object as key.
13251 class InternalizedStringKey : public HashTableKey {
13252  public:
13253   explicit InternalizedStringKey(Handle<String> string)
13254       : string_(string) { }
13255
13256   bool IsMatch(Object* string) override {
13257     return String::cast(string)->Equals(*string_);
13258   }
13259
13260   uint32_t Hash() override { return string_->Hash(); }
13261
13262   uint32_t HashForObject(Object* other) override {
13263     return String::cast(other)->Hash();
13264   }
13265
13266   Handle<Object> AsHandle(Isolate* isolate) override {
13267     // Internalize the string if possible.
13268     MaybeHandle<Map> maybe_map =
13269         isolate->factory()->InternalizedStringMapForString(string_);
13270     Handle<Map> map;
13271     if (maybe_map.ToHandle(&map)) {
13272       string_->set_map_no_write_barrier(*map);
13273       DCHECK(string_->IsInternalizedString());
13274       return string_;
13275     }
13276     // Otherwise allocate a new internalized string.
13277     return isolate->factory()->NewInternalizedStringImpl(
13278         string_, string_->length(), string_->hash_field());
13279   }
13280
13281   static uint32_t StringHash(Object* obj) {
13282     return String::cast(obj)->Hash();
13283   }
13284
13285   Handle<String> string_;
13286 };
13287
13288
13289 template<typename Derived, typename Shape, typename Key>
13290 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
13291   IteratePointers(v, 0, kElementsStartOffset);
13292 }
13293
13294
13295 template<typename Derived, typename Shape, typename Key>
13296 void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
13297   IteratePointers(v,
13298                   kElementsStartOffset,
13299                   kHeaderSize + length() * kPointerSize);
13300 }
13301
13302
13303 template<typename Derived, typename Shape, typename Key>
13304 Handle<Derived> HashTable<Derived, Shape, Key>::New(
13305     Isolate* isolate,
13306     int at_least_space_for,
13307     MinimumCapacity capacity_option,
13308     PretenureFlag pretenure) {
13309   DCHECK(0 <= at_least_space_for);
13310   DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
13311
13312   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
13313                      ? at_least_space_for
13314                      : isolate->creating_default_snapshot()
13315                            ? ComputeCapacityForSerialization(at_least_space_for)
13316                            : ComputeCapacity(at_least_space_for);
13317   if (capacity > HashTable::kMaxCapacity) {
13318     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
13319   }
13320
13321   Factory* factory = isolate->factory();
13322   int length = EntryToIndex(capacity);
13323   Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
13324   array->set_map_no_write_barrier(*factory->hash_table_map());
13325   Handle<Derived> table = Handle<Derived>::cast(array);
13326
13327   table->SetNumberOfElements(0);
13328   table->SetNumberOfDeletedElements(0);
13329   table->SetCapacity(capacity);
13330   return table;
13331 }
13332
13333
13334 // Find entry for key otherwise return kNotFound.
13335 template <typename Derived, typename Shape>
13336 int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
13337   if (!key->IsUniqueName()) {
13338     return DerivedDictionary::FindEntry(key);
13339   }
13340
13341   // Optimized for unique names. Knowledge of the key type allows:
13342   // 1. Move the check if the key is unique out of the loop.
13343   // 2. Avoid comparing hash codes in unique-to-unique comparison.
13344   // 3. Detect a case when a dictionary key is not unique but the key is.
13345   //    In case of positive result the dictionary key may be replaced by the
13346   //    internalized string with minimal performance penalty. It gives a chance
13347   //    to perform further lookups in code stubs (and significant performance
13348   //    boost a certain style of code).
13349
13350   // EnsureCapacity will guarantee the hash table is never full.
13351   uint32_t capacity = this->Capacity();
13352   uint32_t entry = Derived::FirstProbe(key->Hash(), capacity);
13353   uint32_t count = 1;
13354
13355   while (true) {
13356     int index = Derived::EntryToIndex(entry);
13357     Object* element = this->get(index);
13358     if (element->IsUndefined()) break;  // Empty entry.
13359     if (*key == element) return entry;
13360     if (!element->IsUniqueName() &&
13361         !element->IsTheHole() &&
13362         Name::cast(element)->Equals(*key)) {
13363       // Replace a key that is a non-internalized string by the equivalent
13364       // internalized string for faster further lookups.
13365       this->set(index, *key);
13366       return entry;
13367     }
13368     DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
13369     entry = Derived::NextProbe(entry, count++, capacity);
13370   }
13371   return Derived::kNotFound;
13372 }
13373
13374
13375 template<typename Derived, typename Shape, typename Key>
13376 void HashTable<Derived, Shape, Key>::Rehash(
13377     Handle<Derived> new_table,
13378     Key key) {
13379   DCHECK(NumberOfElements() < new_table->Capacity());
13380
13381   DisallowHeapAllocation no_gc;
13382   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
13383
13384   // Copy prefix to new array.
13385   for (int i = kPrefixStartIndex;
13386        i < kPrefixStartIndex + Shape::kPrefixSize;
13387        i++) {
13388     new_table->set(i, get(i), mode);
13389   }
13390
13391   // Rehash the elements.
13392   int capacity = this->Capacity();
13393   for (int i = 0; i < capacity; i++) {
13394     uint32_t from_index = EntryToIndex(i);
13395     Object* k = this->get(from_index);
13396     if (IsKey(k)) {
13397       uint32_t hash = this->HashForObject(key, k);
13398       uint32_t insertion_index =
13399           EntryToIndex(new_table->FindInsertionEntry(hash));
13400       for (int j = 0; j < Shape::kEntrySize; j++) {
13401         new_table->set(insertion_index + j, get(from_index + j), mode);
13402       }
13403     }
13404   }
13405   new_table->SetNumberOfElements(NumberOfElements());
13406   new_table->SetNumberOfDeletedElements(0);
13407 }
13408
13409
13410 template<typename Derived, typename Shape, typename Key>
13411 uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
13412     Key key,
13413     Object* k,
13414     int probe,
13415     uint32_t expected) {
13416   uint32_t hash = this->HashForObject(key, k);
13417   uint32_t capacity = this->Capacity();
13418   uint32_t entry = FirstProbe(hash, capacity);
13419   for (int i = 1; i < probe; i++) {
13420     if (entry == expected) return expected;
13421     entry = NextProbe(entry, i, capacity);
13422   }
13423   return entry;
13424 }
13425
13426
13427 template<typename Derived, typename Shape, typename Key>
13428 void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
13429                                           uint32_t entry2,
13430                                           WriteBarrierMode mode) {
13431   int index1 = EntryToIndex(entry1);
13432   int index2 = EntryToIndex(entry2);
13433   Object* temp[Shape::kEntrySize];
13434   for (int j = 0; j < Shape::kEntrySize; j++) {
13435     temp[j] = get(index1 + j);
13436   }
13437   for (int j = 0; j < Shape::kEntrySize; j++) {
13438     set(index1 + j, get(index2 + j), mode);
13439   }
13440   for (int j = 0; j < Shape::kEntrySize; j++) {
13441     set(index2 + j, temp[j], mode);
13442   }
13443 }
13444
13445
13446 template<typename Derived, typename Shape, typename Key>
13447 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
13448   DisallowHeapAllocation no_gc;
13449   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
13450   uint32_t capacity = Capacity();
13451   bool done = false;
13452   for (int probe = 1; !done; probe++) {
13453     // All elements at entries given by one of the first _probe_ probes
13454     // are placed correctly. Other elements might need to be moved.
13455     done = true;
13456     for (uint32_t current = 0; current < capacity; current++) {
13457       Object* current_key = get(EntryToIndex(current));
13458       if (IsKey(current_key)) {
13459         uint32_t target = EntryForProbe(key, current_key, probe, current);
13460         if (current == target) continue;
13461         Object* target_key = get(EntryToIndex(target));
13462         if (!IsKey(target_key) ||
13463             EntryForProbe(key, target_key, probe, target) != target) {
13464           // Put the current element into the correct position.
13465           Swap(current, target, mode);
13466           // The other element will be processed on the next iteration.
13467           current--;
13468         } else {
13469           // The place for the current element is occupied. Leave the element
13470           // for the next probe.
13471           done = false;
13472         }
13473       }
13474     }
13475   }
13476 }
13477
13478
13479 template<typename Derived, typename Shape, typename Key>
13480 Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
13481     Handle<Derived> table,
13482     int n,
13483     Key key,
13484     PretenureFlag pretenure) {
13485   Isolate* isolate = table->GetIsolate();
13486   int capacity = table->Capacity();
13487   int nof = table->NumberOfElements() + n;
13488   int nod = table->NumberOfDeletedElements();
13489   // Return if:
13490   //   50% is still free after adding n elements and
13491   //   at most 50% of the free elements are deleted elements.
13492   if (nod <= (capacity - nof) >> 1) {
13493     int needed_free = nof >> 1;
13494     if (nof + needed_free <= capacity) return table;
13495   }
13496
13497   const int kMinCapacityForPretenure = 256;
13498   bool should_pretenure = pretenure == TENURED ||
13499       ((capacity > kMinCapacityForPretenure) &&
13500           !isolate->heap()->InNewSpace(*table));
13501   Handle<Derived> new_table = HashTable::New(
13502       isolate,
13503       nof * 2,
13504       USE_DEFAULT_MINIMUM_CAPACITY,
13505       should_pretenure ? TENURED : NOT_TENURED);
13506
13507   table->Rehash(new_table, key);
13508   return new_table;
13509 }
13510
13511
13512 template<typename Derived, typename Shape, typename Key>
13513 Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
13514                                                        Key key) {
13515   int capacity = table->Capacity();
13516   int nof = table->NumberOfElements();
13517
13518   // Shrink to fit the number of elements if only a quarter of the
13519   // capacity is filled with elements.
13520   if (nof > (capacity >> 2)) return table;
13521   // Allocate a new dictionary with room for at least the current
13522   // number of elements. The allocation method will make sure that
13523   // there is extra room in the dictionary for additions. Don't go
13524   // lower than room for 16 elements.
13525   int at_least_room_for = nof;
13526   if (at_least_room_for < 16) return table;
13527
13528   Isolate* isolate = table->GetIsolate();
13529   const int kMinCapacityForPretenure = 256;
13530   bool pretenure =
13531       (at_least_room_for > kMinCapacityForPretenure) &&
13532       !isolate->heap()->InNewSpace(*table);
13533   Handle<Derived> new_table = HashTable::New(
13534       isolate,
13535       at_least_room_for,
13536       USE_DEFAULT_MINIMUM_CAPACITY,
13537       pretenure ? TENURED : NOT_TENURED);
13538
13539   table->Rehash(new_table, key);
13540   return new_table;
13541 }
13542
13543
13544 template<typename Derived, typename Shape, typename Key>
13545 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
13546   uint32_t capacity = Capacity();
13547   uint32_t entry = FirstProbe(hash, capacity);
13548   uint32_t count = 1;
13549   // EnsureCapacity will guarantee the hash table is never full.
13550   while (true) {
13551     Object* element = KeyAt(entry);
13552     if (element->IsUndefined() || element->IsTheHole()) break;
13553     entry = NextProbe(entry, count++, capacity);
13554   }
13555   return entry;
13556 }
13557
13558
13559 // Force instantiation of template instances class.
13560 // Please note this list is compiler dependent.
13561
13562 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
13563
13564 template class HashTable<CompilationCacheTable,
13565                          CompilationCacheShape,
13566                          HashTableKey*>;
13567
13568 template class HashTable<ObjectHashTable,
13569                          ObjectHashTableShape,
13570                          Handle<Object> >;
13571
13572 template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
13573
13574 template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
13575
13576 template class Dictionary<GlobalDictionary, GlobalDictionaryShape,
13577                           Handle<Name> >;
13578
13579 template class Dictionary<SeededNumberDictionary,
13580                           SeededNumberDictionaryShape,
13581                           uint32_t>;
13582
13583 template class Dictionary<UnseededNumberDictionary,
13584                           UnseededNumberDictionaryShape,
13585                           uint32_t>;
13586
13587 template Handle<SeededNumberDictionary>
13588 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13589     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
13590
13591 template Handle<UnseededNumberDictionary>
13592 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13593     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
13594
13595 template Handle<NameDictionary>
13596 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
13597     New(Isolate*, int n, PretenureFlag pretenure);
13598
13599 template Handle<GlobalDictionary>
13600 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::New(
13601     Isolate*, int n, PretenureFlag pretenure);
13602
13603 template Handle<SeededNumberDictionary>
13604 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13605     AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
13606
13607 template Handle<UnseededNumberDictionary>
13608 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13609     AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
13610
13611 template Object*
13612 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13613     SlowReverseLookup(Object* value);
13614
13615 template Object*
13616 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
13617     SlowReverseLookup(Object* value);
13618
13619 template Handle<Object>
13620 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
13621     Handle<NameDictionary>, int);
13622
13623 template Handle<Object>
13624 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
13625            uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
13626
13627 template Handle<NameDictionary>
13628 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
13629     New(Isolate*, int, MinimumCapacity, PretenureFlag);
13630
13631 template Handle<NameDictionary>
13632 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
13633     Shrink(Handle<NameDictionary>, Handle<Name>);
13634
13635 template Handle<SeededNumberDictionary>
13636 HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13637     Shrink(Handle<SeededNumberDictionary>, uint32_t);
13638
13639 template Handle<NameDictionary>
13640 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
13641     Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
13642
13643 template Handle<GlobalDictionary>
13644     Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name> >::Add(
13645         Handle<GlobalDictionary>, Handle<Name>, Handle<Object>,
13646         PropertyDetails);
13647
13648 template Handle<FixedArray> Dictionary<
13649     NameDictionary, NameDictionaryShape,
13650     Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
13651
13652 template Handle<FixedArray> Dictionary<
13653     NameDictionary, NameDictionaryShape,
13654     Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
13655
13656 template Handle<SeededNumberDictionary>
13657 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13658     Add(Handle<SeededNumberDictionary>,
13659         uint32_t,
13660         Handle<Object>,
13661         PropertyDetails);
13662
13663 template Handle<UnseededNumberDictionary>
13664 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13665     Add(Handle<UnseededNumberDictionary>,
13666         uint32_t,
13667         Handle<Object>,
13668         PropertyDetails);
13669
13670 template Handle<SeededNumberDictionary>
13671 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
13672     EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
13673
13674 template Handle<UnseededNumberDictionary>
13675 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
13676     EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
13677
13678 template Handle<NameDictionary>
13679 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
13680     EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
13681
13682 template bool Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
13683                          uint32_t>::HasComplexElements();
13684
13685 template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
13686                        uint32_t>::FindEntry(uint32_t);
13687
13688 template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
13689     Handle<Name>);
13690
13691
13692 Handle<Object> JSObject::PrepareSlowElementsForSort(
13693     Handle<JSObject> object, uint32_t limit) {
13694   DCHECK(object->HasDictionaryElements());
13695   Isolate* isolate = object->GetIsolate();
13696   // Must stay in dictionary mode, either because of requires_slow_elements,
13697   // or because we are not going to sort (and therefore compact) all of the
13698   // elements.
13699   Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
13700   Handle<SeededNumberDictionary> new_dict =
13701       SeededNumberDictionary::New(isolate, dict->NumberOfElements());
13702
13703   uint32_t pos = 0;
13704   uint32_t undefs = 0;
13705   int capacity = dict->Capacity();
13706   Handle<Smi> bailout(Smi::FromInt(-1), isolate);
13707   // Entry to the new dictionary does not cause it to grow, as we have
13708   // allocated one that is large enough for all entries.
13709   DisallowHeapAllocation no_gc;
13710   for (int i = 0; i < capacity; i++) {
13711     Object* k = dict->KeyAt(i);
13712     if (!dict->IsKey(k)) continue;
13713
13714     DCHECK(k->IsNumber());
13715     DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
13716     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
13717     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
13718
13719     HandleScope scope(isolate);
13720     Handle<Object> value(dict->ValueAt(i), isolate);
13721     PropertyDetails details = dict->DetailsAt(i);
13722     if (details.type() == ACCESSOR_CONSTANT || details.IsReadOnly()) {
13723       // Bail out and do the sorting of undefineds and array holes in JS.
13724       // Also bail out if the element is not supposed to be moved.
13725       return bailout;
13726     }
13727
13728     uint32_t key = NumberToUint32(k);
13729     if (key < limit) {
13730       if (value->IsUndefined()) {
13731         undefs++;
13732       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
13733         // Adding an entry with the key beyond smi-range requires
13734         // allocation. Bailout.
13735         return bailout;
13736       } else {
13737         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
13738             new_dict, pos, value, details);
13739         DCHECK(result.is_identical_to(new_dict));
13740         USE(result);
13741         pos++;
13742       }
13743     } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
13744       // Adding an entry with the key beyond smi-range requires
13745       // allocation. Bailout.
13746       return bailout;
13747     } else {
13748       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
13749           new_dict, key, value, details);
13750       DCHECK(result.is_identical_to(new_dict));
13751       USE(result);
13752     }
13753   }
13754
13755   uint32_t result = pos;
13756   PropertyDetails no_details = PropertyDetails::Empty();
13757   while (undefs > 0) {
13758     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
13759       // Adding an entry with the key beyond smi-range requires
13760       // allocation. Bailout.
13761       return bailout;
13762     }
13763     HandleScope scope(isolate);
13764     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
13765         new_dict, pos, isolate->factory()->undefined_value(), no_details);
13766     DCHECK(result.is_identical_to(new_dict));
13767     USE(result);
13768     pos++;
13769     undefs--;
13770   }
13771
13772   object->set_elements(*new_dict);
13773
13774   AllowHeapAllocation allocate_return_value;
13775   return isolate->factory()->NewNumberFromUint(result);
13776 }
13777
13778
13779 // Collects all defined (non-hole) and non-undefined (array) elements at
13780 // the start of the elements array.
13781 // If the object is in dictionary mode, it is converted to fast elements
13782 // mode.
13783 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
13784                                                 uint32_t limit) {
13785   Isolate* isolate = object->GetIsolate();
13786   if (object->HasSloppyArgumentsElements() ||
13787       object->map()->is_observed()) {
13788     return handle(Smi::FromInt(-1), isolate);
13789   }
13790
13791   if (object->HasDictionaryElements()) {
13792     // Convert to fast elements containing only the existing properties.
13793     // Ordering is irrelevant, since we are going to sort anyway.
13794     Handle<SeededNumberDictionary> dict(object->element_dictionary());
13795     if (object->IsJSArray() || dict->requires_slow_elements() ||
13796         dict->max_number_key() >= limit) {
13797       return JSObject::PrepareSlowElementsForSort(object, limit);
13798     }
13799     // Convert to fast elements.
13800
13801     Handle<Map> new_map =
13802         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
13803
13804     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
13805         NOT_TENURED: TENURED;
13806     Handle<FixedArray> fast_elements =
13807         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
13808     dict->CopyValuesTo(*fast_elements);
13809     JSObject::ValidateElements(object);
13810
13811     JSObject::SetMapAndElements(object, new_map, fast_elements);
13812   } else if (object->HasExternalArrayElements() ||
13813              object->HasFixedTypedArrayElements()) {
13814     // Typed arrays cannot have holes or undefined elements.
13815     return handle(Smi::FromInt(
13816         FixedArrayBase::cast(object->elements())->length()), isolate);
13817   } else if (!object->HasFastDoubleElements()) {
13818     EnsureWritableFastElements(object);
13819   }
13820   DCHECK(object->HasFastSmiOrObjectElements() ||
13821          object->HasFastDoubleElements());
13822
13823   // Collect holes at the end, undefined before that and the rest at the
13824   // start, and return the number of non-hole, non-undefined values.
13825
13826   Handle<FixedArrayBase> elements_base(object->elements());
13827   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
13828   if (limit > elements_length) {
13829     limit = elements_length ;
13830   }
13831   if (limit == 0) {
13832     return handle(Smi::FromInt(0), isolate);
13833   }
13834
13835   uint32_t result = 0;
13836   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
13837     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
13838     // Split elements into defined and the_hole, in that order.
13839     unsigned int holes = limit;
13840     // Assume most arrays contain no holes and undefined values, so minimize the
13841     // number of stores of non-undefined, non-the-hole values.
13842     for (unsigned int i = 0; i < holes; i++) {
13843       if (elements->is_the_hole(i)) {
13844         holes--;
13845       } else {
13846         continue;
13847       }
13848       // Position i needs to be filled.
13849       while (holes > i) {
13850         if (elements->is_the_hole(holes)) {
13851           holes--;
13852         } else {
13853           elements->set(i, elements->get_scalar(holes));
13854           break;
13855         }
13856       }
13857     }
13858     result = holes;
13859     while (holes < limit) {
13860       elements->set_the_hole(holes);
13861       holes++;
13862     }
13863   } else {
13864     FixedArray* elements = FixedArray::cast(*elements_base);
13865     DisallowHeapAllocation no_gc;
13866
13867     // Split elements into defined, undefined and the_hole, in that order.  Only
13868     // count locations for undefined and the hole, and fill them afterwards.
13869     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
13870     unsigned int undefs = limit;
13871     unsigned int holes = limit;
13872     // Assume most arrays contain no holes and undefined values, so minimize the
13873     // number of stores of non-undefined, non-the-hole values.
13874     for (unsigned int i = 0; i < undefs; i++) {
13875       Object* current = elements->get(i);
13876       if (current->IsTheHole()) {
13877         holes--;
13878         undefs--;
13879       } else if (current->IsUndefined()) {
13880         undefs--;
13881       } else {
13882         continue;
13883       }
13884       // Position i needs to be filled.
13885       while (undefs > i) {
13886         current = elements->get(undefs);
13887         if (current->IsTheHole()) {
13888           holes--;
13889           undefs--;
13890         } else if (current->IsUndefined()) {
13891           undefs--;
13892         } else {
13893           elements->set(i, current, write_barrier);
13894           break;
13895         }
13896       }
13897     }
13898     result = undefs;
13899     while (undefs < holes) {
13900       elements->set_undefined(undefs);
13901       undefs++;
13902     }
13903     while (holes < limit) {
13904       elements->set_the_hole(holes);
13905       holes++;
13906     }
13907   }
13908
13909   return isolate->factory()->NewNumberFromUint(result);
13910 }
13911
13912
13913 ExternalArrayType JSTypedArray::type() {
13914   switch (elements()->map()->instance_type()) {
13915 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
13916     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
13917     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
13918       return kExternal##Type##Array;
13919
13920     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
13921 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
13922
13923     default:
13924       UNREACHABLE();
13925       return static_cast<ExternalArrayType>(-1);
13926   }
13927 }
13928
13929
13930 size_t JSTypedArray::element_size() {
13931   switch (elements()->map()->instance_type()) {
13932 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)          \
13933     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
13934       return size;
13935
13936     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
13937 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
13938
13939     default:
13940       UNREACHABLE();
13941       return 0;
13942   }
13943 }
13944
13945
13946 void FixedArray::SetValue(uint32_t index, Object* value) { set(index, value); }
13947
13948
13949 void FixedDoubleArray::SetValue(uint32_t index, Object* value) {
13950   set(index, value->Number());
13951 }
13952
13953
13954 void ExternalUint8ClampedArray::SetValue(uint32_t index, Object* value) {
13955   uint8_t clamped_value = 0;
13956   if (value->IsSmi()) {
13957     int int_value = Smi::cast(value)->value();
13958     if (int_value < 0) {
13959       clamped_value = 0;
13960     } else if (int_value > 255) {
13961       clamped_value = 255;
13962     } else {
13963       clamped_value = static_cast<uint8_t>(int_value);
13964     }
13965   } else if (value->IsHeapNumber()) {
13966     double double_value = HeapNumber::cast(value)->value();
13967     if (!(double_value > 0)) {
13968       // NaN and less than zero clamp to zero.
13969       clamped_value = 0;
13970     } else if (double_value > 255) {
13971       // Greater than 255 clamp to 255.
13972       clamped_value = 255;
13973     } else {
13974       // Other doubles are rounded to the nearest integer.
13975       clamped_value = static_cast<uint8_t>(lrint(double_value));
13976     }
13977   } else {
13978     // Clamp undefined to zero (default). All other types have been
13979     // converted to a number type further up in the call chain.
13980     DCHECK(value->IsUndefined());
13981   }
13982   set(index, clamped_value);
13983 }
13984
13985
13986 template <typename ExternalArrayClass, typename ValueType>
13987 static void ExternalArrayIntSetter(ExternalArrayClass* receiver, uint32_t index,
13988                                    Object* value) {
13989   ValueType cast_value = 0;
13990   if (value->IsSmi()) {
13991     int int_value = Smi::cast(value)->value();
13992     cast_value = static_cast<ValueType>(int_value);
13993   } else if (value->IsHeapNumber()) {
13994     double double_value = HeapNumber::cast(value)->value();
13995     cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
13996   } else {
13997     // Clamp undefined to zero (default). All other types have been
13998     // converted to a number type further up in the call chain.
13999     DCHECK(value->IsUndefined());
14000   }
14001   receiver->set(index, cast_value);
14002 }
14003
14004
14005 void ExternalInt8Array::SetValue(uint32_t index, Object* value) {
14006   ExternalArrayIntSetter<ExternalInt8Array, int8_t>(this, index, value);
14007 }
14008
14009
14010 void ExternalUint8Array::SetValue(uint32_t index, Object* value) {
14011   ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(this, index, value);
14012 }
14013
14014
14015 void ExternalInt16Array::SetValue(uint32_t index, Object* value) {
14016   ExternalArrayIntSetter<ExternalInt16Array, int16_t>(this, index, value);
14017 }
14018
14019
14020 void ExternalUint16Array::SetValue(uint32_t index, Object* value) {
14021   ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(this, index, value);
14022 }
14023
14024
14025 void ExternalInt32Array::SetValue(uint32_t index, Object* value) {
14026   ExternalArrayIntSetter<ExternalInt32Array, int32_t>(this, index, value);
14027 }
14028
14029
14030 void ExternalUint32Array::SetValue(uint32_t index, Object* value) {
14031   uint32_t cast_value = 0;
14032   if (value->IsSmi()) {
14033     int int_value = Smi::cast(value)->value();
14034     cast_value = static_cast<uint32_t>(int_value);
14035   } else if (value->IsHeapNumber()) {
14036     double double_value = HeapNumber::cast(value)->value();
14037     cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
14038   } else {
14039     // Clamp undefined to zero (default). All other types have been
14040     // converted to a number type further up in the call chain.
14041     DCHECK(value->IsUndefined());
14042   }
14043   set(index, cast_value);
14044 }
14045
14046
14047 void ExternalFloat32Array::SetValue(uint32_t index, Object* value) {
14048   float cast_value = std::numeric_limits<float>::quiet_NaN();
14049   if (value->IsSmi()) {
14050     int int_value = Smi::cast(value)->value();
14051     cast_value = static_cast<float>(int_value);
14052   } else if (value->IsHeapNumber()) {
14053     double double_value = HeapNumber::cast(value)->value();
14054     cast_value = static_cast<float>(double_value);
14055   } else {
14056     // Clamp undefined to NaN (default). All other types have been
14057     // converted to a number type further up in the call chain.
14058     DCHECK(value->IsUndefined());
14059   }
14060   set(index, cast_value);
14061 }
14062
14063
14064 void ExternalFloat64Array::SetValue(uint32_t index, Object* value) {
14065   double double_value = std::numeric_limits<double>::quiet_NaN();
14066   if (value->IsNumber()) {
14067     double_value = value->Number();
14068   } else {
14069     // Clamp undefined to NaN (default). All other types have been
14070     // converted to a number type further up in the call chain.
14071     DCHECK(value->IsUndefined());
14072   }
14073   set(index, double_value);
14074 }
14075
14076
14077 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global,
14078                                           Handle<Name> name) {
14079   DCHECK(!global->HasFastProperties());
14080   auto dictionary = handle(global->global_dictionary());
14081   int entry = dictionary->FindEntry(name);
14082   if (entry == GlobalDictionary::kNotFound) return;
14083   PropertyCell::InvalidateEntry(dictionary, entry);
14084 }
14085
14086
14087 // TODO(ishell): rename to EnsureEmptyPropertyCell or something.
14088 Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
14089     Handle<GlobalObject> global, Handle<Name> name) {
14090   DCHECK(!global->HasFastProperties());
14091   auto dictionary = handle(global->global_dictionary());
14092   int entry = dictionary->FindEntry(name);
14093   Handle<PropertyCell> cell;
14094   if (entry != GlobalDictionary::kNotFound) {
14095     // This call should be idempotent.
14096     DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
14097     cell = handle(PropertyCell::cast(dictionary->ValueAt(entry)));
14098     DCHECK(cell->property_details().cell_type() ==
14099                PropertyCellType::kUninitialized ||
14100            cell->property_details().cell_type() ==
14101                PropertyCellType::kInvalidated);
14102     DCHECK(cell->value()->IsTheHole());
14103     return cell;
14104   }
14105   Isolate* isolate = global->GetIsolate();
14106   cell = isolate->factory()->NewPropertyCell();
14107   PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized);
14108   dictionary = GlobalDictionary::Add(dictionary, name, cell, details);
14109   global->set_properties(*dictionary);
14110   return cell;
14111 }
14112
14113
14114 // This class is used for looking up two character strings in the string table.
14115 // If we don't have a hit we don't want to waste much time so we unroll the
14116 // string hash calculation loop here for speed.  Doesn't work if the two
14117 // characters form a decimal integer, since such strings have a different hash
14118 // algorithm.
14119 class TwoCharHashTableKey : public HashTableKey {
14120  public:
14121   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
14122     : c1_(c1), c2_(c2) {
14123     // Char 1.
14124     uint32_t hash = seed;
14125     hash += c1;
14126     hash += hash << 10;
14127     hash ^= hash >> 6;
14128     // Char 2.
14129     hash += c2;
14130     hash += hash << 10;
14131     hash ^= hash >> 6;
14132     // GetHash.
14133     hash += hash << 3;
14134     hash ^= hash >> 11;
14135     hash += hash << 15;
14136     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
14137     hash_ = hash;
14138 #ifdef DEBUG
14139     // If this assert fails then we failed to reproduce the two-character
14140     // version of the string hashing algorithm above.  One reason could be
14141     // that we were passed two digits as characters, since the hash
14142     // algorithm is different in that case.
14143     uint16_t chars[2] = {c1, c2};
14144     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
14145     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
14146     DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
14147 #endif
14148   }
14149
14150   bool IsMatch(Object* o) override {
14151     if (!o->IsString()) return false;
14152     String* other = String::cast(o);
14153     if (other->length() != 2) return false;
14154     if (other->Get(0) != c1_) return false;
14155     return other->Get(1) == c2_;
14156   }
14157
14158   uint32_t Hash() override { return hash_; }
14159   uint32_t HashForObject(Object* key) override {
14160     if (!key->IsString()) return 0;
14161     return String::cast(key)->Hash();
14162   }
14163
14164   Handle<Object> AsHandle(Isolate* isolate) override {
14165     // The TwoCharHashTableKey is only used for looking in the string
14166     // table, not for adding to it.
14167     UNREACHABLE();
14168     return MaybeHandle<Object>().ToHandleChecked();
14169   }
14170
14171  private:
14172   uint16_t c1_;
14173   uint16_t c2_;
14174   uint32_t hash_;
14175 };
14176
14177
14178 MaybeHandle<String> StringTable::InternalizeStringIfExists(
14179     Isolate* isolate,
14180     Handle<String> string) {
14181   if (string->IsInternalizedString()) {
14182     return string;
14183   }
14184   return LookupStringIfExists(isolate, string);
14185 }
14186
14187
14188 MaybeHandle<String> StringTable::LookupStringIfExists(
14189     Isolate* isolate,
14190     Handle<String> string) {
14191   Handle<StringTable> string_table = isolate->factory()->string_table();
14192   InternalizedStringKey key(string);
14193   int entry = string_table->FindEntry(&key);
14194   if (entry == kNotFound) {
14195     return MaybeHandle<String>();
14196   } else {
14197     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14198     DCHECK(StringShape(*result).IsInternalized());
14199     return result;
14200   }
14201 }
14202
14203
14204 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
14205     Isolate* isolate,
14206     uint16_t c1,
14207     uint16_t c2) {
14208   Handle<StringTable> string_table = isolate->factory()->string_table();
14209   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
14210   int entry = string_table->FindEntry(&key);
14211   if (entry == kNotFound) {
14212     return MaybeHandle<String>();
14213   } else {
14214     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14215     DCHECK(StringShape(*result).IsInternalized());
14216     return result;
14217   }
14218 }
14219
14220
14221 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
14222                                                    int expected) {
14223   Handle<StringTable> table = isolate->factory()->string_table();
14224   // We need a key instance for the virtual hash function.
14225   InternalizedStringKey dummy_key(Handle<String>::null());
14226   table = StringTable::EnsureCapacity(table, expected, &dummy_key);
14227   isolate->factory()->set_string_table(table);
14228 }
14229
14230
14231 Handle<String> StringTable::LookupString(Isolate* isolate,
14232                                          Handle<String> string) {
14233   InternalizedStringKey key(string);
14234   return LookupKey(isolate, &key);
14235 }
14236
14237
14238 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
14239   Handle<StringTable> table = isolate->factory()->string_table();
14240   int entry = table->FindEntry(key);
14241
14242   // String already in table.
14243   if (entry != kNotFound) {
14244     return handle(String::cast(table->KeyAt(entry)), isolate);
14245   }
14246
14247   // Adding new string. Grow table if needed.
14248   table = StringTable::EnsureCapacity(table, 1, key);
14249
14250   // Create string object.
14251   Handle<Object> string = key->AsHandle(isolate);
14252   // There must be no attempts to internalize strings that could throw
14253   // InvalidStringLength error.
14254   CHECK(!string.is_null());
14255
14256   // Add the new string and return it along with the string table.
14257   entry = table->FindInsertionEntry(key->Hash());
14258   table->set(EntryToIndex(entry), *string);
14259   table->ElementAdded();
14260
14261   isolate->factory()->set_string_table(table);
14262   return Handle<String>::cast(string);
14263 }
14264
14265
14266 String* StringTable::LookupKeyIfExists(Isolate* isolate, HashTableKey* key) {
14267   Handle<StringTable> table = isolate->factory()->string_table();
14268   int entry = table->FindEntry(key);
14269   if (entry != kNotFound) return String::cast(table->KeyAt(entry));
14270   return NULL;
14271 }
14272
14273
14274 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
14275                                              Handle<Context> context,
14276                                              LanguageMode language_mode) {
14277   Isolate* isolate = GetIsolate();
14278   Handle<SharedFunctionInfo> shared(context->closure()->shared());
14279   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
14280   int entry = FindEntry(&key);
14281   if (entry == kNotFound) return isolate->factory()->undefined_value();
14282   int index = EntryToIndex(entry);
14283   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
14284   return Handle<Object>(get(index + 1), isolate);
14285 }
14286
14287
14288 Handle<Object> CompilationCacheTable::LookupEval(
14289     Handle<String> src, Handle<SharedFunctionInfo> outer_info,
14290     LanguageMode language_mode, int scope_position) {
14291   Isolate* isolate = GetIsolate();
14292   // Cache key is the tuple (source, outer shared function info, scope position)
14293   // to unambiguously identify the context chain the cached eval code assumes.
14294   StringSharedKey key(src, outer_info, language_mode, scope_position);
14295   int entry = FindEntry(&key);
14296   if (entry == kNotFound) return isolate->factory()->undefined_value();
14297   int index = EntryToIndex(entry);
14298   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
14299   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14300 }
14301
14302
14303 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
14304                                                    JSRegExp::Flags flags) {
14305   Isolate* isolate = GetIsolate();
14306   DisallowHeapAllocation no_allocation;
14307   RegExpKey key(src, flags);
14308   int entry = FindEntry(&key);
14309   if (entry == kNotFound) return isolate->factory()->undefined_value();
14310   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14311 }
14312
14313
14314 Handle<CompilationCacheTable> CompilationCacheTable::Put(
14315     Handle<CompilationCacheTable> cache, Handle<String> src,
14316     Handle<Context> context, LanguageMode language_mode, Handle<Object> value) {
14317   Isolate* isolate = cache->GetIsolate();
14318   Handle<SharedFunctionInfo> shared(context->closure()->shared());
14319   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
14320   {
14321     Handle<Object> k = key.AsHandle(isolate);
14322     DisallowHeapAllocation no_allocation_scope;
14323     int entry = cache->FindEntry(&key);
14324     if (entry != kNotFound) {
14325       cache->set(EntryToIndex(entry), *k);
14326       cache->set(EntryToIndex(entry) + 1, *value);
14327       return cache;
14328     }
14329   }
14330
14331   cache = EnsureCapacity(cache, 1, &key);
14332   int entry = cache->FindInsertionEntry(key.Hash());
14333   Handle<Object> k =
14334       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
14335   cache->set(EntryToIndex(entry), *k);
14336   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
14337   cache->ElementAdded();
14338   return cache;
14339 }
14340
14341
14342 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
14343     Handle<CompilationCacheTable> cache, Handle<String> src,
14344     Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
14345     int scope_position) {
14346   Isolate* isolate = cache->GetIsolate();
14347   StringSharedKey key(src, outer_info, value->language_mode(), scope_position);
14348   {
14349     Handle<Object> k = key.AsHandle(isolate);
14350     DisallowHeapAllocation no_allocation_scope;
14351     int entry = cache->FindEntry(&key);
14352     if (entry != kNotFound) {
14353       cache->set(EntryToIndex(entry), *k);
14354       cache->set(EntryToIndex(entry) + 1, *value);
14355       return cache;
14356     }
14357   }
14358
14359   cache = EnsureCapacity(cache, 1, &key);
14360   int entry = cache->FindInsertionEntry(key.Hash());
14361   Handle<Object> k =
14362       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
14363   cache->set(EntryToIndex(entry), *k);
14364   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
14365   cache->ElementAdded();
14366   return cache;
14367 }
14368
14369
14370 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
14371       Handle<CompilationCacheTable> cache, Handle<String> src,
14372       JSRegExp::Flags flags, Handle<FixedArray> value) {
14373   RegExpKey key(src, flags);
14374   cache = EnsureCapacity(cache, 1, &key);
14375   int entry = cache->FindInsertionEntry(key.Hash());
14376   // We store the value in the key slot, and compare the search key
14377   // to the stored value with a custon IsMatch function during lookups.
14378   cache->set(EntryToIndex(entry), *value);
14379   cache->set(EntryToIndex(entry) + 1, *value);
14380   cache->ElementAdded();
14381   return cache;
14382 }
14383
14384
14385 void CompilationCacheTable::Age() {
14386   DisallowHeapAllocation no_allocation;
14387   Object* the_hole_value = GetHeap()->the_hole_value();
14388   for (int entry = 0, size = Capacity(); entry < size; entry++) {
14389     int entry_index = EntryToIndex(entry);
14390     int value_index = entry_index + 1;
14391
14392     if (get(entry_index)->IsNumber()) {
14393       Smi* count = Smi::cast(get(value_index));
14394       count = Smi::FromInt(count->value() - 1);
14395       if (count->value() == 0) {
14396         NoWriteBarrierSet(this, entry_index, the_hole_value);
14397         NoWriteBarrierSet(this, value_index, the_hole_value);
14398         ElementRemoved();
14399       } else {
14400         NoWriteBarrierSet(this, value_index, count);
14401       }
14402     } else if (get(entry_index)->IsFixedArray()) {
14403       SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
14404       if (info->code()->kind() != Code::FUNCTION || info->code()->IsOld()) {
14405         NoWriteBarrierSet(this, entry_index, the_hole_value);
14406         NoWriteBarrierSet(this, value_index, the_hole_value);
14407         ElementRemoved();
14408       }
14409     }
14410   }
14411 }
14412
14413
14414 void CompilationCacheTable::Remove(Object* value) {
14415   DisallowHeapAllocation no_allocation;
14416   Object* the_hole_value = GetHeap()->the_hole_value();
14417   for (int entry = 0, size = Capacity(); entry < size; entry++) {
14418     int entry_index = EntryToIndex(entry);
14419     int value_index = entry_index + 1;
14420     if (get(value_index) == value) {
14421       NoWriteBarrierSet(this, entry_index, the_hole_value);
14422       NoWriteBarrierSet(this, value_index, the_hole_value);
14423       ElementRemoved();
14424     }
14425   }
14426   return;
14427 }
14428
14429
14430 // StringsKey used for HashTable where key is array of internalized strings.
14431 class StringsKey : public HashTableKey {
14432  public:
14433   explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
14434
14435   bool IsMatch(Object* strings) override {
14436     FixedArray* o = FixedArray::cast(strings);
14437     int len = strings_->length();
14438     if (o->length() != len) return false;
14439     for (int i = 0; i < len; i++) {
14440       if (o->get(i) != strings_->get(i)) return false;
14441     }
14442     return true;
14443   }
14444
14445   uint32_t Hash() override { return HashForObject(*strings_); }
14446
14447   uint32_t HashForObject(Object* obj) override {
14448     FixedArray* strings = FixedArray::cast(obj);
14449     int len = strings->length();
14450     uint32_t hash = 0;
14451     for (int i = 0; i < len; i++) {
14452       hash ^= String::cast(strings->get(i))->Hash();
14453     }
14454     return hash;
14455   }
14456
14457   Handle<Object> AsHandle(Isolate* isolate) override { return strings_; }
14458
14459  private:
14460   Handle<FixedArray> strings_;
14461 };
14462
14463
14464 template<typename Derived, typename Shape, typename Key>
14465 Handle<Derived> Dictionary<Derived, Shape, Key>::New(
14466     Isolate* isolate,
14467     int at_least_space_for,
14468     PretenureFlag pretenure) {
14469   DCHECK(0 <= at_least_space_for);
14470   Handle<Derived> dict = DerivedHashTable::New(isolate,
14471                                                at_least_space_for,
14472                                                USE_DEFAULT_MINIMUM_CAPACITY,
14473                                                pretenure);
14474
14475   // Initialize the next enumeration index.
14476   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
14477   return dict;
14478 }
14479
14480
14481 template <typename Derived, typename Shape, typename Key>
14482 Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
14483     Handle<Derived> dictionary) {
14484   Factory* factory = dictionary->GetIsolate()->factory();
14485   int length = dictionary->NumberOfElements();
14486
14487   Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
14488   Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
14489
14490   // Fill both the iteration order array and the enumeration order array
14491   // with property details.
14492   int capacity = dictionary->Capacity();
14493   int pos = 0;
14494   for (int i = 0; i < capacity; i++) {
14495     if (dictionary->IsKey(dictionary->KeyAt(i))) {
14496       int index = dictionary->DetailsAt(i).dictionary_index();
14497       iteration_order->set(pos, Smi::FromInt(i));
14498       enumeration_order->set(pos, Smi::FromInt(index));
14499       pos++;
14500     }
14501   }
14502   DCHECK(pos == length);
14503
14504   // Sort the arrays wrt. enumeration order.
14505   iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
14506   return iteration_order;
14507 }
14508
14509
14510 template <typename Derived, typename Shape, typename Key>
14511 Handle<FixedArray>
14512 Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
14513     Handle<Derived> dictionary) {
14514   int length = dictionary->NumberOfElements();
14515
14516   Handle<FixedArray> iteration_order = BuildIterationIndicesArray(dictionary);
14517   DCHECK(iteration_order->length() == length);
14518
14519   // Iterate over the dictionary using the enumeration order and update
14520   // the dictionary with new enumeration indices.
14521   for (int i = 0; i < length; i++) {
14522     int index = Smi::cast(iteration_order->get(i))->value();
14523     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
14524
14525     int enum_index = PropertyDetails::kInitialIndex + i;
14526
14527     PropertyDetails details = dictionary->DetailsAt(index);
14528     PropertyDetails new_details = details.set_index(enum_index);
14529     dictionary->DetailsAtPut(index, new_details);
14530   }
14531
14532   // Set the next enumeration index.
14533   dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
14534   return iteration_order;
14535 }
14536
14537
14538 template<typename Derived, typename Shape, typename Key>
14539 Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
14540     Handle<Derived> dictionary, int n, Key key) {
14541   // Check whether there are enough enumeration indices to add n elements.
14542   if (Shape::kIsEnumerable &&
14543       !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
14544     // If not, we generate new indices for the properties.
14545     GenerateNewEnumerationIndices(dictionary);
14546   }
14547   return DerivedHashTable::EnsureCapacity(dictionary, n, key);
14548 }
14549
14550
14551 template <typename Derived, typename Shape, typename Key>
14552 Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
14553     Handle<Derived> dictionary, int entry) {
14554   Factory* factory = dictionary->GetIsolate()->factory();
14555   PropertyDetails details = dictionary->DetailsAt(entry);
14556   if (!details.IsConfigurable()) return factory->false_value();
14557
14558   dictionary->SetEntry(
14559       entry, factory->the_hole_value(), factory->the_hole_value());
14560   dictionary->ElementRemoved();
14561   return factory->true_value();
14562 }
14563
14564
14565 template<typename Derived, typename Shape, typename Key>
14566 Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
14567     Handle<Derived> dictionary, Key key, Handle<Object> value) {
14568   int entry = dictionary->FindEntry(key);
14569
14570   // If the entry is present set the value;
14571   if (entry != Dictionary::kNotFound) {
14572     dictionary->ValueAtPut(entry, *value);
14573     return dictionary;
14574   }
14575
14576   // Check whether the dictionary should be extended.
14577   dictionary = EnsureCapacity(dictionary, 1, key);
14578 #ifdef DEBUG
14579   USE(Shape::AsHandle(dictionary->GetIsolate(), key));
14580 #endif
14581   PropertyDetails details = PropertyDetails::Empty();
14582
14583   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
14584   return dictionary;
14585 }
14586
14587
14588 template<typename Derived, typename Shape, typename Key>
14589 Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
14590     Handle<Derived> dictionary,
14591     Key key,
14592     Handle<Object> value,
14593     PropertyDetails details) {
14594   // Valdate key is absent.
14595   SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
14596   // Check whether the dictionary should be extended.
14597   dictionary = EnsureCapacity(dictionary, 1, key);
14598
14599   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
14600   return dictionary;
14601 }
14602
14603
14604 // Add a key, value pair to the dictionary.
14605 template<typename Derived, typename Shape, typename Key>
14606 void Dictionary<Derived, Shape, Key>::AddEntry(
14607     Handle<Derived> dictionary,
14608     Key key,
14609     Handle<Object> value,
14610     PropertyDetails details,
14611     uint32_t hash) {
14612   // Compute the key object.
14613   Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
14614
14615   uint32_t entry = dictionary->FindInsertionEntry(hash);
14616   // Insert element at empty or deleted entry
14617   if (details.dictionary_index() == 0 && Shape::kIsEnumerable) {
14618     // Assign an enumeration index to the property and update
14619     // SetNextEnumerationIndex.
14620     int index = dictionary->NextEnumerationIndex();
14621     details = details.set_index(index);
14622     dictionary->SetNextEnumerationIndex(index + 1);
14623   }
14624   dictionary->SetEntry(entry, k, value, details);
14625   DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
14626           dictionary->KeyAt(entry)->IsName()));
14627   dictionary->ElementAdded();
14628 }
14629
14630
14631 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
14632   DisallowHeapAllocation no_allocation;
14633   // If the dictionary requires slow elements an element has already
14634   // been added at a high index.
14635   if (requires_slow_elements()) return;
14636   // Check if this index is high enough that we should require slow
14637   // elements.
14638   if (key > kRequiresSlowElementsLimit) {
14639     // TODO(verwaest): Remove this hack.
14640     GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
14641     set_requires_slow_elements();
14642     return;
14643   }
14644   // Update max key value.
14645   Object* max_index_object = get(kMaxNumberKeyIndex);
14646   if (!max_index_object->IsSmi() || max_number_key() < key) {
14647     FixedArray::set(kMaxNumberKeyIndex,
14648                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
14649   }
14650 }
14651
14652
14653 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
14654     Handle<SeededNumberDictionary> dictionary,
14655     uint32_t key,
14656     Handle<Object> value,
14657     PropertyDetails details) {
14658   dictionary->UpdateMaxNumberKey(key);
14659   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
14660   return Add(dictionary, key, value, details);
14661 }
14662
14663
14664 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
14665     Handle<UnseededNumberDictionary> dictionary,
14666     uint32_t key,
14667     Handle<Object> value) {
14668   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
14669   return Add(dictionary, key, value, PropertyDetails::Empty());
14670 }
14671
14672
14673 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
14674     Handle<SeededNumberDictionary> dictionary,
14675     uint32_t key,
14676     Handle<Object> value) {
14677   dictionary->UpdateMaxNumberKey(key);
14678   return AtPut(dictionary, key, value);
14679 }
14680
14681
14682 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
14683     Handle<UnseededNumberDictionary> dictionary,
14684     uint32_t key,
14685     Handle<Object> value) {
14686   return AtPut(dictionary, key, value);
14687 }
14688
14689
14690 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
14691     Handle<SeededNumberDictionary> dictionary,
14692     uint32_t key,
14693     Handle<Object> value,
14694     PropertyDetails details) {
14695   int entry = dictionary->FindEntry(key);
14696   if (entry == kNotFound) {
14697     return AddNumberEntry(dictionary, key, value, details);
14698   }
14699   // Preserve enumeration index.
14700   details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
14701   Handle<Object> object_key =
14702       SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
14703   dictionary->SetEntry(entry, object_key, value, details);
14704   return dictionary;
14705 }
14706
14707
14708 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
14709     Handle<UnseededNumberDictionary> dictionary,
14710     uint32_t key,
14711     Handle<Object> value) {
14712   int entry = dictionary->FindEntry(key);
14713   if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
14714   Handle<Object> object_key =
14715       UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
14716   dictionary->SetEntry(entry, object_key, value);
14717   return dictionary;
14718 }
14719
14720
14721 template <typename Derived, typename Shape, typename Key>
14722 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
14723     PropertyAttributes filter) {
14724   int capacity = this->Capacity();
14725   int result = 0;
14726   for (int i = 0; i < capacity; i++) {
14727     Object* k = this->KeyAt(i);
14728     if (this->IsKey(k) && !FilterKey(k, filter)) {
14729       if (this->IsDeleted(i)) continue;
14730       PropertyDetails details = this->DetailsAt(i);
14731       PropertyAttributes attr = details.attributes();
14732       if ((attr & filter) == 0) result++;
14733     }
14734   }
14735   return result;
14736 }
14737
14738
14739 template <typename Derived, typename Shape, typename Key>
14740 bool Dictionary<Derived, Shape, Key>::HasComplexElements() {
14741   int capacity = this->Capacity();
14742   for (int i = 0; i < capacity; i++) {
14743     Object* k = this->KeyAt(i);
14744     if (this->IsKey(k) && !FilterKey(k, NONE)) {
14745       if (this->IsDeleted(i)) continue;
14746       PropertyDetails details = this->DetailsAt(i);
14747       if (details.type() == ACCESSOR_CONSTANT) return true;
14748       PropertyAttributes attr = details.attributes();
14749       if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true;
14750     }
14751   }
14752   return false;
14753 }
14754
14755
14756 template <typename Derived, typename Shape, typename Key>
14757 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
14758     FixedArray* storage, PropertyAttributes filter,
14759     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
14760   DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
14761   int capacity = this->Capacity();
14762   int index = 0;
14763   for (int i = 0; i < capacity; i++) {
14764     Object* k = this->KeyAt(i);
14765     if (this->IsKey(k) && !FilterKey(k, filter)) {
14766       if (this->IsDeleted(i)) continue;
14767       PropertyDetails details = this->DetailsAt(i);
14768       PropertyAttributes attr = details.attributes();
14769       if ((attr & filter) == 0) storage->set(index++, k);
14770     }
14771   }
14772   if (sort_mode == Dictionary::SORTED) {
14773     storage->SortPairs(storage, index);
14774   }
14775   DCHECK(storage->length() >= index);
14776 }
14777
14778
14779 template <typename Dictionary>
14780 struct EnumIndexComparator {
14781   explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {}
14782   bool operator() (Smi* a, Smi* b) {
14783     PropertyDetails da(dict->DetailsAt(a->value()));
14784     PropertyDetails db(dict->DetailsAt(b->value()));
14785     return da.dictionary_index() < db.dictionary_index();
14786   }
14787   Dictionary* dict;
14788 };
14789
14790
14791 template <typename Derived, typename Shape, typename Key>
14792 void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(FixedArray* storage) {
14793   int length = storage->length();
14794   int capacity = this->Capacity();
14795   int properties = 0;
14796   for (int i = 0; i < capacity; i++) {
14797     Object* k = this->KeyAt(i);
14798     if (this->IsKey(k) && !k->IsSymbol()) {
14799       PropertyDetails details = this->DetailsAt(i);
14800       if (details.IsDontEnum() || this->IsDeleted(i)) continue;
14801       storage->set(properties, Smi::FromInt(i));
14802       properties++;
14803       if (properties == length) break;
14804     }
14805   }
14806   CHECK_EQ(length, properties);
14807   EnumIndexComparator<Derived> cmp(static_cast<Derived*>(this));
14808   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
14809   std::sort(start, start + length, cmp);
14810   for (int i = 0; i < length; i++) {
14811     int index = Smi::cast(storage->get(i))->value();
14812     storage->set(i, this->KeyAt(index));
14813   }
14814 }
14815
14816
14817 template <typename Derived, typename Shape, typename Key>
14818 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
14819     FixedArray* storage, int index, PropertyAttributes filter,
14820     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
14821   DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
14822   int capacity = this->Capacity();
14823   for (int i = 0; i < capacity; i++) {
14824     Object* k = this->KeyAt(i);
14825     if (this->IsKey(k) && !FilterKey(k, filter)) {
14826       if (this->IsDeleted(i)) continue;
14827       PropertyDetails details = this->DetailsAt(i);
14828       PropertyAttributes attr = details.attributes();
14829       if ((attr & filter) == 0) storage->set(index++, k);
14830     }
14831   }
14832   if (sort_mode == Dictionary::SORTED) {
14833     storage->SortPairs(storage, index);
14834   }
14835   DCHECK(storage->length() >= index);
14836 }
14837
14838
14839 // Backwards lookup (slow).
14840 template<typename Derived, typename Shape, typename Key>
14841 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
14842   int capacity = this->Capacity();
14843   for (int i = 0; i < capacity; i++) {
14844     Object* k = this->KeyAt(i);
14845     if (this->IsKey(k)) {
14846       Object* e = this->ValueAt(i);
14847       // TODO(dcarney): this should be templatized.
14848       if (e->IsPropertyCell()) {
14849         e = PropertyCell::cast(e)->value();
14850       }
14851       if (e == value) return k;
14852     }
14853   }
14854   Heap* heap = Dictionary::GetHeap();
14855   return heap->undefined_value();
14856 }
14857
14858
14859 Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
14860                                 int32_t hash) {
14861   DisallowHeapAllocation no_gc;
14862   DCHECK(IsKey(*key));
14863
14864   int entry = FindEntry(isolate, key, hash);
14865   if (entry == kNotFound) return isolate->heap()->the_hole_value();
14866   return get(EntryToIndex(entry) + 1);
14867 }
14868
14869
14870 Object* ObjectHashTable::Lookup(Handle<Object> key) {
14871   DisallowHeapAllocation no_gc;
14872   DCHECK(IsKey(*key));
14873
14874   Isolate* isolate = GetIsolate();
14875
14876   // If the object does not have an identity hash, it was never used as a key.
14877   Object* hash = key->GetHash();
14878   if (hash->IsUndefined()) {
14879     return isolate->heap()->the_hole_value();
14880   }
14881   return Lookup(isolate, key, Smi::cast(hash)->value());
14882 }
14883
14884
14885 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
14886   return Lookup(GetIsolate(), key, hash);
14887 }
14888
14889
14890 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
14891                                              Handle<Object> key,
14892                                              Handle<Object> value) {
14893   DCHECK(table->IsKey(*key));
14894   DCHECK(!value->IsTheHole());
14895
14896   Isolate* isolate = table->GetIsolate();
14897   // Make sure the key object has an identity hash code.
14898   int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
14899
14900   return Put(table, key, value, hash);
14901 }
14902
14903
14904 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
14905                                              Handle<Object> key,
14906                                              Handle<Object> value,
14907                                              int32_t hash) {
14908   DCHECK(table->IsKey(*key));
14909   DCHECK(!value->IsTheHole());
14910
14911   Isolate* isolate = table->GetIsolate();
14912
14913   int entry = table->FindEntry(isolate, key, hash);
14914
14915   // Key is already in table, just overwrite value.
14916   if (entry != kNotFound) {
14917     table->set(EntryToIndex(entry) + 1, *value);
14918     return table;
14919   }
14920
14921   // Check whether the hash table should be extended.
14922   table = EnsureCapacity(table, 1, key);
14923   table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
14924   return table;
14925 }
14926
14927
14928 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
14929                                                 Handle<Object> key,
14930                                                 bool* was_present) {
14931   DCHECK(table->IsKey(*key));
14932
14933   Object* hash = key->GetHash();
14934   if (hash->IsUndefined()) {
14935     *was_present = false;
14936     return table;
14937   }
14938
14939   return Remove(table, key, was_present, Smi::cast(hash)->value());
14940 }
14941
14942
14943 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
14944                                                 Handle<Object> key,
14945                                                 bool* was_present,
14946                                                 int32_t hash) {
14947   DCHECK(table->IsKey(*key));
14948
14949   int entry = table->FindEntry(table->GetIsolate(), key, hash);
14950   if (entry == kNotFound) {
14951     *was_present = false;
14952     return table;
14953   }
14954
14955   *was_present = true;
14956   table->RemoveEntry(entry);
14957   return Shrink(table, key);
14958 }
14959
14960
14961 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
14962   set(EntryToIndex(entry), key);
14963   set(EntryToIndex(entry) + 1, value);
14964   ElementAdded();
14965 }
14966
14967
14968 void ObjectHashTable::RemoveEntry(int entry) {
14969   set_the_hole(EntryToIndex(entry));
14970   set_the_hole(EntryToIndex(entry) + 1);
14971   ElementRemoved();
14972 }
14973
14974
14975 Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
14976   DisallowHeapAllocation no_gc;
14977   DCHECK(IsKey(*key));
14978   int entry = FindEntry(key);
14979   if (entry == kNotFound) return GetHeap()->the_hole_value();
14980   return get(EntryToValueIndex(entry));
14981 }
14982
14983
14984 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
14985                                          Handle<HeapObject> key,
14986                                          Handle<HeapObject> value) {
14987   DCHECK(table->IsKey(*key));
14988   int entry = table->FindEntry(key);
14989   // Key is already in table, just overwrite value.
14990   if (entry != kNotFound) {
14991     table->set(EntryToValueIndex(entry), *value);
14992     return table;
14993   }
14994
14995   Handle<WeakCell> key_cell = key->GetIsolate()->factory()->NewWeakCell(key);
14996
14997   // Check whether the hash table should be extended.
14998   table = EnsureCapacity(table, 1, key, TENURED);
14999
15000   table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
15001   return table;
15002 }
15003
15004
15005 void WeakHashTable::AddEntry(int entry, Handle<WeakCell> key_cell,
15006                              Handle<HeapObject> value) {
15007   DisallowHeapAllocation no_allocation;
15008   set(EntryToIndex(entry), *key_cell);
15009   set(EntryToValueIndex(entry), *value);
15010   ElementAdded();
15011 }
15012
15013
15014 #ifdef DEBUG
15015 Object* WeakValueHashTable::LookupWeak(Handle<Object> key) {
15016   Object* value = Lookup(key);
15017   if (value->IsWeakCell() && !WeakCell::cast(value)->cleared()) {
15018     value = WeakCell::cast(value)->value();
15019   }
15020   return value;
15021 }
15022 #endif  // DEBUG
15023
15024
15025 Handle<WeakValueHashTable> WeakValueHashTable::PutWeak(
15026     Handle<WeakValueHashTable> table, Handle<Object> key,
15027     Handle<HeapObject> value) {
15028   Handle<WeakCell> cell = value->GetIsolate()->factory()->NewWeakCell(value);
15029   return Handle<WeakValueHashTable>::cast(
15030       Put(Handle<ObjectHashTable>::cast(table), key, cell));
15031 }
15032
15033
15034 Handle<FixedArray> WeakValueHashTable::GetWeakValues(
15035     Handle<WeakValueHashTable> table) {
15036   Isolate* isolate = table->GetIsolate();
15037   uint32_t capacity = table->Capacity();
15038   Handle<FixedArray> results = isolate->factory()->NewFixedArray(capacity);
15039   int length = 0;
15040   for (uint32_t i = 0; i < capacity; i++) {
15041     uint32_t key_index = table->EntryToIndex(i);
15042     Object* key = table->get(key_index);
15043     if (!table->IsKey(key)) continue;
15044     uint32_t value_index = table->EntryToValueIndex(i);
15045     WeakCell* value_cell = WeakCell::cast(table->get(value_index));
15046     if (value_cell->cleared()) {
15047       table->RemoveEntry(i);
15048     } else {
15049       results->set(length++, value_cell->value());
15050     }
15051   }
15052   results->Shrink(length);
15053   return results;
15054 }
15055
15056
15057 template<class Derived, class Iterator, int entrysize>
15058 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
15059     Isolate* isolate, int capacity, PretenureFlag pretenure) {
15060   // Capacity must be a power of two, since we depend on being able
15061   // to divide and multiple by 2 (kLoadFactor) to derive capacity
15062   // from number of buckets. If we decide to change kLoadFactor
15063   // to something other than 2, capacity should be stored as another
15064   // field of this object.
15065   capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
15066   if (capacity > kMaxCapacity) {
15067     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
15068   }
15069   int num_buckets = capacity / kLoadFactor;
15070   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
15071       kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
15072   backing_store->set_map_no_write_barrier(
15073       isolate->heap()->ordered_hash_table_map());
15074   Handle<Derived> table = Handle<Derived>::cast(backing_store);
15075   for (int i = 0; i < num_buckets; ++i) {
15076     table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
15077   }
15078   table->SetNumberOfBuckets(num_buckets);
15079   table->SetNumberOfElements(0);
15080   table->SetNumberOfDeletedElements(0);
15081   return table;
15082 }
15083
15084
15085 template<class Derived, class Iterator, int entrysize>
15086 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
15087     Handle<Derived> table) {
15088   DCHECK(!table->IsObsolete());
15089
15090   int nof = table->NumberOfElements();
15091   int nod = table->NumberOfDeletedElements();
15092   int capacity = table->Capacity();
15093   if ((nof + nod) < capacity) return table;
15094   // Don't need to grow if we can simply clear out deleted entries instead.
15095   // Note that we can't compact in place, though, so we always allocate
15096   // a new table.
15097   return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
15098 }
15099
15100
15101 template<class Derived, class Iterator, int entrysize>
15102 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
15103     Handle<Derived> table) {
15104   DCHECK(!table->IsObsolete());
15105
15106   int nof = table->NumberOfElements();
15107   int capacity = table->Capacity();
15108   if (nof >= (capacity >> 2)) return table;
15109   return Rehash(table, capacity / 2);
15110 }
15111
15112
15113 template<class Derived, class Iterator, int entrysize>
15114 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
15115     Handle<Derived> table) {
15116   DCHECK(!table->IsObsolete());
15117
15118   Handle<Derived> new_table =
15119       Allocate(table->GetIsolate(),
15120                kMinCapacity,
15121                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15122
15123   table->SetNextTable(*new_table);
15124   table->SetNumberOfDeletedElements(kClearedTableSentinel);
15125
15126   return new_table;
15127 }
15128
15129
15130 template<class Derived, class Iterator, int entrysize>
15131 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
15132     Handle<Derived> table, int new_capacity) {
15133   DCHECK(!table->IsObsolete());
15134
15135   Handle<Derived> new_table =
15136       Allocate(table->GetIsolate(),
15137                new_capacity,
15138                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15139   int nof = table->NumberOfElements();
15140   int nod = table->NumberOfDeletedElements();
15141   int new_buckets = new_table->NumberOfBuckets();
15142   int new_entry = 0;
15143   int removed_holes_index = 0;
15144
15145   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
15146     Object* key = table->KeyAt(old_entry);
15147     if (key->IsTheHole()) {
15148       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
15149       continue;
15150     }
15151
15152     Object* hash = key->GetHash();
15153     int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
15154     Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
15155     new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
15156     int new_index = new_table->EntryToIndex(new_entry);
15157     int old_index = table->EntryToIndex(old_entry);
15158     for (int i = 0; i < entrysize; ++i) {
15159       Object* value = table->get(old_index + i);
15160       new_table->set(new_index + i, value);
15161     }
15162     new_table->set(new_index + kChainOffset, chain_entry);
15163     ++new_entry;
15164   }
15165
15166   DCHECK_EQ(nod, removed_holes_index);
15167
15168   new_table->SetNumberOfElements(nof);
15169   table->SetNextTable(*new_table);
15170
15171   return new_table;
15172 }
15173
15174
15175 template Handle<OrderedHashSet>
15176 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
15177     Isolate* isolate, int capacity, PretenureFlag pretenure);
15178
15179 template Handle<OrderedHashSet>
15180 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
15181     Handle<OrderedHashSet> table);
15182
15183 template Handle<OrderedHashSet>
15184 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
15185     Handle<OrderedHashSet> table);
15186
15187 template Handle<OrderedHashSet>
15188 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
15189     Handle<OrderedHashSet> table);
15190
15191
15192 template Handle<OrderedHashMap>
15193 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
15194     Isolate* isolate, int capacity, PretenureFlag pretenure);
15195
15196 template Handle<OrderedHashMap>
15197 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
15198     Handle<OrderedHashMap> table);
15199
15200 template Handle<OrderedHashMap>
15201 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
15202     Handle<OrderedHashMap> table);
15203
15204 template Handle<OrderedHashMap>
15205 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
15206     Handle<OrderedHashMap> table);
15207
15208
15209 template<class Derived, class TableType>
15210 void OrderedHashTableIterator<Derived, TableType>::Transition() {
15211   DisallowHeapAllocation no_allocation;
15212   TableType* table = TableType::cast(this->table());
15213   if (!table->IsObsolete()) return;
15214
15215   int index = Smi::cast(this->index())->value();
15216   while (table->IsObsolete()) {
15217     TableType* next_table = table->NextTable();
15218
15219     if (index > 0) {
15220       int nod = table->NumberOfDeletedElements();
15221
15222       if (nod == TableType::kClearedTableSentinel) {
15223         index = 0;
15224       } else {
15225         int old_index = index;
15226         for (int i = 0; i < nod; ++i) {
15227           int removed_index = table->RemovedIndexAt(i);
15228           if (removed_index >= old_index) break;
15229           --index;
15230         }
15231       }
15232     }
15233
15234     table = next_table;
15235   }
15236
15237   set_table(table);
15238   set_index(Smi::FromInt(index));
15239 }
15240
15241
15242 template<class Derived, class TableType>
15243 bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
15244   DisallowHeapAllocation no_allocation;
15245   if (this->table()->IsUndefined()) return false;
15246
15247   Transition();
15248
15249   TableType* table = TableType::cast(this->table());
15250   int index = Smi::cast(this->index())->value();
15251   int used_capacity = table->UsedCapacity();
15252
15253   while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
15254     index++;
15255   }
15256
15257   set_index(Smi::FromInt(index));
15258
15259   if (index < used_capacity) return true;
15260
15261   set_table(GetHeap()->undefined_value());
15262   return false;
15263 }
15264
15265
15266 template<class Derived, class TableType>
15267 Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
15268   DisallowHeapAllocation no_allocation;
15269   if (HasMore()) {
15270     FixedArray* array = FixedArray::cast(value_array->elements());
15271     static_cast<Derived*>(this)->PopulateValueArray(array);
15272     MoveNext();
15273     return Smi::cast(kind());
15274   }
15275   return Smi::FromInt(0);
15276 }
15277
15278
15279 template Smi*
15280 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
15281     JSArray* value_array);
15282
15283 template bool
15284 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
15285
15286 template void
15287 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
15288
15289 template Object*
15290 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
15291
15292 template void
15293 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
15294
15295
15296 template Smi*
15297 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
15298     JSArray* value_array);
15299
15300 template bool
15301 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
15302
15303 template void
15304 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
15305
15306 template Object*
15307 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
15308
15309 template void
15310 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
15311
15312
15313 // Check if there is a break point at this code position.
15314 bool DebugInfo::HasBreakPoint(int code_position) {
15315   // Get the break point info object for this code position.
15316   Object* break_point_info = GetBreakPointInfo(code_position);
15317
15318   // If there is no break point info object or no break points in the break
15319   // point info object there is no break point at this code position.
15320   if (break_point_info->IsUndefined()) return false;
15321   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
15322 }
15323
15324
15325 // Get the break point info object for this code position.
15326 Object* DebugInfo::GetBreakPointInfo(int code_position) {
15327   // Find the index of the break point info object for this code position.
15328   int index = GetBreakPointInfoIndex(code_position);
15329
15330   // Return the break point info object if any.
15331   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
15332   return BreakPointInfo::cast(break_points()->get(index));
15333 }
15334
15335
15336 // Clear a break point at the specified code position.
15337 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
15338                                 int code_position,
15339                                 Handle<Object> break_point_object) {
15340   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15341                                   debug_info->GetIsolate());
15342   if (break_point_info->IsUndefined()) return;
15343   BreakPointInfo::ClearBreakPoint(
15344       Handle<BreakPointInfo>::cast(break_point_info),
15345       break_point_object);
15346 }
15347
15348
15349 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
15350                               int code_position,
15351                               int source_position,
15352                               int statement_position,
15353                               Handle<Object> break_point_object) {
15354   Isolate* isolate = debug_info->GetIsolate();
15355   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15356                                   isolate);
15357   if (!break_point_info->IsUndefined()) {
15358     BreakPointInfo::SetBreakPoint(
15359         Handle<BreakPointInfo>::cast(break_point_info),
15360         break_point_object);
15361     return;
15362   }
15363
15364   // Adding a new break point for a code position which did not have any
15365   // break points before. Try to find a free slot.
15366   int index = kNoBreakPointInfo;
15367   for (int i = 0; i < debug_info->break_points()->length(); i++) {
15368     if (debug_info->break_points()->get(i)->IsUndefined()) {
15369       index = i;
15370       break;
15371     }
15372   }
15373   if (index == kNoBreakPointInfo) {
15374     // No free slot - extend break point info array.
15375     Handle<FixedArray> old_break_points =
15376         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
15377     Handle<FixedArray> new_break_points =
15378         isolate->factory()->NewFixedArray(
15379             old_break_points->length() +
15380             DebugInfo::kEstimatedNofBreakPointsInFunction);
15381
15382     debug_info->set_break_points(*new_break_points);
15383     for (int i = 0; i < old_break_points->length(); i++) {
15384       new_break_points->set(i, old_break_points->get(i));
15385     }
15386     index = old_break_points->length();
15387   }
15388   DCHECK(index != kNoBreakPointInfo);
15389
15390   // Allocate new BreakPointInfo object and set the break point.
15391   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
15392       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
15393   new_break_point_info->set_code_position(Smi::FromInt(code_position));
15394   new_break_point_info->set_source_position(Smi::FromInt(source_position));
15395   new_break_point_info->
15396       set_statement_position(Smi::FromInt(statement_position));
15397   new_break_point_info->set_break_point_objects(
15398       isolate->heap()->undefined_value());
15399   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
15400   debug_info->break_points()->set(index, *new_break_point_info);
15401 }
15402
15403
15404 // Get the break point objects for a code position.
15405 Handle<Object> DebugInfo::GetBreakPointObjects(int code_position) {
15406   Object* break_point_info = GetBreakPointInfo(code_position);
15407   if (break_point_info->IsUndefined()) {
15408     return GetIsolate()->factory()->undefined_value();
15409   }
15410   return Handle<Object>(
15411       BreakPointInfo::cast(break_point_info)->break_point_objects(),
15412       GetIsolate());
15413 }
15414
15415
15416 // Get the total number of break points.
15417 int DebugInfo::GetBreakPointCount() {
15418   if (break_points()->IsUndefined()) return 0;
15419   int count = 0;
15420   for (int i = 0; i < break_points()->length(); i++) {
15421     if (!break_points()->get(i)->IsUndefined()) {
15422       BreakPointInfo* break_point_info =
15423           BreakPointInfo::cast(break_points()->get(i));
15424       count += break_point_info->GetBreakPointCount();
15425     }
15426   }
15427   return count;
15428 }
15429
15430
15431 Handle<Object> DebugInfo::FindBreakPointInfo(
15432     Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
15433   Isolate* isolate = debug_info->GetIsolate();
15434   if (!debug_info->break_points()->IsUndefined()) {
15435     for (int i = 0; i < debug_info->break_points()->length(); i++) {
15436       if (!debug_info->break_points()->get(i)->IsUndefined()) {
15437         Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
15438             BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
15439         if (BreakPointInfo::HasBreakPointObject(break_point_info,
15440                                                 break_point_object)) {
15441           return break_point_info;
15442         }
15443       }
15444     }
15445   }
15446   return isolate->factory()->undefined_value();
15447 }
15448
15449
15450 // Find the index of the break point info object for the specified code
15451 // position.
15452 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
15453   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
15454   for (int i = 0; i < break_points()->length(); i++) {
15455     if (!break_points()->get(i)->IsUndefined()) {
15456       BreakPointInfo* break_point_info =
15457           BreakPointInfo::cast(break_points()->get(i));
15458       if (break_point_info->code_position()->value() == code_position) {
15459         return i;
15460       }
15461     }
15462   }
15463   return kNoBreakPointInfo;
15464 }
15465
15466
15467 // Remove the specified break point object.
15468 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
15469                                      Handle<Object> break_point_object) {
15470   Isolate* isolate = break_point_info->GetIsolate();
15471   // If there are no break points just ignore.
15472   if (break_point_info->break_point_objects()->IsUndefined()) return;
15473   // If there is a single break point clear it if it is the same.
15474   if (!break_point_info->break_point_objects()->IsFixedArray()) {
15475     if (break_point_info->break_point_objects() == *break_point_object) {
15476       break_point_info->set_break_point_objects(
15477           isolate->heap()->undefined_value());
15478     }
15479     return;
15480   }
15481   // If there are multiple break points shrink the array
15482   DCHECK(break_point_info->break_point_objects()->IsFixedArray());
15483   Handle<FixedArray> old_array =
15484       Handle<FixedArray>(
15485           FixedArray::cast(break_point_info->break_point_objects()));
15486   Handle<FixedArray> new_array =
15487       isolate->factory()->NewFixedArray(old_array->length() - 1);
15488   int found_count = 0;
15489   for (int i = 0; i < old_array->length(); i++) {
15490     if (old_array->get(i) == *break_point_object) {
15491       DCHECK(found_count == 0);
15492       found_count++;
15493     } else {
15494       new_array->set(i - found_count, old_array->get(i));
15495     }
15496   }
15497   // If the break point was found in the list change it.
15498   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
15499 }
15500
15501
15502 // Add the specified break point object.
15503 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
15504                                    Handle<Object> break_point_object) {
15505   Isolate* isolate = break_point_info->GetIsolate();
15506
15507   // If there was no break point objects before just set it.
15508   if (break_point_info->break_point_objects()->IsUndefined()) {
15509     break_point_info->set_break_point_objects(*break_point_object);
15510     return;
15511   }
15512   // If the break point object is the same as before just ignore.
15513   if (break_point_info->break_point_objects() == *break_point_object) return;
15514   // If there was one break point object before replace with array.
15515   if (!break_point_info->break_point_objects()->IsFixedArray()) {
15516     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
15517     array->set(0, break_point_info->break_point_objects());
15518     array->set(1, *break_point_object);
15519     break_point_info->set_break_point_objects(*array);
15520     return;
15521   }
15522   // If there was more than one break point before extend array.
15523   Handle<FixedArray> old_array =
15524       Handle<FixedArray>(
15525           FixedArray::cast(break_point_info->break_point_objects()));
15526   Handle<FixedArray> new_array =
15527       isolate->factory()->NewFixedArray(old_array->length() + 1);
15528   for (int i = 0; i < old_array->length(); i++) {
15529     // If the break point was there before just ignore.
15530     if (old_array->get(i) == *break_point_object) return;
15531     new_array->set(i, old_array->get(i));
15532   }
15533   // Add the new break point.
15534   new_array->set(old_array->length(), *break_point_object);
15535   break_point_info->set_break_point_objects(*new_array);
15536 }
15537
15538
15539 bool BreakPointInfo::HasBreakPointObject(
15540     Handle<BreakPointInfo> break_point_info,
15541     Handle<Object> break_point_object) {
15542   // No break point.
15543   if (break_point_info->break_point_objects()->IsUndefined()) return false;
15544   // Single break point.
15545   if (!break_point_info->break_point_objects()->IsFixedArray()) {
15546     return break_point_info->break_point_objects() == *break_point_object;
15547   }
15548   // Multiple break points.
15549   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
15550   for (int i = 0; i < array->length(); i++) {
15551     if (array->get(i) == *break_point_object) {
15552       return true;
15553     }
15554   }
15555   return false;
15556 }
15557
15558
15559 // Get the number of break points.
15560 int BreakPointInfo::GetBreakPointCount() {
15561   // No break point.
15562   if (break_point_objects()->IsUndefined()) return 0;
15563   // Single break point.
15564   if (!break_point_objects()->IsFixedArray()) return 1;
15565   // Multiple break points.
15566   return FixedArray::cast(break_point_objects())->length();
15567 }
15568
15569
15570 Object* JSDate::GetField(Object* object, Smi* index) {
15571   return JSDate::cast(object)->DoGetField(
15572       static_cast<FieldIndex>(index->value()));
15573 }
15574
15575
15576 Object* JSDate::DoGetField(FieldIndex index) {
15577   DCHECK(index != kDateValue);
15578
15579   DateCache* date_cache = GetIsolate()->date_cache();
15580
15581   if (index < kFirstUncachedField) {
15582     Object* stamp = cache_stamp();
15583     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
15584       // Since the stamp is not NaN, the value is also not NaN.
15585       int64_t local_time_ms =
15586           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
15587       SetCachedFields(local_time_ms, date_cache);
15588     }
15589     switch (index) {
15590       case kYear: return year();
15591       case kMonth: return month();
15592       case kDay: return day();
15593       case kWeekday: return weekday();
15594       case kHour: return hour();
15595       case kMinute: return min();
15596       case kSecond: return sec();
15597       default: UNREACHABLE();
15598     }
15599   }
15600
15601   if (index >= kFirstUTCField) {
15602     return GetUTCField(index, value()->Number(), date_cache);
15603   }
15604
15605   double time = value()->Number();
15606   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
15607
15608   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
15609   int days = DateCache::DaysFromTime(local_time_ms);
15610
15611   if (index == kDays) return Smi::FromInt(days);
15612
15613   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
15614   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
15615   DCHECK(index == kTimeInDay);
15616   return Smi::FromInt(time_in_day_ms);
15617 }
15618
15619
15620 Object* JSDate::GetUTCField(FieldIndex index,
15621                             double value,
15622                             DateCache* date_cache) {
15623   DCHECK(index >= kFirstUTCField);
15624
15625   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
15626
15627   int64_t time_ms = static_cast<int64_t>(value);
15628
15629   if (index == kTimezoneOffset) {
15630     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
15631   }
15632
15633   int days = DateCache::DaysFromTime(time_ms);
15634
15635   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
15636
15637   if (index <= kDayUTC) {
15638     int year, month, day;
15639     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
15640     if (index == kYearUTC) return Smi::FromInt(year);
15641     if (index == kMonthUTC) return Smi::FromInt(month);
15642     DCHECK(index == kDayUTC);
15643     return Smi::FromInt(day);
15644   }
15645
15646   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
15647   switch (index) {
15648     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
15649     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
15650     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
15651     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
15652     case kDaysUTC: return Smi::FromInt(days);
15653     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
15654     default: UNREACHABLE();
15655   }
15656
15657   UNREACHABLE();
15658   return NULL;
15659 }
15660
15661
15662 void JSDate::SetValue(Object* value, bool is_value_nan) {
15663   set_value(value);
15664   if (is_value_nan) {
15665     HeapNumber* nan = GetIsolate()->heap()->nan_value();
15666     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
15667     set_year(nan, SKIP_WRITE_BARRIER);
15668     set_month(nan, SKIP_WRITE_BARRIER);
15669     set_day(nan, SKIP_WRITE_BARRIER);
15670     set_hour(nan, SKIP_WRITE_BARRIER);
15671     set_min(nan, SKIP_WRITE_BARRIER);
15672     set_sec(nan, SKIP_WRITE_BARRIER);
15673     set_weekday(nan, SKIP_WRITE_BARRIER);
15674   } else {
15675     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
15676   }
15677 }
15678
15679
15680 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
15681   int days = DateCache::DaysFromTime(local_time_ms);
15682   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
15683   int year, month, day;
15684   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
15685   int weekday = date_cache->Weekday(days);
15686   int hour = time_in_day_ms / (60 * 60 * 1000);
15687   int min = (time_in_day_ms / (60 * 1000)) % 60;
15688   int sec = (time_in_day_ms / 1000) % 60;
15689   set_cache_stamp(date_cache->stamp());
15690   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
15691   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
15692   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
15693   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
15694   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
15695   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
15696   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
15697 }
15698
15699
15700 void JSArrayBuffer::Neuter() {
15701   CHECK(is_neuterable());
15702   CHECK(is_external());
15703   set_backing_store(NULL);
15704   set_byte_length(Smi::FromInt(0));
15705   set_was_neutered(true);
15706 }
15707
15708
15709 static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) {
15710   switch (elements_kind) {
15711 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
15712     case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
15713
15714     TYPED_ARRAYS(TYPED_ARRAY_CASE)
15715 #undef TYPED_ARRAY_CASE
15716
15717     default:
15718       UNREACHABLE();
15719       return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
15720   }
15721 }
15722
15723
15724 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
15725     Handle<JSTypedArray> typed_array) {
15726
15727   Handle<Map> map(typed_array->map());
15728   Isolate* isolate = typed_array->GetIsolate();
15729
15730   DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
15731
15732   Handle<Map> new_map = Map::TransitionElementsTo(
15733           map,
15734           FixedToExternalElementsKind(map->elements_kind()));
15735
15736   Handle<FixedTypedArrayBase> fixed_typed_array(
15737       FixedTypedArrayBase::cast(typed_array->elements()));
15738
15739   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
15740                                isolate);
15741   void* backing_store =
15742       isolate->array_buffer_allocator()->AllocateUninitialized(
15743           fixed_typed_array->DataSize());
15744   buffer->set_backing_store(backing_store);
15745   buffer->set_is_external(false);
15746   isolate->heap()->RegisterNewArrayBuffer(isolate->heap()->InNewSpace(*buffer),
15747                                           backing_store,
15748                                           fixed_typed_array->DataSize());
15749   memcpy(buffer->backing_store(),
15750          fixed_typed_array->DataPtr(),
15751          fixed_typed_array->DataSize());
15752   Handle<ExternalArray> new_elements =
15753       isolate->factory()->NewExternalArray(
15754           fixed_typed_array->length(), typed_array->type(),
15755           static_cast<uint8_t*>(buffer->backing_store()));
15756
15757   JSObject::SetMapAndElements(typed_array, new_map, new_elements);
15758
15759   return buffer;
15760 }
15761
15762
15763 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
15764   if (IsExternalArrayElementsKind(map()->elements_kind())) {
15765     Handle<Object> result(buffer(), GetIsolate());
15766     return Handle<JSArrayBuffer>::cast(result);
15767   }
15768   Handle<JSTypedArray> self(this);
15769   return MaterializeArrayBuffer(self);
15770 }
15771
15772
15773 Handle<PropertyCell> PropertyCell::InvalidateEntry(
15774     Handle<GlobalDictionary> dictionary, int entry) {
15775   Isolate* isolate = dictionary->GetIsolate();
15776   // Swap with a copy.
15777   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
15778   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
15779   auto new_cell = isolate->factory()->NewPropertyCell();
15780   new_cell->set_value(cell->value());
15781   dictionary->ValueAtPut(entry, *new_cell);
15782   bool is_the_hole = cell->value()->IsTheHole();
15783   // Cell is officially mutable henceforth.
15784   PropertyDetails details = cell->property_details();
15785   details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated
15786                                               : PropertyCellType::kMutable);
15787   new_cell->set_property_details(details);
15788   // Old cell is ready for invalidation.
15789   if (is_the_hole) {
15790     cell->set_value(isolate->heap()->undefined_value());
15791   } else {
15792     cell->set_value(isolate->heap()->the_hole_value());
15793   }
15794   cell->dependent_code()->DeoptimizeDependentCodeGroup(
15795       isolate, DependentCode::kPropertyCellChangedGroup);
15796   return new_cell;
15797 }
15798
15799
15800 PropertyCellConstantType PropertyCell::GetConstantType() {
15801   if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
15802   return PropertyCellConstantType::kStableMap;
15803 }
15804
15805
15806 static bool RemainsConstantType(Handle<PropertyCell> cell,
15807                                 Handle<Object> value) {
15808   // TODO(dcarney): double->smi and smi->double transition from kConstant
15809   if (cell->value()->IsSmi() && value->IsSmi()) {
15810     return true;
15811   } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
15812     return HeapObject::cast(cell->value())->map() ==
15813                HeapObject::cast(*value)->map() &&
15814            HeapObject::cast(*value)->map()->is_stable();
15815   }
15816   return false;
15817 }
15818
15819
15820 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell,
15821                                            Handle<Object> value,
15822                                            PropertyDetails details) {
15823   PropertyCellType type = details.cell_type();
15824   DCHECK(!value->IsTheHole());
15825   if (cell->value()->IsTheHole()) {
15826     switch (type) {
15827       // Only allow a cell to transition once into constant state.
15828       case PropertyCellType::kUninitialized:
15829         if (value->IsUndefined()) return PropertyCellType::kUndefined;
15830         return PropertyCellType::kConstant;
15831       case PropertyCellType::kInvalidated:
15832         return PropertyCellType::kMutable;
15833       default:
15834         UNREACHABLE();
15835         return PropertyCellType::kMutable;
15836     }
15837   }
15838   switch (type) {
15839     case PropertyCellType::kUndefined:
15840       return PropertyCellType::kConstant;
15841     case PropertyCellType::kConstant:
15842       if (*value == cell->value()) return PropertyCellType::kConstant;
15843     // Fall through.
15844     case PropertyCellType::kConstantType:
15845       if (RemainsConstantType(cell, value)) {
15846         return PropertyCellType::kConstantType;
15847       }
15848     // Fall through.
15849     case PropertyCellType::kMutable:
15850       return PropertyCellType::kMutable;
15851   }
15852   UNREACHABLE();
15853   return PropertyCellType::kMutable;
15854 }
15855
15856
15857 void PropertyCell::UpdateCell(Handle<GlobalDictionary> dictionary, int entry,
15858                               Handle<Object> value, PropertyDetails details) {
15859   DCHECK(!value->IsTheHole());
15860   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
15861   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
15862   const PropertyDetails original_details = cell->property_details();
15863   // Data accesses could be cached in ics or optimized code.
15864   bool invalidate =
15865       original_details.kind() == kData && details.kind() == kAccessor;
15866   int index = original_details.dictionary_index();
15867   PropertyCellType old_type = original_details.cell_type();
15868   // Preserve the enumeration index unless the property was deleted or never
15869   // initialized.
15870   if (cell->value()->IsTheHole()) {
15871     index = dictionary->NextEnumerationIndex();
15872     dictionary->SetNextEnumerationIndex(index + 1);
15873     // Negative lookup cells must be invalidated.
15874     invalidate = true;
15875   }
15876   DCHECK(index > 0);
15877   details = details.set_index(index);
15878
15879   PropertyCellType new_type = UpdatedType(cell, value, original_details);
15880   if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry);
15881
15882   // Install new property details and cell value.
15883   details = details.set_cell_type(new_type);
15884   cell->set_property_details(details);
15885   cell->set_value(*value);
15886
15887   // Deopt when transitioning from a constant type.
15888   if (!invalidate && (old_type != new_type)) {
15889     auto isolate = dictionary->GetIsolate();
15890     cell->dependent_code()->DeoptimizeDependentCodeGroup(
15891         isolate, DependentCode::kPropertyCellChangedGroup);
15892   }
15893 }
15894
15895
15896 // static
15897 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
15898                                             Handle<Object> new_value) {
15899   if (cell->value() != *new_value) {
15900     cell->set_value(*new_value);
15901     Isolate* isolate = cell->GetIsolate();
15902     cell->dependent_code()->DeoptimizeDependentCodeGroup(
15903         isolate, DependentCode::kPropertyCellChangedGroup);
15904   }
15905 }
15906 }  // namespace internal
15907 }  // namespace v8