Upstream version 10.38.220.0
[platform/framework/web/crosswalk.git] / src / v8 / src / objects.cc
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #include "src/accessors.h"
8 #include "src/allocation-site-scopes.h"
9 #include "src/api.h"
10 #include "src/arguments.h"
11 #include "src/bootstrapper.h"
12 #include "src/code-stubs.h"
13 #include "src/codegen.h"
14 #include "src/cpu-profiler.h"
15 #include "src/date.h"
16 #include "src/debug.h"
17 #include "src/deoptimizer.h"
18 #include "src/elements.h"
19 #include "src/execution.h"
20 #include "src/field-index-inl.h"
21 #include "src/field-index.h"
22 #include "src/full-codegen.h"
23 #include "src/heap/mark-compact.h"
24 #include "src/heap/objects-visiting-inl.h"
25 #include "src/hydrogen.h"
26 #include "src/isolate-inl.h"
27 #include "src/log.h"
28 #include "src/lookup.h"
29 #include "src/macro-assembler.h"
30 #include "src/objects-inl.h"
31 #include "src/prototype.h"
32 #include "src/safepoint-table.h"
33 #include "src/string-search.h"
34 #include "src/string-stream.h"
35 #include "src/utils.h"
36
37 #ifdef ENABLE_DISASSEMBLER
38 #include "src/disasm.h"
39 #include "src/disassembler.h"
40 #endif
41
42 namespace v8 {
43 namespace internal {
44
45 Handle<HeapType> Object::OptimalType(Isolate* isolate,
46                                      Representation representation) {
47   if (representation.IsNone()) return HeapType::None(isolate);
48   if (FLAG_track_field_types) {
49     if (representation.IsHeapObject() && IsHeapObject()) {
50       // We can track only JavaScript objects with stable maps.
51       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
52       if (map->is_stable() &&
53           map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
54           map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
55         return HeapType::Class(map, isolate);
56       }
57     }
58   }
59   return HeapType::Any(isolate);
60 }
61
62
63 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
64                                          Handle<Object> object,
65                                          Handle<Context> native_context) {
66   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
67   Handle<JSFunction> constructor;
68   if (object->IsNumber()) {
69     constructor = handle(native_context->number_function(), isolate);
70   } else if (object->IsBoolean()) {
71     constructor = handle(native_context->boolean_function(), isolate);
72   } else if (object->IsString()) {
73     constructor = handle(native_context->string_function(), isolate);
74   } else if (object->IsSymbol()) {
75     constructor = handle(native_context->symbol_function(), isolate);
76   } else {
77     return MaybeHandle<JSReceiver>();
78   }
79   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
80   Handle<JSValue>::cast(result)->set_value(*object);
81   return result;
82 }
83
84
85 bool Object::BooleanValue() {
86   if (IsBoolean()) return IsTrue();
87   if (IsSmi()) return Smi::cast(this)->value() != 0;
88   if (IsUndefined() || IsNull()) return false;
89   if (IsUndetectableObject()) return false;   // Undetectable object is false.
90   if (IsString()) return String::cast(this)->length() != 0;
91   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
92   return true;
93 }
94
95
96 bool Object::IsCallable() const {
97   const Object* fun = this;
98   while (fun->IsJSFunctionProxy()) {
99     fun = JSFunctionProxy::cast(fun)->call_trap();
100   }
101   return fun->IsJSFunction() ||
102          (fun->IsHeapObject() &&
103           HeapObject::cast(fun)->map()->has_instance_call_handler());
104 }
105
106
107 void Object::Lookup(Handle<Name> name, LookupResult* result) {
108   DisallowHeapAllocation no_gc;
109   Object* holder = NULL;
110   if (IsJSReceiver()) {
111     holder = this;
112   } else {
113     Context* native_context = result->isolate()->context()->native_context();
114     if (IsNumber()) {
115       holder = native_context->number_function()->instance_prototype();
116     } else if (IsString()) {
117       holder = native_context->string_function()->instance_prototype();
118     } else if (IsSymbol()) {
119       holder = native_context->symbol_function()->instance_prototype();
120     } else if (IsBoolean()) {
121       holder = native_context->boolean_function()->instance_prototype();
122     } else {
123       result->isolate()->PushStackTraceAndDie(
124           0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001);
125     }
126   }
127   DCHECK(holder != NULL);  // Cannot handle null or undefined.
128   JSReceiver::cast(holder)->Lookup(name, result);
129 }
130
131
132 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
133   for (; it->IsFound(); it->Next()) {
134     switch (it->state()) {
135       case LookupIterator::NOT_FOUND:
136         UNREACHABLE();
137       case LookupIterator::JSPROXY:
138         return JSProxy::GetPropertyWithHandler(it->GetHolder<JSProxy>(),
139                                                it->GetReceiver(), it->name());
140       case LookupIterator::INTERCEPTOR: {
141         MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithInterceptor(
142             it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
143         if (!maybe_result.is_null()) return maybe_result;
144         if (it->isolate()->has_pending_exception()) return maybe_result;
145         break;
146       }
147       case LookupIterator::ACCESS_CHECK:
148         if (it->HasAccess(v8::ACCESS_GET)) break;
149         return JSObject::GetPropertyWithFailedAccessCheck(it);
150       case LookupIterator::PROPERTY:
151         if (it->HasProperty()) {
152           switch (it->property_kind()) {
153             case LookupIterator::ACCESSOR:
154               return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
155                                              it->GetHolder<JSObject>(),
156                                              it->GetAccessors());
157             case LookupIterator::DATA:
158               return it->GetDataValue();
159           }
160         }
161         break;
162     }
163   }
164   return it->factory()->undefined_value();
165 }
166
167
168 bool Object::ToInt32(int32_t* value) {
169   if (IsSmi()) {
170     *value = Smi::cast(this)->value();
171     return true;
172   }
173   if (IsHeapNumber()) {
174     double num = HeapNumber::cast(this)->value();
175     if (FastI2D(FastD2I(num)) == num) {
176       *value = FastD2I(num);
177       return true;
178     }
179   }
180   return false;
181 }
182
183
184 bool Object::ToUint32(uint32_t* value) {
185   if (IsSmi()) {
186     int num = Smi::cast(this)->value();
187     if (num >= 0) {
188       *value = static_cast<uint32_t>(num);
189       return true;
190     }
191   }
192   if (IsHeapNumber()) {
193     double num = HeapNumber::cast(this)->value();
194     if (num >= 0 && FastUI2D(FastD2UI(num)) == num) {
195       *value = FastD2UI(num);
196       return true;
197     }
198   }
199   return false;
200 }
201
202
203 bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
204   if (!object->IsHeapObject()) return false;
205   return IsTemplateFor(HeapObject::cast(object)->map());
206 }
207
208
209 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
210   // There is a constraint on the object; check.
211   if (!map->IsJSObjectMap()) return false;
212   // Fetch the constructor function of the object.
213   Object* cons_obj = map->constructor();
214   if (!cons_obj->IsJSFunction()) return false;
215   JSFunction* fun = JSFunction::cast(cons_obj);
216   // Iterate through the chain of inheriting function templates to
217   // see if the required one occurs.
218   for (Object* type = fun->shared()->function_data();
219        type->IsFunctionTemplateInfo();
220        type = FunctionTemplateInfo::cast(type)->parent_template()) {
221     if (type == this) return true;
222   }
223   // Didn't find the required type in the inheritance chain.
224   return false;
225 }
226
227
228 template<typename To>
229 static inline To* CheckedCast(void *from) {
230   uintptr_t temp = reinterpret_cast<uintptr_t>(from);
231   DCHECK(temp % sizeof(To) == 0);
232   return reinterpret_cast<To*>(temp);
233 }
234
235
236 static Handle<Object> PerformCompare(const BitmaskCompareDescriptor& descriptor,
237                                      char* ptr,
238                                      Isolate* isolate) {
239   uint32_t bitmask = descriptor.bitmask;
240   uint32_t compare_value = descriptor.compare_value;
241   uint32_t value;
242   switch (descriptor.size) {
243     case 1:
244       value = static_cast<uint32_t>(*CheckedCast<uint8_t>(ptr));
245       compare_value &= 0xff;
246       bitmask &= 0xff;
247       break;
248     case 2:
249       value = static_cast<uint32_t>(*CheckedCast<uint16_t>(ptr));
250       compare_value &= 0xffff;
251       bitmask &= 0xffff;
252       break;
253     case 4:
254       value = *CheckedCast<uint32_t>(ptr);
255       break;
256     default:
257       UNREACHABLE();
258       return isolate->factory()->undefined_value();
259   }
260   return isolate->factory()->ToBoolean(
261       (bitmask & value) == (bitmask & compare_value));
262 }
263
264
265 static Handle<Object> PerformCompare(const PointerCompareDescriptor& descriptor,
266                                      char* ptr,
267                                      Isolate* isolate) {
268   uintptr_t compare_value =
269       reinterpret_cast<uintptr_t>(descriptor.compare_value);
270   uintptr_t value = *CheckedCast<uintptr_t>(ptr);
271   return isolate->factory()->ToBoolean(compare_value == value);
272 }
273
274
275 static Handle<Object> GetPrimitiveValue(
276     const PrimitiveValueDescriptor& descriptor,
277     char* ptr,
278     Isolate* isolate) {
279   int32_t int32_value = 0;
280   switch (descriptor.data_type) {
281     case kDescriptorInt8Type:
282       int32_value = *CheckedCast<int8_t>(ptr);
283       break;
284     case kDescriptorUint8Type:
285       int32_value = *CheckedCast<uint8_t>(ptr);
286       break;
287     case kDescriptorInt16Type:
288       int32_value = *CheckedCast<int16_t>(ptr);
289       break;
290     case kDescriptorUint16Type:
291       int32_value = *CheckedCast<uint16_t>(ptr);
292       break;
293     case kDescriptorInt32Type:
294       int32_value = *CheckedCast<int32_t>(ptr);
295       break;
296     case kDescriptorUint32Type: {
297       uint32_t value = *CheckedCast<uint32_t>(ptr);
298       AllowHeapAllocation allow_gc;
299       return isolate->factory()->NewNumberFromUint(value);
300     }
301     case kDescriptorBoolType: {
302       uint8_t byte = *CheckedCast<uint8_t>(ptr);
303       return isolate->factory()->ToBoolean(
304           byte & (0x1 << descriptor.bool_offset));
305     }
306     case kDescriptorFloatType: {
307       float value = *CheckedCast<float>(ptr);
308       AllowHeapAllocation allow_gc;
309       return isolate->factory()->NewNumber(value);
310     }
311     case kDescriptorDoubleType: {
312       double value = *CheckedCast<double>(ptr);
313       AllowHeapAllocation allow_gc;
314       return isolate->factory()->NewNumber(value);
315     }
316   }
317   AllowHeapAllocation allow_gc;
318   return isolate->factory()->NewNumberFromInt(int32_value);
319 }
320
321
322 static Handle<Object> GetDeclaredAccessorProperty(
323     Handle<Object> receiver,
324     Handle<DeclaredAccessorInfo> info,
325     Isolate* isolate) {
326   DisallowHeapAllocation no_gc;
327   char* current = reinterpret_cast<char*>(*receiver);
328   DeclaredAccessorDescriptorIterator iterator(info->descriptor());
329   while (true) {
330     const DeclaredAccessorDescriptorData* data = iterator.Next();
331     switch (data->type) {
332       case kDescriptorReturnObject: {
333         DCHECK(iterator.Complete());
334         current = *CheckedCast<char*>(current);
335         return handle(*CheckedCast<Object*>(current), isolate);
336       }
337       case kDescriptorPointerDereference:
338         DCHECK(!iterator.Complete());
339         current = *reinterpret_cast<char**>(current);
340         break;
341       case kDescriptorPointerShift:
342         DCHECK(!iterator.Complete());
343         current += data->pointer_shift_descriptor.byte_offset;
344         break;
345       case kDescriptorObjectDereference: {
346         DCHECK(!iterator.Complete());
347         Object* object = CheckedCast<Object>(current);
348         int field = data->object_dereference_descriptor.internal_field;
349         Object* smi = JSObject::cast(object)->GetInternalField(field);
350         DCHECK(smi->IsSmi());
351         current = reinterpret_cast<char*>(smi);
352         break;
353       }
354       case kDescriptorBitmaskCompare:
355         DCHECK(iterator.Complete());
356         return PerformCompare(data->bitmask_compare_descriptor,
357                               current,
358                               isolate);
359       case kDescriptorPointerCompare:
360         DCHECK(iterator.Complete());
361         return PerformCompare(data->pointer_compare_descriptor,
362                               current,
363                               isolate);
364       case kDescriptorPrimitiveValue:
365         DCHECK(iterator.Complete());
366         return GetPrimitiveValue(data->primitive_value_descriptor,
367                                  current,
368                                  isolate);
369     }
370   }
371   UNREACHABLE();
372   return isolate->factory()->undefined_value();
373 }
374
375
376 Handle<FixedArray> JSObject::EnsureWritableFastElements(
377     Handle<JSObject> object) {
378   DCHECK(object->HasFastSmiOrObjectElements());
379   Isolate* isolate = object->GetIsolate();
380   Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
381   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
382   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
383       elems, isolate->factory()->fixed_array_map());
384   object->set_elements(*writable_elems);
385   isolate->counters()->cow_arrays_converted()->Increment();
386   return writable_elems;
387 }
388
389
390 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
391                                                     Handle<Object> receiver,
392                                                     Handle<Name> name) {
393   Isolate* isolate = proxy->GetIsolate();
394
395   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
396   if (name->IsSymbol()) return isolate->factory()->undefined_value();
397
398   Handle<Object> args[] = { receiver, name };
399   return CallTrap(
400       proxy, "get",  isolate->derived_get_trap(), ARRAY_SIZE(args), args);
401 }
402
403
404 MaybeHandle<Object> Object::GetPropertyWithAccessor(Handle<Object> receiver,
405                                                     Handle<Name> name,
406                                                     Handle<JSObject> holder,
407                                                     Handle<Object> structure) {
408   Isolate* isolate = name->GetIsolate();
409   DCHECK(!structure->IsForeign());
410   // api style callbacks.
411   if (structure->IsAccessorInfo()) {
412     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
413     if (!info->IsCompatibleReceiver(*receiver)) {
414       Handle<Object> args[2] = { name, receiver };
415       Handle<Object> error =
416           isolate->factory()->NewTypeError("incompatible_method_receiver",
417                                            HandleVector(args,
418                                                         ARRAY_SIZE(args)));
419       return isolate->Throw<Object>(error);
420     }
421     // TODO(rossberg): Handling symbols in the API requires changing the API,
422     // so we do not support it for now.
423     if (name->IsSymbol()) return isolate->factory()->undefined_value();
424     if (structure->IsDeclaredAccessorInfo()) {
425       return GetDeclaredAccessorProperty(
426           receiver,
427           Handle<DeclaredAccessorInfo>::cast(structure),
428           isolate);
429     }
430
431     Handle<ExecutableAccessorInfo> data =
432         Handle<ExecutableAccessorInfo>::cast(structure);
433     v8::AccessorGetterCallback call_fun =
434         v8::ToCData<v8::AccessorGetterCallback>(data->getter());
435     if (call_fun == NULL) return isolate->factory()->undefined_value();
436
437     Handle<String> key = Handle<String>::cast(name);
438     LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
439     PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
440     v8::Handle<v8::Value> result =
441         args.Call(call_fun, v8::Utils::ToLocal(key));
442     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
443     if (result.IsEmpty()) {
444       return isolate->factory()->undefined_value();
445     }
446     Handle<Object> return_value = v8::Utils::OpenHandle(*result);
447     return_value->VerifyApiCallResultType();
448     // Rebox handle before return.
449     return handle(*return_value, isolate);
450   }
451
452   // __defineGetter__ callback
453   Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
454                         isolate);
455   if (getter->IsSpecFunction()) {
456     // TODO(rossberg): nicer would be to cast to some JSCallable here...
457     return Object::GetPropertyWithDefinedGetter(
458         receiver, Handle<JSReceiver>::cast(getter));
459   }
460   // Getter is not a function.
461   return isolate->factory()->undefined_value();
462 }
463
464
465 bool AccessorInfo::IsCompatibleReceiverType(Isolate* isolate,
466                                             Handle<AccessorInfo> info,
467                                             Handle<HeapType> type) {
468   if (!info->HasExpectedReceiverType()) return true;
469   Handle<Map> map = IC::TypeToMap(*type, isolate);
470   if (!map->IsJSObjectMap()) return false;
471   return FunctionTemplateInfo::cast(info->expected_receiver_type())
472       ->IsTemplateFor(*map);
473 }
474
475
476 MaybeHandle<Object> Object::SetPropertyWithAccessor(
477     Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
478     Handle<JSObject> holder, Handle<Object> structure, StrictMode strict_mode) {
479   Isolate* isolate = name->GetIsolate();
480
481   // We should never get here to initialize a const with the hole
482   // value since a const declaration would conflict with the setter.
483   DCHECK(!structure->IsForeign());
484   if (structure->IsExecutableAccessorInfo()) {
485     // Don't call executable accessor setters with non-JSObject receivers.
486     if (!receiver->IsJSObject()) return value;
487     // api style callbacks
488     ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure);
489     if (!info->IsCompatibleReceiver(*receiver)) {
490       Handle<Object> args[2] = { name, receiver };
491       Handle<Object> error =
492           isolate->factory()->NewTypeError("incompatible_method_receiver",
493                                            HandleVector(args,
494                                                         ARRAY_SIZE(args)));
495       return isolate->Throw<Object>(error);
496     }
497     // TODO(rossberg): Support symbols in the API.
498     if (name->IsSymbol()) return value;
499     Object* call_obj = info->setter();
500     v8::AccessorSetterCallback call_fun =
501         v8::ToCData<v8::AccessorSetterCallback>(call_obj);
502     if (call_fun == NULL) return value;
503     Handle<String> key = Handle<String>::cast(name);
504     LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
505     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
506     args.Call(call_fun,
507               v8::Utils::ToLocal(key),
508               v8::Utils::ToLocal(value));
509     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
510     return value;
511   }
512
513   if (structure->IsAccessorPair()) {
514     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
515     if (setter->IsSpecFunction()) {
516       // TODO(rossberg): nicer would be to cast to some JSCallable here...
517       return SetPropertyWithDefinedSetter(
518           receiver, Handle<JSReceiver>::cast(setter), value);
519     } else {
520       if (strict_mode == SLOPPY) return value;
521       Handle<Object> args[2] = { name, holder };
522       Handle<Object> error =
523           isolate->factory()->NewTypeError("no_setter_in_callback",
524                                            HandleVector(args, 2));
525       return isolate->Throw<Object>(error);
526     }
527   }
528
529   // TODO(dcarney): Handle correctly.
530   if (structure->IsDeclaredAccessorInfo()) {
531     return value;
532   }
533
534   UNREACHABLE();
535   return MaybeHandle<Object>();
536 }
537
538
539 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
540     Handle<Object> receiver,
541     Handle<JSReceiver> getter) {
542   Isolate* isolate = getter->GetIsolate();
543   Debug* debug = isolate->debug();
544   // Handle stepping into a getter if step into is active.
545   // TODO(rossberg): should this apply to getters that are function proxies?
546   if (debug->StepInActive() && getter->IsJSFunction()) {
547     debug->HandleStepIn(
548         Handle<JSFunction>::cast(getter), Handle<Object>::null(), 0, false);
549   }
550
551   return Execution::Call(isolate, getter, receiver, 0, NULL, true);
552 }
553
554
555 MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
556     Handle<Object> receiver,
557     Handle<JSReceiver> setter,
558     Handle<Object> value) {
559   Isolate* isolate = setter->GetIsolate();
560
561   Debug* debug = isolate->debug();
562   // Handle stepping into a setter if step into is active.
563   // TODO(rossberg): should this apply to getters that are function proxies?
564   if (debug->StepInActive() && setter->IsJSFunction()) {
565     debug->HandleStepIn(
566         Handle<JSFunction>::cast(setter), Handle<Object>::null(), 0, false);
567   }
568
569   Handle<Object> argv[] = { value };
570   RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver,
571                                                ARRAY_SIZE(argv), argv, true),
572                       Object);
573   return value;
574 }
575
576
577 static bool FindAllCanReadHolder(LookupIterator* it) {
578   it->skip_interceptor();
579   it->skip_access_check();
580   for (; it->IsFound(); it->Next()) {
581     if (it->state() == LookupIterator::PROPERTY &&
582         it->HasProperty() &&
583         it->property_kind() == LookupIterator::ACCESSOR) {
584       Handle<Object> accessors = it->GetAccessors();
585       if (accessors->IsAccessorInfo()) {
586         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
587       }
588     }
589   }
590   return false;
591 }
592
593
594 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
595     LookupIterator* it) {
596   Handle<JSObject> checked = it->GetHolder<JSObject>();
597   if (FindAllCanReadHolder(it)) {
598     return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
599                                    it->GetHolder<JSObject>(),
600                                    it->GetAccessors());
601   }
602   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET);
603   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
604   return it->factory()->undefined_value();
605 }
606
607
608 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
609     LookupIterator* it) {
610   Handle<JSObject> checked = it->GetHolder<JSObject>();
611   if (FindAllCanReadHolder(it))
612     return maybe(it->property_details().attributes());
613   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
614   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
615                                       Maybe<PropertyAttributes>());
616   return maybe(ABSENT);
617 }
618
619
620 static bool FindAllCanWriteHolder(LookupIterator* it) {
621   it->skip_interceptor();
622   it->skip_access_check();
623   for (; it->IsFound(); it->Next()) {
624     if (it->state() == LookupIterator::PROPERTY && it->HasProperty() &&
625         it->property_kind() == LookupIterator::ACCESSOR) {
626       Handle<Object> accessors = it->GetAccessors();
627       if (accessors->IsAccessorInfo()) {
628         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
629       }
630     }
631   }
632   return false;
633 }
634
635
636 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
637     LookupIterator* it, Handle<Object> value, StrictMode strict_mode) {
638   Handle<JSObject> checked = it->GetHolder<JSObject>();
639   if (FindAllCanWriteHolder(it)) {
640     return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
641                                    it->GetHolder<JSObject>(),
642                                    it->GetAccessors(), strict_mode);
643   }
644
645   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_SET);
646   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
647   return value;
648 }
649
650
651 Object* JSObject::GetNormalizedProperty(const LookupResult* result) {
652   DCHECK(!HasFastProperties());
653   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
654   if (IsGlobalObject()) {
655     value = PropertyCell::cast(value)->value();
656   }
657   DCHECK(!value->IsPropertyCell() && !value->IsCell());
658   return value;
659 }
660
661
662 Handle<Object> JSObject::GetNormalizedProperty(Handle<JSObject> object,
663                                                const LookupResult* result) {
664   DCHECK(!object->HasFastProperties());
665   Isolate* isolate = object->GetIsolate();
666   Handle<Object> value(object->property_dictionary()->ValueAt(
667       result->GetDictionaryEntry()), isolate);
668   if (object->IsGlobalObject()) {
669     value = handle(Handle<PropertyCell>::cast(value)->value(), isolate);
670     DCHECK(!value->IsTheHole());
671   }
672   DCHECK(!value->IsPropertyCell() && !value->IsCell());
673   return value;
674 }
675
676
677 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
678                                      const LookupResult* result,
679                                      Handle<Object> value) {
680   DCHECK(!object->HasFastProperties());
681   NameDictionary* property_dictionary = object->property_dictionary();
682   if (object->IsGlobalObject()) {
683     Handle<PropertyCell> cell(PropertyCell::cast(
684         property_dictionary->ValueAt(result->GetDictionaryEntry())));
685     PropertyCell::SetValueInferType(cell, value);
686   } else {
687     property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value);
688   }
689 }
690
691
692 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
693                                      Handle<Name> name,
694                                      Handle<Object> value,
695                                      PropertyDetails details) {
696   CHECK(!object->HasFastProperties());
697   Handle<NameDictionary> property_dictionary(object->property_dictionary());
698
699   if (!name->IsUniqueName()) {
700     name = object->GetIsolate()->factory()->InternalizeString(
701         Handle<String>::cast(name));
702   }
703
704   int entry = property_dictionary->FindEntry(name);
705   if (entry == NameDictionary::kNotFound) {
706     Handle<Object> store_value = value;
707     if (object->IsGlobalObject()) {
708       store_value = object->GetIsolate()->factory()->NewPropertyCell(value);
709     }
710
711     property_dictionary = NameDictionary::Add(
712         property_dictionary, name, store_value, details);
713     object->set_properties(*property_dictionary);
714     return;
715   }
716
717   PropertyDetails original_details = property_dictionary->DetailsAt(entry);
718   int enumeration_index;
719   // Preserve the enumeration index unless the property was deleted.
720   if (original_details.IsDeleted()) {
721     enumeration_index = property_dictionary->NextEnumerationIndex();
722     property_dictionary->SetNextEnumerationIndex(enumeration_index + 1);
723   } else {
724     enumeration_index = original_details.dictionary_index();
725     DCHECK(enumeration_index > 0);
726   }
727
728   details = PropertyDetails(
729       details.attributes(), details.type(), enumeration_index);
730
731   if (object->IsGlobalObject()) {
732     Handle<PropertyCell> cell(
733         PropertyCell::cast(property_dictionary->ValueAt(entry)));
734     PropertyCell::SetValueInferType(cell, value);
735     // Please note we have to update the property details.
736     property_dictionary->DetailsAtPut(entry, details);
737   } else {
738     property_dictionary->SetEntry(entry, name, value, details);
739   }
740 }
741
742
743 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
744                                                   Handle<Name> name,
745                                                   DeleteMode mode) {
746   DCHECK(!object->HasFastProperties());
747   Isolate* isolate = object->GetIsolate();
748   Handle<NameDictionary> dictionary(object->property_dictionary());
749   int entry = dictionary->FindEntry(name);
750   if (entry != NameDictionary::kNotFound) {
751     // If we have a global object set the cell to the hole.
752     if (object->IsGlobalObject()) {
753       PropertyDetails details = dictionary->DetailsAt(entry);
754       if (details.IsDontDelete()) {
755         if (mode != FORCE_DELETION) return isolate->factory()->false_value();
756         // When forced to delete global properties, we have to make a
757         // map change to invalidate any ICs that think they can load
758         // from the DontDelete cell without checking if it contains
759         // the hole value.
760         Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
761         DCHECK(new_map->is_dictionary_map());
762         JSObject::MigrateToMap(object, new_map);
763       }
764       Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
765       Handle<Object> value = isolate->factory()->the_hole_value();
766       PropertyCell::SetValueInferType(cell, value);
767       dictionary->DetailsAtPut(entry, details.AsDeleted());
768     } else {
769       Handle<Object> deleted(
770           NameDictionary::DeleteProperty(dictionary, entry, mode));
771       if (*deleted == isolate->heap()->true_value()) {
772         Handle<NameDictionary> new_properties =
773             NameDictionary::Shrink(dictionary, name);
774         object->set_properties(*new_properties);
775       }
776       return deleted;
777     }
778   }
779   return isolate->factory()->true_value();
780 }
781
782
783 bool JSObject::IsDirty() {
784   Object* cons_obj = map()->constructor();
785   if (!cons_obj->IsJSFunction())
786     return true;
787   JSFunction* fun = JSFunction::cast(cons_obj);
788   if (!fun->shared()->IsApiFunction())
789     return true;
790   // If the object is fully fast case and has the same map it was
791   // created with then no changes can have been made to it.
792   return map() != fun->initial_map()
793       || !HasFastObjectElements()
794       || !HasFastProperties();
795 }
796
797
798 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
799                                                    Handle<Object> object,
800                                                    Handle<Object> receiver,
801                                                    uint32_t index) {
802   if (object->IsUndefined()) {
803     // TODO(verwaest): Why is this check here?
804     UNREACHABLE();
805     return isolate->factory()->undefined_value();
806   }
807
808   // Iterate up the prototype chain until an element is found or the null
809   // prototype is encountered.
810   for (PrototypeIterator iter(isolate, object,
811                               object->IsJSProxy() || object->IsJSObject()
812                                   ? PrototypeIterator::START_AT_RECEIVER
813                                   : PrototypeIterator::START_AT_PROTOTYPE);
814        !iter.IsAtEnd(); iter.Advance()) {
815     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
816       return JSProxy::GetElementWithHandler(
817           Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
818           index);
819     }
820
821     // Inline the case for JSObjects. Doing so significantly improves the
822     // performance of fetching elements where checking the prototype chain is
823     // necessary.
824     Handle<JSObject> js_object =
825         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
826
827     // Check access rights if needed.
828     if (js_object->IsAccessCheckNeeded()) {
829       if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
830         isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
831         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
832         return isolate->factory()->undefined_value();
833       }
834     }
835
836     if (js_object->HasIndexedInterceptor()) {
837       return JSObject::GetElementWithInterceptor(js_object, receiver, index);
838     }
839
840     if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
841       Handle<Object> result;
842       ASSIGN_RETURN_ON_EXCEPTION(
843           isolate, result,
844           js_object->GetElementsAccessor()->Get(receiver, js_object, index),
845           Object);
846       if (!result->IsTheHole()) return result;
847     }
848   }
849
850   return isolate->factory()->undefined_value();
851 }
852
853
854 Map* Object::GetRootMap(Isolate* isolate) {
855   DisallowHeapAllocation no_alloc;
856   if (IsSmi()) {
857     Context* context = isolate->context()->native_context();
858     return context->number_function()->initial_map();
859   }
860
861   HeapObject* heap_object = HeapObject::cast(this);
862
863   // The object is either a number, a string, a boolean,
864   // a real JS object, or a Harmony proxy.
865   if (heap_object->IsJSReceiver()) {
866     return heap_object->map();
867   }
868   Context* context = isolate->context()->native_context();
869
870   if (heap_object->IsHeapNumber()) {
871     return context->number_function()->initial_map();
872   }
873   if (heap_object->IsString()) {
874     return context->string_function()->initial_map();
875   }
876   if (heap_object->IsSymbol()) {
877     return context->symbol_function()->initial_map();
878   }
879   if (heap_object->IsBoolean()) {
880     return context->boolean_function()->initial_map();
881   }
882   return isolate->heap()->null_value()->map();
883 }
884
885
886 Object* Object::GetHash() {
887   // The object is either a number, a name, an odd-ball,
888   // a real JS object, or a Harmony proxy.
889   if (IsNumber()) {
890     uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
891     return Smi::FromInt(hash & Smi::kMaxValue);
892   }
893   if (IsName()) {
894     uint32_t hash = Name::cast(this)->Hash();
895     return Smi::FromInt(hash);
896   }
897   if (IsOddball()) {
898     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
899     return Smi::FromInt(hash);
900   }
901
902   DCHECK(IsJSReceiver());
903   return JSReceiver::cast(this)->GetIdentityHash();
904 }
905
906
907 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
908   Handle<Object> hash(object->GetHash(), isolate);
909   if (hash->IsSmi()) return Handle<Smi>::cast(hash);
910
911   DCHECK(object->IsJSReceiver());
912   return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
913 }
914
915
916 bool Object::SameValue(Object* other) {
917   if (other == this) return true;
918
919   // The object is either a number, a name, an odd-ball,
920   // a real JS object, or a Harmony proxy.
921   if (IsNumber() && other->IsNumber()) {
922     double this_value = Number();
923     double other_value = other->Number();
924     bool equal = this_value == other_value;
925     // SameValue(NaN, NaN) is true.
926     if (!equal) return std::isnan(this_value) && std::isnan(other_value);
927     // SameValue(0.0, -0.0) is false.
928     return (this_value != 0) || ((1 / this_value) == (1 / other_value));
929   }
930   if (IsString() && other->IsString()) {
931     return String::cast(this)->Equals(String::cast(other));
932   }
933   return false;
934 }
935
936
937 bool Object::SameValueZero(Object* other) {
938   if (other == this) return true;
939
940   // The object is either a number, a name, an odd-ball,
941   // a real JS object, or a Harmony proxy.
942   if (IsNumber() && other->IsNumber()) {
943     double this_value = Number();
944     double other_value = other->Number();
945     // +0 == -0 is true
946     return this_value == other_value
947         || (std::isnan(this_value) && std::isnan(other_value));
948   }
949   if (IsString() && other->IsString()) {
950     return String::cast(this)->Equals(String::cast(other));
951   }
952   return false;
953 }
954
955
956 void Object::ShortPrint(FILE* out) {
957   OFStream os(out);
958   os << Brief(this);
959 }
960
961
962 void Object::ShortPrint(StringStream* accumulator) {
963   OStringStream os;
964   os << Brief(this);
965   accumulator->Add(os.c_str());
966 }
967
968
969 OStream& operator<<(OStream& os, const Brief& v) {
970   if (v.value->IsSmi()) {
971     Smi::cast(v.value)->SmiPrint(os);
972   } else {
973     // TODO(svenpanne) Const-correct HeapObjectShortPrint!
974     HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
975     obj->HeapObjectShortPrint(os);
976   }
977   return os;
978 }
979
980
981 void Smi::SmiPrint(OStream& os) const {  // NOLINT
982   os << value();
983 }
984
985
986 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
987 // English?  Returns false for non-ASCII or words that don't start with
988 // a capital letter.  The a/an rule follows pronunciation in English.
989 // We don't use the BBC's overcorrect "an historic occasion" though if
990 // you speak a dialect you may well say "an 'istoric occasion".
991 static bool AnWord(String* str) {
992   if (str->length() == 0) return false;  // A nothing.
993   int c0 = str->Get(0);
994   int c1 = str->length() > 1 ? str->Get(1) : 0;
995   if (c0 == 'U') {
996     if (c1 > 'Z') {
997       return true;  // An Umpire, but a UTF8String, a U.
998     }
999   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
1000     return true;    // An Ape, an ABCBook.
1001   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
1002            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
1003             c0 == 'S' || c0 == 'X')) {
1004     return true;    // An MP3File, an M.
1005   }
1006   return false;
1007 }
1008
1009
1010 Handle<String> String::SlowFlatten(Handle<ConsString> cons,
1011                                    PretenureFlag pretenure) {
1012   DCHECK(AllowHeapAllocation::IsAllowed());
1013   DCHECK(cons->second()->length() != 0);
1014   Isolate* isolate = cons->GetIsolate();
1015   int length = cons->length();
1016   PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
1017                                                             : TENURED;
1018   Handle<SeqString> result;
1019   if (cons->IsOneByteRepresentation()) {
1020     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
1021         length, tenure).ToHandleChecked();
1022     DisallowHeapAllocation no_gc;
1023     WriteToFlat(*cons, flat->GetChars(), 0, length);
1024     result = flat;
1025   } else {
1026     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
1027         length, tenure).ToHandleChecked();
1028     DisallowHeapAllocation no_gc;
1029     WriteToFlat(*cons, flat->GetChars(), 0, length);
1030     result = flat;
1031   }
1032   cons->set_first(*result);
1033   cons->set_second(isolate->heap()->empty_string());
1034   DCHECK(result->IsFlat());
1035   return result;
1036 }
1037
1038
1039
1040 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
1041   // Externalizing twice leaks the external resource, so it's
1042   // prohibited by the API.
1043   DCHECK(!this->IsExternalString());
1044 #ifdef ENABLE_SLOW_DCHECKS
1045   if (FLAG_enable_slow_asserts) {
1046     // Assert that the resource and the string are equivalent.
1047     DCHECK(static_cast<size_t>(this->length()) == resource->length());
1048     ScopedVector<uc16> smart_chars(this->length());
1049     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1050     DCHECK(memcmp(smart_chars.start(),
1051                   resource->data(),
1052                   resource->length() * sizeof(smart_chars[0])) == 0);
1053   }
1054 #endif  // DEBUG
1055   int size = this->Size();  // Byte size of the original string.
1056   // Abort if size does not allow in-place conversion.
1057   if (size < ExternalString::kShortSize) return false;
1058   Heap* heap = GetHeap();
1059   bool is_ascii = this->IsOneByteRepresentation();
1060   bool is_internalized = this->IsInternalizedString();
1061
1062   // Morph the string to an external string by replacing the map and
1063   // reinitializing the fields.  This won't work if
1064   // - the space the existing string occupies is too small for a regular
1065   //   external string.
1066   // - the existing string is in old pointer space and the backing store of
1067   //   the external string is not aligned.  The GC cannot deal with a field
1068   //   containing a possibly unaligned address to outside of V8's heap.
1069   // In either case we resort to a short external string instead, omitting
1070   // the field caching the address of the backing store.  When we encounter
1071   // short external strings in generated code, we need to bailout to runtime.
1072   Map* new_map;
1073   if (size < ExternalString::kSize ||
1074       heap->old_pointer_space()->Contains(this)) {
1075     new_map = is_internalized
1076         ? (is_ascii
1077             ? heap->
1078                 short_external_internalized_string_with_one_byte_data_map()
1079             : heap->short_external_internalized_string_map())
1080         : (is_ascii
1081             ? heap->short_external_string_with_one_byte_data_map()
1082             : heap->short_external_string_map());
1083   } else {
1084     new_map = is_internalized
1085         ? (is_ascii
1086             ? heap->external_internalized_string_with_one_byte_data_map()
1087             : heap->external_internalized_string_map())
1088         : (is_ascii
1089             ? heap->external_string_with_one_byte_data_map()
1090             : heap->external_string_map());
1091   }
1092
1093   // Byte size of the external String object.
1094   int new_size = this->SizeFromMap(new_map);
1095   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1096
1097   // We are storing the new map using release store after creating a filler for
1098   // the left-over space to avoid races with the sweeper thread.
1099   this->synchronized_set_map(new_map);
1100
1101   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
1102   self->set_resource(resource);
1103   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1104
1105   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1106   return true;
1107 }
1108
1109
1110 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
1111   // Externalizing twice leaks the external resource, so it's
1112   // prohibited by the API.
1113   DCHECK(!this->IsExternalString());
1114 #ifdef ENABLE_SLOW_DCHECKS
1115   if (FLAG_enable_slow_asserts) {
1116     // Assert that the resource and the string are equivalent.
1117     DCHECK(static_cast<size_t>(this->length()) == resource->length());
1118     if (this->IsTwoByteRepresentation()) {
1119       ScopedVector<uint16_t> smart_chars(this->length());
1120       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1121       DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
1122     }
1123     ScopedVector<char> smart_chars(this->length());
1124     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1125     DCHECK(memcmp(smart_chars.start(),
1126                   resource->data(),
1127                   resource->length() * sizeof(smart_chars[0])) == 0);
1128   }
1129 #endif  // DEBUG
1130   int size = this->Size();  // Byte size of the original string.
1131   // Abort if size does not allow in-place conversion.
1132   if (size < ExternalString::kShortSize) return false;
1133   Heap* heap = GetHeap();
1134   bool is_internalized = this->IsInternalizedString();
1135
1136   // Morph the string to an external string by replacing the map and
1137   // reinitializing the fields.  This won't work if
1138   // - the space the existing string occupies is too small for a regular
1139   //   external string.
1140   // - the existing string is in old pointer space and the backing store of
1141   //   the external string is not aligned.  The GC cannot deal with a field
1142   //   containing a possibly unaligned address to outside of V8's heap.
1143   // In either case we resort to a short external string instead, omitting
1144   // the field caching the address of the backing store.  When we encounter
1145   // short external strings in generated code, we need to bailout to runtime.
1146   Map* new_map;
1147   if (size < ExternalString::kSize ||
1148       heap->old_pointer_space()->Contains(this)) {
1149     new_map = is_internalized
1150         ? heap->short_external_ascii_internalized_string_map()
1151         : heap->short_external_ascii_string_map();
1152   } else {
1153     new_map = is_internalized
1154         ? heap->external_ascii_internalized_string_map()
1155         : heap->external_ascii_string_map();
1156   }
1157
1158   // Byte size of the external String object.
1159   int new_size = this->SizeFromMap(new_map);
1160   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1161
1162   // We are storing the new map using release store after creating a filler for
1163   // the left-over space to avoid races with the sweeper thread.
1164   this->synchronized_set_map(new_map);
1165
1166   ExternalAsciiString* self = ExternalAsciiString::cast(this);
1167   self->set_resource(resource);
1168   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1169
1170   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1171   return true;
1172 }
1173
1174
1175 void String::StringShortPrint(StringStream* accumulator) {
1176   int len = length();
1177   if (len > kMaxShortPrintLength) {
1178     accumulator->Add("<Very long string[%u]>", len);
1179     return;
1180   }
1181
1182   if (!LooksValid()) {
1183     accumulator->Add("<Invalid String>");
1184     return;
1185   }
1186
1187   ConsStringIteratorOp op;
1188   StringCharacterStream stream(this, &op);
1189
1190   bool truncated = false;
1191   if (len > kMaxShortPrintLength) {
1192     len = kMaxShortPrintLength;
1193     truncated = true;
1194   }
1195   bool ascii = true;
1196   for (int i = 0; i < len; i++) {
1197     uint16_t c = stream.GetNext();
1198
1199     if (c < 32 || c >= 127) {
1200       ascii = false;
1201     }
1202   }
1203   stream.Reset(this);
1204   if (ascii) {
1205     accumulator->Add("<String[%u]: ", length());
1206     for (int i = 0; i < len; i++) {
1207       accumulator->Put(static_cast<char>(stream.GetNext()));
1208     }
1209     accumulator->Put('>');
1210   } else {
1211     // Backslash indicates that the string contains control
1212     // characters and that backslashes are therefore escaped.
1213     accumulator->Add("<String[%u]\\: ", length());
1214     for (int i = 0; i < len; i++) {
1215       uint16_t c = stream.GetNext();
1216       if (c == '\n') {
1217         accumulator->Add("\\n");
1218       } else if (c == '\r') {
1219         accumulator->Add("\\r");
1220       } else if (c == '\\') {
1221         accumulator->Add("\\\\");
1222       } else if (c < 32 || c > 126) {
1223         accumulator->Add("\\x%02x", c);
1224       } else {
1225         accumulator->Put(static_cast<char>(c));
1226       }
1227     }
1228     if (truncated) {
1229       accumulator->Put('.');
1230       accumulator->Put('.');
1231       accumulator->Put('.');
1232     }
1233     accumulator->Put('>');
1234   }
1235   return;
1236 }
1237
1238
1239 void String::PrintUC16(OStream& os, int start, int end) {  // NOLINT
1240   if (end < 0) end = length();
1241   ConsStringIteratorOp op;
1242   StringCharacterStream stream(this, &op, start);
1243   for (int i = start; i < end && stream.HasMore(); i++) {
1244     os << AsUC16(stream.GetNext());
1245   }
1246 }
1247
1248
1249 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1250   switch (map()->instance_type()) {
1251     case JS_ARRAY_TYPE: {
1252       double length = JSArray::cast(this)->length()->IsUndefined()
1253           ? 0
1254           : JSArray::cast(this)->length()->Number();
1255       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1256       break;
1257     }
1258     case JS_WEAK_MAP_TYPE: {
1259       accumulator->Add("<JS WeakMap>");
1260       break;
1261     }
1262     case JS_WEAK_SET_TYPE: {
1263       accumulator->Add("<JS WeakSet>");
1264       break;
1265     }
1266     case JS_REGEXP_TYPE: {
1267       accumulator->Add("<JS RegExp>");
1268       break;
1269     }
1270     case JS_FUNCTION_TYPE: {
1271       JSFunction* function = JSFunction::cast(this);
1272       Object* fun_name = function->shared()->DebugName();
1273       bool printed = false;
1274       if (fun_name->IsString()) {
1275         String* str = String::cast(fun_name);
1276         if (str->length() > 0) {
1277           accumulator->Add("<JS Function ");
1278           accumulator->Put(str);
1279           printed = true;
1280         }
1281       }
1282       if (!printed) {
1283         accumulator->Add("<JS Function");
1284       }
1285       accumulator->Add(" (SharedFunctionInfo %p)",
1286                        reinterpret_cast<void*>(function->shared()));
1287       accumulator->Put('>');
1288       break;
1289     }
1290     case JS_GENERATOR_OBJECT_TYPE: {
1291       accumulator->Add("<JS Generator>");
1292       break;
1293     }
1294     case JS_MODULE_TYPE: {
1295       accumulator->Add("<JS Module>");
1296       break;
1297     }
1298     // All other JSObjects are rather similar to each other (JSObject,
1299     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1300     default: {
1301       Map* map_of_this = map();
1302       Heap* heap = GetHeap();
1303       Object* constructor = map_of_this->constructor();
1304       bool printed = false;
1305       if (constructor->IsHeapObject() &&
1306           !heap->Contains(HeapObject::cast(constructor))) {
1307         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1308       } else {
1309         bool global_object = IsJSGlobalProxy();
1310         if (constructor->IsJSFunction()) {
1311           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1312             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1313           } else {
1314             Object* constructor_name =
1315                 JSFunction::cast(constructor)->shared()->name();
1316             if (constructor_name->IsString()) {
1317               String* str = String::cast(constructor_name);
1318               if (str->length() > 0) {
1319                 bool vowel = AnWord(str);
1320                 accumulator->Add("<%sa%s ",
1321                        global_object ? "Global Object: " : "",
1322                        vowel ? "n" : "");
1323                 accumulator->Put(str);
1324                 accumulator->Add(" with %smap %p",
1325                     map_of_this->is_deprecated() ? "deprecated " : "",
1326                     map_of_this);
1327                 printed = true;
1328               }
1329             }
1330           }
1331         }
1332         if (!printed) {
1333           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1334         }
1335       }
1336       if (IsJSValue()) {
1337         accumulator->Add(" value = ");
1338         JSValue::cast(this)->value()->ShortPrint(accumulator);
1339       }
1340       accumulator->Put('>');
1341       break;
1342     }
1343   }
1344 }
1345
1346
1347 void JSObject::PrintElementsTransition(
1348     FILE* file, Handle<JSObject> object,
1349     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
1350     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
1351   if (from_kind != to_kind) {
1352     OFStream os(file);
1353     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
1354        << ElementsKindToString(to_kind) << "] in ";
1355     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
1356     PrintF(file, " for ");
1357     object->ShortPrint(file);
1358     PrintF(file, " from ");
1359     from_elements->ShortPrint(file);
1360     PrintF(file, " to ");
1361     to_elements->ShortPrint(file);
1362     PrintF(file, "\n");
1363   }
1364 }
1365
1366
1367 void Map::PrintGeneralization(FILE* file,
1368                               const char* reason,
1369                               int modify_index,
1370                               int split,
1371                               int descriptors,
1372                               bool constant_to_field,
1373                               Representation old_representation,
1374                               Representation new_representation,
1375                               HeapType* old_field_type,
1376                               HeapType* new_field_type) {
1377   OFStream os(file);
1378   os << "[generalizing ";
1379   constructor_name()->PrintOn(file);
1380   os << "] ";
1381   Name* name = instance_descriptors()->GetKey(modify_index);
1382   if (name->IsString()) {
1383     String::cast(name)->PrintOn(file);
1384   } else {
1385     os << "{symbol " << static_cast<void*>(name) << "}";
1386   }
1387   os << ":";
1388   if (constant_to_field) {
1389     os << "c";
1390   } else {
1391     os << old_representation.Mnemonic() << "{";
1392     old_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1393     os << "}";
1394   }
1395   os << "->" << new_representation.Mnemonic() << "{";
1396   new_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1397   os << "} (";
1398   if (strlen(reason) > 0) {
1399     os << reason;
1400   } else {
1401     os << "+" << (descriptors - split) << " maps";
1402   }
1403   os << ") [";
1404   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1405   os << "]\n";
1406 }
1407
1408
1409 void JSObject::PrintInstanceMigration(FILE* file,
1410                                       Map* original_map,
1411                                       Map* new_map) {
1412   PrintF(file, "[migrating ");
1413   map()->constructor_name()->PrintOn(file);
1414   PrintF(file, "] ");
1415   DescriptorArray* o = original_map->instance_descriptors();
1416   DescriptorArray* n = new_map->instance_descriptors();
1417   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
1418     Representation o_r = o->GetDetails(i).representation();
1419     Representation n_r = n->GetDetails(i).representation();
1420     if (!o_r.Equals(n_r)) {
1421       String::cast(o->GetKey(i))->PrintOn(file);
1422       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
1423     } else if (o->GetDetails(i).type() == CONSTANT &&
1424                n->GetDetails(i).type() == FIELD) {
1425       Name* name = o->GetKey(i);
1426       if (name->IsString()) {
1427         String::cast(name)->PrintOn(file);
1428       } else {
1429         PrintF(file, "{symbol %p}", static_cast<void*>(name));
1430       }
1431       PrintF(file, " ");
1432     }
1433   }
1434   PrintF(file, "\n");
1435 }
1436
1437
1438 void HeapObject::HeapObjectShortPrint(OStream& os) {  // NOLINT
1439   Heap* heap = GetHeap();
1440   if (!heap->Contains(this)) {
1441     os << "!!!INVALID POINTER!!!";
1442     return;
1443   }
1444   if (!heap->Contains(map())) {
1445     os << "!!!INVALID MAP!!!";
1446     return;
1447   }
1448
1449   os << this << " ";
1450
1451   if (IsString()) {
1452     HeapStringAllocator allocator;
1453     StringStream accumulator(&allocator);
1454     String::cast(this)->StringShortPrint(&accumulator);
1455     os << accumulator.ToCString().get();
1456     return;
1457   }
1458   if (IsJSObject()) {
1459     HeapStringAllocator allocator;
1460     StringStream accumulator(&allocator);
1461     JSObject::cast(this)->JSObjectShortPrint(&accumulator);
1462     os << accumulator.ToCString().get();
1463     return;
1464   }
1465   switch (map()->instance_type()) {
1466     case MAP_TYPE:
1467       os << "<Map(elements=" << Map::cast(this)->elements_kind() << ")>";
1468       break;
1469     case FIXED_ARRAY_TYPE:
1470       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
1471       break;
1472     case FIXED_DOUBLE_ARRAY_TYPE:
1473       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
1474          << "]>";
1475       break;
1476     case BYTE_ARRAY_TYPE:
1477       os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
1478       break;
1479     case FREE_SPACE_TYPE:
1480       os << "<FreeSpace[" << FreeSpace::cast(this)->Size() << "]>";
1481       break;
1482 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
1483   case EXTERNAL_##TYPE##_ARRAY_TYPE:                                          \
1484     os << "<External" #Type "Array["                                          \
1485        << External##Type##Array::cast(this)->length() << "]>";                \
1486     break;                                                                    \
1487   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
1488     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
1489        << "]>";                                                               \
1490     break;
1491
1492     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1493 #undef TYPED_ARRAY_SHORT_PRINT
1494
1495     case SHARED_FUNCTION_INFO_TYPE: {
1496       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
1497       SmartArrayPointer<char> debug_name =
1498           shared->DebugName()->ToCString();
1499       if (debug_name[0] != 0) {
1500         os << "<SharedFunctionInfo " << debug_name.get() << ">";
1501       } else {
1502         os << "<SharedFunctionInfo>";
1503       }
1504       break;
1505     }
1506     case JS_MESSAGE_OBJECT_TYPE:
1507       os << "<JSMessageObject>";
1508       break;
1509 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1510   case NAME##_TYPE:                        \
1511     os << "<" #Name ">";                   \
1512     break;
1513   STRUCT_LIST(MAKE_STRUCT_CASE)
1514 #undef MAKE_STRUCT_CASE
1515     case CODE_TYPE: {
1516       Code* code = Code::cast(this);
1517       os << "<Code: " << Code::Kind2String(code->kind()) << ">";
1518       break;
1519     }
1520     case ODDBALL_TYPE: {
1521       if (IsUndefined()) {
1522         os << "<undefined>";
1523       } else if (IsTheHole()) {
1524         os << "<the hole>";
1525       } else if (IsNull()) {
1526         os << "<null>";
1527       } else if (IsTrue()) {
1528         os << "<true>";
1529       } else if (IsFalse()) {
1530         os << "<false>";
1531       } else {
1532         os << "<Odd Oddball>";
1533       }
1534       break;
1535     }
1536     case SYMBOL_TYPE: {
1537       Symbol* symbol = Symbol::cast(this);
1538       os << "<Symbol: " << symbol->Hash();
1539       if (!symbol->name()->IsUndefined()) {
1540         os << " ";
1541         HeapStringAllocator allocator;
1542         StringStream accumulator(&allocator);
1543         String::cast(symbol->name())->StringShortPrint(&accumulator);
1544         os << accumulator.ToCString().get();
1545       }
1546       os << ">";
1547       break;
1548     }
1549     case HEAP_NUMBER_TYPE: {
1550       os << "<Number: ";
1551       HeapNumber::cast(this)->HeapNumberPrint(os);
1552       os << ">";
1553       break;
1554     }
1555     case MUTABLE_HEAP_NUMBER_TYPE: {
1556       os << "<MutableNumber: ";
1557       HeapNumber::cast(this)->HeapNumberPrint(os);
1558       os << '>';
1559       break;
1560     }
1561     case FLOAT32x4_TYPE:
1562       os << "<Float32x4: ";
1563       Float32x4::cast(this)->Float32x4Print(os);
1564       os << '>';
1565       break;
1566     case FLOAT64x2_TYPE:
1567       os << "<Float64x2: ";
1568       Float64x2::cast(this)->Float64x2Print(os);
1569       os << '>';
1570       break;
1571     case INT32x4_TYPE:
1572       os << "<Int32x4: ";
1573       Int32x4::cast(this)->Int32x4Print(os);
1574       os << '>';
1575       break;
1576     case JS_PROXY_TYPE:
1577       os << "<JSProxy>";
1578       break;
1579     case JS_FUNCTION_PROXY_TYPE:
1580       os << "<JSFunctionProxy>";
1581       break;
1582     case FOREIGN_TYPE:
1583       os << "<Foreign>";
1584       break;
1585     case CELL_TYPE: {
1586       os << "Cell for ";
1587       HeapStringAllocator allocator;
1588       StringStream accumulator(&allocator);
1589       Cell::cast(this)->value()->ShortPrint(&accumulator);
1590       os << accumulator.ToCString().get();
1591       break;
1592     }
1593     case PROPERTY_CELL_TYPE: {
1594       os << "PropertyCell for ";
1595       HeapStringAllocator allocator;
1596       StringStream accumulator(&allocator);
1597       PropertyCell::cast(this)->value()->ShortPrint(&accumulator);
1598       os << accumulator.ToCString().get();
1599       break;
1600     }
1601     default:
1602       os << "<Other heap object (" << map()->instance_type() << ")>";
1603       break;
1604   }
1605 }
1606
1607
1608 void HeapObject::Iterate(ObjectVisitor* v) {
1609   // Handle header
1610   IteratePointer(v, kMapOffset);
1611   // Handle object body
1612   Map* m = map();
1613   IterateBody(m->instance_type(), SizeFromMap(m), v);
1614 }
1615
1616
1617 void HeapObject::IterateBody(InstanceType type, int object_size,
1618                              ObjectVisitor* v) {
1619   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1620   // During GC, the map pointer field is encoded.
1621   if (type < FIRST_NONSTRING_TYPE) {
1622     switch (type & kStringRepresentationMask) {
1623       case kSeqStringTag:
1624         break;
1625       case kConsStringTag:
1626         ConsString::BodyDescriptor::IterateBody(this, v);
1627         break;
1628       case kSlicedStringTag:
1629         SlicedString::BodyDescriptor::IterateBody(this, v);
1630         break;
1631       case kExternalStringTag:
1632         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1633           reinterpret_cast<ExternalAsciiString*>(this)->
1634               ExternalAsciiStringIterateBody(v);
1635         } else {
1636           reinterpret_cast<ExternalTwoByteString*>(this)->
1637               ExternalTwoByteStringIterateBody(v);
1638         }
1639         break;
1640     }
1641     return;
1642   }
1643
1644   switch (type) {
1645     case FIXED_ARRAY_TYPE:
1646       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1647       break;
1648     case CONSTANT_POOL_ARRAY_TYPE:
1649       reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v);
1650       break;
1651     case FIXED_DOUBLE_ARRAY_TYPE:
1652       break;
1653     case JS_OBJECT_TYPE:
1654     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1655     case JS_GENERATOR_OBJECT_TYPE:
1656     case JS_MODULE_TYPE:
1657     case JS_VALUE_TYPE:
1658     case JS_DATE_TYPE:
1659     case JS_ARRAY_TYPE:
1660     case JS_ARRAY_BUFFER_TYPE:
1661     case JS_TYPED_ARRAY_TYPE:
1662     case JS_DATA_VIEW_TYPE:
1663     case JS_SET_TYPE:
1664     case JS_MAP_TYPE:
1665     case JS_SET_ITERATOR_TYPE:
1666     case JS_MAP_ITERATOR_TYPE:
1667     case JS_WEAK_MAP_TYPE:
1668     case JS_WEAK_SET_TYPE:
1669     case JS_REGEXP_TYPE:
1670     case JS_GLOBAL_PROXY_TYPE:
1671     case JS_GLOBAL_OBJECT_TYPE:
1672     case JS_BUILTINS_OBJECT_TYPE:
1673     case JS_MESSAGE_OBJECT_TYPE:
1674     case FLOAT32x4_TYPE:
1675     case FLOAT64x2_TYPE:
1676     case INT32x4_TYPE:
1677       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1678       break;
1679     case JS_FUNCTION_TYPE:
1680       reinterpret_cast<JSFunction*>(this)
1681           ->JSFunctionIterateBody(object_size, v);
1682       break;
1683     case ODDBALL_TYPE:
1684       Oddball::BodyDescriptor::IterateBody(this, v);
1685       break;
1686     case JS_PROXY_TYPE:
1687       JSProxy::BodyDescriptor::IterateBody(this, v);
1688       break;
1689     case JS_FUNCTION_PROXY_TYPE:
1690       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1691       break;
1692     case FOREIGN_TYPE:
1693       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1694       break;
1695     case MAP_TYPE:
1696       Map::BodyDescriptor::IterateBody(this, v);
1697       break;
1698     case CODE_TYPE:
1699       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1700       break;
1701     case CELL_TYPE:
1702       Cell::BodyDescriptor::IterateBody(this, v);
1703       break;
1704     case PROPERTY_CELL_TYPE:
1705       PropertyCell::BodyDescriptor::IterateBody(this, v);
1706       break;
1707     case SYMBOL_TYPE:
1708       Symbol::BodyDescriptor::IterateBody(this, v);
1709       break;
1710
1711     case HEAP_NUMBER_TYPE:
1712     case MUTABLE_HEAP_NUMBER_TYPE:
1713     case FILLER_TYPE:
1714     case BYTE_ARRAY_TYPE:
1715     case FREE_SPACE_TYPE:
1716       break;
1717
1718 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
1719     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
1720     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
1721       break;
1722
1723     TYPED_ARRAYS(TYPED_ARRAY_CASE)
1724 #undef TYPED_ARRAY_CASE
1725
1726     case SHARED_FUNCTION_INFO_TYPE: {
1727       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1728       break;
1729     }
1730
1731 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1732         case NAME##_TYPE:
1733       STRUCT_LIST(MAKE_STRUCT_CASE)
1734 #undef MAKE_STRUCT_CASE
1735       if (type == ALLOCATION_SITE_TYPE) {
1736         AllocationSite::BodyDescriptor::IterateBody(this, v);
1737       } else {
1738         StructBodyDescriptor::IterateBody(this, object_size, v);
1739       }
1740       break;
1741     default:
1742       PrintF("Unknown type: %d\n", type);
1743       UNREACHABLE();
1744   }
1745 }
1746
1747
1748 bool HeapNumber::HeapNumberBooleanValue() {
1749   return DoubleToBoolean(value());
1750 }
1751
1752
1753 void HeapNumber::HeapNumberPrint(OStream& os) {  // NOLINT
1754   os << value();
1755 }
1756
1757
1758 void Float32x4::Float32x4Print(OStream& os) {
1759   // The Windows version of vsnprintf can allocate when printing a %g string
1760   // into a buffer that may not be big enough.  We don't want random memory
1761   // allocation when producing post-crash stack traces, so we print into a
1762   // buffer that is plenty big enough for any floating point number, then
1763   // print that using vsnprintf (which may truncate but never allocate if
1764   // there is no more space in the buffer).
1765   EmbeddedVector<char, 100> buffer;
1766   SNPrintF(buffer, "%.16g %.16g %.16g %.16g", x(), y(), z(), w());
1767   os << buffer.start();
1768 }
1769
1770
1771 void Int32x4::Int32x4Print(OStream& os) {
1772   // The Windows version of vsnprintf can allocate when printing a %g string
1773   // into a buffer that may not be big enough.  We don't want random memory
1774   // allocation when producing post-crash stack traces, so we print into a
1775   // buffer that is plenty big enough for any floating point number, then
1776   // print that using vsnprintf (which may truncate but never allocate if
1777   // there is no more space in the buffer).
1778   EmbeddedVector<char, 100> buffer;
1779   SNPrintF(buffer, "%u %u %u %u", x(), y(), z(), w());
1780   os << buffer.start();
1781 }
1782
1783
1784 void Float64x2::Float64x2Print(OStream& os) {
1785   // The Windows version of vsnprintf can allocate when printing a %g string
1786   // into a buffer that may not be big enough.  We don't want random memory
1787   // allocation when producing post-crash stack traces, so we print into a
1788   // buffer that is plenty big enough for any floating point number, then
1789   // print that using vsnprintf (which may truncate but never allocate if
1790   // there is no more space in the buffer).
1791   EmbeddedVector<char, 100> buffer;
1792   SNPrintF(buffer, "%.16g %.16g", x(), y());
1793   os << buffer.start();
1794 }
1795
1796
1797 String* JSReceiver::class_name() {
1798   if (IsJSFunction() || IsJSFunctionProxy()) {
1799     return GetHeap()->function_class_string();
1800   }
1801   if (map()->constructor()->IsJSFunction()) {
1802     JSFunction* constructor = JSFunction::cast(map()->constructor());
1803     return String::cast(constructor->shared()->instance_class_name());
1804   }
1805   // If the constructor is not present, return "Object".
1806   return GetHeap()->Object_string();
1807 }
1808
1809
1810 String* Map::constructor_name() {
1811   if (constructor()->IsJSFunction()) {
1812     JSFunction* constructor = JSFunction::cast(this->constructor());
1813     String* name = String::cast(constructor->shared()->name());
1814     if (name->length() > 0) return name;
1815     String* inferred_name = constructor->shared()->inferred_name();
1816     if (inferred_name->length() > 0) return inferred_name;
1817     Object* proto = prototype();
1818     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1819   }
1820   // TODO(rossberg): what about proxies?
1821   // If the constructor is not present, return "Object".
1822   return GetHeap()->Object_string();
1823 }
1824
1825
1826 String* JSReceiver::constructor_name() {
1827   return map()->constructor_name();
1828 }
1829
1830
1831 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
1832                                     Handle<Name> name,
1833                                     Handle<HeapType> type,
1834                                     PropertyAttributes attributes,
1835                                     Representation representation,
1836                                     TransitionFlag flag) {
1837   DCHECK(DescriptorArray::kNotFound ==
1838          map->instance_descriptors()->Search(
1839              *name, map->NumberOfOwnDescriptors()));
1840
1841   // Ensure the descriptor array does not get too big.
1842   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1843     return MaybeHandle<Map>();
1844   }
1845
1846   Isolate* isolate = map->GetIsolate();
1847
1848   // Compute the new index for new field.
1849   int index = map->NextFreePropertyIndex();
1850
1851   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1852     representation = Representation::Tagged();
1853     type = HeapType::Any(isolate);
1854   }
1855
1856   FieldDescriptor new_field_desc(name, index, type, attributes, representation);
1857   Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1858   int unused_property_fields = new_map->unused_property_fields() - 1;
1859   if (unused_property_fields < 0) {
1860     unused_property_fields += JSObject::kFieldsAdded;
1861   }
1862   new_map->set_unused_property_fields(unused_property_fields);
1863   return new_map;
1864 }
1865
1866
1867 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1868                                        Handle<Name> name,
1869                                        Handle<Object> constant,
1870                                        PropertyAttributes attributes,
1871                                        TransitionFlag flag) {
1872   // Ensure the descriptor array does not get too big.
1873   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1874     return MaybeHandle<Map>();
1875   }
1876
1877   // Allocate new instance descriptors with (name, constant) added.
1878   ConstantDescriptor new_constant_desc(name, constant, attributes);
1879   return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1880 }
1881
1882
1883 void JSObject::AddFastProperty(Handle<JSObject> object,
1884                                Handle<Name> name,
1885                                Handle<Object> value,
1886                                PropertyAttributes attributes,
1887                                StoreFromKeyed store_mode,
1888                                TransitionFlag flag) {
1889   DCHECK(!object->IsJSGlobalProxy());
1890
1891   MaybeHandle<Map> maybe_map;
1892   if (value->IsJSFunction()) {
1893     maybe_map = Map::CopyWithConstant(
1894         handle(object->map()), name, value, attributes, flag);
1895   } else if (!object->map()->TooManyFastProperties(store_mode)) {
1896     Isolate* isolate = object->GetIsolate();
1897     Representation representation = value->OptimalRepresentation();
1898     maybe_map = Map::CopyWithField(
1899         handle(object->map(), isolate), name,
1900         value->OptimalType(isolate, representation),
1901         attributes, representation, flag);
1902   }
1903
1904   Handle<Map> new_map;
1905   if (!maybe_map.ToHandle(&new_map)) {
1906     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
1907     return;
1908   }
1909
1910   JSObject::MigrateToNewProperty(object, new_map, value);
1911 }
1912
1913
1914 void JSObject::AddSlowProperty(Handle<JSObject> object,
1915                                Handle<Name> name,
1916                                Handle<Object> value,
1917                                PropertyAttributes attributes) {
1918   DCHECK(!object->HasFastProperties());
1919   Isolate* isolate = object->GetIsolate();
1920   Handle<NameDictionary> dict(object->property_dictionary());
1921   if (object->IsGlobalObject()) {
1922     // In case name is an orphaned property reuse the cell.
1923     int entry = dict->FindEntry(name);
1924     if (entry != NameDictionary::kNotFound) {
1925       Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry)));
1926       PropertyCell::SetValueInferType(cell, value);
1927       // Assign an enumeration index to the property and update
1928       // SetNextEnumerationIndex.
1929       int index = dict->NextEnumerationIndex();
1930       PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
1931       dict->SetNextEnumerationIndex(index + 1);
1932       dict->SetEntry(entry, name, cell, details);
1933       return;
1934     }
1935     Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value);
1936     PropertyCell::SetValueInferType(cell, value);
1937     value = cell;
1938   }
1939   PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
1940   Handle<NameDictionary> result =
1941       NameDictionary::Add(dict, name, value, details);
1942   if (*dict != *result) object->set_properties(*result);
1943 }
1944
1945
1946 MaybeHandle<Object> JSObject::AddPropertyInternal(
1947     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
1948     PropertyAttributes attributes, JSReceiver::StoreFromKeyed store_mode,
1949     ExtensibilityCheck extensibility_check, TransitionFlag transition_flag) {
1950   DCHECK(!object->IsJSGlobalProxy());
1951   Isolate* isolate = object->GetIsolate();
1952
1953   if (!name->IsUniqueName()) {
1954     name = isolate->factory()->InternalizeString(
1955         Handle<String>::cast(name));
1956   }
1957
1958   if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
1959       !object->map()->is_extensible()) {
1960     Handle<Object> args[1] = {name};
1961     Handle<Object> error = isolate->factory()->NewTypeError(
1962         "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
1963     return isolate->Throw<Object>(error);
1964   }
1965
1966   if (object->HasFastProperties()) {
1967     AddFastProperty(object, name, value, attributes, store_mode,
1968                     transition_flag);
1969   }
1970
1971   if (!object->HasFastProperties()) {
1972     AddSlowProperty(object, name, value, attributes);
1973   }
1974
1975   if (object->map()->is_observed() &&
1976       *name != isolate->heap()->hidden_string()) {
1977     Handle<Object> old_value = isolate->factory()->the_hole_value();
1978     EnqueueChangeRecord(object, "add", name, old_value);
1979   }
1980
1981   return value;
1982 }
1983
1984
1985 Context* JSObject::GetCreationContext() {
1986   Object* constructor = this->map()->constructor();
1987   JSFunction* function;
1988   if (!constructor->IsJSFunction()) {
1989     // Functions have null as a constructor,
1990     // but any JSFunction knows its context immediately.
1991     function = JSFunction::cast(this);
1992   } else {
1993     function = JSFunction::cast(constructor);
1994   }
1995
1996   return function->context()->native_context();
1997 }
1998
1999
2000 void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
2001                                    const char* type_str,
2002                                    Handle<Name> name,
2003                                    Handle<Object> old_value) {
2004   DCHECK(!object->IsJSGlobalProxy());
2005   DCHECK(!object->IsJSGlobalObject());
2006   Isolate* isolate = object->GetIsolate();
2007   HandleScope scope(isolate);
2008   Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
2009   Handle<Object> args[] = { type, object, name, old_value };
2010   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
2011
2012   Execution::Call(isolate,
2013                   Handle<JSFunction>(isolate->observers_notify_change()),
2014                   isolate->factory()->undefined_value(),
2015                   argc, args).Assert();
2016 }
2017
2018
2019 static void ReplaceSlowProperty(Handle<JSObject> object,
2020                                 Handle<Name> name,
2021                                 Handle<Object> value,
2022                                 PropertyAttributes attributes) {
2023   NameDictionary* dictionary = object->property_dictionary();
2024   int old_index = dictionary->FindEntry(name);
2025   int new_enumeration_index = 0;  // 0 means "Use the next available index."
2026   if (old_index != -1) {
2027     // All calls to ReplaceSlowProperty have had all transitions removed.
2028     new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index();
2029   }
2030
2031   PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
2032   JSObject::SetNormalizedProperty(object, name, value, new_details);
2033 }
2034
2035
2036 const char* Representation::Mnemonic() const {
2037   switch (kind_) {
2038     case kNone: return "v";
2039     case kTagged: return "t";
2040     case kSmi: return "s";
2041     case kDouble: return "d";
2042     case kFloat32x4: return "float32x4";
2043     case kFloat64x2: return "float64x2";
2044     case kInt32x4: return "int32x44";
2045     case kInteger32: return "i";
2046     case kHeapObject: return "h";
2047     case kExternal: return "x";
2048     default:
2049       UNREACHABLE();
2050       return NULL;
2051   }
2052 }
2053
2054
2055 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
2056                                  int target_inobject, int target_unused,
2057                                  int* old_number_of_fields) {
2058   // If fields were added (or removed), rewrite the instance.
2059   *old_number_of_fields = NumberOfFields();
2060   DCHECK(target_number_of_fields >= *old_number_of_fields);
2061   if (target_number_of_fields != *old_number_of_fields) return true;
2062
2063   // If smi descriptors were replaced by double descriptors, rewrite.
2064   DescriptorArray* old_desc = instance_descriptors();
2065   DescriptorArray* new_desc = target->instance_descriptors();
2066   int limit = NumberOfOwnDescriptors();
2067   for (int i = 0; i < limit; i++) {
2068     if (new_desc->GetDetails(i).representation().IsDouble() !=
2069         old_desc->GetDetails(i).representation().IsDouble()) {
2070       return true;
2071     }
2072   }
2073
2074   // If no fields were added, and no inobject properties were removed, setting
2075   // the map is sufficient.
2076   if (target_inobject == inobject_properties()) return false;
2077   // In-object slack tracking may have reduced the object size of the new map.
2078   // In that case, succeed if all existing fields were inobject, and they still
2079   // fit within the new inobject size.
2080   DCHECK(target_inobject < inobject_properties());
2081   if (target_number_of_fields <= target_inobject) {
2082     DCHECK(target_number_of_fields + target_unused == target_inobject);
2083     return false;
2084   }
2085   // Otherwise, properties will need to be moved to the backing store.
2086   return true;
2087 }
2088
2089
2090 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) {
2091   Isolate* isolate = parent->GetIsolate();
2092   Handle<Name> name = isolate->factory()->elements_transition_symbol();
2093   ConnectTransition(parent, child, name, FULL_TRANSITION);
2094 }
2095
2096
2097 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
2098   if (object->map() == *new_map) return;
2099   if (object->HasFastProperties()) {
2100     if (!new_map->is_dictionary_map()) {
2101       Handle<Map> old_map(object->map());
2102       MigrateFastToFast(object, new_map);
2103       if (old_map->is_prototype_map()) {
2104         // Clear out the old descriptor array to avoid problems to sharing
2105         // the descriptor array without using an explicit.
2106         old_map->InitializeDescriptors(
2107             old_map->GetHeap()->empty_descriptor_array());
2108         // Ensure that no transition was inserted for prototype migrations.
2109         DCHECK(!old_map->HasTransitionArray());
2110         DCHECK(new_map->GetBackPointer()->IsUndefined());
2111       }
2112     } else {
2113       MigrateFastToSlow(object, new_map, 0);
2114     }
2115   } else {
2116     // For slow-to-fast migrations JSObject::TransformToFastProperties()
2117     // must be used instead.
2118     CHECK(new_map->is_dictionary_map());
2119
2120     // Slow-to-slow migration is trivial.
2121     object->set_map(*new_map);
2122   }
2123 }
2124
2125
2126 // To migrate a fast instance to a fast map:
2127 // - First check whether the instance needs to be rewritten. If not, simply
2128 //   change the map.
2129 // - Otherwise, allocate a fixed array large enough to hold all fields, in
2130 //   addition to unused space.
2131 // - Copy all existing properties in, in the following order: backing store
2132 //   properties, unused fields, inobject properties.
2133 // - If all allocation succeeded, commit the state atomically:
2134 //   * Copy inobject properties from the backing store back into the object.
2135 //   * Trim the difference in instance size of the object. This also cleanly
2136 //     frees inobject properties that moved to the backing store.
2137 //   * If there are properties left in the backing store, trim of the space used
2138 //     to temporarily store the inobject properties.
2139 //   * If there are properties left in the backing store, install the backing
2140 //     store.
2141 void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
2142   Isolate* isolate = object->GetIsolate();
2143   Handle<Map> old_map(object->map());
2144   int old_number_of_fields;
2145   int number_of_fields = new_map->NumberOfFields();
2146   int inobject = new_map->inobject_properties();
2147   int unused = new_map->unused_property_fields();
2148
2149   // Nothing to do if no functions were converted to fields and no smis were
2150   // converted to doubles.
2151   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
2152                                        unused, &old_number_of_fields)) {
2153     object->synchronized_set_map(*new_map);
2154     return;
2155   }
2156
2157   int total_size = number_of_fields + unused;
2158   int external = total_size - inobject;
2159
2160   if ((old_map->unused_property_fields() == 0) &&
2161       (number_of_fields != old_number_of_fields) &&
2162       (new_map->GetBackPointer() == *old_map)) {
2163     DCHECK(number_of_fields == old_number_of_fields + 1);
2164     // This migration is a transition from a map that has run out out property
2165     // space. Therefore it could be done by extending the backing store.
2166     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
2167     Handle<FixedArray> new_storage =
2168         FixedArray::CopySize(old_storage, external);
2169
2170     // Properly initialize newly added property.
2171     PropertyDetails details = new_map->GetLastDescriptorDetails();
2172     Handle<Object> value;
2173     if (details.representation().IsDouble()) {
2174       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2175     } else {
2176       value = isolate->factory()->uninitialized_value();
2177     }
2178     DCHECK(details.type() == FIELD);
2179     int target_index = details.field_index() - inobject;
2180     DCHECK(target_index >= 0);  // Must be a backing store index.
2181     new_storage->set(target_index, *value);
2182
2183     // From here on we cannot fail and we shouldn't GC anymore.
2184     DisallowHeapAllocation no_allocation;
2185
2186     // Set the new property value and do the map transition.
2187     object->set_properties(*new_storage);
2188     object->synchronized_set_map(*new_map);
2189     return;
2190   }
2191   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
2192
2193   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
2194   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
2195   int old_nof = old_map->NumberOfOwnDescriptors();
2196   int new_nof = new_map->NumberOfOwnDescriptors();
2197
2198   // This method only supports generalizing instances to at least the same
2199   // number of properties.
2200   DCHECK(old_nof <= new_nof);
2201
2202   for (int i = 0; i < old_nof; i++) {
2203     PropertyDetails details = new_descriptors->GetDetails(i);
2204     if (details.type() != FIELD) continue;
2205     PropertyDetails old_details = old_descriptors->GetDetails(i);
2206     if (old_details.type() == CALLBACKS) {
2207       DCHECK(details.representation().IsTagged());
2208       continue;
2209     }
2210     DCHECK(old_details.type() == CONSTANT ||
2211            old_details.type() == FIELD);
2212     Object* raw_value = old_details.type() == CONSTANT
2213         ? old_descriptors->GetValue(i)
2214         : object->RawFastPropertyAt(FieldIndex::ForDescriptor(*old_map, i));
2215     Handle<Object> value(raw_value, isolate);
2216     if (!old_details.representation().IsDouble() &&
2217         details.representation().IsDouble()) {
2218       if (old_details.representation().IsNone()) {
2219         value = handle(Smi::FromInt(0), isolate);
2220       }
2221       value = Object::NewStorageFor(isolate, value, details.representation());
2222     } else if (old_details.representation().IsDouble() &&
2223                !details.representation().IsDouble()) {
2224       value = Object::WrapForRead(isolate, value, old_details.representation());
2225     }
2226     DCHECK(!(details.representation().IsDouble() && value->IsSmi()));
2227     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2228     if (target_index < 0) target_index += total_size;
2229     array->set(target_index, *value);
2230   }
2231
2232   for (int i = old_nof; i < new_nof; i++) {
2233     PropertyDetails details = new_descriptors->GetDetails(i);
2234     if (details.type() != FIELD) continue;
2235     Handle<Object> value;
2236     if (details.representation().IsDouble()) {
2237       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2238     } else {
2239       value = isolate->factory()->uninitialized_value();
2240     }
2241     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2242     if (target_index < 0) target_index += total_size;
2243     array->set(target_index, *value);
2244   }
2245
2246   // From here on we cannot fail and we shouldn't GC anymore.
2247   DisallowHeapAllocation no_allocation;
2248
2249   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2250   // avoid overwriting |one_pointer_filler_map|.
2251   int limit = Min(inobject, number_of_fields);
2252   for (int i = 0; i < limit; i++) {
2253     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
2254     object->FastPropertyAtPut(index, array->get(external + i));
2255   }
2256
2257   Heap* heap = isolate->heap();
2258
2259   // If there are properties in the new backing store, trim it to the correct
2260   // size and install the backing store into the object.
2261   if (external > 0) {
2262     heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, inobject);
2263     object->set_properties(*array);
2264   }
2265
2266   // Create filler object past the new instance size.
2267   int new_instance_size = new_map->instance_size();
2268   int instance_size_delta = old_map->instance_size() - new_instance_size;
2269   DCHECK(instance_size_delta >= 0);
2270
2271   if (instance_size_delta > 0) {
2272     Address address = object->address();
2273     heap->CreateFillerObjectAt(
2274         address + new_instance_size, instance_size_delta);
2275     heap->AdjustLiveBytes(address, -instance_size_delta, Heap::FROM_MUTATOR);
2276   }
2277
2278   // We are storing the new map using release store after creating a filler for
2279   // the left-over space to avoid races with the sweeper thread.
2280   object->synchronized_set_map(*new_map);
2281 }
2282
2283
2284 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object,
2285                                              int modify_index,
2286                                              Representation new_representation,
2287                                              Handle<HeapType> new_field_type) {
2288   Handle<Map> new_map = Map::GeneralizeRepresentation(
2289       handle(object->map()), modify_index, new_representation, new_field_type,
2290       FORCE_FIELD);
2291   MigrateToMap(object, new_map);
2292 }
2293
2294
2295 int Map::NumberOfFields() {
2296   DescriptorArray* descriptors = instance_descriptors();
2297   int result = 0;
2298   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2299     if (descriptors->GetDetails(i).type() == FIELD) result++;
2300   }
2301   return result;
2302 }
2303
2304
2305 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
2306                                                   int modify_index,
2307                                                   StoreMode store_mode,
2308                                                   PropertyAttributes attributes,
2309                                                   const char* reason) {
2310   Isolate* isolate = map->GetIsolate();
2311   Handle<Map> new_map = Copy(map);
2312
2313   DescriptorArray* descriptors = new_map->instance_descriptors();
2314   int length = descriptors->number_of_descriptors();
2315   for (int i = 0; i < length; i++) {
2316     descriptors->SetRepresentation(i, Representation::Tagged());
2317     if (descriptors->GetDetails(i).type() == FIELD) {
2318       descriptors->SetValue(i, HeapType::Any());
2319     }
2320   }
2321
2322   // Unless the instance is being migrated, ensure that modify_index is a field.
2323   PropertyDetails details = descriptors->GetDetails(modify_index);
2324   if (store_mode == FORCE_FIELD &&
2325       (details.type() != FIELD || details.attributes() != attributes)) {
2326     int field_index = details.type() == FIELD ? details.field_index()
2327                                               : new_map->NumberOfFields();
2328     FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
2329                       field_index, attributes, Representation::Tagged());
2330     descriptors->Replace(modify_index, &d);
2331     if (details.type() != FIELD) {
2332       int unused_property_fields = new_map->unused_property_fields() - 1;
2333       if (unused_property_fields < 0) {
2334         unused_property_fields += JSObject::kFieldsAdded;
2335       }
2336       new_map->set_unused_property_fields(unused_property_fields);
2337     }
2338   } else {
2339     DCHECK(details.attributes() == attributes);
2340   }
2341
2342   if (FLAG_trace_generalization) {
2343     HeapType* field_type = (details.type() == FIELD)
2344         ? map->instance_descriptors()->GetFieldType(modify_index)
2345         : NULL;
2346     map->PrintGeneralization(stdout, reason, modify_index,
2347                         new_map->NumberOfOwnDescriptors(),
2348                         new_map->NumberOfOwnDescriptors(),
2349                         details.type() == CONSTANT && store_mode == FORCE_FIELD,
2350                         details.representation(), Representation::Tagged(),
2351                         field_type, HeapType::Any());
2352   }
2353   return new_map;
2354 }
2355
2356
2357 // static
2358 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
2359                                                   int modify_index,
2360                                                   StoreMode store_mode,
2361                                                   const char* reason) {
2362   PropertyDetails details =
2363       map->instance_descriptors()->GetDetails(modify_index);
2364   return CopyGeneralizeAllRepresentations(map, modify_index, store_mode,
2365                                           details.attributes(), reason);
2366 }
2367
2368
2369 void Map::DeprecateTransitionTree() {
2370   if (is_deprecated()) return;
2371   if (HasTransitionArray()) {
2372     TransitionArray* transitions = this->transitions();
2373     for (int i = 0; i < transitions->number_of_transitions(); i++) {
2374       transitions->GetTarget(i)->DeprecateTransitionTree();
2375     }
2376   }
2377   deprecate();
2378   dependent_code()->DeoptimizeDependentCodeGroup(
2379       GetIsolate(), DependentCode::kTransitionGroup);
2380   NotifyLeafMapLayoutChange();
2381 }
2382
2383
2384 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2385 // the current instance_descriptors to ensure proper sharing of descriptor
2386 // arrays.
2387 void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors) {
2388   if (HasTransitionArray()) {
2389     TransitionArray* transitions = this->transitions();
2390     int transition = transitions->Search(key);
2391     if (transition != TransitionArray::kNotFound) {
2392       transitions->GetTarget(transition)->DeprecateTransitionTree();
2393     }
2394   }
2395
2396   // Don't overwrite the empty descriptor array.
2397   if (NumberOfOwnDescriptors() == 0) return;
2398
2399   DescriptorArray* to_replace = instance_descriptors();
2400   Map* current = this;
2401   GetHeap()->incremental_marking()->RecordWrites(to_replace);
2402   while (current->instance_descriptors() == to_replace) {
2403     current->SetEnumLength(kInvalidEnumCacheSentinel);
2404     current->set_instance_descriptors(new_descriptors);
2405     Object* next = current->GetBackPointer();
2406     if (next->IsUndefined()) break;
2407     current = Map::cast(next);
2408   }
2409
2410   set_owns_descriptors(false);
2411 }
2412
2413
2414 Map* Map::FindRootMap() {
2415   Map* result = this;
2416   while (true) {
2417     Object* back = result->GetBackPointer();
2418     if (back->IsUndefined()) return result;
2419     result = Map::cast(back);
2420   }
2421 }
2422
2423
2424 Map* Map::FindLastMatchMap(int verbatim,
2425                            int length,
2426                            DescriptorArray* descriptors) {
2427   DisallowHeapAllocation no_allocation;
2428
2429   // This can only be called on roots of transition trees.
2430   DCHECK(GetBackPointer()->IsUndefined());
2431
2432   Map* current = this;
2433
2434   for (int i = verbatim; i < length; i++) {
2435     if (!current->HasTransitionArray()) break;
2436     Name* name = descriptors->GetKey(i);
2437     TransitionArray* transitions = current->transitions();
2438     int transition = transitions->Search(name);
2439     if (transition == TransitionArray::kNotFound) break;
2440
2441     Map* next = transitions->GetTarget(transition);
2442     DescriptorArray* next_descriptors = next->instance_descriptors();
2443
2444     PropertyDetails details = descriptors->GetDetails(i);
2445     PropertyDetails next_details = next_descriptors->GetDetails(i);
2446     if (details.type() != next_details.type()) break;
2447     if (details.attributes() != next_details.attributes()) break;
2448     if (!details.representation().Equals(next_details.representation())) break;
2449     if (next_details.type() == FIELD) {
2450       if (!descriptors->GetFieldType(i)->NowIs(
2451               next_descriptors->GetFieldType(i))) break;
2452     } else {
2453       if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break;
2454     }
2455
2456     current = next;
2457   }
2458   return current;
2459 }
2460
2461
2462 Map* Map::FindFieldOwner(int descriptor) {
2463   DisallowHeapAllocation no_allocation;
2464   DCHECK_EQ(FIELD, instance_descriptors()->GetDetails(descriptor).type());
2465   Map* result = this;
2466   while (true) {
2467     Object* back = result->GetBackPointer();
2468     if (back->IsUndefined()) break;
2469     Map* parent = Map::cast(back);
2470     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
2471     result = parent;
2472   }
2473   return result;
2474 }
2475
2476
2477 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
2478                           Handle<HeapType> new_type) {
2479   DisallowHeapAllocation no_allocation;
2480   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
2481   if (details.type() != FIELD) return;
2482   if (HasTransitionArray()) {
2483     TransitionArray* transitions = this->transitions();
2484     for (int i = 0; i < transitions->number_of_transitions(); ++i) {
2485       transitions->GetTarget(i)->UpdateFieldType(descriptor, name, new_type);
2486     }
2487   }
2488   // Skip if already updated the shared descriptor.
2489   if (instance_descriptors()->GetFieldType(descriptor) == *new_type) return;
2490   FieldDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
2491                     new_type, details.attributes(), details.representation());
2492   instance_descriptors()->Replace(descriptor, &d);
2493 }
2494
2495
2496 // static
2497 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
2498                                           Handle<HeapType> type2,
2499                                           Isolate* isolate) {
2500   static const int kMaxClassesPerFieldType = 5;
2501   if (type1->NowIs(type2)) return type2;
2502   if (type2->NowIs(type1)) return type1;
2503   if (type1->NowStable() && type2->NowStable()) {
2504     Handle<HeapType> type = HeapType::Union(type1, type2, isolate);
2505     if (type->NumClasses() <= kMaxClassesPerFieldType) {
2506       DCHECK(type->NowStable());
2507       DCHECK(type1->NowIs(type));
2508       DCHECK(type2->NowIs(type));
2509       return type;
2510     }
2511   }
2512   return HeapType::Any(isolate);
2513 }
2514
2515
2516 // static
2517 void Map::GeneralizeFieldType(Handle<Map> map,
2518                               int modify_index,
2519                               Handle<HeapType> new_field_type) {
2520   Isolate* isolate = map->GetIsolate();
2521
2522   // Check if we actually need to generalize the field type at all.
2523   Handle<HeapType> old_field_type(
2524       map->instance_descriptors()->GetFieldType(modify_index), isolate);
2525   if (new_field_type->NowIs(old_field_type)) {
2526     DCHECK(Map::GeneralizeFieldType(old_field_type,
2527                                     new_field_type,
2528                                     isolate)->NowIs(old_field_type));
2529     return;
2530   }
2531
2532   // Determine the field owner.
2533   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
2534   Handle<DescriptorArray> descriptors(
2535       field_owner->instance_descriptors(), isolate);
2536   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
2537
2538   // Determine the generalized new field type.
2539   new_field_type = Map::GeneralizeFieldType(
2540       old_field_type, new_field_type, isolate);
2541
2542   PropertyDetails details = descriptors->GetDetails(modify_index);
2543   Handle<Name> name(descriptors->GetKey(modify_index));
2544   field_owner->UpdateFieldType(modify_index, name, new_field_type);
2545   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
2546       isolate, DependentCode::kFieldTypeGroup);
2547
2548   if (FLAG_trace_generalization) {
2549     map->PrintGeneralization(
2550         stdout, "field type generalization",
2551         modify_index, map->NumberOfOwnDescriptors(),
2552         map->NumberOfOwnDescriptors(), false,
2553         details.representation(), details.representation(),
2554         *old_field_type, *new_field_type);
2555   }
2556 }
2557
2558
2559 // Generalize the representation of the descriptor at |modify_index|.
2560 // This method rewrites the transition tree to reflect the new change. To avoid
2561 // high degrees over polymorphism, and to stabilize quickly, on every rewrite
2562 // the new type is deduced by merging the current type with any potential new
2563 // (partial) version of the type in the transition tree.
2564 // To do this, on each rewrite:
2565 // - Search the root of the transition tree using FindRootMap.
2566 // - Find |target_map|, the newest matching version of this map using the keys
2567 //   in the |old_map|'s descriptor array to walk the transition tree.
2568 // - Merge/generalize the descriptor array of the |old_map| and |target_map|.
2569 // - Generalize the |modify_index| descriptor using |new_representation| and
2570 //   |new_field_type|.
2571 // - Walk the tree again starting from the root towards |target_map|. Stop at
2572 //   |split_map|, the first map who's descriptor array does not match the merged
2573 //   descriptor array.
2574 // - If |target_map| == |split_map|, |target_map| is in the expected state.
2575 //   Return it.
2576 // - Otherwise, invalidate the outdated transition target from |target_map|, and
2577 //   replace its transition tree with a new branch for the updated descriptors.
2578 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
2579                                           int modify_index,
2580                                           Representation new_representation,
2581                                           Handle<HeapType> new_field_type,
2582                                           StoreMode store_mode) {
2583   Isolate* isolate = old_map->GetIsolate();
2584
2585   Handle<DescriptorArray> old_descriptors(
2586       old_map->instance_descriptors(), isolate);
2587   int old_nof = old_map->NumberOfOwnDescriptors();
2588   PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2589   Representation old_representation = old_details.representation();
2590
2591   // It's fine to transition from None to anything but double without any
2592   // modification to the object, because the default uninitialized value for
2593   // representation None can be overwritten by both smi and tagged values.
2594   // Doubles, however, would require a box allocation.
2595   if (old_representation.IsNone() &&
2596       !new_representation.IsNone() &&
2597       !new_representation.IsDouble()) {
2598     DCHECK(old_details.type() == FIELD);
2599     DCHECK(old_descriptors->GetFieldType(modify_index)->NowIs(
2600             HeapType::None()));
2601     if (FLAG_trace_generalization) {
2602       old_map->PrintGeneralization(
2603           stdout, "uninitialized field",
2604           modify_index, old_map->NumberOfOwnDescriptors(),
2605           old_map->NumberOfOwnDescriptors(), false,
2606           old_representation, new_representation,
2607           old_descriptors->GetFieldType(modify_index), *new_field_type);
2608     }
2609     old_descriptors->SetRepresentation(modify_index, new_representation);
2610     old_descriptors->SetValue(modify_index, *new_field_type);
2611     return old_map;
2612   }
2613
2614   // Check the state of the root map.
2615   Handle<Map> root_map(old_map->FindRootMap(), isolate);
2616   if (!old_map->EquivalentToForTransition(*root_map)) {
2617     return CopyGeneralizeAllRepresentations(
2618         old_map, modify_index, store_mode, "not equivalent");
2619   }
2620   int root_nof = root_map->NumberOfOwnDescriptors();
2621   if (modify_index < root_nof) {
2622     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2623     if ((old_details.type() != FIELD && store_mode == FORCE_FIELD) ||
2624         (old_details.type() == FIELD &&
2625          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
2626           !new_representation.fits_into(old_details.representation())))) {
2627       return CopyGeneralizeAllRepresentations(
2628           old_map, modify_index, store_mode, "root modification");
2629     }
2630   }
2631
2632   Handle<Map> target_map = root_map;
2633   for (int i = root_nof; i < old_nof; ++i) {
2634     int j = target_map->SearchTransition(old_descriptors->GetKey(i));
2635     if (j == TransitionArray::kNotFound) break;
2636     Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
2637     Handle<DescriptorArray> tmp_descriptors = handle(
2638         tmp_map->instance_descriptors(), isolate);
2639
2640     // Check if target map is incompatible.
2641     PropertyDetails old_details = old_descriptors->GetDetails(i);
2642     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2643     PropertyType old_type = old_details.type();
2644     PropertyType tmp_type = tmp_details.type();
2645     if (tmp_details.attributes() != old_details.attributes() ||
2646         ((tmp_type == CALLBACKS || old_type == CALLBACKS) &&
2647          (tmp_type != old_type ||
2648           tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) {
2649       return CopyGeneralizeAllRepresentations(
2650           old_map, modify_index, store_mode, "incompatible");
2651     }
2652     Representation old_representation = old_details.representation();
2653     Representation tmp_representation = tmp_details.representation();
2654     if (!old_representation.fits_into(tmp_representation) ||
2655         (!new_representation.fits_into(tmp_representation) &&
2656          modify_index == i)) {
2657       break;
2658     }
2659     if (tmp_type == FIELD) {
2660       // Generalize the field type as necessary.
2661       Handle<HeapType> old_field_type = (old_type == FIELD)
2662           ? handle(old_descriptors->GetFieldType(i), isolate)
2663           : old_descriptors->GetValue(i)->OptimalType(
2664               isolate, tmp_representation);
2665       if (modify_index == i) {
2666         old_field_type = GeneralizeFieldType(
2667             new_field_type, old_field_type, isolate);
2668       }
2669       GeneralizeFieldType(tmp_map, i, old_field_type);
2670     } else if (tmp_type == CONSTANT) {
2671       if (old_type != CONSTANT ||
2672           old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) {
2673         break;
2674       }
2675     } else {
2676       DCHECK_EQ(tmp_type, old_type);
2677       DCHECK_EQ(tmp_descriptors->GetValue(i), old_descriptors->GetValue(i));
2678     }
2679     target_map = tmp_map;
2680   }
2681
2682   // Directly change the map if the target map is more general.
2683   Handle<DescriptorArray> target_descriptors(
2684       target_map->instance_descriptors(), isolate);
2685   int target_nof = target_map->NumberOfOwnDescriptors();
2686   if (target_nof == old_nof &&
2687       (store_mode != FORCE_FIELD ||
2688        target_descriptors->GetDetails(modify_index).type() == FIELD)) {
2689     DCHECK(modify_index < target_nof);
2690     DCHECK(new_representation.fits_into(
2691             target_descriptors->GetDetails(modify_index).representation()));
2692     DCHECK(target_descriptors->GetDetails(modify_index).type() != FIELD ||
2693            new_field_type->NowIs(
2694                target_descriptors->GetFieldType(modify_index)));
2695     return target_map;
2696   }
2697
2698   // Find the last compatible target map in the transition tree.
2699   for (int i = target_nof; i < old_nof; ++i) {
2700     int j = target_map->SearchTransition(old_descriptors->GetKey(i));
2701     if (j == TransitionArray::kNotFound) break;
2702     Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
2703     Handle<DescriptorArray> tmp_descriptors(
2704         tmp_map->instance_descriptors(), isolate);
2705
2706     // Check if target map is compatible.
2707     PropertyDetails old_details = old_descriptors->GetDetails(i);
2708     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2709     if (tmp_details.attributes() != old_details.attributes() ||
2710         ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) &&
2711          (tmp_details.type() != old_details.type() ||
2712           tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) {
2713       return CopyGeneralizeAllRepresentations(
2714           old_map, modify_index, store_mode, "incompatible");
2715     }
2716     target_map = tmp_map;
2717   }
2718   target_nof = target_map->NumberOfOwnDescriptors();
2719   target_descriptors = handle(target_map->instance_descriptors(), isolate);
2720
2721   // Allocate a new descriptor array large enough to hold the required
2722   // descriptors, with minimally the exact same size as the old descriptor
2723   // array.
2724   int new_slack = Max(
2725       old_nof, old_descriptors->number_of_descriptors()) - old_nof;
2726   Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
2727       isolate, old_nof, new_slack);
2728   DCHECK(new_descriptors->length() > target_descriptors->length() ||
2729          new_descriptors->NumberOfSlackDescriptors() > 0 ||
2730          new_descriptors->number_of_descriptors() ==
2731          old_descriptors->number_of_descriptors());
2732   DCHECK(new_descriptors->number_of_descriptors() == old_nof);
2733
2734   // 0 -> |root_nof|
2735   int current_offset = 0;
2736   for (int i = 0; i < root_nof; ++i) {
2737     PropertyDetails old_details = old_descriptors->GetDetails(i);
2738     if (old_details.type() == FIELD) current_offset++;
2739     Descriptor d(handle(old_descriptors->GetKey(i), isolate),
2740                  handle(old_descriptors->GetValue(i), isolate),
2741                  old_details);
2742     new_descriptors->Set(i, &d);
2743   }
2744
2745   // |root_nof| -> |target_nof|
2746   for (int i = root_nof; i < target_nof; ++i) {
2747     Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
2748     PropertyDetails old_details = old_descriptors->GetDetails(i);
2749     PropertyDetails target_details = target_descriptors->GetDetails(i);
2750     target_details = target_details.CopyWithRepresentation(
2751         old_details.representation().generalize(
2752             target_details.representation()));
2753     if (modify_index == i) {
2754       target_details = target_details.CopyWithRepresentation(
2755           new_representation.generalize(target_details.representation()));
2756     }
2757     DCHECK_EQ(old_details.attributes(), target_details.attributes());
2758     if (old_details.type() == FIELD ||
2759         target_details.type() == FIELD ||
2760         (modify_index == i && store_mode == FORCE_FIELD) ||
2761         (target_descriptors->GetValue(i) != old_descriptors->GetValue(i))) {
2762       Handle<HeapType> old_field_type = (old_details.type() == FIELD)
2763           ? handle(old_descriptors->GetFieldType(i), isolate)
2764           : old_descriptors->GetValue(i)->OptimalType(
2765               isolate, target_details.representation());
2766       Handle<HeapType> target_field_type = (target_details.type() == FIELD)
2767           ? handle(target_descriptors->GetFieldType(i), isolate)
2768           : target_descriptors->GetValue(i)->OptimalType(
2769               isolate, target_details.representation());
2770       target_field_type = GeneralizeFieldType(
2771           target_field_type, old_field_type, isolate);
2772       if (modify_index == i) {
2773         target_field_type = GeneralizeFieldType(
2774             target_field_type, new_field_type, isolate);
2775       }
2776       FieldDescriptor d(target_key,
2777                         current_offset++,
2778                         target_field_type,
2779                         target_details.attributes(),
2780                         target_details.representation());
2781       new_descriptors->Set(i, &d);
2782     } else {
2783       DCHECK_NE(FIELD, target_details.type());
2784       Descriptor d(target_key,
2785                    handle(target_descriptors->GetValue(i), isolate),
2786                    target_details);
2787       new_descriptors->Set(i, &d);
2788     }
2789   }
2790
2791   // |target_nof| -> |old_nof|
2792   for (int i = target_nof; i < old_nof; ++i) {
2793     PropertyDetails old_details = old_descriptors->GetDetails(i);
2794     Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
2795     if (modify_index == i) {
2796       old_details = old_details.CopyWithRepresentation(
2797           new_representation.generalize(old_details.representation()));
2798     }
2799     if (old_details.type() == FIELD) {
2800       Handle<HeapType> old_field_type(
2801           old_descriptors->GetFieldType(i), isolate);
2802       if (modify_index == i) {
2803         old_field_type = GeneralizeFieldType(
2804             old_field_type, new_field_type, isolate);
2805       }
2806       FieldDescriptor d(old_key,
2807                         current_offset++,
2808                         old_field_type,
2809                         old_details.attributes(),
2810                         old_details.representation());
2811       new_descriptors->Set(i, &d);
2812     } else {
2813       DCHECK(old_details.type() == CONSTANT || old_details.type() == CALLBACKS);
2814       if (modify_index == i && store_mode == FORCE_FIELD) {
2815         FieldDescriptor d(old_key,
2816                           current_offset++,
2817                           GeneralizeFieldType(
2818                               old_descriptors->GetValue(i)->OptimalType(
2819                                   isolate, old_details.representation()),
2820                               new_field_type, isolate),
2821                           old_details.attributes(),
2822                           old_details.representation());
2823         new_descriptors->Set(i, &d);
2824       } else {
2825         DCHECK_NE(FIELD, old_details.type());
2826         Descriptor d(old_key,
2827                      handle(old_descriptors->GetValue(i), isolate),
2828                      old_details);
2829         new_descriptors->Set(i, &d);
2830       }
2831     }
2832   }
2833
2834   new_descriptors->Sort();
2835
2836   DCHECK(store_mode != FORCE_FIELD ||
2837          new_descriptors->GetDetails(modify_index).type() == FIELD);
2838
2839   Handle<Map> split_map(root_map->FindLastMatchMap(
2840           root_nof, old_nof, *new_descriptors), isolate);
2841   int split_nof = split_map->NumberOfOwnDescriptors();
2842   DCHECK_NE(old_nof, split_nof);
2843
2844   split_map->DeprecateTarget(
2845       old_descriptors->GetKey(split_nof), *new_descriptors);
2846
2847   if (FLAG_trace_generalization) {
2848     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2849     PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
2850     Handle<HeapType> old_field_type = (old_details.type() == FIELD)
2851         ? handle(old_descriptors->GetFieldType(modify_index), isolate)
2852         : HeapType::Constant(handle(old_descriptors->GetValue(modify_index),
2853                                     isolate), isolate);
2854     Handle<HeapType> new_field_type = (new_details.type() == FIELD)
2855         ? handle(new_descriptors->GetFieldType(modify_index), isolate)
2856         : HeapType::Constant(handle(new_descriptors->GetValue(modify_index),
2857                                     isolate), isolate);
2858     old_map->PrintGeneralization(
2859         stdout, "", modify_index, split_nof, old_nof,
2860         old_details.type() == CONSTANT && store_mode == FORCE_FIELD,
2861         old_details.representation(), new_details.representation(),
2862         *old_field_type, *new_field_type);
2863   }
2864
2865   // Add missing transitions.
2866   Handle<Map> new_map = split_map;
2867   for (int i = split_nof; i < old_nof; ++i) {
2868     new_map = CopyInstallDescriptors(new_map, i, new_descriptors);
2869   }
2870   new_map->set_owns_descriptors(true);
2871   return new_map;
2872 }
2873
2874
2875 // Generalize the representation of all FIELD descriptors.
2876 Handle<Map> Map::GeneralizeAllFieldRepresentations(
2877     Handle<Map> map) {
2878   Handle<DescriptorArray> descriptors(map->instance_descriptors());
2879   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
2880     if (descriptors->GetDetails(i).type() == FIELD) {
2881       map = GeneralizeRepresentation(map, i, Representation::Tagged(),
2882                                      HeapType::Any(map->GetIsolate()),
2883                                      FORCE_FIELD);
2884     }
2885   }
2886   return map;
2887 }
2888
2889
2890 // static
2891 MaybeHandle<Map> Map::TryUpdate(Handle<Map> map) {
2892   Handle<Map> proto_map(map);
2893   while (proto_map->prototype()->IsJSObject()) {
2894     Handle<JSObject> holder(JSObject::cast(proto_map->prototype()));
2895     proto_map = Handle<Map>(holder->map());
2896     if (proto_map->is_deprecated() && JSObject::TryMigrateInstance(holder)) {
2897       proto_map = Handle<Map>(holder->map());
2898     }
2899   }
2900   return TryUpdateInternal(map);
2901 }
2902
2903
2904 // static
2905 Handle<Map> Map::Update(Handle<Map> map) {
2906   return GeneralizeRepresentation(map, 0, Representation::None(),
2907                                   HeapType::None(map->GetIsolate()),
2908                                   ALLOW_AS_CONSTANT);
2909 }
2910
2911
2912 // static
2913 MaybeHandle<Map> Map::TryUpdateInternal(Handle<Map> old_map) {
2914   DisallowHeapAllocation no_allocation;
2915   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
2916
2917   if (!old_map->is_deprecated()) return old_map;
2918
2919   // Check the state of the root map.
2920   Map* root_map = old_map->FindRootMap();
2921   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
2922   int root_nof = root_map->NumberOfOwnDescriptors();
2923
2924   int old_nof = old_map->NumberOfOwnDescriptors();
2925   DescriptorArray* old_descriptors = old_map->instance_descriptors();
2926
2927   Map* new_map = root_map;
2928   for (int i = root_nof; i < old_nof; ++i) {
2929     int j = new_map->SearchTransition(old_descriptors->GetKey(i));
2930     if (j == TransitionArray::kNotFound) return MaybeHandle<Map>();
2931     new_map = new_map->GetTransition(j);
2932     DescriptorArray* new_descriptors = new_map->instance_descriptors();
2933
2934     PropertyDetails new_details = new_descriptors->GetDetails(i);
2935     PropertyDetails old_details = old_descriptors->GetDetails(i);
2936     if (old_details.attributes() != new_details.attributes() ||
2937         !old_details.representation().fits_into(new_details.representation())) {
2938       return MaybeHandle<Map>();
2939     }
2940     PropertyType new_type = new_details.type();
2941     PropertyType old_type = old_details.type();
2942     Object* new_value = new_descriptors->GetValue(i);
2943     Object* old_value = old_descriptors->GetValue(i);
2944     switch (new_type) {
2945       case FIELD:
2946         if ((old_type == FIELD &&
2947              !HeapType::cast(old_value)->NowIs(HeapType::cast(new_value))) ||
2948             (old_type == CONSTANT &&
2949              !HeapType::cast(new_value)->NowContains(old_value)) ||
2950             (old_type == CALLBACKS &&
2951              !HeapType::Any()->Is(HeapType::cast(new_value)))) {
2952           return MaybeHandle<Map>();
2953         }
2954         break;
2955
2956       case CONSTANT:
2957       case CALLBACKS:
2958         if (old_type != new_type || old_value != new_value) {
2959           return MaybeHandle<Map>();
2960         }
2961         break;
2962
2963       case NORMAL:
2964       case HANDLER:
2965       case INTERCEPTOR:
2966       case NONEXISTENT:
2967         UNREACHABLE();
2968     }
2969   }
2970   if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
2971   return handle(new_map);
2972 }
2973
2974
2975 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
2976                                                          Handle<Object> value) {
2977   // TODO(rossberg): Support symbols in the API.
2978   if (it->name()->IsSymbol()) return value;
2979
2980   Handle<String> name_string = Handle<String>::cast(it->name());
2981   Handle<JSObject> holder = it->GetHolder<JSObject>();
2982   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
2983   if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>();
2984
2985   LOG(it->isolate(),
2986       ApiNamedPropertyAccess("interceptor-named-set", *holder, *name_string));
2987   PropertyCallbackArguments args(it->isolate(), interceptor->data(), *holder,
2988                                  *holder);
2989   v8::NamedPropertySetterCallback setter =
2990       v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter());
2991   v8::Handle<v8::Value> result = args.Call(
2992       setter, v8::Utils::ToLocal(name_string), v8::Utils::ToLocal(value));
2993   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
2994   if (!result.IsEmpty()) return value;
2995
2996   return MaybeHandle<Object>();
2997 }
2998
2999
3000 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
3001                                         Handle<Name> name, Handle<Object> value,
3002                                         StrictMode strict_mode,
3003                                         StoreFromKeyed store_mode) {
3004   LookupIterator it(object, name);
3005   return SetProperty(&it, value, strict_mode, store_mode);
3006 }
3007
3008
3009 MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
3010                                         Handle<Object> value,
3011                                         StrictMode strict_mode,
3012                                         StoreFromKeyed store_mode) {
3013   // Make sure that the top context does not change when doing callbacks or
3014   // interceptor calls.
3015   AssertNoContextChange ncc(it->isolate());
3016
3017   bool done = false;
3018   for (; it->IsFound(); it->Next()) {
3019     switch (it->state()) {
3020       case LookupIterator::NOT_FOUND:
3021         UNREACHABLE();
3022
3023       case LookupIterator::ACCESS_CHECK:
3024         // TODO(verwaest): Remove the distinction. This is mostly bogus since we
3025         // don't know whether we'll want to fetch attributes or call a setter
3026         // until we find the property.
3027         if (it->HasAccess(v8::ACCESS_SET)) break;
3028         return JSObject::SetPropertyWithFailedAccessCheck(it, value,
3029                                                           strict_mode);
3030
3031       case LookupIterator::JSPROXY:
3032         if (it->HolderIsReceiverOrHiddenPrototype()) {
3033           return JSProxy::SetPropertyWithHandler(it->GetHolder<JSProxy>(),
3034                                                  it->GetReceiver(), it->name(),
3035                                                  value, strict_mode);
3036         } else {
3037           // TODO(verwaest): Use the MaybeHandle to indicate result.
3038           bool has_result = false;
3039           MaybeHandle<Object> maybe_result =
3040               JSProxy::SetPropertyViaPrototypesWithHandler(
3041                   it->GetHolder<JSProxy>(), it->GetReceiver(), it->name(),
3042                   value, strict_mode, &has_result);
3043           if (has_result) return maybe_result;
3044           done = true;
3045         }
3046         break;
3047
3048       case LookupIterator::INTERCEPTOR:
3049         if (it->HolderIsReceiverOrHiddenPrototype()) {
3050           MaybeHandle<Object> maybe_result =
3051               JSObject::SetPropertyWithInterceptor(it, value);
3052           if (!maybe_result.is_null()) return maybe_result;
3053           if (it->isolate()->has_pending_exception()) return maybe_result;
3054         } else {
3055           Maybe<PropertyAttributes> maybe_attributes =
3056               JSObject::GetPropertyAttributesWithInterceptor(
3057                   it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
3058           if (!maybe_attributes.has_value) return MaybeHandle<Object>();
3059           done = maybe_attributes.value != ABSENT;
3060           if (done && (maybe_attributes.value & READ_ONLY) != 0) {
3061             return WriteToReadOnlyProperty(it, value, strict_mode);
3062           }
3063         }
3064         break;
3065
3066       case LookupIterator::PROPERTY:
3067         if (!it->HasProperty()) break;
3068         if (it->property_details().IsReadOnly()) {
3069           return WriteToReadOnlyProperty(it, value, strict_mode);
3070         }
3071         switch (it->property_kind()) {
3072           case LookupIterator::ACCESSOR:
3073             if (it->HolderIsReceiverOrHiddenPrototype() ||
3074                 !it->GetAccessors()->IsDeclaredAccessorInfo()) {
3075               return SetPropertyWithAccessor(it->GetReceiver(), it->name(),
3076                                              value, it->GetHolder<JSObject>(),
3077                                              it->GetAccessors(), strict_mode);
3078             }
3079             break;
3080           case LookupIterator::DATA:
3081             if (it->HolderIsReceiverOrHiddenPrototype()) {
3082               return SetDataProperty(it, value);
3083             }
3084         }
3085         done = true;
3086         break;
3087     }
3088
3089     if (done) break;
3090   }
3091
3092   return AddDataProperty(it, value, NONE, strict_mode, store_mode);
3093 }
3094
3095
3096 MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it,
3097                                                     Handle<Object> value,
3098                                                     StrictMode strict_mode) {
3099   if (strict_mode != STRICT) return value;
3100
3101   Handle<Object> args[] = {it->name(), it->GetReceiver()};
3102   Handle<Object> error = it->factory()->NewTypeError(
3103       "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3104   return it->isolate()->Throw<Object>(error);
3105 }
3106
3107
3108 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
3109                                             Handle<Object> value) {
3110   // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3111   // have own properties.
3112   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3113
3114   // Store on the holder which may be hidden behind the receiver.
3115   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
3116
3117   // Old value for the observation change record.
3118   // Fetch before transforming the object since the encoding may become
3119   // incompatible with what's cached in |it|.
3120   bool is_observed =
3121       receiver->map()->is_observed() &&
3122       !it->name().is_identical_to(it->factory()->hidden_string());
3123   MaybeHandle<Object> maybe_old;
3124   if (is_observed) maybe_old = it->GetDataValue();
3125
3126   // Possibly migrate to the most up-to-date map that will be able to store
3127   // |value| under it->name().
3128   it->PrepareForDataProperty(value);
3129
3130   // Write the property value.
3131   it->WriteDataValue(value);
3132
3133   // Send the change record if there are observers.
3134   if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
3135     JSObject::EnqueueChangeRecord(receiver, "update", it->name(),
3136                                   maybe_old.ToHandleChecked());
3137   }
3138
3139   return value;
3140 }
3141
3142
3143 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3144                                             Handle<Object> value,
3145                                             PropertyAttributes attributes,
3146                                             StrictMode strict_mode,
3147                                             StoreFromKeyed store_mode) {
3148   DCHECK(!it->GetReceiver()->IsJSProxy());
3149   if (!it->GetReceiver()->IsJSObject()) {
3150     // TODO(verwaest): Throw a TypeError with a more specific message.
3151     return WriteToReadOnlyProperty(it, value, strict_mode);
3152   }
3153   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3154
3155   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3156   // instead. If the prototype is Null, the proxy is detached.
3157   if (receiver->IsJSGlobalProxy()) {
3158     // Trying to assign to a detached proxy.
3159     PrototypeIterator iter(it->isolate(), receiver);
3160     if (iter.IsAtEnd()) return value;
3161     receiver =
3162         Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter));
3163   }
3164
3165   if (!receiver->map()->is_extensible()) {
3166     if (strict_mode == SLOPPY) return value;
3167
3168     Handle<Object> args[1] = {it->name()};
3169     Handle<Object> error = it->factory()->NewTypeError(
3170         "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
3171     return it->isolate()->Throw<Object>(error);
3172   }
3173
3174   // Possibly migrate to the most up-to-date map that will be able to store
3175   // |value| under it->name() with |attributes|.
3176   it->TransitionToDataProperty(value, attributes, store_mode);
3177
3178   // TODO(verwaest): Encapsulate dictionary handling better.
3179   if (receiver->map()->is_dictionary_map()) {
3180     // TODO(verwaest): Probably should ensure this is done beforehand.
3181     it->InternalizeName();
3182     JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3183   } else {
3184     // Write the property value.
3185     it->WriteDataValue(value);
3186   }
3187
3188   // Send the change record if there are observers.
3189   if (receiver->map()->is_observed() &&
3190       !it->name().is_identical_to(it->factory()->hidden_string())) {
3191     JSObject::EnqueueChangeRecord(receiver, "add", it->name(),
3192                                   it->factory()->the_hole_value());
3193   }
3194
3195   return value;
3196 }
3197
3198
3199 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3200     Handle<JSObject> object,
3201     uint32_t index,
3202     Handle<Object> value,
3203     bool* found,
3204     StrictMode strict_mode) {
3205   Isolate *isolate = object->GetIsolate();
3206   for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
3207        iter.Advance()) {
3208     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
3209       return JSProxy::SetPropertyViaPrototypesWithHandler(
3210           Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object,
3211           isolate->factory()->Uint32ToString(index),  // name
3212           value, strict_mode, found);
3213     }
3214     Handle<JSObject> js_proto =
3215         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
3216     if (!js_proto->HasDictionaryElements()) {
3217       continue;
3218     }
3219     Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
3220     int entry = dictionary->FindEntry(index);
3221     if (entry != SeededNumberDictionary::kNotFound) {
3222       PropertyDetails details = dictionary->DetailsAt(entry);
3223       if (details.type() == CALLBACKS) {
3224         *found = true;
3225         Handle<Object> structure(dictionary->ValueAt(entry), isolate);
3226         return SetElementWithCallback(object, structure, index, value, js_proto,
3227                                       strict_mode);
3228       }
3229     }
3230   }
3231   *found = false;
3232   return isolate->factory()->the_hole_value();
3233 }
3234
3235
3236 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3237   // Only supports adding slack to owned descriptors.
3238   DCHECK(map->owns_descriptors());
3239
3240   Handle<DescriptorArray> descriptors(map->instance_descriptors());
3241   int old_size = map->NumberOfOwnDescriptors();
3242   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3243
3244   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3245       descriptors, old_size, slack);
3246
3247   if (old_size == 0) {
3248     map->set_instance_descriptors(*new_descriptors);
3249     return;
3250   }
3251
3252   // If the source descriptors had an enum cache we copy it. This ensures
3253   // that the maps to which we push the new descriptor array back can rely
3254   // on a cache always being available once it is set. If the map has more
3255   // enumerated descriptors than available in the original cache, the cache
3256   // will be lazily replaced by the extended cache when needed.
3257   if (descriptors->HasEnumCache()) {
3258     new_descriptors->CopyEnumCacheFrom(*descriptors);
3259   }
3260
3261   // Replace descriptors by new_descriptors in all maps that share it.
3262   map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
3263
3264   Map* walk_map;
3265   for (Object* current = map->GetBackPointer();
3266        !current->IsUndefined();
3267        current = walk_map->GetBackPointer()) {
3268     walk_map = Map::cast(current);
3269     if (walk_map->instance_descriptors() != *descriptors) break;
3270     walk_map->set_instance_descriptors(*new_descriptors);
3271   }
3272
3273   map->set_instance_descriptors(*new_descriptors);
3274 }
3275
3276
3277 template<class T>
3278 static int AppendUniqueCallbacks(NeanderArray* callbacks,
3279                                  Handle<typename T::Array> array,
3280                                  int valid_descriptors) {
3281   int nof_callbacks = callbacks->length();
3282
3283   Isolate* isolate = array->GetIsolate();
3284   // Ensure the keys are unique names before writing them into the
3285   // instance descriptor. Since it may cause a GC, it has to be done before we
3286   // temporarily put the heap in an invalid state while appending descriptors.
3287   for (int i = 0; i < nof_callbacks; ++i) {
3288     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3289     if (entry->name()->IsUniqueName()) continue;
3290     Handle<String> key =
3291         isolate->factory()->InternalizeString(
3292             Handle<String>(String::cast(entry->name())));
3293     entry->set_name(*key);
3294   }
3295
3296   // Fill in new callback descriptors.  Process the callbacks from
3297   // back to front so that the last callback with a given name takes
3298   // precedence over previously added callbacks with that name.
3299   for (int i = nof_callbacks - 1; i >= 0; i--) {
3300     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3301     Handle<Name> key(Name::cast(entry->name()));
3302     // Check if a descriptor with this name already exists before writing.
3303     if (!T::Contains(key, entry, valid_descriptors, array)) {
3304       T::Insert(key, entry, valid_descriptors, array);
3305       valid_descriptors++;
3306     }
3307   }
3308
3309   return valid_descriptors;
3310 }
3311
3312 struct DescriptorArrayAppender {
3313   typedef DescriptorArray Array;
3314   static bool Contains(Handle<Name> key,
3315                        Handle<AccessorInfo> entry,
3316                        int valid_descriptors,
3317                        Handle<DescriptorArray> array) {
3318     DisallowHeapAllocation no_gc;
3319     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
3320   }
3321   static void Insert(Handle<Name> key,
3322                      Handle<AccessorInfo> entry,
3323                      int valid_descriptors,
3324                      Handle<DescriptorArray> array) {
3325     DisallowHeapAllocation no_gc;
3326     CallbacksDescriptor desc(key, entry, entry->property_attributes());
3327     array->Append(&desc);
3328   }
3329 };
3330
3331
3332 struct FixedArrayAppender {
3333   typedef FixedArray Array;
3334   static bool Contains(Handle<Name> key,
3335                        Handle<AccessorInfo> entry,
3336                        int valid_descriptors,
3337                        Handle<FixedArray> array) {
3338     for (int i = 0; i < valid_descriptors; i++) {
3339       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
3340     }
3341     return false;
3342   }
3343   static void Insert(Handle<Name> key,
3344                      Handle<AccessorInfo> entry,
3345                      int valid_descriptors,
3346                      Handle<FixedArray> array) {
3347     DisallowHeapAllocation no_gc;
3348     array->set(valid_descriptors, *entry);
3349   }
3350 };
3351
3352
3353 void Map::AppendCallbackDescriptors(Handle<Map> map,
3354                                     Handle<Object> descriptors) {
3355   int nof = map->NumberOfOwnDescriptors();
3356   Handle<DescriptorArray> array(map->instance_descriptors());
3357   NeanderArray callbacks(descriptors);
3358   DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
3359   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3360   map->SetNumberOfOwnDescriptors(nof);
3361 }
3362
3363
3364 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
3365                                Handle<FixedArray> array,
3366                                int valid_descriptors) {
3367   NeanderArray callbacks(descriptors);
3368   DCHECK(array->length() >= callbacks.length() + valid_descriptors);
3369   return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3370                                                    array,
3371                                                    valid_descriptors);
3372 }
3373
3374
3375 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
3376   DCHECK(!map.is_null());
3377   for (int i = 0; i < maps->length(); ++i) {
3378     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
3379   }
3380   return false;
3381 }
3382
3383
3384 template <class T>
3385 static Handle<T> MaybeNull(T* p) {
3386   if (p == NULL) return Handle<T>::null();
3387   return Handle<T>(p);
3388 }
3389
3390
3391 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
3392   ElementsKind kind = elements_kind();
3393   Handle<Map> transitioned_map = Handle<Map>::null();
3394   Handle<Map> current_map(this);
3395   bool packed = IsFastPackedElementsKind(kind);
3396   if (IsTransitionableFastElementsKind(kind)) {
3397     while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
3398       kind = GetNextMoreGeneralFastElementsKind(kind, false);
3399       Handle<Map> maybe_transitioned_map =
3400           MaybeNull(current_map->LookupElementsTransitionMap(kind));
3401       if (maybe_transitioned_map.is_null()) break;
3402       if (ContainsMap(candidates, maybe_transitioned_map) &&
3403           (packed || !IsFastPackedElementsKind(kind))) {
3404         transitioned_map = maybe_transitioned_map;
3405         if (!IsFastPackedElementsKind(kind)) packed = false;
3406       }
3407       current_map = maybe_transitioned_map;
3408     }
3409   }
3410   return transitioned_map;
3411 }
3412
3413
3414 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
3415   Map* current_map = map;
3416   int target_kind =
3417       IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
3418       ? to_kind
3419       : TERMINAL_FAST_ELEMENTS_KIND;
3420
3421   // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
3422   // allows to change elements from arbitrary kind to any ExternalArray
3423   // elements kind. Satisfy its requirements, checking whether we already
3424   // have the cached transition.
3425   if (IsExternalArrayElementsKind(to_kind) &&
3426       !IsFixedTypedArrayElementsKind(map->elements_kind())) {
3427     if (map->HasElementsTransition()) {
3428         Map* next_map = map->elements_transition_map();
3429         if (next_map->elements_kind() == to_kind) return next_map;
3430     }
3431     return map;
3432   }
3433
3434   ElementsKind kind = map->elements_kind();
3435   while (kind != target_kind) {
3436     kind = GetNextTransitionElementsKind(kind);
3437     if (!current_map->HasElementsTransition()) return current_map;
3438     current_map = current_map->elements_transition_map();
3439   }
3440
3441   if (to_kind != kind && current_map->HasElementsTransition()) {
3442     DCHECK(to_kind == DICTIONARY_ELEMENTS);
3443     Map* next_map = current_map->elements_transition_map();
3444     if (next_map->elements_kind() == to_kind) return next_map;
3445   }
3446
3447   DCHECK(current_map->elements_kind() == target_kind);
3448   return current_map;
3449 }
3450
3451
3452 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3453   Map* to_map = FindClosestElementsTransition(this, to_kind);
3454   if (to_map->elements_kind() == to_kind) return to_map;
3455   return NULL;
3456 }
3457
3458
3459 bool Map::IsMapInArrayPrototypeChain() {
3460   Isolate* isolate = GetIsolate();
3461   if (isolate->initial_array_prototype()->map() == this) {
3462     return true;
3463   }
3464
3465   if (isolate->initial_object_prototype()->map() == this) {
3466     return true;
3467   }
3468
3469   return false;
3470 }
3471
3472
3473 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
3474                                                  ElementsKind to_kind) {
3475   DCHECK(IsTransitionElementsKind(map->elements_kind()));
3476
3477   Handle<Map> current_map = map;
3478
3479   ElementsKind kind = map->elements_kind();
3480   if (!map->is_prototype_map()) {
3481     while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3482       kind = GetNextTransitionElementsKind(kind);
3483       current_map =
3484           Map::CopyAsElementsKind(current_map, kind, INSERT_TRANSITION);
3485     }
3486   }
3487
3488   // In case we are exiting the fast elements kind system, just add the map in
3489   // the end.
3490   if (kind != to_kind) {
3491     current_map = Map::CopyAsElementsKind(
3492         current_map, to_kind, INSERT_TRANSITION);
3493   }
3494
3495   DCHECK(current_map->elements_kind() == to_kind);
3496   return current_map;
3497 }
3498
3499
3500 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
3501                                       ElementsKind to_kind) {
3502   ElementsKind from_kind = map->elements_kind();
3503   if (from_kind == to_kind) return map;
3504
3505   Isolate* isolate = map->GetIsolate();
3506   Context* native_context = isolate->context()->native_context();
3507   Object* maybe_array_maps = native_context->js_array_maps();
3508   if (maybe_array_maps->IsFixedArray()) {
3509     DisallowHeapAllocation no_gc;
3510     FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
3511     if (array_maps->get(from_kind) == *map) {
3512       Object* maybe_transitioned_map = array_maps->get(to_kind);
3513       if (maybe_transitioned_map->IsMap()) {
3514         return handle(Map::cast(maybe_transitioned_map));
3515       }
3516     }
3517   }
3518
3519   return TransitionElementsToSlow(map, to_kind);
3520 }
3521
3522
3523 Handle<Map> Map::TransitionElementsToSlow(Handle<Map> map,
3524                                           ElementsKind to_kind) {
3525   ElementsKind from_kind = map->elements_kind();
3526
3527   if (from_kind == to_kind) {
3528     return map;
3529   }
3530
3531   bool allow_store_transition =
3532       // Only remember the map transition if there is not an already existing
3533       // non-matching element transition.
3534       !map->IsUndefined() && !map->is_dictionary_map() &&
3535       IsTransitionElementsKind(from_kind);
3536
3537   // Only store fast element maps in ascending generality.
3538   if (IsFastElementsKind(to_kind)) {
3539     allow_store_transition &=
3540         IsTransitionableFastElementsKind(from_kind) &&
3541         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3542   }
3543
3544   if (!allow_store_transition) {
3545     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
3546   }
3547
3548   return Map::AsElementsKind(map, to_kind);
3549 }
3550
3551
3552 // static
3553 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
3554   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
3555
3556   if (closest_map->elements_kind() == kind) {
3557     return closest_map;
3558   }
3559
3560   return AddMissingElementsTransitions(closest_map, kind);
3561 }
3562
3563
3564 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
3565                                                ElementsKind to_kind) {
3566   Handle<Map> map(object->map());
3567   return Map::TransitionElementsTo(map, to_kind);
3568 }
3569
3570
3571 void JSObject::LookupOwnRealNamedProperty(Handle<Name> name,
3572                                           LookupResult* result) {
3573   DisallowHeapAllocation no_gc;
3574   if (IsJSGlobalProxy()) {
3575     PrototypeIterator iter(GetIsolate(), this);
3576     if (iter.IsAtEnd()) return result->NotFound();
3577     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
3578     return JSObject::cast(iter.GetCurrent())
3579         ->LookupOwnRealNamedProperty(name, result);
3580   }
3581
3582   if (HasFastProperties()) {
3583     map()->LookupDescriptor(this, *name, result);
3584     // A property or a map transition was found. We return all of these result
3585     // types because LookupOwnRealNamedProperty is used when setting
3586     // properties where map transitions are handled.
3587     DCHECK(!result->IsFound() ||
3588            (result->holder() == this && result->IsFastPropertyType()));
3589     return;
3590   }
3591
3592   int entry = property_dictionary()->FindEntry(name);
3593   if (entry != NameDictionary::kNotFound) {
3594     Object* value = property_dictionary()->ValueAt(entry);
3595     if (IsGlobalObject()) {
3596       PropertyDetails d = property_dictionary()->DetailsAt(entry);
3597       if (d.IsDeleted() || PropertyCell::cast(value)->value()->IsTheHole()) {
3598         result->NotFound();
3599         return;
3600       }
3601       value = PropertyCell::cast(value)->value();
3602     }
3603     result->DictionaryResult(this, entry);
3604     return;
3605   }
3606
3607   result->NotFound();
3608 }
3609
3610
3611 void JSObject::LookupRealNamedProperty(Handle<Name> name,
3612                                        LookupResult* result) {
3613   DisallowHeapAllocation no_gc;
3614   LookupOwnRealNamedProperty(name, result);
3615   if (result->IsFound()) return;
3616
3617   LookupRealNamedPropertyInPrototypes(name, result);
3618 }
3619
3620
3621 void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name,
3622                                                    LookupResult* result) {
3623   DisallowHeapAllocation no_gc;
3624   Isolate* isolate = GetIsolate();
3625   for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd(); iter.Advance()) {
3626     if (iter.GetCurrent()->IsJSProxy()) {
3627       return result->HandlerResult(JSProxy::cast(iter.GetCurrent()));
3628     }
3629     JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result);
3630     DCHECK(!(result->IsFound() && result->type() == INTERCEPTOR));
3631     if (result->IsFound()) return;
3632   }
3633   result->NotFound();
3634 }
3635
3636
3637 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy,
3638                                             Handle<Name> name) {
3639   Isolate* isolate = proxy->GetIsolate();
3640
3641   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3642   if (name->IsSymbol()) return maybe(false);
3643
3644   Handle<Object> args[] = { name };
3645   Handle<Object> result;
3646   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3647       isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(),
3648                                 ARRAY_SIZE(args), args),
3649       Maybe<bool>());
3650
3651   return maybe(result->BooleanValue());
3652 }
3653
3654
3655 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy,
3656                                                     Handle<Object> receiver,
3657                                                     Handle<Name> name,
3658                                                     Handle<Object> value,
3659                                                     StrictMode strict_mode) {
3660   Isolate* isolate = proxy->GetIsolate();
3661
3662   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3663   if (name->IsSymbol()) return value;
3664
3665   Handle<Object> args[] = { receiver, name, value };
3666   RETURN_ON_EXCEPTION(
3667       isolate,
3668       CallTrap(proxy,
3669                "set",
3670                isolate->derived_set_trap(),
3671                ARRAY_SIZE(args),
3672                args),
3673       Object);
3674
3675   return value;
3676 }
3677
3678
3679 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3680     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3681     Handle<Object> value, StrictMode strict_mode, bool* done) {
3682   Isolate* isolate = proxy->GetIsolate();
3683   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy.
3684
3685   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3686   if (name->IsSymbol()) {
3687     *done = false;
3688     return isolate->factory()->the_hole_value();
3689   }
3690
3691   *done = true;  // except where redefined...
3692   Handle<Object> args[] = { name };
3693   Handle<Object> result;
3694   ASSIGN_RETURN_ON_EXCEPTION(
3695       isolate, result,
3696       CallTrap(proxy,
3697                "getPropertyDescriptor",
3698                Handle<Object>(),
3699                ARRAY_SIZE(args),
3700                args),
3701       Object);
3702
3703   if (result->IsUndefined()) {
3704     *done = false;
3705     return isolate->factory()->the_hole_value();
3706   }
3707
3708   // Emulate [[GetProperty]] semantics for proxies.
3709   Handle<Object> argv[] = { result };
3710   Handle<Object> desc;
3711   ASSIGN_RETURN_ON_EXCEPTION(
3712       isolate, desc,
3713       Execution::Call(isolate,
3714                       isolate->to_complete_property_descriptor(),
3715                       result,
3716                       ARRAY_SIZE(argv),
3717                       argv),
3718       Object);
3719
3720   // [[GetProperty]] requires to check that all properties are configurable.
3721   Handle<String> configurable_name =
3722       isolate->factory()->InternalizeOneByteString(
3723           STATIC_ASCII_VECTOR("configurable_"));
3724   Handle<Object> configurable =
3725       Object::GetProperty(desc, configurable_name).ToHandleChecked();
3726   DCHECK(configurable->IsBoolean());
3727   if (configurable->IsFalse()) {
3728     Handle<String> trap =
3729         isolate->factory()->InternalizeOneByteString(
3730             STATIC_ASCII_VECTOR("getPropertyDescriptor"));
3731     Handle<Object> args[] = { handler, trap, name };
3732     Handle<Object> error = isolate->factory()->NewTypeError(
3733         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
3734     return isolate->Throw<Object>(error);
3735   }
3736   DCHECK(configurable->IsTrue());
3737
3738   // Check for DataDescriptor.
3739   Handle<String> hasWritable_name =
3740       isolate->factory()->InternalizeOneByteString(
3741           STATIC_ASCII_VECTOR("hasWritable_"));
3742   Handle<Object> hasWritable =
3743       Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
3744   DCHECK(hasWritable->IsBoolean());
3745   if (hasWritable->IsTrue()) {
3746     Handle<String> writable_name =
3747         isolate->factory()->InternalizeOneByteString(
3748             STATIC_ASCII_VECTOR("writable_"));
3749     Handle<Object> writable =
3750         Object::GetProperty(desc, writable_name).ToHandleChecked();
3751     DCHECK(writable->IsBoolean());
3752     *done = writable->IsFalse();
3753     if (!*done) return isolate->factory()->the_hole_value();
3754     if (strict_mode == SLOPPY) return value;
3755     Handle<Object> args[] = { name, receiver };
3756     Handle<Object> error = isolate->factory()->NewTypeError(
3757         "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3758     return isolate->Throw<Object>(error);
3759   }
3760
3761   // We have an AccessorDescriptor.
3762   Handle<String> set_name = isolate->factory()->InternalizeOneByteString(
3763       STATIC_ASCII_VECTOR("set_"));
3764   Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
3765   if (!setter->IsUndefined()) {
3766     // TODO(rossberg): nicer would be to cast to some JSCallable here...
3767     return SetPropertyWithDefinedSetter(
3768         receiver, Handle<JSReceiver>::cast(setter), value);
3769   }
3770
3771   if (strict_mode == SLOPPY) return value;
3772   Handle<Object> args2[] = { name, proxy };
3773   Handle<Object> error = isolate->factory()->NewTypeError(
3774       "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
3775   return isolate->Throw<Object>(error);
3776 }
3777
3778
3779 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
3780     Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) {
3781   Isolate* isolate = proxy->GetIsolate();
3782
3783   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3784   if (name->IsSymbol()) return isolate->factory()->false_value();
3785
3786   Handle<Object> args[] = { name };
3787   Handle<Object> result;
3788   ASSIGN_RETURN_ON_EXCEPTION(
3789       isolate, result,
3790       CallTrap(proxy,
3791                "delete",
3792                Handle<Object>(),
3793                ARRAY_SIZE(args),
3794                args),
3795       Object);
3796
3797   bool result_bool = result->BooleanValue();
3798   if (mode == STRICT_DELETION && !result_bool) {
3799     Handle<Object> handler(proxy->handler(), isolate);
3800     Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
3801         STATIC_ASCII_VECTOR("delete"));
3802     Handle<Object> args[] = { handler, trap_name };
3803     Handle<Object> error = isolate->factory()->NewTypeError(
3804         "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
3805     return isolate->Throw<Object>(error);
3806   }
3807   return isolate->factory()->ToBoolean(result_bool);
3808 }
3809
3810
3811 MaybeHandle<Object> JSProxy::DeleteElementWithHandler(
3812     Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) {
3813   Isolate* isolate = proxy->GetIsolate();
3814   Handle<String> name = isolate->factory()->Uint32ToString(index);
3815   return JSProxy::DeletePropertyWithHandler(proxy, name, mode);
3816 }
3817
3818
3819 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
3820     Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
3821   Isolate* isolate = proxy->GetIsolate();
3822   HandleScope scope(isolate);
3823
3824   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3825   if (name->IsSymbol()) return maybe(ABSENT);
3826
3827   Handle<Object> args[] = { name };
3828   Handle<Object> result;
3829   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3830       isolate, result,
3831       proxy->CallTrap(proxy, "getPropertyDescriptor", Handle<Object>(),
3832                       ARRAY_SIZE(args), args),
3833       Maybe<PropertyAttributes>());
3834
3835   if (result->IsUndefined()) return maybe(ABSENT);
3836
3837   Handle<Object> argv[] = { result };
3838   Handle<Object> desc;
3839   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3840       isolate, desc,
3841       Execution::Call(isolate, isolate->to_complete_property_descriptor(),
3842                       result, ARRAY_SIZE(argv), argv),
3843       Maybe<PropertyAttributes>());
3844
3845   // Convert result to PropertyAttributes.
3846   Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3847       STATIC_ASCII_VECTOR("enumerable_"));
3848   Handle<Object> enumerable;
3849   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable,
3850                                    Object::GetProperty(desc, enum_n),
3851                                    Maybe<PropertyAttributes>());
3852   Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
3853       STATIC_ASCII_VECTOR("configurable_"));
3854   Handle<Object> configurable;
3855   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
3856                                    Object::GetProperty(desc, conf_n),
3857                                    Maybe<PropertyAttributes>());
3858   Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
3859       STATIC_ASCII_VECTOR("writable_"));
3860   Handle<Object> writable;
3861   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
3862                                    Object::GetProperty(desc, writ_n),
3863                                    Maybe<PropertyAttributes>());
3864   if (!writable->BooleanValue()) {
3865     Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
3866         STATIC_ASCII_VECTOR("set_"));
3867     Handle<Object> setter;
3868     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
3869                                      Object::GetProperty(desc, set_n),
3870                                      Maybe<PropertyAttributes>());
3871     writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
3872   }
3873
3874   if (configurable->IsFalse()) {
3875     Handle<Object> handler(proxy->handler(), isolate);
3876     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3877         STATIC_ASCII_VECTOR("getPropertyDescriptor"));
3878     Handle<Object> args[] = { handler, trap, name };
3879     Handle<Object> error = isolate->factory()->NewTypeError(
3880         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
3881     isolate->Throw(*error);
3882     return maybe(NONE);
3883   }
3884
3885   int attributes = NONE;
3886   if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
3887   if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
3888   if (!writable->BooleanValue()) attributes |= READ_ONLY;
3889   return maybe(static_cast<PropertyAttributes>(attributes));
3890 }
3891
3892
3893 Maybe<PropertyAttributes> JSProxy::GetElementAttributeWithHandler(
3894     Handle<JSProxy> proxy, Handle<JSReceiver> receiver, uint32_t index) {
3895   Isolate* isolate = proxy->GetIsolate();
3896   Handle<String> name = isolate->factory()->Uint32ToString(index);
3897   return GetPropertyAttributesWithHandler(proxy, receiver, name);
3898 }
3899
3900
3901 void JSProxy::Fix(Handle<JSProxy> proxy) {
3902   Isolate* isolate = proxy->GetIsolate();
3903
3904   // Save identity hash.
3905   Handle<Object> hash(proxy->GetIdentityHash(), isolate);
3906
3907   if (proxy->IsJSFunctionProxy()) {
3908     isolate->factory()->BecomeJSFunction(proxy);
3909     // Code will be set on the JavaScript side.
3910   } else {
3911     isolate->factory()->BecomeJSObject(proxy);
3912   }
3913   DCHECK(proxy->IsJSObject());
3914
3915   // Inherit identity, if it was present.
3916   if (hash->IsSmi()) {
3917     JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
3918                               Handle<Smi>::cast(hash));
3919   }
3920 }
3921
3922
3923 MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
3924                                       const char* name,
3925                                       Handle<Object> derived,
3926                                       int argc,
3927                                       Handle<Object> argv[]) {
3928   Isolate* isolate = proxy->GetIsolate();
3929   Handle<Object> handler(proxy->handler(), isolate);
3930
3931   Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
3932   Handle<Object> trap;
3933   ASSIGN_RETURN_ON_EXCEPTION(
3934       isolate, trap,
3935       Object::GetPropertyOrElement(handler, trap_name),
3936       Object);
3937
3938   if (trap->IsUndefined()) {
3939     if (derived.is_null()) {
3940       Handle<Object> args[] = { handler, trap_name };
3941       Handle<Object> error = isolate->factory()->NewTypeError(
3942         "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
3943       return isolate->Throw<Object>(error);
3944     }
3945     trap = Handle<Object>(derived);
3946   }
3947
3948   return Execution::Call(isolate, trap, handler, argc, argv);
3949 }
3950
3951
3952 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
3953   DCHECK(object->map()->inobject_properties() == map->inobject_properties());
3954   ElementsKind obj_kind = object->map()->elements_kind();
3955   ElementsKind map_kind = map->elements_kind();
3956   if (map_kind != obj_kind) {
3957     ElementsKind to_kind = map_kind;
3958     if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
3959         IsDictionaryElementsKind(obj_kind)) {
3960       to_kind = obj_kind;
3961     }
3962     if (IsDictionaryElementsKind(to_kind)) {
3963       NormalizeElements(object);
3964     } else {
3965       TransitionElementsKind(object, to_kind);
3966     }
3967     map = Map::AsElementsKind(map, to_kind);
3968   }
3969   JSObject::MigrateToMap(object, map);
3970 }
3971
3972
3973 void JSObject::MigrateInstance(Handle<JSObject> object) {
3974   Handle<Map> original_map(object->map());
3975   Handle<Map> map = Map::Update(original_map);
3976   map->set_migration_target(true);
3977   MigrateToMap(object, map);
3978   if (FLAG_trace_migration) {
3979     object->PrintInstanceMigration(stdout, *original_map, *map);
3980   }
3981 }
3982
3983
3984 // static
3985 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
3986   Isolate* isolate = object->GetIsolate();
3987   DisallowDeoptimization no_deoptimization(isolate);
3988   Handle<Map> original_map(object->map(), isolate);
3989   Handle<Map> new_map;
3990   if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
3991     return false;
3992   }
3993   JSObject::MigrateToMap(object, new_map);
3994   if (FLAG_trace_migration) {
3995     object->PrintInstanceMigration(stdout, *original_map, object->map());
3996   }
3997   return true;
3998 }
3999
4000
4001 MaybeHandle<Object> JSObject::SetPropertyUsingTransition(
4002     Handle<JSObject> object,
4003     LookupResult* lookup,
4004     Handle<Name> name,
4005     Handle<Object> value,
4006     PropertyAttributes attributes) {
4007   Handle<Map> transition_map(lookup->GetTransitionTarget());
4008   int descriptor = transition_map->LastAdded();
4009
4010   Handle<DescriptorArray> descriptors(transition_map->instance_descriptors());
4011   PropertyDetails details = descriptors->GetDetails(descriptor);
4012
4013   if (details.type() == CALLBACKS || attributes != details.attributes()) {
4014     // AddPropertyInternal will either normalize the object, or create a new
4015     // fast copy of the map. If we get a fast copy of the map, all field
4016     // representations will be tagged since the transition is omitted.
4017     return JSObject::AddPropertyInternal(
4018         object, name, value, attributes,
4019         JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED,
4020         JSReceiver::OMIT_EXTENSIBILITY_CHECK, OMIT_TRANSITION);
4021   }
4022
4023   // Keep the target CONSTANT if the same value is stored.
4024   // TODO(verwaest): Also support keeping the placeholder
4025   // (value->IsUninitialized) as constant.
4026   if (!lookup->CanHoldValue(value)) {
4027     Representation field_representation = value->OptimalRepresentation();
4028     Handle<HeapType> field_type = value->OptimalType(
4029         lookup->isolate(), field_representation);
4030     transition_map = Map::GeneralizeRepresentation(
4031         transition_map, descriptor,
4032         field_representation, field_type, FORCE_FIELD);
4033   }
4034
4035   JSObject::MigrateToNewProperty(object, transition_map, value);
4036   return value;
4037 }
4038
4039
4040 void JSObject::MigrateToNewProperty(Handle<JSObject> object,
4041                                     Handle<Map> map,
4042                                     Handle<Object> value) {
4043   JSObject::MigrateToMap(object, map);
4044   if (map->GetLastDescriptorDetails().type() != FIELD) return;
4045   object->WriteToField(map->LastAdded(), *value);
4046 }
4047
4048
4049 void JSObject::WriteToField(int descriptor, Object* value) {
4050   DisallowHeapAllocation no_gc;
4051
4052   DescriptorArray* desc = map()->instance_descriptors();
4053   PropertyDetails details = desc->GetDetails(descriptor);
4054
4055   DCHECK(details.type() == FIELD);
4056
4057   FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
4058   if (details.representation().IsDouble()) {
4059     // Nothing more to be done.
4060     if (value->IsUninitialized()) return;
4061     HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
4062     DCHECK(box->IsMutableHeapNumber());
4063     box->set_value(value->Number());
4064   } else {
4065     FastPropertyAtPut(index, value);
4066   }
4067 }
4068
4069
4070 void JSObject::SetPropertyToField(LookupResult* lookup, Handle<Object> value) {
4071   if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) {
4072     Representation field_representation = value->OptimalRepresentation();
4073     Handle<HeapType> field_type = value->OptimalType(
4074         lookup->isolate(), field_representation);
4075     JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()),
4076                                             lookup->GetDescriptorIndex(),
4077                                             field_representation, field_type);
4078   }
4079   lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value);
4080 }
4081
4082
4083 void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup,
4084                                         Handle<Name> name,
4085                                         Handle<Object> value,
4086                                         PropertyAttributes attributes) {
4087   Handle<JSObject> object(lookup->holder());
4088   if (object->map()->TooManyFastProperties(Object::MAY_BE_STORE_FROM_KEYED)) {
4089     JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
4090   } else if (object->map()->is_prototype_map()) {
4091     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0);
4092   }
4093
4094   if (!object->HasFastProperties()) {
4095     ReplaceSlowProperty(object, name, value, attributes);
4096     ReoptimizeIfPrototype(object);
4097     return;
4098   }
4099
4100   int descriptor_index = lookup->GetDescriptorIndex();
4101   if (lookup->GetAttributes() == attributes) {
4102     JSObject::GeneralizeFieldRepresentation(object, descriptor_index,
4103                                             Representation::Tagged(),
4104                                             HeapType::Any(lookup->isolate()));
4105   } else {
4106     Handle<Map> old_map(object->map());
4107     Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map,
4108         descriptor_index, FORCE_FIELD, attributes, "attributes mismatch");
4109     JSObject::MigrateToMap(object, new_map);
4110   }
4111
4112   object->WriteToField(descriptor_index, *value);
4113 }
4114
4115
4116 void JSObject::SetPropertyToFieldWithAttributes(LookupResult* lookup,
4117                                                 Handle<Name> name,
4118                                                 Handle<Object> value,
4119                                                 PropertyAttributes attributes) {
4120   if (lookup->GetAttributes() == attributes) {
4121     if (value->IsUninitialized()) return;
4122     SetPropertyToField(lookup, value);
4123   } else {
4124     ConvertAndSetOwnProperty(lookup, name, value, attributes);
4125   }
4126 }
4127
4128
4129 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
4130                            Handle<Object> value,
4131                            PropertyAttributes attributes) {
4132 #ifdef DEBUG
4133   uint32_t index;
4134   DCHECK(!object->IsJSProxy());
4135   DCHECK(!name->AsArrayIndex(&index));
4136   LookupIterator it(object, name, LookupIterator::CHECK_OWN_REAL);
4137   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
4138   DCHECK(maybe.has_value);
4139   DCHECK(!it.IsFound());
4140   DCHECK(object->map()->is_extensible());
4141 #endif
4142   SetOwnPropertyIgnoreAttributes(object, name, value, attributes,
4143                                  OMIT_EXTENSIBILITY_CHECK).Check();
4144 }
4145
4146
4147 // Reconfigures a property to a data property with attributes, even if it is not
4148 // reconfigurable.
4149 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4150     Handle<JSObject> object,
4151     Handle<Name> name,
4152     Handle<Object> value,
4153     PropertyAttributes attributes,
4154     ExtensibilityCheck extensibility_check,
4155     StoreFromKeyed store_from_keyed,
4156     ExecutableAccessorInfoHandling handling) {
4157   DCHECK(!value->IsTheHole());
4158   Isolate* isolate = object->GetIsolate();
4159
4160   // Make sure that the top context does not change when doing callbacks or
4161   // interceptor calls.
4162   AssertNoContextChange ncc(isolate);
4163
4164   LookupResult lookup(isolate);
4165   object->LookupOwn(name, &lookup, true);
4166   if (!lookup.IsFound()) {
4167     object->map()->LookupTransition(*object, *name, &lookup);
4168   }
4169
4170   // Check access rights if needed.
4171   if (object->IsAccessCheckNeeded()) {
4172     if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4173       LookupIterator it(object, name, LookupIterator::CHECK_OWN);
4174       return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4175     }
4176   }
4177
4178   if (object->IsJSGlobalProxy()) {
4179     PrototypeIterator iter(isolate, object);
4180     if (iter.IsAtEnd()) return value;
4181     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4182     return SetOwnPropertyIgnoreAttributes(
4183         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), name,
4184         value, attributes, extensibility_check);
4185   }
4186
4187   if (lookup.IsInterceptor() ||
4188       (lookup.IsDescriptorOrDictionary() && lookup.type() == CALLBACKS)) {
4189     object->LookupOwnRealNamedProperty(name, &lookup);
4190   }
4191
4192   // Check for accessor in prototype chain removed here in clone.
4193   if (!lookup.IsFound()) {
4194     object->map()->LookupTransition(*object, *name, &lookup);
4195     TransitionFlag flag = lookup.IsFound()
4196         ? OMIT_TRANSITION : INSERT_TRANSITION;
4197     // Neither properties nor transitions found.
4198     return AddPropertyInternal(object, name, value, attributes,
4199                                store_from_keyed, extensibility_check, flag);
4200   }
4201
4202   Handle<Object> old_value = isolate->factory()->the_hole_value();
4203   PropertyAttributes old_attributes = ABSENT;
4204   bool is_observed = object->map()->is_observed() &&
4205                      *name != isolate->heap()->hidden_string();
4206   if (is_observed && lookup.IsProperty()) {
4207     if (lookup.IsDataProperty()) {
4208       old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked();
4209     }
4210     old_attributes = lookup.GetAttributes();
4211   }
4212
4213   bool executed_set_prototype = false;
4214
4215   // Check of IsReadOnly removed from here in clone.
4216   if (lookup.IsTransition()) {
4217     Handle<Object> result;
4218     ASSIGN_RETURN_ON_EXCEPTION(
4219         isolate, result,
4220         SetPropertyUsingTransition(
4221             handle(lookup.holder()), &lookup, name, value, attributes),
4222         Object);
4223   } else {
4224     switch (lookup.type()) {
4225       case NORMAL:
4226         ReplaceSlowProperty(object, name, value, attributes);
4227         break;
4228       case FIELD:
4229         SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4230         break;
4231       case CONSTANT:
4232         // Only replace the constant if necessary.
4233         if (lookup.GetAttributes() != attributes ||
4234             *value != lookup.GetConstant()) {
4235           SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4236         }
4237         break;
4238       case CALLBACKS:
4239       {
4240         Handle<Object> callback(lookup.GetCallbackObject(), isolate);
4241         if (callback->IsExecutableAccessorInfo() &&
4242             handling == DONT_FORCE_FIELD) {
4243           Handle<Object> result;
4244           ASSIGN_RETURN_ON_EXCEPTION(
4245               isolate, result, JSObject::SetPropertyWithAccessor(
4246                                    object, name, value, handle(lookup.holder()),
4247                                    callback, STRICT),
4248               Object);
4249
4250           if (attributes != lookup.GetAttributes()) {
4251             Handle<ExecutableAccessorInfo> new_data =
4252                 Accessors::CloneAccessor(
4253                     isolate, Handle<ExecutableAccessorInfo>::cast(callback));
4254             new_data->set_property_attributes(attributes);
4255             if (attributes & READ_ONLY) {
4256               // This way we don't have to introduce a lookup to the setter,
4257               // simply make it unavailable to reflect the attributes.
4258               new_data->clear_setter();
4259             }
4260
4261             SetPropertyCallback(object, name, new_data, attributes);
4262           }
4263           if (is_observed) {
4264             // If we are setting the prototype of a function and are observed,
4265             // don't send change records because the prototype handles that
4266             // itself.
4267             executed_set_prototype = object->IsJSFunction() &&
4268                 String::Equals(isolate->factory()->prototype_string(),
4269                                Handle<String>::cast(name)) &&
4270                 Handle<JSFunction>::cast(object)->should_have_prototype();
4271           }
4272         } else {
4273           ConvertAndSetOwnProperty(&lookup, name, value, attributes);
4274         }
4275         break;
4276       }
4277       case NONEXISTENT:
4278       case HANDLER:
4279       case INTERCEPTOR:
4280         UNREACHABLE();
4281     }
4282   }
4283
4284   if (is_observed && !executed_set_prototype) {
4285     if (lookup.IsTransition()) {
4286       EnqueueChangeRecord(object, "add", name, old_value);
4287     } else if (old_value->IsTheHole()) {
4288       EnqueueChangeRecord(object, "reconfigure", name, old_value);
4289     } else {
4290       LookupResult new_lookup(isolate);
4291       object->LookupOwn(name, &new_lookup, true);
4292       bool value_changed = false;
4293       if (new_lookup.IsDataProperty()) {
4294         Handle<Object> new_value =
4295             Object::GetPropertyOrElement(object, name).ToHandleChecked();
4296         value_changed = !old_value->SameValue(*new_value);
4297       }
4298       if (new_lookup.GetAttributes() != old_attributes) {
4299         if (!value_changed) old_value = isolate->factory()->the_hole_value();
4300         EnqueueChangeRecord(object, "reconfigure", name, old_value);
4301       } else if (value_changed) {
4302         EnqueueChangeRecord(object, "update", name, old_value);
4303       }
4304     }
4305   }
4306
4307   return value;
4308 }
4309
4310
4311 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4312     Handle<JSObject> holder,
4313     Handle<Object> receiver,
4314     Handle<Name> name) {
4315   // TODO(rossberg): Support symbols in the API.
4316   if (name->IsSymbol()) return maybe(ABSENT);
4317
4318   Isolate* isolate = holder->GetIsolate();
4319   HandleScope scope(isolate);
4320
4321   // Make sure that the top context does not change when doing
4322   // callbacks or interceptor calls.
4323   AssertNoContextChange ncc(isolate);
4324
4325   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
4326   PropertyCallbackArguments args(
4327       isolate, interceptor->data(), *receiver, *holder);
4328   if (!interceptor->query()->IsUndefined()) {
4329     v8::NamedPropertyQueryCallback query =
4330         v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query());
4331     LOG(isolate,
4332         ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
4333     v8::Handle<v8::Integer> result =
4334         args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name)));
4335     if (!result.IsEmpty()) {
4336       DCHECK(result->IsInt32());
4337       return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
4338     }
4339   } else if (!interceptor->getter()->IsUndefined()) {
4340     v8::NamedPropertyGetterCallback getter =
4341         v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
4342     LOG(isolate,
4343         ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
4344     v8::Handle<v8::Value> result =
4345         args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name)));
4346     if (!result.IsEmpty()) return maybe(DONT_ENUM);
4347   }
4348
4349   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
4350   return maybe(ABSENT);
4351 }
4352
4353
4354 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
4355     Handle<JSReceiver> object, Handle<Name> name) {
4356   // Check whether the name is an array index.
4357   uint32_t index = 0;
4358   if (object->IsJSObject() && name->AsArrayIndex(&index)) {
4359     return GetOwnElementAttribute(object, index);
4360   }
4361   LookupIterator it(object, name, LookupIterator::CHECK_OWN);
4362   return GetPropertyAttributes(&it);
4363 }
4364
4365
4366 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
4367     LookupIterator* it) {
4368   for (; it->IsFound(); it->Next()) {
4369     switch (it->state()) {
4370       case LookupIterator::NOT_FOUND:
4371         UNREACHABLE();
4372       case LookupIterator::JSPROXY:
4373         return JSProxy::GetPropertyAttributesWithHandler(
4374             it->GetHolder<JSProxy>(), it->GetReceiver(), it->name());
4375       case LookupIterator::INTERCEPTOR: {
4376         Maybe<PropertyAttributes> result =
4377             JSObject::GetPropertyAttributesWithInterceptor(
4378                 it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
4379         if (!result.has_value) return result;
4380         if (result.value != ABSENT) return result;
4381         break;
4382       }
4383       case LookupIterator::ACCESS_CHECK:
4384         if (it->HasAccess(v8::ACCESS_HAS)) break;
4385         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
4386       case LookupIterator::PROPERTY:
4387         if (it->HasProperty()) {
4388           return maybe(it->property_details().attributes());
4389         }
4390         break;
4391     }
4392   }
4393   return maybe(ABSENT);
4394 }
4395
4396
4397 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver(
4398     Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4399     bool check_prototype) {
4400   Isolate* isolate = object->GetIsolate();
4401
4402   // Check access rights if needed.
4403   if (object->IsAccessCheckNeeded()) {
4404     if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
4405       isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
4406       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
4407       return maybe(ABSENT);
4408     }
4409   }
4410
4411   if (object->IsJSGlobalProxy()) {
4412     PrototypeIterator iter(isolate, object);
4413     if (iter.IsAtEnd()) return maybe(ABSENT);
4414     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4415     return JSObject::GetElementAttributeWithReceiver(
4416         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4417         index, check_prototype);
4418   }
4419
4420   // Check for lookup interceptor except when bootstrapping.
4421   if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
4422     return JSObject::GetElementAttributeWithInterceptor(
4423         object, receiver, index, check_prototype);
4424   }
4425
4426   return GetElementAttributeWithoutInterceptor(
4427       object, receiver, index, check_prototype);
4428 }
4429
4430
4431 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor(
4432     Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4433     bool check_prototype) {
4434   Isolate* isolate = object->GetIsolate();
4435   HandleScope scope(isolate);
4436
4437   // Make sure that the top context does not change when doing
4438   // callbacks or interceptor calls.
4439   AssertNoContextChange ncc(isolate);
4440
4441   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
4442   PropertyCallbackArguments args(
4443       isolate, interceptor->data(), *receiver, *object);
4444   if (!interceptor->query()->IsUndefined()) {
4445     v8::IndexedPropertyQueryCallback query =
4446         v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4447     LOG(isolate,
4448         ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index));
4449     v8::Handle<v8::Integer> result = args.Call(query, index);
4450     if (!result.IsEmpty())
4451       return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
4452   } else if (!interceptor->getter()->IsUndefined()) {
4453     v8::IndexedPropertyGetterCallback getter =
4454         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4455     LOG(isolate,
4456         ApiIndexedPropertyAccess(
4457             "interceptor-indexed-get-has", *object, index));
4458     v8::Handle<v8::Value> result = args.Call(getter, index);
4459     if (!result.IsEmpty()) return maybe(NONE);
4460   }
4461
4462   return GetElementAttributeWithoutInterceptor(
4463        object, receiver, index, check_prototype);
4464 }
4465
4466
4467 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor(
4468     Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4469     bool check_prototype) {
4470   PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes(
4471       receiver, object, index);
4472   if (attr != ABSENT) return maybe(attr);
4473
4474   // Handle [] on String objects.
4475   if (object->IsStringObjectWithCharacterAt(index)) {
4476     return maybe(static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE));
4477   }
4478
4479   if (!check_prototype) return maybe(ABSENT);
4480
4481   PrototypeIterator iter(object->GetIsolate(), object);
4482   if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
4483     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
4484     return JSProxy::GetElementAttributeWithHandler(
4485         Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4486         index);
4487   }
4488   if (iter.IsAtEnd()) return maybe(ABSENT);
4489   return GetElementAttributeWithReceiver(
4490       Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4491       index, true);
4492 }
4493
4494
4495 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
4496   Handle<FixedArray> array(
4497       isolate->factory()->NewFixedArray(kEntries, TENURED));
4498   return Handle<NormalizedMapCache>::cast(array);
4499 }
4500
4501
4502 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
4503                                          PropertyNormalizationMode mode) {
4504   DisallowHeapAllocation no_gc;
4505   Object* value = FixedArray::get(GetIndex(fast_map));
4506   if (!value->IsMap() ||
4507       !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4508     return MaybeHandle<Map>();
4509   }
4510   return handle(Map::cast(value));
4511 }
4512
4513
4514 void NormalizedMapCache::Set(Handle<Map> fast_map,
4515                              Handle<Map> normalized_map) {
4516   DisallowHeapAllocation no_gc;
4517   DCHECK(normalized_map->is_dictionary_map());
4518   FixedArray::set(GetIndex(fast_map), *normalized_map);
4519 }
4520
4521
4522 void NormalizedMapCache::Clear() {
4523   int entries = length();
4524   for (int i = 0; i != entries; i++) {
4525     set_undefined(i);
4526   }
4527 }
4528
4529
4530 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
4531                                     Handle<Name> name,
4532                                     Handle<Code> code) {
4533   Handle<Map> map(object->map());
4534   Map::UpdateCodeCache(map, name, code);
4535 }
4536
4537
4538 void JSObject::NormalizeProperties(Handle<JSObject> object,
4539                                    PropertyNormalizationMode mode,
4540                                    int expected_additional_properties) {
4541   if (!object->HasFastProperties()) return;
4542
4543   Handle<Map> map(object->map());
4544   Handle<Map> new_map = Map::Normalize(map, mode);
4545
4546   MigrateFastToSlow(object, new_map, expected_additional_properties);
4547 }
4548
4549
4550 void JSObject::MigrateFastToSlow(Handle<JSObject> object,
4551                                  Handle<Map> new_map,
4552                                  int expected_additional_properties) {
4553   // The global object is always normalized.
4554   DCHECK(!object->IsGlobalObject());
4555   // JSGlobalProxy must never be normalized
4556   DCHECK(!object->IsJSGlobalProxy());
4557
4558   Isolate* isolate = object->GetIsolate();
4559   HandleScope scope(isolate);
4560   Handle<Map> map(object->map());
4561
4562   // Allocate new content.
4563   int real_size = map->NumberOfOwnDescriptors();
4564   int property_count = real_size;
4565   if (expected_additional_properties > 0) {
4566     property_count += expected_additional_properties;
4567   } else {
4568     property_count += 2;  // Make space for two more properties.
4569   }
4570   Handle<NameDictionary> dictionary =
4571       NameDictionary::New(isolate, property_count);
4572
4573   Handle<DescriptorArray> descs(map->instance_descriptors());
4574   for (int i = 0; i < real_size; i++) {
4575     PropertyDetails details = descs->GetDetails(i);
4576     switch (details.type()) {
4577       case CONSTANT: {
4578         Handle<Name> key(descs->GetKey(i));
4579         Handle<Object> value(descs->GetConstant(i), isolate);
4580         PropertyDetails d = PropertyDetails(
4581             details.attributes(), NORMAL, i + 1);
4582         dictionary = NameDictionary::Add(dictionary, key, value, d);
4583         break;
4584       }
4585       case FIELD: {
4586         Handle<Name> key(descs->GetKey(i));
4587         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4588         Handle<Object> value(
4589             object->RawFastPropertyAt(index), isolate);
4590         if (details.representation().IsDouble()) {
4591           DCHECK(value->IsMutableHeapNumber());
4592           Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
4593           value = isolate->factory()->NewHeapNumber(old->value());
4594         }
4595         PropertyDetails d =
4596             PropertyDetails(details.attributes(), NORMAL, i + 1);
4597         dictionary = NameDictionary::Add(dictionary, key, value, d);
4598         break;
4599       }
4600       case CALLBACKS: {
4601         Handle<Name> key(descs->GetKey(i));
4602         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4603         PropertyDetails d = PropertyDetails(
4604             details.attributes(), CALLBACKS, i + 1);
4605         dictionary = NameDictionary::Add(dictionary, key, value, d);
4606         break;
4607       }
4608       case INTERCEPTOR:
4609         break;
4610       case HANDLER:
4611       case NORMAL:
4612       case NONEXISTENT:
4613         UNREACHABLE();
4614         break;
4615     }
4616   }
4617
4618   // Copy the next enumeration index from instance descriptor.
4619   dictionary->SetNextEnumerationIndex(real_size + 1);
4620
4621   // From here on we cannot fail and we shouldn't GC anymore.
4622   DisallowHeapAllocation no_allocation;
4623
4624   // Resize the object in the heap if necessary.
4625   int new_instance_size = new_map->instance_size();
4626   int instance_size_delta = map->instance_size() - new_instance_size;
4627   DCHECK(instance_size_delta >= 0);
4628
4629   if (instance_size_delta > 0) {
4630     Heap* heap = isolate->heap();
4631     heap->CreateFillerObjectAt(object->address() + new_instance_size,
4632                                instance_size_delta);
4633     heap->AdjustLiveBytes(object->address(), -instance_size_delta,
4634                           Heap::FROM_MUTATOR);
4635   }
4636
4637   // We are storing the new map using release store after creating a filler for
4638   // the left-over space to avoid races with the sweeper thread.
4639   object->synchronized_set_map(*new_map);
4640
4641   object->set_properties(*dictionary);
4642
4643   isolate->counters()->props_to_dictionary()->Increment();
4644
4645 #ifdef DEBUG
4646   if (FLAG_trace_normalization) {
4647     OFStream os(stdout);
4648     os << "Object properties have been normalized:\n";
4649     object->Print(os);
4650   }
4651 #endif
4652 }
4653
4654
4655 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
4656                                  int unused_property_fields) {
4657   if (object->HasFastProperties()) return;
4658   DCHECK(!object->IsGlobalObject());
4659   Isolate* isolate = object->GetIsolate();
4660   Factory* factory = isolate->factory();
4661   Handle<NameDictionary> dictionary(object->property_dictionary());
4662
4663   // Make sure we preserve dictionary representation if there are too many
4664   // descriptors.
4665   int number_of_elements = dictionary->NumberOfElements();
4666   if (number_of_elements > kMaxNumberOfDescriptors) return;
4667
4668   if (number_of_elements != dictionary->NextEnumerationIndex()) {
4669     NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
4670   }
4671
4672   int instance_descriptor_length = 0;
4673   int number_of_fields = 0;
4674
4675   // Compute the length of the instance descriptor.
4676   int capacity = dictionary->Capacity();
4677   for (int i = 0; i < capacity; i++) {
4678     Object* k = dictionary->KeyAt(i);
4679     if (dictionary->IsKey(k)) {
4680       Object* value = dictionary->ValueAt(i);
4681       PropertyType type = dictionary->DetailsAt(i).type();
4682       DCHECK(type != FIELD);
4683       instance_descriptor_length++;
4684       if (type == NORMAL && !value->IsJSFunction()) {
4685         number_of_fields += 1;
4686       }
4687     }
4688   }
4689
4690   int inobject_props = object->map()->inobject_properties();
4691
4692   // Allocate new map.
4693   Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
4694   new_map->set_dictionary_map(false);
4695
4696   if (instance_descriptor_length == 0) {
4697     DisallowHeapAllocation no_gc;
4698     DCHECK_LE(unused_property_fields, inobject_props);
4699     // Transform the object.
4700     new_map->set_unused_property_fields(inobject_props);
4701     object->synchronized_set_map(*new_map);
4702     object->set_properties(isolate->heap()->empty_fixed_array());
4703     // Check that it really works.
4704     DCHECK(object->HasFastProperties());
4705     return;
4706   }
4707
4708   // Allocate the instance descriptor.
4709   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
4710       isolate, instance_descriptor_length);
4711
4712   int number_of_allocated_fields =
4713       number_of_fields + unused_property_fields - inobject_props;
4714   if (number_of_allocated_fields < 0) {
4715     // There is enough inobject space for all fields (including unused).
4716     number_of_allocated_fields = 0;
4717     unused_property_fields = inobject_props - number_of_fields;
4718   }
4719
4720   // Allocate the fixed array for the fields.
4721   Handle<FixedArray> fields = factory->NewFixedArray(
4722       number_of_allocated_fields);
4723
4724   // Fill in the instance descriptor and the fields.
4725   int current_offset = 0;
4726   for (int i = 0; i < capacity; i++) {
4727     Object* k = dictionary->KeyAt(i);
4728     if (dictionary->IsKey(k)) {
4729       Object* value = dictionary->ValueAt(i);
4730       Handle<Name> key;
4731       if (k->IsSymbol()) {
4732         key = handle(Symbol::cast(k));
4733       } else {
4734         // Ensure the key is a unique name before writing into the
4735         // instance descriptor.
4736         key = factory->InternalizeString(handle(String::cast(k)));
4737       }
4738
4739       PropertyDetails details = dictionary->DetailsAt(i);
4740       int enumeration_index = details.dictionary_index();
4741       PropertyType type = details.type();
4742
4743       if (value->IsJSFunction()) {
4744         ConstantDescriptor d(key,
4745                              handle(value, isolate),
4746                              details.attributes());
4747         descriptors->Set(enumeration_index - 1, &d);
4748       } else if (type == NORMAL) {
4749         if (current_offset < inobject_props) {
4750           object->InObjectPropertyAtPut(current_offset,
4751                                         value,
4752                                         UPDATE_WRITE_BARRIER);
4753         } else {
4754           int offset = current_offset - inobject_props;
4755           fields->set(offset, value);
4756         }
4757         FieldDescriptor d(key,
4758                           current_offset++,
4759                           details.attributes(),
4760                           // TODO(verwaest): value->OptimalRepresentation();
4761                           Representation::Tagged());
4762         descriptors->Set(enumeration_index - 1, &d);
4763       } else if (type == CALLBACKS) {
4764         CallbacksDescriptor d(key,
4765                               handle(value, isolate),
4766                               details.attributes());
4767         descriptors->Set(enumeration_index - 1, &d);
4768       } else {
4769         UNREACHABLE();
4770       }
4771     }
4772   }
4773   DCHECK(current_offset == number_of_fields);
4774
4775   descriptors->Sort();
4776
4777   DisallowHeapAllocation no_gc;
4778   new_map->InitializeDescriptors(*descriptors);
4779   new_map->set_unused_property_fields(unused_property_fields);
4780
4781   // Transform the object.
4782   object->synchronized_set_map(*new_map);
4783
4784   object->set_properties(*fields);
4785   DCHECK(object->IsJSObject());
4786
4787   // Check that it really works.
4788   DCHECK(object->HasFastProperties());
4789 }
4790
4791
4792 void JSObject::ResetElements(Handle<JSObject> object) {
4793   Isolate* isolate = object->GetIsolate();
4794   CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
4795   if (object->map()->has_dictionary_elements()) {
4796     Handle<SeededNumberDictionary> new_elements =
4797         SeededNumberDictionary::New(isolate, 0);
4798     object->set_elements(*new_elements);
4799   } else {
4800     object->set_elements(object->map()->GetInitialElements());
4801   }
4802 }
4803
4804
4805 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4806     Handle<FixedArrayBase> array,
4807     int length,
4808     Handle<SeededNumberDictionary> dictionary) {
4809   Isolate* isolate = array->GetIsolate();
4810   Factory* factory = isolate->factory();
4811   bool has_double_elements = array->IsFixedDoubleArray();
4812   for (int i = 0; i < length; i++) {
4813     Handle<Object> value;
4814     if (has_double_elements) {
4815       Handle<FixedDoubleArray> double_array =
4816           Handle<FixedDoubleArray>::cast(array);
4817       if (double_array->is_the_hole(i)) {
4818         value = factory->the_hole_value();
4819       } else {
4820         value = factory->NewHeapNumber(double_array->get_scalar(i));
4821       }
4822     } else {
4823       value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4824     }
4825     if (!value->IsTheHole()) {
4826       PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
4827       dictionary =
4828           SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4829     }
4830   }
4831   return dictionary;
4832 }
4833
4834
4835 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4836     Handle<JSObject> object) {
4837   DCHECK(!object->HasExternalArrayElements() &&
4838          !object->HasFixedTypedArrayElements());
4839   Isolate* isolate = object->GetIsolate();
4840
4841   // Find the backing store.
4842   Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements()));
4843   bool is_arguments =
4844       (array->map() == isolate->heap()->sloppy_arguments_elements_map());
4845   if (is_arguments) {
4846     array = handle(FixedArrayBase::cast(
4847         Handle<FixedArray>::cast(array)->get(1)));
4848   }
4849   if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array);
4850
4851   DCHECK(object->HasFastSmiOrObjectElements() ||
4852          object->HasFastDoubleElements() ||
4853          object->HasFastArgumentsElements());
4854   // Compute the effective length and allocate a new backing store.
4855   int length = object->IsJSArray()
4856       ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4857       : array->length();
4858   int old_capacity = 0;
4859   int used_elements = 0;
4860   object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4861   Handle<SeededNumberDictionary> dictionary =
4862       SeededNumberDictionary::New(isolate, used_elements);
4863
4864   dictionary = CopyFastElementsToDictionary(array, length, dictionary);
4865
4866   // Switch to using the dictionary as the backing storage for elements.
4867   if (is_arguments) {
4868     FixedArray::cast(object->elements())->set(1, *dictionary);
4869   } else {
4870     // Set the new map first to satify the elements type assert in
4871     // set_elements().
4872     Handle<Map> new_map =
4873         JSObject::GetElementsTransitionMap(object, DICTIONARY_ELEMENTS);
4874
4875     JSObject::MigrateToMap(object, new_map);
4876     object->set_elements(*dictionary);
4877   }
4878
4879   isolate->counters()->elements_to_dictionary()->Increment();
4880
4881 #ifdef DEBUG
4882   if (FLAG_trace_normalization) {
4883     OFStream os(stdout);
4884     os << "Object elements have been normalized:\n";
4885     object->Print(os);
4886   }
4887 #endif
4888
4889   DCHECK(object->HasDictionaryElements() ||
4890          object->HasDictionaryArgumentsElements());
4891   return dictionary;
4892 }
4893
4894
4895 static Smi* GenerateIdentityHash(Isolate* isolate) {
4896   int hash_value;
4897   int attempts = 0;
4898   do {
4899     // Generate a random 32-bit hash value but limit range to fit
4900     // within a smi.
4901     hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4902     attempts++;
4903   } while (hash_value == 0 && attempts < 30);
4904   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
4905
4906   return Smi::FromInt(hash_value);
4907 }
4908
4909
4910 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4911   DCHECK(!object->IsJSGlobalProxy());
4912   Isolate* isolate = object->GetIsolate();
4913   SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4914 }
4915
4916
4917 template<typename ProxyType>
4918 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
4919   Isolate* isolate = proxy->GetIsolate();
4920
4921   Handle<Object> maybe_hash(proxy->hash(), isolate);
4922   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4923
4924   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4925   proxy->set_hash(*hash);
4926   return hash;
4927 }
4928
4929
4930 Object* JSObject::GetIdentityHash() {
4931   DisallowHeapAllocation no_gc;
4932   Isolate* isolate = GetIsolate();
4933   if (IsJSGlobalProxy()) {
4934     return JSGlobalProxy::cast(this)->hash();
4935   }
4936   Object* stored_value =
4937       GetHiddenProperty(isolate->factory()->identity_hash_string());
4938   return stored_value->IsSmi()
4939       ? stored_value
4940       : isolate->heap()->undefined_value();
4941 }
4942
4943
4944 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
4945   if (object->IsJSGlobalProxy()) {
4946     return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
4947   }
4948
4949   Isolate* isolate = object->GetIsolate();
4950
4951   Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
4952   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4953
4954   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4955   SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4956   return hash;
4957 }
4958
4959
4960 Object* JSProxy::GetIdentityHash() {
4961   return this->hash();
4962 }
4963
4964
4965 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
4966   return GetOrCreateIdentityHashHelper(proxy);
4967 }
4968
4969
4970 Object* JSObject::GetHiddenProperty(Handle<Name> key) {
4971   DisallowHeapAllocation no_gc;
4972   DCHECK(key->IsUniqueName());
4973   if (IsJSGlobalProxy()) {
4974     // JSGlobalProxies store their hash internally.
4975     DCHECK(*key != GetHeap()->identity_hash_string());
4976     // For a proxy, use the prototype as target object.
4977     PrototypeIterator iter(GetIsolate(), this);
4978     // If the proxy is detached, return undefined.
4979     if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
4980     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
4981     return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key);
4982   }
4983   DCHECK(!IsJSGlobalProxy());
4984   Object* inline_value = GetHiddenPropertiesHashTable();
4985
4986   if (inline_value->IsSmi()) {
4987     // Handle inline-stored identity hash.
4988     if (*key == GetHeap()->identity_hash_string()) {
4989       return inline_value;
4990     } else {
4991       return GetHeap()->the_hole_value();
4992     }
4993   }
4994
4995   if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
4996
4997   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
4998   Object* entry = hashtable->Lookup(key);
4999   return entry;
5000 }
5001
5002
5003 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
5004                                            Handle<Name> key,
5005                                            Handle<Object> value) {
5006   Isolate* isolate = object->GetIsolate();
5007
5008   DCHECK(key->IsUniqueName());
5009   if (object->IsJSGlobalProxy()) {
5010     // JSGlobalProxies store their hash internally.
5011     DCHECK(*key != *isolate->factory()->identity_hash_string());
5012     // For a proxy, use the prototype as target object.
5013     PrototypeIterator iter(isolate, object);
5014     // If the proxy is detached, return undefined.
5015     if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
5016     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5017     return SetHiddenProperty(
5018         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key,
5019         value);
5020   }
5021   DCHECK(!object->IsJSGlobalProxy());
5022
5023   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5024
5025   // If there is no backing store yet, store the identity hash inline.
5026   if (value->IsSmi() &&
5027       *key == *isolate->factory()->identity_hash_string() &&
5028       (inline_value->IsUndefined() || inline_value->IsSmi())) {
5029     return JSObject::SetHiddenPropertiesHashTable(object, value);
5030   }
5031
5032   Handle<ObjectHashTable> hashtable =
5033       GetOrCreateHiddenPropertiesHashtable(object);
5034
5035   // If it was found, check if the key is already in the dictionary.
5036   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
5037                                                            value);
5038   if (*new_table != *hashtable) {
5039     // If adding the key expanded the dictionary (i.e., Add returned a new
5040     // dictionary), store it back to the object.
5041     SetHiddenPropertiesHashTable(object, new_table);
5042   }
5043
5044   // Return this to mark success.
5045   return object;
5046 }
5047
5048
5049 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
5050   Isolate* isolate = object->GetIsolate();
5051   DCHECK(key->IsUniqueName());
5052
5053   if (object->IsJSGlobalProxy()) {
5054     PrototypeIterator iter(isolate, object);
5055     if (iter.IsAtEnd()) return;
5056     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5057     return DeleteHiddenProperty(
5058         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key);
5059   }
5060
5061   Object* inline_value = object->GetHiddenPropertiesHashTable();
5062
5063   // We never delete (inline-stored) identity hashes.
5064   DCHECK(*key != *isolate->factory()->identity_hash_string());
5065   if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
5066
5067   Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
5068   bool was_present = false;
5069   ObjectHashTable::Remove(hashtable, key, &was_present);
5070 }
5071
5072
5073 bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
5074   Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
5075   LookupIterator it(object, hidden, LookupIterator::CHECK_OWN_REAL);
5076   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
5077   // Cannot get an exception since the hidden_string isn't accessible to JS.
5078   DCHECK(maybe.has_value);
5079   return maybe.value != ABSENT;
5080 }
5081
5082
5083 Object* JSObject::GetHiddenPropertiesHashTable() {
5084   DCHECK(!IsJSGlobalProxy());
5085   if (HasFastProperties()) {
5086     // If the object has fast properties, check whether the first slot
5087     // in the descriptor array matches the hidden string. Since the
5088     // hidden strings hash code is zero (and no other name has hash
5089     // code zero) it will always occupy the first entry if present.
5090     DescriptorArray* descriptors = this->map()->instance_descriptors();
5091     if (descriptors->number_of_descriptors() > 0) {
5092       int sorted_index = descriptors->GetSortedKeyIndex(0);
5093       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
5094           sorted_index < map()->NumberOfOwnDescriptors()) {
5095         DCHECK(descriptors->GetType(sorted_index) == FIELD);
5096         DCHECK(descriptors->GetDetails(sorted_index).representation().
5097                IsCompatibleForLoad(Representation::Tagged()));
5098         FieldIndex index = FieldIndex::ForDescriptor(this->map(),
5099                                                      sorted_index);
5100         return this->RawFastPropertyAt(index);
5101       } else {
5102         return GetHeap()->undefined_value();
5103       }
5104     } else {
5105       return GetHeap()->undefined_value();
5106     }
5107   } else {
5108     Isolate* isolate = GetIsolate();
5109     LookupResult result(isolate);
5110     LookupOwnRealNamedProperty(isolate->factory()->hidden_string(), &result);
5111     if (result.IsFound()) {
5112       DCHECK(result.IsNormal());
5113       DCHECK(result.holder() == this);
5114       return GetNormalizedProperty(&result);
5115     }
5116     return GetHeap()->undefined_value();
5117   }
5118 }
5119
5120 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
5121     Handle<JSObject> object) {
5122   Isolate* isolate = object->GetIsolate();
5123
5124   static const int kInitialCapacity = 4;
5125   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5126   if (inline_value->IsHashTable()) {
5127     return Handle<ObjectHashTable>::cast(inline_value);
5128   }
5129
5130   Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
5131       isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
5132
5133   if (inline_value->IsSmi()) {
5134     // We were storing the identity hash inline and now allocated an actual
5135     // dictionary.  Put the identity hash into the new dictionary.
5136     hashtable = ObjectHashTable::Put(hashtable,
5137                                      isolate->factory()->identity_hash_string(),
5138                                      inline_value);
5139   }
5140
5141   JSObject::SetOwnPropertyIgnoreAttributes(
5142       object, isolate->factory()->hidden_string(),
5143       hashtable, DONT_ENUM).Assert();
5144
5145   return hashtable;
5146 }
5147
5148
5149 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
5150                                                       Handle<Object> value) {
5151   DCHECK(!object->IsJSGlobalProxy());
5152
5153   Isolate* isolate = object->GetIsolate();
5154
5155   // We can store the identity hash inline iff there is no backing store
5156   // for hidden properties yet.
5157   DCHECK(JSObject::HasHiddenProperties(object) != value->IsSmi());
5158   if (object->HasFastProperties()) {
5159     // If the object has fast properties, check whether the first slot
5160     // in the descriptor array matches the hidden string. Since the
5161     // hidden strings hash code is zero (and no other name has hash
5162     // code zero) it will always occupy the first entry if present.
5163     DescriptorArray* descriptors = object->map()->instance_descriptors();
5164     if (descriptors->number_of_descriptors() > 0) {
5165       int sorted_index = descriptors->GetSortedKeyIndex(0);
5166       if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string()
5167           && sorted_index < object->map()->NumberOfOwnDescriptors()) {
5168         object->WriteToField(sorted_index, *value);
5169         return object;
5170       }
5171     }
5172   }
5173
5174   SetOwnPropertyIgnoreAttributes(object, isolate->factory()->hidden_string(),
5175                                  value, DONT_ENUM,
5176                                  OMIT_EXTENSIBILITY_CHECK).Assert();
5177   return object;
5178 }
5179
5180
5181 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object,
5182                                                        Handle<Name> name,
5183                                                        DeleteMode delete_mode) {
5184   // Check own property, ignore interceptor.
5185   Isolate* isolate = object->GetIsolate();
5186   LookupResult lookup(isolate);
5187   object->LookupOwnRealNamedProperty(name, &lookup);
5188   if (!lookup.IsFound()) return isolate->factory()->true_value();
5189
5190   PropertyNormalizationMode mode = object->map()->is_prototype_map()
5191                                        ? KEEP_INOBJECT_PROPERTIES
5192                                        : CLEAR_INOBJECT_PROPERTIES;
5193   // Normalize object if needed.
5194   NormalizeProperties(object, mode, 0);
5195
5196   Handle<Object> result = DeleteNormalizedProperty(object, name, delete_mode);
5197   ReoptimizeIfPrototype(object);
5198   return result;
5199 }
5200
5201
5202 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
5203     Handle<JSObject> object, Handle<Name> name) {
5204   Isolate* isolate = object->GetIsolate();
5205
5206   // TODO(rossberg): Support symbols in the API.
5207   if (name->IsSymbol()) return isolate->factory()->false_value();
5208
5209   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
5210   if (!interceptor->deleter()->IsUndefined()) {
5211     v8::NamedPropertyDeleterCallback deleter =
5212         v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter());
5213     LOG(isolate,
5214         ApiNamedPropertyAccess("interceptor-named-delete", *object, *name));
5215     PropertyCallbackArguments args(
5216         isolate, interceptor->data(), *object, *object);
5217     v8::Handle<v8::Boolean> result =
5218         args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name)));
5219     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5220     if (!result.IsEmpty()) {
5221       DCHECK(result->IsBoolean());
5222       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5223       result_internal->VerifyApiCallResultType();
5224       // Rebox CustomArguments::kReturnValueOffset before returning.
5225       return handle(*result_internal, isolate);
5226     }
5227   }
5228   Handle<Object> result =
5229       DeletePropertyPostInterceptor(object, name, NORMAL_DELETION);
5230   return result;
5231 }
5232
5233
5234 MaybeHandle<Object> JSObject::DeleteElementWithInterceptor(
5235     Handle<JSObject> object,
5236     uint32_t index) {
5237   Isolate* isolate = object->GetIsolate();
5238   Factory* factory = isolate->factory();
5239
5240   // Make sure that the top context does not change when doing
5241   // callbacks or interceptor calls.
5242   AssertNoContextChange ncc(isolate);
5243
5244   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
5245   if (interceptor->deleter()->IsUndefined()) return factory->false_value();
5246   v8::IndexedPropertyDeleterCallback deleter =
5247       v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
5248   LOG(isolate,
5249       ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index));
5250   PropertyCallbackArguments args(
5251       isolate, interceptor->data(), *object, *object);
5252   v8::Handle<v8::Boolean> result = args.Call(deleter, index);
5253   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5254   if (!result.IsEmpty()) {
5255     DCHECK(result->IsBoolean());
5256     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5257     result_internal->VerifyApiCallResultType();
5258     // Rebox CustomArguments::kReturnValueOffset before returning.
5259     return handle(*result_internal, isolate);
5260   }
5261   MaybeHandle<Object> delete_result = object->GetElementsAccessor()->Delete(
5262       object, index, NORMAL_DELETION);
5263   return delete_result;
5264 }
5265
5266
5267 MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
5268                                             uint32_t index,
5269                                             DeleteMode mode) {
5270   Isolate* isolate = object->GetIsolate();
5271   Factory* factory = isolate->factory();
5272
5273   // Check access rights if needed.
5274   if (object->IsAccessCheckNeeded() &&
5275       !isolate->MayIndexedAccess(object, index, v8::ACCESS_DELETE)) {
5276     isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
5277     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5278     return factory->false_value();
5279   }
5280
5281   if (object->IsStringObjectWithCharacterAt(index)) {
5282     if (mode == STRICT_DELETION) {
5283       // Deleting a non-configurable property in strict mode.
5284       Handle<Object> name = factory->NewNumberFromUint(index);
5285       Handle<Object> args[2] = { name, object };
5286       Handle<Object> error =
5287           factory->NewTypeError("strict_delete_property",
5288                                 HandleVector(args, 2));
5289       isolate->Throw(*error);
5290       return Handle<Object>();
5291     }
5292     return factory->false_value();
5293   }
5294
5295   if (object->IsJSGlobalProxy()) {
5296     PrototypeIterator iter(isolate, object);
5297     if (iter.IsAtEnd()) return factory->false_value();
5298     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5299     return DeleteElement(
5300         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
5301         mode);
5302   }
5303
5304   Handle<Object> old_value;
5305   bool should_enqueue_change_record = false;
5306   if (object->map()->is_observed()) {
5307     Maybe<bool> maybe = HasOwnElement(object, index);
5308     if (!maybe.has_value) return MaybeHandle<Object>();
5309     should_enqueue_change_record = maybe.value;
5310     if (should_enqueue_change_record) {
5311       if (!GetOwnElementAccessorPair(object, index).is_null()) {
5312         old_value = Handle<Object>::cast(factory->the_hole_value());
5313       } else {
5314         old_value = Object::GetElement(
5315             isolate, object, index).ToHandleChecked();
5316       }
5317     }
5318   }
5319
5320   // Skip interceptor if forcing deletion.
5321   MaybeHandle<Object> maybe_result;
5322   if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) {
5323     maybe_result = DeleteElementWithInterceptor(object, index);
5324   } else {
5325     maybe_result = object->GetElementsAccessor()->Delete(object, index, mode);
5326   }
5327   Handle<Object> result;
5328   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
5329
5330   if (should_enqueue_change_record) {
5331     Maybe<bool> maybe = HasOwnElement(object, index);
5332     if (!maybe.has_value) return MaybeHandle<Object>();
5333     if (!maybe.value) {
5334       Handle<String> name = factory->Uint32ToString(index);
5335       EnqueueChangeRecord(object, "delete", name, old_value);
5336     }
5337   }
5338
5339   return result;
5340 }
5341
5342
5343 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
5344                                              Handle<Name> name,
5345                                              DeleteMode delete_mode) {
5346   Isolate* isolate = object->GetIsolate();
5347   // ECMA-262, 3rd, 8.6.2.5
5348   DCHECK(name->IsName());
5349
5350   // Check access rights if needed.
5351   if (object->IsAccessCheckNeeded() &&
5352       !isolate->MayNamedAccess(object, name, v8::ACCESS_DELETE)) {
5353     isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
5354     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5355     return isolate->factory()->false_value();
5356   }
5357
5358   if (object->IsJSGlobalProxy()) {
5359     PrototypeIterator iter(isolate, object);
5360     if (iter.IsAtEnd()) return isolate->factory()->false_value();
5361     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5362     return JSGlobalObject::DeleteProperty(
5363         Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)), name,
5364         delete_mode);
5365   }
5366
5367   uint32_t index = 0;
5368   if (name->AsArrayIndex(&index)) {
5369     return DeleteElement(object, index, delete_mode);
5370   }
5371
5372   LookupResult lookup(isolate);
5373   object->LookupOwn(name, &lookup, true);
5374   if (!lookup.IsFound()) return isolate->factory()->true_value();
5375   // Ignore attributes if forcing a deletion.
5376   if (lookup.IsDontDelete() && delete_mode != FORCE_DELETION) {
5377     if (delete_mode == STRICT_DELETION) {
5378       // Deleting a non-configurable property in strict mode.
5379       Handle<Object> args[2] = { name, object };
5380       Handle<Object> error = isolate->factory()->NewTypeError(
5381           "strict_delete_property", HandleVector(args, ARRAY_SIZE(args)));
5382       isolate->Throw(*error);
5383       return Handle<Object>();
5384     }
5385     return isolate->factory()->false_value();
5386   }
5387
5388   Handle<Object> old_value = isolate->factory()->the_hole_value();
5389   bool is_observed = object->map()->is_observed() &&
5390                      *name != isolate->heap()->hidden_string();
5391   if (is_observed && lookup.IsDataProperty()) {
5392     old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked();
5393   }
5394   Handle<Object> result;
5395
5396   // Check for interceptor.
5397   if (lookup.IsInterceptor()) {
5398     // Skip interceptor if forcing a deletion.
5399     if (delete_mode == FORCE_DELETION) {
5400       result = DeletePropertyPostInterceptor(object, name, delete_mode);
5401     } else {
5402       ASSIGN_RETURN_ON_EXCEPTION(
5403           isolate, result,
5404           DeletePropertyWithInterceptor(object, name),
5405           Object);
5406     }
5407   } else {
5408     PropertyNormalizationMode mode = object->map()->is_prototype_map()
5409                                          ? KEEP_INOBJECT_PROPERTIES
5410                                          : CLEAR_INOBJECT_PROPERTIES;
5411     // Normalize object if needed.
5412     NormalizeProperties(object, mode, 0);
5413     // Make sure the properties are normalized before removing the entry.
5414     result = DeleteNormalizedProperty(object, name, delete_mode);
5415     ReoptimizeIfPrototype(object);
5416   }
5417
5418   if (is_observed) {
5419     Maybe<bool> maybe = HasOwnProperty(object, name);
5420     if (!maybe.has_value) return MaybeHandle<Object>();
5421     if (!maybe.value) {
5422       EnqueueChangeRecord(object, "delete", name, old_value);
5423     }
5424   }
5425
5426   return result;
5427 }
5428
5429
5430 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
5431                                               uint32_t index,
5432                                               DeleteMode mode) {
5433   if (object->IsJSProxy()) {
5434     return JSProxy::DeleteElementWithHandler(
5435         Handle<JSProxy>::cast(object), index, mode);
5436   }
5437   return JSObject::DeleteElement(Handle<JSObject>::cast(object), index, mode);
5438 }
5439
5440
5441 MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
5442                                                Handle<Name> name,
5443                                                DeleteMode mode) {
5444   if (object->IsJSProxy()) {
5445     return JSProxy::DeletePropertyWithHandler(
5446         Handle<JSProxy>::cast(object), name, mode);
5447   }
5448   return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, mode);
5449 }
5450
5451
5452 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
5453                                             ElementsKind kind,
5454                                             Object* object) {
5455   DCHECK(IsFastObjectElementsKind(kind) ||
5456          kind == DICTIONARY_ELEMENTS);
5457   if (IsFastObjectElementsKind(kind)) {
5458     int length = IsJSArray()
5459         ? Smi::cast(JSArray::cast(this)->length())->value()
5460         : elements->length();
5461     for (int i = 0; i < length; ++i) {
5462       Object* element = elements->get(i);
5463       if (!element->IsTheHole() && element == object) return true;
5464     }
5465   } else {
5466     Object* key =
5467         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5468     if (!key->IsUndefined()) return true;
5469   }
5470   return false;
5471 }
5472
5473
5474 // Check whether this object references another object.
5475 bool JSObject::ReferencesObject(Object* obj) {
5476   Map* map_of_this = map();
5477   Heap* heap = GetHeap();
5478   DisallowHeapAllocation no_allocation;
5479
5480   // Is the object the constructor for this object?
5481   if (map_of_this->constructor() == obj) {
5482     return true;
5483   }
5484
5485   // Is the object the prototype for this object?
5486   if (map_of_this->prototype() == obj) {
5487     return true;
5488   }
5489
5490   // Check if the object is among the named properties.
5491   Object* key = SlowReverseLookup(obj);
5492   if (!key->IsUndefined()) {
5493     return true;
5494   }
5495
5496   // Check if the object is among the indexed properties.
5497   ElementsKind kind = GetElementsKind();
5498   switch (kind) {
5499     // Raw pixels and external arrays do not reference other
5500     // objects.
5501 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5502     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
5503     case TYPE##_ELEMENTS:                                                      \
5504       break;
5505
5506     TYPED_ARRAYS(TYPED_ARRAY_CASE)
5507 #undef TYPED_ARRAY_CASE
5508
5509     case FAST_DOUBLE_ELEMENTS:
5510     case FAST_HOLEY_DOUBLE_ELEMENTS:
5511       break;
5512     case FAST_SMI_ELEMENTS:
5513     case FAST_HOLEY_SMI_ELEMENTS:
5514       break;
5515     case FAST_ELEMENTS:
5516     case FAST_HOLEY_ELEMENTS:
5517     case DICTIONARY_ELEMENTS: {
5518       FixedArray* elements = FixedArray::cast(this->elements());
5519       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5520       break;
5521     }
5522     case SLOPPY_ARGUMENTS_ELEMENTS: {
5523       FixedArray* parameter_map = FixedArray::cast(elements());
5524       // Check the mapped parameters.
5525       int length = parameter_map->length();
5526       for (int i = 2; i < length; ++i) {
5527         Object* value = parameter_map->get(i);
5528         if (!value->IsTheHole() && value == obj) return true;
5529       }
5530       // Check the arguments.
5531       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5532       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5533           FAST_HOLEY_ELEMENTS;
5534       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5535       break;
5536     }
5537   }
5538
5539   // For functions check the context.
5540   if (IsJSFunction()) {
5541     // Get the constructor function for arguments array.
5542     Map* arguments_map =
5543         heap->isolate()->context()->native_context()->sloppy_arguments_map();
5544     JSFunction* arguments_function =
5545         JSFunction::cast(arguments_map->constructor());
5546
5547     // Get the context and don't check if it is the native context.
5548     JSFunction* f = JSFunction::cast(this);
5549     Context* context = f->context();
5550     if (context->IsNativeContext()) {
5551       return false;
5552     }
5553
5554     // Check the non-special context slots.
5555     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5556       // Only check JS objects.
5557       if (context->get(i)->IsJSObject()) {
5558         JSObject* ctxobj = JSObject::cast(context->get(i));
5559         // If it is an arguments array check the content.
5560         if (ctxobj->map()->constructor() == arguments_function) {
5561           if (ctxobj->ReferencesObject(obj)) {
5562             return true;
5563           }
5564         } else if (ctxobj == obj) {
5565           return true;
5566         }
5567       }
5568     }
5569
5570     // Check the context extension (if any) if it can have references.
5571     if (context->has_extension() && !context->IsCatchContext()) {
5572       // With harmony scoping, a JSFunction may have a global context.
5573       // TODO(mvstanton): walk into the ScopeInfo.
5574       if (FLAG_harmony_scoping && context->IsGlobalContext()) {
5575         return false;
5576       }
5577
5578       return JSObject::cast(context->extension())->ReferencesObject(obj);
5579     }
5580   }
5581
5582   // No references to object.
5583   return false;
5584 }
5585
5586
5587 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5588   Isolate* isolate = object->GetIsolate();
5589
5590   if (!object->map()->is_extensible()) return object;
5591
5592   if (object->IsAccessCheckNeeded() &&
5593       !isolate->MayNamedAccess(
5594           object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5595     isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5596     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5597     return isolate->factory()->false_value();
5598   }
5599
5600   if (object->IsJSGlobalProxy()) {
5601     PrototypeIterator iter(isolate, object);
5602     if (iter.IsAtEnd()) return object;
5603     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5604     return PreventExtensions(
5605         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5606   }
5607
5608   // It's not possible to seal objects with external array elements
5609   if (object->HasExternalArrayElements() ||
5610       object->HasFixedTypedArrayElements()) {
5611     Handle<Object> error  =
5612         isolate->factory()->NewTypeError(
5613             "cant_prevent_ext_external_array_elements",
5614             HandleVector(&object, 1));
5615     return isolate->Throw<Object>(error);
5616   }
5617
5618   // If there are fast elements we normalize.
5619   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5620   DCHECK(object->HasDictionaryElements() ||
5621          object->HasDictionaryArgumentsElements());
5622
5623   // Make sure that we never go back to fast case.
5624   dictionary->set_requires_slow_elements();
5625
5626   // Do a map transition, other objects with this map may still
5627   // be extensible.
5628   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5629   Handle<Map> new_map = Map::Copy(handle(object->map()));
5630
5631   new_map->set_is_extensible(false);
5632   JSObject::MigrateToMap(object, new_map);
5633   DCHECK(!object->map()->is_extensible());
5634
5635   if (object->map()->is_observed()) {
5636     EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5637                         isolate->factory()->the_hole_value());
5638   }
5639   return object;
5640 }
5641
5642
5643 template<typename Dictionary>
5644 static void FreezeDictionary(Dictionary* dictionary) {
5645   int capacity = dictionary->Capacity();
5646   for (int i = 0; i < capacity; i++) {
5647     Object* k = dictionary->KeyAt(i);
5648     if (dictionary->IsKey(k) &&
5649         !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
5650       PropertyDetails details = dictionary->DetailsAt(i);
5651       int attrs = DONT_DELETE;
5652       // READ_ONLY is an invalid attribute for JS setters/getters.
5653       if (details.type() == CALLBACKS) {
5654         Object* v = dictionary->ValueAt(i);
5655         if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
5656         if (!v->IsAccessorPair()) attrs |= READ_ONLY;
5657       } else {
5658         attrs |= READ_ONLY;
5659       }
5660       details = details.CopyAddAttributes(
5661           static_cast<PropertyAttributes>(attrs));
5662       dictionary->DetailsAtPut(i, details);
5663     }
5664   }
5665 }
5666
5667
5668 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
5669   // Freezing sloppy arguments should be handled elsewhere.
5670   DCHECK(!object->HasSloppyArgumentsElements());
5671   DCHECK(!object->map()->is_observed());
5672
5673   if (object->map()->is_frozen()) return object;
5674
5675   Isolate* isolate = object->GetIsolate();
5676   if (object->IsAccessCheckNeeded() &&
5677       !isolate->MayNamedAccess(
5678           object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5679     isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5680     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5681     return isolate->factory()->false_value();
5682   }
5683
5684   if (object->IsJSGlobalProxy()) {
5685     PrototypeIterator iter(isolate, object);
5686     if (iter.IsAtEnd()) return object;
5687     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5688     return Freeze(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5689   }
5690
5691   // It's not possible to freeze objects with external array elements
5692   if (object->HasExternalArrayElements() ||
5693       object->HasFixedTypedArrayElements()) {
5694     Handle<Object> error  =
5695         isolate->factory()->NewTypeError(
5696             "cant_prevent_ext_external_array_elements",
5697             HandleVector(&object, 1));
5698     return isolate->Throw<Object>(error);
5699   }
5700
5701   Handle<SeededNumberDictionary> new_element_dictionary;
5702   if (!object->elements()->IsDictionary()) {
5703     int length = object->IsJSArray()
5704         ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5705         : object->elements()->length();
5706     if (length > 0) {
5707       int capacity = 0;
5708       int used = 0;
5709       object->GetElementsCapacityAndUsage(&capacity, &used);
5710       new_element_dictionary = SeededNumberDictionary::New(isolate, used);
5711
5712       // Move elements to a dictionary; avoid calling NormalizeElements to avoid
5713       // unnecessary transitions.
5714       new_element_dictionary = CopyFastElementsToDictionary(
5715           handle(object->elements()), length, new_element_dictionary);
5716     } else {
5717       // No existing elements, use a pre-allocated empty backing store
5718       new_element_dictionary =
5719           isolate->factory()->empty_slow_element_dictionary();
5720     }
5721   }
5722
5723   Handle<Map> old_map(object->map(), isolate);
5724   int transition_index = old_map->SearchTransition(
5725       isolate->heap()->frozen_symbol());
5726   if (transition_index != TransitionArray::kNotFound) {
5727     Handle<Map> transition_map(old_map->GetTransition(transition_index));
5728     DCHECK(transition_map->has_dictionary_elements());
5729     DCHECK(transition_map->is_frozen());
5730     DCHECK(!transition_map->is_extensible());
5731     JSObject::MigrateToMap(object, transition_map);
5732   } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5733     // Create a new descriptor array with fully-frozen properties
5734     Handle<Map> new_map = Map::CopyForFreeze(old_map);
5735     JSObject::MigrateToMap(object, new_map);
5736   } else {
5737     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5738     // Slow path: need to normalize properties for safety
5739     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5740
5741     // Create a new map, since other objects with this map may be extensible.
5742     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5743     Handle<Map> new_map = Map::Copy(handle(object->map()));
5744     new_map->freeze();
5745     new_map->set_is_extensible(false);
5746     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5747     JSObject::MigrateToMap(object, new_map);
5748
5749     // Freeze dictionary-mode properties
5750     FreezeDictionary(object->property_dictionary());
5751   }
5752
5753   DCHECK(object->map()->has_dictionary_elements());
5754   if (!new_element_dictionary.is_null()) {
5755     object->set_elements(*new_element_dictionary);
5756   }
5757
5758   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5759     SeededNumberDictionary* dictionary = object->element_dictionary();
5760     // Make sure we never go back to the fast case
5761     dictionary->set_requires_slow_elements();
5762     // Freeze all elements in the dictionary
5763     FreezeDictionary(dictionary);
5764   }
5765
5766   return object;
5767 }
5768
5769
5770 void JSObject::SetObserved(Handle<JSObject> object) {
5771   DCHECK(!object->IsJSGlobalProxy());
5772   DCHECK(!object->IsJSGlobalObject());
5773   Isolate* isolate = object->GetIsolate();
5774   Handle<Map> new_map;
5775   Handle<Map> old_map(object->map(), isolate);
5776   DCHECK(!old_map->is_observed());
5777   int transition_index = old_map->SearchTransition(
5778       isolate->heap()->observed_symbol());
5779   if (transition_index != TransitionArray::kNotFound) {
5780     new_map = handle(old_map->GetTransition(transition_index), isolate);
5781     DCHECK(new_map->is_observed());
5782   } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5783     new_map = Map::CopyForObserved(old_map);
5784   } else {
5785     new_map = Map::Copy(old_map);
5786     new_map->set_is_observed();
5787   }
5788   JSObject::MigrateToMap(object, new_map);
5789 }
5790
5791
5792 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
5793                                         Representation representation,
5794                                         FieldIndex index) {
5795   Isolate* isolate = object->GetIsolate();
5796   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
5797   return Object::WrapForRead(isolate, raw_value, representation);
5798 }
5799
5800
5801 template<class ContextObject>
5802 class JSObjectWalkVisitor {
5803  public:
5804   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5805                       JSObject::DeepCopyHints hints)
5806     : site_context_(site_context),
5807       copying_(copying),
5808       hints_(hints) {}
5809
5810   MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
5811
5812  protected:
5813   MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
5814       Handle<JSObject> object,
5815       Handle<JSObject> value) {
5816     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5817     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
5818     site_context()->ExitScope(current_site, value);
5819     return copy_of_value;
5820   }
5821
5822   inline ContextObject* site_context() { return site_context_; }
5823   inline Isolate* isolate() { return site_context()->isolate(); }
5824
5825   inline bool copying() const { return copying_; }
5826
5827  private:
5828   ContextObject* site_context_;
5829   const bool copying_;
5830   const JSObject::DeepCopyHints hints_;
5831 };
5832
5833
5834 template <class ContextObject>
5835 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
5836     Handle<JSObject> object) {
5837   Isolate* isolate = this->isolate();
5838   bool copying = this->copying();
5839   bool shallow = hints_ == JSObject::kObjectIsShallow;
5840
5841   if (!shallow) {
5842     StackLimitCheck check(isolate);
5843
5844     if (check.HasOverflowed()) {
5845       isolate->StackOverflow();
5846       return MaybeHandle<JSObject>();
5847     }
5848   }
5849
5850   if (object->map()->is_deprecated()) {
5851     JSObject::MigrateInstance(object);
5852   }
5853
5854   Handle<JSObject> copy;
5855   if (copying) {
5856     Handle<AllocationSite> site_to_pass;
5857     if (site_context()->ShouldCreateMemento(object)) {
5858       site_to_pass = site_context()->current();
5859     }
5860     copy = isolate->factory()->CopyJSObjectWithAllocationSite(
5861         object, site_to_pass);
5862   } else {
5863     copy = object;
5864   }
5865
5866   DCHECK(copying || copy.is_identical_to(object));
5867
5868   ElementsKind kind = copy->GetElementsKind();
5869   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5870       FixedArray::cast(copy->elements())->map() ==
5871         isolate->heap()->fixed_cow_array_map()) {
5872     isolate->counters()->cow_arrays_created_runtime()->Increment();
5873   }
5874
5875   if (!shallow) {
5876     HandleScope scope(isolate);
5877
5878     // Deep copy own properties.
5879     if (copy->HasFastProperties()) {
5880       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5881       int limit = copy->map()->NumberOfOwnDescriptors();
5882       for (int i = 0; i < limit; i++) {
5883         PropertyDetails details = descriptors->GetDetails(i);
5884         if (details.type() != FIELD) continue;
5885         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
5886         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5887         if (value->IsJSObject()) {
5888           ASSIGN_RETURN_ON_EXCEPTION(
5889               isolate, value,
5890               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5891               JSObject);
5892         } else {
5893           Representation representation = details.representation();
5894           value = Object::NewStorageFor(isolate, value, representation);
5895         }
5896         if (copying) {
5897           copy->FastPropertyAtPut(index, *value);
5898         }
5899       }
5900     } else {
5901       Handle<FixedArray> names =
5902           isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
5903       copy->GetOwnPropertyNames(*names, 0);
5904       for (int i = 0; i < names->length(); i++) {
5905         DCHECK(names->get(i)->IsString());
5906         Handle<String> key_string(String::cast(names->get(i)));
5907         Maybe<PropertyAttributes> maybe =
5908             JSReceiver::GetOwnPropertyAttributes(copy, key_string);
5909         DCHECK(maybe.has_value);
5910         PropertyAttributes attributes = maybe.value;
5911         // Only deep copy fields from the object literal expression.
5912         // In particular, don't try to copy the length attribute of
5913         // an array.
5914         if (attributes != NONE) continue;
5915         Handle<Object> value =
5916             Object::GetProperty(copy, key_string).ToHandleChecked();
5917         if (value->IsJSObject()) {
5918           Handle<JSObject> result;
5919           ASSIGN_RETURN_ON_EXCEPTION(
5920               isolate, result,
5921               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5922               JSObject);
5923           if (copying) {
5924             // Creating object copy for literals. No strict mode needed.
5925             JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert();
5926           }
5927         }
5928       }
5929     }
5930
5931     // Deep copy own elements.
5932     // Pixel elements cannot be created using an object literal.
5933     DCHECK(!copy->HasExternalArrayElements());
5934     switch (kind) {
5935       case FAST_SMI_ELEMENTS:
5936       case FAST_ELEMENTS:
5937       case FAST_HOLEY_SMI_ELEMENTS:
5938       case FAST_HOLEY_ELEMENTS: {
5939         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5940         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5941 #ifdef DEBUG
5942           for (int i = 0; i < elements->length(); i++) {
5943             DCHECK(!elements->get(i)->IsJSObject());
5944           }
5945 #endif
5946         } else {
5947           for (int i = 0; i < elements->length(); i++) {
5948             Handle<Object> value(elements->get(i), isolate);
5949             DCHECK(value->IsSmi() ||
5950                    value->IsTheHole() ||
5951                    (IsFastObjectElementsKind(copy->GetElementsKind())));
5952             if (value->IsJSObject()) {
5953               Handle<JSObject> result;
5954               ASSIGN_RETURN_ON_EXCEPTION(
5955                   isolate, result,
5956                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5957                   JSObject);
5958               if (copying) {
5959                 elements->set(i, *result);
5960               }
5961             }
5962           }
5963         }
5964         break;
5965       }
5966       case DICTIONARY_ELEMENTS: {
5967         Handle<SeededNumberDictionary> element_dictionary(
5968             copy->element_dictionary());
5969         int capacity = element_dictionary->Capacity();
5970         for (int i = 0; i < capacity; i++) {
5971           Object* k = element_dictionary->KeyAt(i);
5972           if (element_dictionary->IsKey(k)) {
5973             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
5974             if (value->IsJSObject()) {
5975               Handle<JSObject> result;
5976               ASSIGN_RETURN_ON_EXCEPTION(
5977                   isolate, result,
5978                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5979                   JSObject);
5980               if (copying) {
5981                 element_dictionary->ValueAtPut(i, *result);
5982               }
5983             }
5984           }
5985         }
5986         break;
5987       }
5988       case SLOPPY_ARGUMENTS_ELEMENTS:
5989         UNIMPLEMENTED();
5990         break;
5991
5992
5993 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5994       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
5995       case TYPE##_ELEMENTS:                                                    \
5996
5997       TYPED_ARRAYS(TYPED_ARRAY_CASE)
5998 #undef TYPED_ARRAY_CASE
5999
6000       case FAST_DOUBLE_ELEMENTS:
6001       case FAST_HOLEY_DOUBLE_ELEMENTS:
6002         // No contained objects, nothing to do.
6003         break;
6004     }
6005   }
6006
6007   return copy;
6008 }
6009
6010
6011 MaybeHandle<JSObject> JSObject::DeepWalk(
6012     Handle<JSObject> object,
6013     AllocationSiteCreationContext* site_context) {
6014   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
6015                                                        kNoHints);
6016   MaybeHandle<JSObject> result = v.StructureWalk(object);
6017   Handle<JSObject> for_assert;
6018   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
6019   return result;
6020 }
6021
6022
6023 MaybeHandle<JSObject> JSObject::DeepCopy(
6024     Handle<JSObject> object,
6025     AllocationSiteUsageContext* site_context,
6026     DeepCopyHints hints) {
6027   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
6028   MaybeHandle<JSObject> copy = v.StructureWalk(object);
6029   Handle<JSObject> for_assert;
6030   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
6031   return copy;
6032 }
6033
6034
6035 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
6036                                          Handle<Name> key) {
6037   Isolate* isolate = object->GetIsolate();
6038   LookupResult lookup(isolate);
6039   {
6040     DisallowHeapAllocation no_allocation;
6041     object->LookupRealNamedProperty(key, &lookup);
6042   }
6043   Handle<Object> result = isolate->factory()->undefined_value();
6044   if (lookup.IsFound() && !lookup.IsTransition()) {
6045     switch (lookup.type()) {
6046       case NORMAL:
6047         result = GetNormalizedProperty(
6048             Handle<JSObject>(lookup.holder(), isolate), &lookup);
6049         break;
6050       case FIELD:
6051         result = FastPropertyAt(Handle<JSObject>(lookup.holder(), isolate),
6052                                 lookup.representation(),
6053                                 lookup.GetFieldIndex());
6054         break;
6055       case CONSTANT:
6056         result = Handle<Object>(lookup.GetConstant(), isolate);
6057         break;
6058       case CALLBACKS:
6059       case HANDLER:
6060       case INTERCEPTOR:
6061         break;
6062       case NONEXISTENT:
6063         UNREACHABLE();
6064     }
6065   }
6066   return result;
6067 }
6068
6069
6070 // Tests for the fast common case for property enumeration:
6071 // - This object and all prototypes has an enum cache (which means that
6072 //   it is no proxy, has no interceptors and needs no access checks).
6073 // - This object has no elements.
6074 // - No prototype has enumerable properties/elements.
6075 bool JSReceiver::IsSimpleEnum() {
6076   for (PrototypeIterator iter(GetIsolate(), this,
6077                               PrototypeIterator::START_AT_RECEIVER);
6078        !iter.IsAtEnd(); iter.Advance()) {
6079     if (!iter.GetCurrent()->IsJSObject()) return false;
6080     JSObject* curr = JSObject::cast(iter.GetCurrent());
6081     int enum_length = curr->map()->EnumLength();
6082     if (enum_length == kInvalidEnumCacheSentinel) return false;
6083     if (curr->IsAccessCheckNeeded()) return false;
6084     DCHECK(!curr->HasNamedInterceptor());
6085     DCHECK(!curr->HasIndexedInterceptor());
6086     if (curr->NumberOfEnumElements() > 0) return false;
6087     if (curr != this && enum_length != 0) return false;
6088   }
6089   return true;
6090 }
6091
6092
6093 static bool FilterKey(Object* key, PropertyAttributes filter) {
6094   if ((filter & SYMBOLIC) && key->IsSymbol()) {
6095     return true;
6096   }
6097
6098   if ((filter & PRIVATE_SYMBOL) &&
6099       key->IsSymbol() && Symbol::cast(key)->is_private()) {
6100     return true;
6101   }
6102
6103   if ((filter & STRING) && !key->IsSymbol()) {
6104     return true;
6105   }
6106
6107   return false;
6108 }
6109
6110
6111 int Map::NumberOfDescribedProperties(DescriptorFlag which,
6112                                      PropertyAttributes filter) {
6113   int result = 0;
6114   DescriptorArray* descs = instance_descriptors();
6115   int limit = which == ALL_DESCRIPTORS
6116       ? descs->number_of_descriptors()
6117       : NumberOfOwnDescriptors();
6118   for (int i = 0; i < limit; i++) {
6119     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
6120         !FilterKey(descs->GetKey(i), filter)) {
6121       result++;
6122     }
6123   }
6124   return result;
6125 }
6126
6127
6128 int Map::NextFreePropertyIndex() {
6129   int max_index = -1;
6130   int number_of_own_descriptors = NumberOfOwnDescriptors();
6131   DescriptorArray* descs = instance_descriptors();
6132   for (int i = 0; i < number_of_own_descriptors; i++) {
6133     if (descs->GetType(i) == FIELD) {
6134       int current_index = descs->GetFieldIndex(i);
6135       if (current_index > max_index) max_index = current_index;
6136     }
6137   }
6138   return max_index + 1;
6139 }
6140
6141
6142 void JSReceiver::LookupOwn(
6143     Handle<Name> name, LookupResult* result, bool search_hidden_prototypes) {
6144   DisallowHeapAllocation no_gc;
6145   DCHECK(name->IsName());
6146
6147   if (IsJSGlobalProxy()) {
6148     PrototypeIterator iter(GetIsolate(), this);
6149     if (iter.IsAtEnd()) return result->NotFound();
6150     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
6151     return JSReceiver::cast(iter.GetCurrent())
6152         ->LookupOwn(name, result, search_hidden_prototypes);
6153   }
6154
6155   if (IsJSProxy()) {
6156     result->HandlerResult(JSProxy::cast(this));
6157     return;
6158   }
6159
6160   // Do not use inline caching if the object is a non-global object
6161   // that requires access checks.
6162   if (IsAccessCheckNeeded()) {
6163     result->DisallowCaching();
6164   }
6165
6166   JSObject* js_object = JSObject::cast(this);
6167
6168   // Check for lookup interceptor except when bootstrapping.
6169   if (js_object->HasNamedInterceptor() &&
6170       !GetIsolate()->bootstrapper()->IsActive()) {
6171     result->InterceptorResult(js_object);
6172     return;
6173   }
6174
6175   js_object->LookupOwnRealNamedProperty(name, result);
6176   if (result->IsFound() || !search_hidden_prototypes) return;
6177
6178   PrototypeIterator iter(GetIsolate(), js_object);
6179   if (!iter.GetCurrent()->IsJSReceiver()) return;
6180   JSReceiver* receiver = JSReceiver::cast(iter.GetCurrent());
6181   if (receiver->map()->is_hidden_prototype()) {
6182     receiver->LookupOwn(name, result, search_hidden_prototypes);
6183   }
6184 }
6185
6186
6187 void JSReceiver::Lookup(Handle<Name> name, LookupResult* result) {
6188   DisallowHeapAllocation no_gc;
6189   // Ecma-262 3rd 8.6.2.4
6190   for (PrototypeIterator iter(GetIsolate(), this,
6191                               PrototypeIterator::START_AT_RECEIVER);
6192        !iter.IsAtEnd(); iter.Advance()) {
6193     JSReceiver::cast(iter.GetCurrent())->LookupOwn(name, result, false);
6194     if (result->IsFound()) return;
6195   }
6196   result->NotFound();
6197 }
6198
6199
6200 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
6201   int len = array->length();
6202   for (int i = 0; i < len; i++) {
6203     Object* e = array->get(i);
6204     if (!(e->IsString() || e->IsNumber())) return false;
6205   }
6206   return true;
6207 }
6208
6209
6210 static Handle<FixedArray> ReduceFixedArrayTo(
6211     Handle<FixedArray> array, int length) {
6212   DCHECK(array->length() >= length);
6213   if (array->length() == length) return array;
6214
6215   Handle<FixedArray> new_array =
6216       array->GetIsolate()->factory()->NewFixedArray(length);
6217   for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
6218   return new_array;
6219 }
6220
6221
6222 static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
6223                                               bool cache_result) {
6224   Isolate* isolate = object->GetIsolate();
6225   if (object->HasFastProperties()) {
6226     int own_property_count = object->map()->EnumLength();
6227     // If the enum length of the given map is set to kInvalidEnumCache, this
6228     // means that the map itself has never used the present enum cache. The
6229     // first step to using the cache is to set the enum length of the map by
6230     // counting the number of own descriptors that are not DONT_ENUM or
6231     // SYMBOLIC.
6232     if (own_property_count == kInvalidEnumCacheSentinel) {
6233       own_property_count = object->map()->NumberOfDescribedProperties(
6234           OWN_DESCRIPTORS, DONT_SHOW);
6235     } else {
6236       DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
6237           OWN_DESCRIPTORS, DONT_SHOW));
6238     }
6239
6240     if (object->map()->instance_descriptors()->HasEnumCache()) {
6241       DescriptorArray* desc = object->map()->instance_descriptors();
6242       Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
6243
6244       // In case the number of properties required in the enum are actually
6245       // present, we can reuse the enum cache. Otherwise, this means that the
6246       // enum cache was generated for a previous (smaller) version of the
6247       // Descriptor Array. In that case we regenerate the enum cache.
6248       if (own_property_count <= keys->length()) {
6249         if (cache_result) object->map()->SetEnumLength(own_property_count);
6250         isolate->counters()->enum_cache_hits()->Increment();
6251         return ReduceFixedArrayTo(keys, own_property_count);
6252       }
6253     }
6254
6255     Handle<Map> map(object->map());
6256
6257     if (map->instance_descriptors()->IsEmpty()) {
6258       isolate->counters()->enum_cache_hits()->Increment();
6259       if (cache_result) map->SetEnumLength(0);
6260       return isolate->factory()->empty_fixed_array();
6261     }
6262
6263     isolate->counters()->enum_cache_misses()->Increment();
6264
6265     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
6266         own_property_count);
6267     Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
6268         own_property_count);
6269
6270     Handle<DescriptorArray> descs =
6271         Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
6272
6273     int size = map->NumberOfOwnDescriptors();
6274     int index = 0;
6275
6276     for (int i = 0; i < size; i++) {
6277       PropertyDetails details = descs->GetDetails(i);
6278       Object* key = descs->GetKey(i);
6279       if (!(details.IsDontEnum() || key->IsSymbol())) {
6280         storage->set(index, key);
6281         if (!indices.is_null()) {
6282           if (details.type() != FIELD) {
6283             indices = Handle<FixedArray>();
6284           } else {
6285             FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
6286             int load_by_field_index = field_index.GetLoadByFieldIndex();
6287             indices->set(index, Smi::FromInt(load_by_field_index));
6288           }
6289         }
6290         index++;
6291       }
6292     }
6293     DCHECK(index == storage->length());
6294
6295     Handle<FixedArray> bridge_storage =
6296         isolate->factory()->NewFixedArray(
6297             DescriptorArray::kEnumCacheBridgeLength);
6298     DescriptorArray* desc = object->map()->instance_descriptors();
6299     desc->SetEnumCache(*bridge_storage,
6300                        *storage,
6301                        indices.is_null() ? Object::cast(Smi::FromInt(0))
6302                                          : Object::cast(*indices));
6303     if (cache_result) {
6304       object->map()->SetEnumLength(own_property_count);
6305     }
6306     return storage;
6307   } else {
6308     Handle<NameDictionary> dictionary(object->property_dictionary());
6309     int length = dictionary->NumberOfEnumElements();
6310     if (length == 0) {
6311       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6312     }
6313     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6314     dictionary->CopyEnumKeysTo(*storage);
6315     return storage;
6316   }
6317 }
6318
6319
6320 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6321                                             KeyCollectionType type) {
6322   USE(ContainsOnlyValidKeys);
6323   Isolate* isolate = object->GetIsolate();
6324   Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
6325   Handle<JSFunction> arguments_function(
6326       JSFunction::cast(isolate->sloppy_arguments_map()->constructor()));
6327
6328   // Only collect keys if access is permitted.
6329   for (PrototypeIterator iter(isolate, object,
6330                               PrototypeIterator::START_AT_RECEIVER);
6331        !iter.IsAtEnd(); iter.Advance()) {
6332     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6333       Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
6334                             isolate);
6335       Handle<Object> args[] = { proxy };
6336       Handle<Object> names;
6337       ASSIGN_RETURN_ON_EXCEPTION(
6338           isolate, names,
6339           Execution::Call(isolate,
6340                           isolate->proxy_enumerate(),
6341                           object,
6342                           ARRAY_SIZE(args),
6343                           args),
6344           FixedArray);
6345       ASSIGN_RETURN_ON_EXCEPTION(
6346           isolate, content,
6347           FixedArray::AddKeysFromArrayLike(
6348               content, Handle<JSObject>::cast(names)),
6349           FixedArray);
6350       break;
6351     }
6352
6353     Handle<JSObject> current =
6354         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
6355
6356     // Check access rights if required.
6357     if (current->IsAccessCheckNeeded() &&
6358         !isolate->MayNamedAccess(
6359             current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
6360       isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS);
6361       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6362       break;
6363     }
6364
6365     // Compute the element keys.
6366     Handle<FixedArray> element_keys =
6367         isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6368     current->GetEnumElementKeys(*element_keys);
6369     ASSIGN_RETURN_ON_EXCEPTION(
6370         isolate, content,
6371         FixedArray::UnionOfKeys(content, element_keys),
6372         FixedArray);
6373     DCHECK(ContainsOnlyValidKeys(content));
6374
6375     // Add the element keys from the interceptor.
6376     if (current->HasIndexedInterceptor()) {
6377       Handle<JSObject> result;
6378       if (JSObject::GetKeysForIndexedInterceptor(
6379               current, object).ToHandle(&result)) {
6380         ASSIGN_RETURN_ON_EXCEPTION(
6381             isolate, content,
6382             FixedArray::AddKeysFromArrayLike(content, result),
6383             FixedArray);
6384       }
6385       DCHECK(ContainsOnlyValidKeys(content));
6386     }
6387
6388     // We can cache the computed property keys if access checks are
6389     // not needed and no interceptors are involved.
6390     //
6391     // We do not use the cache if the object has elements and
6392     // therefore it does not make sense to cache the property names
6393     // for arguments objects.  Arguments objects will always have
6394     // elements.
6395     // Wrapped strings have elements, but don't have an elements
6396     // array or dictionary.  So the fast inline test for whether to
6397     // use the cache says yes, so we should not create a cache.
6398     bool cache_enum_keys =
6399         ((current->map()->constructor() != *arguments_function) &&
6400          !current->IsJSValue() &&
6401          !current->IsAccessCheckNeeded() &&
6402          !current->HasNamedInterceptor() &&
6403          !current->HasIndexedInterceptor());
6404     // Compute the property keys and cache them if possible.
6405     ASSIGN_RETURN_ON_EXCEPTION(
6406         isolate, content,
6407         FixedArray::UnionOfKeys(
6408             content, GetEnumPropertyKeys(current, cache_enum_keys)),
6409         FixedArray);
6410     DCHECK(ContainsOnlyValidKeys(content));
6411
6412     // Add the property keys from the interceptor.
6413     if (current->HasNamedInterceptor()) {
6414       Handle<JSObject> result;
6415       if (JSObject::GetKeysForNamedInterceptor(
6416               current, object).ToHandle(&result)) {
6417         ASSIGN_RETURN_ON_EXCEPTION(
6418             isolate, content,
6419             FixedArray::AddKeysFromArrayLike(content, result),
6420             FixedArray);
6421       }
6422       DCHECK(ContainsOnlyValidKeys(content));
6423     }
6424
6425     // If we only want own properties we bail out after the first
6426     // iteration.
6427     if (type == OWN_ONLY) break;
6428   }
6429   return content;
6430 }
6431
6432
6433 // Try to update an accessor in an elements dictionary. Return true if the
6434 // update succeeded, and false otherwise.
6435 static bool UpdateGetterSetterInDictionary(
6436     SeededNumberDictionary* dictionary,
6437     uint32_t index,
6438     Object* getter,
6439     Object* setter,
6440     PropertyAttributes attributes) {
6441   int entry = dictionary->FindEntry(index);
6442   if (entry != SeededNumberDictionary::kNotFound) {
6443     Object* result = dictionary->ValueAt(entry);
6444     PropertyDetails details = dictionary->DetailsAt(entry);
6445     if (details.type() == CALLBACKS && result->IsAccessorPair()) {
6446       DCHECK(!details.IsDontDelete());
6447       if (details.attributes() != attributes) {
6448         dictionary->DetailsAtPut(
6449             entry,
6450             PropertyDetails(attributes, CALLBACKS, index));
6451       }
6452       AccessorPair::cast(result)->SetComponents(getter, setter);
6453       return true;
6454     }
6455   }
6456   return false;
6457 }
6458
6459
6460 void JSObject::DefineElementAccessor(Handle<JSObject> object,
6461                                      uint32_t index,
6462                                      Handle<Object> getter,
6463                                      Handle<Object> setter,
6464                                      PropertyAttributes attributes) {
6465   switch (object->GetElementsKind()) {
6466     case FAST_SMI_ELEMENTS:
6467     case FAST_ELEMENTS:
6468     case FAST_DOUBLE_ELEMENTS:
6469     case FAST_HOLEY_SMI_ELEMENTS:
6470     case FAST_HOLEY_ELEMENTS:
6471     case FAST_HOLEY_DOUBLE_ELEMENTS:
6472       break;
6473
6474 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6475     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
6476     case TYPE##_ELEMENTS:                                                      \
6477
6478     TYPED_ARRAYS(TYPED_ARRAY_CASE)
6479 #undef TYPED_ARRAY_CASE
6480       // Ignore getters and setters on pixel and external array elements.
6481       return;
6482
6483     case DICTIONARY_ELEMENTS:
6484       if (UpdateGetterSetterInDictionary(object->element_dictionary(),
6485                                          index,
6486                                          *getter,
6487                                          *setter,
6488                                          attributes)) {
6489         return;
6490       }
6491       break;
6492     case SLOPPY_ARGUMENTS_ELEMENTS: {
6493       // Ascertain whether we have read-only properties or an existing
6494       // getter/setter pair in an arguments elements dictionary backing
6495       // store.
6496       FixedArray* parameter_map = FixedArray::cast(object->elements());
6497       uint32_t length = parameter_map->length();
6498       Object* probe =
6499           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
6500       if (probe == NULL || probe->IsTheHole()) {
6501         FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
6502         if (arguments->IsDictionary()) {
6503           SeededNumberDictionary* dictionary =
6504               SeededNumberDictionary::cast(arguments);
6505           if (UpdateGetterSetterInDictionary(dictionary,
6506                                              index,
6507                                              *getter,
6508                                              *setter,
6509                                              attributes)) {
6510             return;
6511           }
6512         }
6513       }
6514       break;
6515     }
6516   }
6517
6518   Isolate* isolate = object->GetIsolate();
6519   Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair();
6520   accessors->SetComponents(*getter, *setter);
6521
6522   SetElementCallback(object, index, accessors, attributes);
6523 }
6524
6525
6526 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object,
6527                                                      Handle<Name> name) {
6528   Isolate* isolate = object->GetIsolate();
6529   LookupResult result(isolate);
6530   object->LookupOwnRealNamedProperty(name, &result);
6531   if (result.IsPropertyCallbacks()) {
6532     // Note that the result can actually have IsDontDelete() == true when we
6533     // e.g. have to fall back to the slow case while adding a setter after
6534     // successfully reusing a map transition for a getter. Nevertheless, this is
6535     // OK, because the assertion only holds for the whole addition of both
6536     // accessors, not for the addition of each part. See first comment in
6537     // DefinePropertyAccessor below.
6538     Object* obj = result.GetCallbackObject();
6539     if (obj->IsAccessorPair()) {
6540       return AccessorPair::Copy(handle(AccessorPair::cast(obj), isolate));
6541     }
6542   }
6543   return isolate->factory()->NewAccessorPair();
6544 }
6545
6546
6547 void JSObject::DefinePropertyAccessor(Handle<JSObject> object,
6548                                       Handle<Name> name,
6549                                       Handle<Object> getter,
6550                                       Handle<Object> setter,
6551                                       PropertyAttributes attributes) {
6552   // We could assert that the property is configurable here, but we would need
6553   // to do a lookup, which seems to be a bit of overkill.
6554   bool only_attribute_changes = getter->IsNull() && setter->IsNull();
6555   if (object->HasFastProperties() && !only_attribute_changes &&
6556       (object->map()->NumberOfOwnDescriptors() <= kMaxNumberOfDescriptors)) {
6557     bool getterOk = getter->IsNull() ||
6558         DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes);
6559     bool setterOk = !getterOk || setter->IsNull() ||
6560         DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes);
6561     if (getterOk && setterOk) return;
6562   }
6563
6564   Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name);
6565   accessors->SetComponents(*getter, *setter);
6566
6567   SetPropertyCallback(object, name, accessors, attributes);
6568 }
6569
6570
6571 bool Map::DictionaryElementsInPrototypeChainOnly() {
6572   if (IsDictionaryElementsKind(elements_kind())) {
6573     return false;
6574   }
6575
6576   for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
6577     if (iter.GetCurrent()->IsJSProxy()) {
6578       // Be conservative, don't walk into proxies.
6579       return true;
6580     }
6581
6582     if (IsDictionaryElementsKind(
6583             JSObject::cast(iter.GetCurrent())->map()->elements_kind())) {
6584       return true;
6585     }
6586   }
6587
6588   return false;
6589 }
6590
6591
6592 void JSObject::SetElementCallback(Handle<JSObject> object,
6593                                   uint32_t index,
6594                                   Handle<Object> structure,
6595                                   PropertyAttributes attributes) {
6596   Heap* heap = object->GetHeap();
6597   PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6598
6599   // Normalize elements to make this operation simple.
6600   bool had_dictionary_elements = object->HasDictionaryElements();
6601   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
6602   DCHECK(object->HasDictionaryElements() ||
6603          object->HasDictionaryArgumentsElements());
6604   // Update the dictionary with the new CALLBACKS property.
6605   dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
6606                                            details);
6607   dictionary->set_requires_slow_elements();
6608
6609   // Update the dictionary backing store on the object.
6610   if (object->elements()->map() == heap->sloppy_arguments_elements_map()) {
6611     // Also delete any parameter alias.
6612     //
6613     // TODO(kmillikin): when deleting the last parameter alias we could
6614     // switch to a direct backing store without the parameter map.  This
6615     // would allow GC of the context.
6616     FixedArray* parameter_map = FixedArray::cast(object->elements());
6617     if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
6618       parameter_map->set(index + 2, heap->the_hole_value());
6619     }
6620     parameter_map->set(1, *dictionary);
6621   } else {
6622     object->set_elements(*dictionary);
6623
6624     if (!had_dictionary_elements) {
6625       // KeyedStoreICs (at least the non-generic ones) need a reset.
6626       heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
6627     }
6628   }
6629 }
6630
6631
6632 void JSObject::SetPropertyCallback(Handle<JSObject> object,
6633                                    Handle<Name> name,
6634                                    Handle<Object> structure,
6635                                    PropertyAttributes attributes) {
6636   PropertyNormalizationMode mode = object->map()->is_prototype_map()
6637                                        ? KEEP_INOBJECT_PROPERTIES
6638                                        : CLEAR_INOBJECT_PROPERTIES;
6639   // Normalize object to make this operation simple.
6640   NormalizeProperties(object, mode, 0);
6641
6642   // For the global object allocate a new map to invalidate the global inline
6643   // caches which have a global property cell reference directly in the code.
6644   if (object->IsGlobalObject()) {
6645     Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
6646     DCHECK(new_map->is_dictionary_map());
6647     JSObject::MigrateToMap(object, new_map);
6648
6649     // When running crankshaft, changing the map is not enough. We
6650     // need to deoptimize all functions that rely on this global
6651     // object.
6652     Deoptimizer::DeoptimizeGlobalObject(*object);
6653   }
6654
6655   // Update the dictionary with the new CALLBACKS property.
6656   PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6657   SetNormalizedProperty(object, name, structure, details);
6658
6659   ReoptimizeIfPrototype(object);
6660 }
6661
6662
6663 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
6664                                              Handle<Name> name,
6665                                              Handle<Object> getter,
6666                                              Handle<Object> setter,
6667                                              PropertyAttributes attributes) {
6668   Isolate* isolate = object->GetIsolate();
6669   // Check access rights if needed.
6670   if (object->IsAccessCheckNeeded() &&
6671       !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6672     isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6673     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6674     return isolate->factory()->undefined_value();
6675   }
6676
6677   if (object->IsJSGlobalProxy()) {
6678     PrototypeIterator iter(isolate, object);
6679     if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
6680     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6681     DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
6682                    name, getter, setter, attributes);
6683     return isolate->factory()->undefined_value();
6684   }
6685
6686   // Make sure that the top context does not change when doing callbacks or
6687   // interceptor calls.
6688   AssertNoContextChange ncc(isolate);
6689
6690   // Try to flatten before operating on the string.
6691   if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6692
6693   uint32_t index = 0;
6694   bool is_element = name->AsArrayIndex(&index);
6695
6696   Handle<Object> old_value = isolate->factory()->the_hole_value();
6697   bool is_observed = object->map()->is_observed() &&
6698                      *name != isolate->heap()->hidden_string();
6699   bool preexists = false;
6700   if (is_observed) {
6701     if (is_element) {
6702       Maybe<bool> maybe = HasOwnElement(object, index);
6703       // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used
6704       // uninitialized in this function".
6705       if (!maybe.has_value) {
6706         DCHECK(false);
6707         return isolate->factory()->undefined_value();
6708       }
6709       preexists = maybe.value;
6710       if (preexists && GetOwnElementAccessorPair(object, index).is_null()) {
6711         old_value =
6712             Object::GetElement(isolate, object, index).ToHandleChecked();
6713       }
6714     } else {
6715       LookupResult lookup(isolate);
6716       object->LookupOwn(name, &lookup, true);
6717       preexists = lookup.IsProperty();
6718       if (preexists && lookup.IsDataProperty()) {
6719         old_value =
6720             Object::GetPropertyOrElement(object, name).ToHandleChecked();
6721       }
6722     }
6723   }
6724
6725   if (is_element) {
6726     DefineElementAccessor(object, index, getter, setter, attributes);
6727   } else {
6728     DefinePropertyAccessor(object, name, getter, setter, attributes);
6729   }
6730
6731   if (is_observed) {
6732     const char* type = preexists ? "reconfigure" : "add";
6733     EnqueueChangeRecord(object, type, name, old_value);
6734   }
6735
6736   return isolate->factory()->undefined_value();
6737 }
6738
6739
6740 static bool TryAccessorTransition(Handle<JSObject> self,
6741                                   Handle<Map> transitioned_map,
6742                                   int target_descriptor,
6743                                   AccessorComponent component,
6744                                   Handle<Object> accessor,
6745                                   PropertyAttributes attributes) {
6746   DescriptorArray* descs = transitioned_map->instance_descriptors();
6747   PropertyDetails details = descs->GetDetails(target_descriptor);
6748
6749   // If the transition target was not callbacks, fall back to the slow case.
6750   if (details.type() != CALLBACKS) return false;
6751   Object* descriptor = descs->GetCallbacksObject(target_descriptor);
6752   if (!descriptor->IsAccessorPair()) return false;
6753
6754   Object* target_accessor = AccessorPair::cast(descriptor)->get(component);
6755   PropertyAttributes target_attributes = details.attributes();
6756
6757   // Reuse transition if adding same accessor with same attributes.
6758   if (target_accessor == *accessor && target_attributes == attributes) {
6759     JSObject::MigrateToMap(self, transitioned_map);
6760     return true;
6761   }
6762
6763   // If either not the same accessor, or not the same attributes, fall back to
6764   // the slow case.
6765   return false;
6766 }
6767
6768
6769 bool JSObject::DefineFastAccessor(Handle<JSObject> object,
6770                                   Handle<Name> name,
6771                                   AccessorComponent component,
6772                                   Handle<Object> accessor,
6773                                   PropertyAttributes attributes) {
6774   DCHECK(accessor->IsSpecFunction() || accessor->IsUndefined());
6775   Isolate* isolate = object->GetIsolate();
6776   LookupResult result(isolate);
6777   object->LookupOwn(name, &result);
6778
6779   if (result.IsFound() && !result.IsPropertyCallbacks()) {
6780     return false;
6781   }
6782
6783   // Return success if the same accessor with the same attributes already exist.
6784   AccessorPair* source_accessors = NULL;
6785   if (result.IsPropertyCallbacks()) {
6786     Object* callback_value = result.GetCallbackObject();
6787     if (callback_value->IsAccessorPair()) {
6788       source_accessors = AccessorPair::cast(callback_value);
6789       Object* entry = source_accessors->get(component);
6790       if (entry == *accessor && result.GetAttributes() == attributes) {
6791         return true;
6792       }
6793     } else {
6794       return false;
6795     }
6796
6797     int descriptor_number = result.GetDescriptorIndex();
6798
6799     object->map()->LookupTransition(*object, *name, &result);
6800
6801     if (result.IsFound()) {
6802       Handle<Map> target(result.GetTransitionTarget());
6803       DCHECK(target->NumberOfOwnDescriptors() ==
6804              object->map()->NumberOfOwnDescriptors());
6805       // This works since descriptors are sorted in order of addition.
6806       DCHECK(Name::Equals(
6807           handle(object->map()->instance_descriptors()->GetKey(
6808               descriptor_number)),
6809           name));
6810       return TryAccessorTransition(object, target, descriptor_number,
6811                                    component, accessor, attributes);
6812     }
6813   } else {
6814     // If not, lookup a transition.
6815     object->map()->LookupTransition(*object, *name, &result);
6816
6817     // If there is a transition, try to follow it.
6818     if (result.IsFound()) {
6819       Handle<Map> target(result.GetTransitionTarget());
6820       int descriptor_number = target->LastAdded();
6821       DCHECK(Name::Equals(name,
6822           handle(target->instance_descriptors()->GetKey(descriptor_number))));
6823       return TryAccessorTransition(object, target, descriptor_number,
6824                                    component, accessor, attributes);
6825     }
6826   }
6827
6828   // If there is no transition yet, add a transition to the a new accessor pair
6829   // containing the accessor.  Allocate a new pair if there were no source
6830   // accessors.  Otherwise, copy the pair and modify the accessor.
6831   Handle<AccessorPair> accessors = source_accessors != NULL
6832       ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
6833       : isolate->factory()->NewAccessorPair();
6834   accessors->set(component, *accessor);
6835
6836   CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
6837   Handle<Map> new_map = Map::CopyInsertDescriptor(
6838       handle(object->map()), &new_accessors_desc, INSERT_TRANSITION);
6839
6840   JSObject::MigrateToMap(object, new_map);
6841   return true;
6842 }
6843
6844
6845 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6846                                           Handle<AccessorInfo> info) {
6847   Isolate* isolate = object->GetIsolate();
6848   Factory* factory = isolate->factory();
6849   Handle<Name> name(Name::cast(info->name()));
6850
6851   // Check access rights if needed.
6852   if (object->IsAccessCheckNeeded() &&
6853       !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6854     isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6855     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6856     return factory->undefined_value();
6857   }
6858
6859   if (object->IsJSGlobalProxy()) {
6860     PrototypeIterator iter(isolate, object);
6861     if (iter.IsAtEnd()) return object;
6862     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6863     return SetAccessor(
6864         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), info);
6865   }
6866
6867   // Make sure that the top context does not change when doing callbacks or
6868   // interceptor calls.
6869   AssertNoContextChange ncc(isolate);
6870
6871   // Try to flatten before operating on the string.
6872   if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6873
6874   uint32_t index = 0;
6875   bool is_element = name->AsArrayIndex(&index);
6876
6877   if (is_element) {
6878     if (object->IsJSArray()) return factory->undefined_value();
6879
6880     // Accessors overwrite previous callbacks (cf. with getters/setters).
6881     switch (object->GetElementsKind()) {
6882       case FAST_SMI_ELEMENTS:
6883       case FAST_ELEMENTS:
6884       case FAST_DOUBLE_ELEMENTS:
6885       case FAST_HOLEY_SMI_ELEMENTS:
6886       case FAST_HOLEY_ELEMENTS:
6887       case FAST_HOLEY_DOUBLE_ELEMENTS:
6888         break;
6889
6890 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6891       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
6892       case TYPE##_ELEMENTS:                                                    \
6893
6894       TYPED_ARRAYS(TYPED_ARRAY_CASE)
6895 #undef TYPED_ARRAY_CASE
6896         // Ignore getters and setters on pixel and external array
6897         // elements.
6898         return factory->undefined_value();
6899
6900       case DICTIONARY_ELEMENTS:
6901         break;
6902       case SLOPPY_ARGUMENTS_ELEMENTS:
6903         UNIMPLEMENTED();
6904         break;
6905     }
6906
6907     SetElementCallback(object, index, info, info->property_attributes());
6908   } else {
6909     // Lookup the name.
6910     LookupResult result(isolate);
6911     object->LookupOwn(name, &result, true);
6912     // ES5 forbids turning a property into an accessor if it's not
6913     // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
6914     if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) {
6915       return factory->undefined_value();
6916     }
6917
6918     SetPropertyCallback(object, name, info, info->property_attributes());
6919   }
6920
6921   return object;
6922 }
6923
6924
6925 MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
6926                                           Handle<Name> name,
6927                                           AccessorComponent component) {
6928   Isolate* isolate = object->GetIsolate();
6929
6930   // Make sure that the top context does not change when doing callbacks or
6931   // interceptor calls.
6932   AssertNoContextChange ncc(isolate);
6933
6934   // Make the lookup and include prototypes.
6935   uint32_t index = 0;
6936   if (name->AsArrayIndex(&index)) {
6937     for (PrototypeIterator iter(isolate, object,
6938                                 PrototypeIterator::START_AT_RECEIVER);
6939          !iter.IsAtEnd(); iter.Advance()) {
6940       Handle<Object> current = PrototypeIterator::GetCurrent(iter);
6941       // Check access rights if needed.
6942       if (current->IsAccessCheckNeeded() &&
6943           !isolate->MayNamedAccess(Handle<JSObject>::cast(current), name,
6944                                    v8::ACCESS_HAS)) {
6945         isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(current),
6946                                          v8::ACCESS_HAS);
6947         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6948         return isolate->factory()->undefined_value();
6949       }
6950
6951       if (current->IsJSObject() &&
6952           Handle<JSObject>::cast(current)->HasDictionaryElements()) {
6953         JSObject* js_object = JSObject::cast(*current);
6954         SeededNumberDictionary* dictionary = js_object->element_dictionary();
6955         int entry = dictionary->FindEntry(index);
6956         if (entry != SeededNumberDictionary::kNotFound) {
6957           Object* element = dictionary->ValueAt(entry);
6958           if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
6959               element->IsAccessorPair()) {
6960             return handle(AccessorPair::cast(element)->GetComponent(component),
6961                           isolate);
6962           }
6963         }
6964       }
6965     }
6966   } else {
6967     LookupIterator it(object, name, LookupIterator::SKIP_INTERCEPTOR);
6968     for (; it.IsFound(); it.Next()) {
6969       switch (it.state()) {
6970         case LookupIterator::NOT_FOUND:
6971         case LookupIterator::INTERCEPTOR:
6972           UNREACHABLE();
6973
6974         case LookupIterator::ACCESS_CHECK:
6975           if (it.HasAccess(v8::ACCESS_HAS)) continue;
6976           isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>(),
6977                                            v8::ACCESS_HAS);
6978           RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6979           return isolate->factory()->undefined_value();
6980
6981         case LookupIterator::JSPROXY:
6982           return isolate->factory()->undefined_value();
6983
6984         case LookupIterator::PROPERTY:
6985           if (!it.HasProperty()) continue;
6986           switch (it.property_kind()) {
6987             case LookupIterator::DATA:
6988               continue;
6989             case LookupIterator::ACCESSOR: {
6990               Handle<Object> maybe_pair = it.GetAccessors();
6991               if (maybe_pair->IsAccessorPair()) {
6992                 return handle(
6993                     AccessorPair::cast(*maybe_pair)->GetComponent(component),
6994                     isolate);
6995               }
6996             }
6997           }
6998       }
6999     }
7000   }
7001   return isolate->factory()->undefined_value();
7002 }
7003
7004
7005 Object* JSObject::SlowReverseLookup(Object* value) {
7006   if (HasFastProperties()) {
7007     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
7008     DescriptorArray* descs = map()->instance_descriptors();
7009     for (int i = 0; i < number_of_own_descriptors; i++) {
7010       if (descs->GetType(i) == FIELD) {
7011         Object* property =
7012             RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i));
7013         if (descs->GetDetails(i).representation().IsDouble()) {
7014           DCHECK(property->IsMutableHeapNumber());
7015           if (value->IsNumber() && property->Number() == value->Number()) {
7016             return descs->GetKey(i);
7017           }
7018         } else if (property == value) {
7019           return descs->GetKey(i);
7020         }
7021       } else if (descs->GetType(i) == CONSTANT) {
7022         if (descs->GetConstant(i) == value) {
7023           return descs->GetKey(i);
7024         }
7025       }
7026     }
7027     return GetHeap()->undefined_value();
7028   } else {
7029     return property_dictionary()->SlowReverseLookup(value);
7030   }
7031 }
7032
7033
7034 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
7035   Handle<Map> result = map->GetIsolate()->factory()->NewMap(
7036       map->instance_type(), instance_size);
7037   result->set_prototype(map->prototype());
7038   result->set_constructor(map->constructor());
7039   result->set_bit_field(map->bit_field());
7040   result->set_bit_field2(map->bit_field2());
7041   int new_bit_field3 = map->bit_field3();
7042   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
7043   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
7044   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
7045                                           kInvalidEnumCacheSentinel);
7046   new_bit_field3 = Deprecated::update(new_bit_field3, false);
7047   if (!map->is_dictionary_map()) {
7048     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
7049   }
7050   new_bit_field3 = ConstructionCount::update(new_bit_field3,
7051                                              JSFunction::kNoSlackTracking);
7052   result->set_bit_field3(new_bit_field3);
7053   return result;
7054 }
7055
7056
7057 Handle<Map> Map::Normalize(Handle<Map> fast_map,
7058                            PropertyNormalizationMode mode) {
7059   DCHECK(!fast_map->is_dictionary_map());
7060
7061   Isolate* isolate = fast_map->GetIsolate();
7062   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
7063                              isolate);
7064   bool use_cache = !maybe_cache->IsUndefined();
7065   Handle<NormalizedMapCache> cache;
7066   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
7067
7068   Handle<Map> new_map;
7069   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
7070 #ifdef VERIFY_HEAP
7071     if (FLAG_verify_heap) new_map->DictionaryMapVerify();
7072 #endif
7073 #ifdef ENABLE_SLOW_DCHECKS
7074     if (FLAG_enable_slow_asserts) {
7075       // The cached map should match newly created normalized map bit-by-bit,
7076       // except for the code cache, which can contain some ics which can be
7077       // applied to the shared map.
7078       Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
7079
7080       DCHECK(memcmp(fresh->address(),
7081                     new_map->address(),
7082                     Map::kCodeCacheOffset) == 0);
7083       STATIC_ASSERT(Map::kDependentCodeOffset ==
7084                     Map::kCodeCacheOffset + kPointerSize);
7085       int offset = Map::kDependentCodeOffset + kPointerSize;
7086       DCHECK(memcmp(fresh->address() + offset,
7087                     new_map->address() + offset,
7088                     Map::kSize - offset) == 0);
7089     }
7090 #endif
7091   } else {
7092     new_map = Map::CopyNormalized(fast_map, mode);
7093     if (use_cache) {
7094       cache->Set(fast_map, new_map);
7095       isolate->counters()->normalized_maps()->Increment();
7096     }
7097   }
7098   fast_map->NotifyLeafMapLayoutChange();
7099   return new_map;
7100 }
7101
7102
7103 Handle<Map> Map::CopyNormalized(Handle<Map> map,
7104                                 PropertyNormalizationMode mode) {
7105   int new_instance_size = map->instance_size();
7106   if (mode == CLEAR_INOBJECT_PROPERTIES) {
7107     new_instance_size -= map->inobject_properties() * kPointerSize;
7108   }
7109
7110   Handle<Map> result = RawCopy(map, new_instance_size);
7111
7112   if (mode != CLEAR_INOBJECT_PROPERTIES) {
7113     result->set_inobject_properties(map->inobject_properties());
7114   }
7115
7116   result->set_dictionary_map(true);
7117   result->set_migration_target(false);
7118
7119 #ifdef VERIFY_HEAP
7120   if (FLAG_verify_heap) result->DictionaryMapVerify();
7121 #endif
7122
7123   return result;
7124 }
7125
7126
7127 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
7128   Handle<Map> result = RawCopy(map, map->instance_size());
7129
7130   // Please note instance_type and instance_size are set when allocated.
7131   result->set_inobject_properties(map->inobject_properties());
7132   result->set_unused_property_fields(map->unused_property_fields());
7133
7134   result->set_pre_allocated_property_fields(
7135       map->pre_allocated_property_fields());
7136   result->ClearCodeCache(map->GetHeap());
7137   map->NotifyLeafMapLayoutChange();
7138   return result;
7139 }
7140
7141
7142 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
7143                                  Handle<DescriptorArray> descriptors,
7144                                  Descriptor* descriptor) {
7145   // Sanity check. This path is only to be taken if the map owns its descriptor
7146   // array, implying that its NumberOfOwnDescriptors equals the number of
7147   // descriptors in the descriptor array.
7148   DCHECK(map->NumberOfOwnDescriptors() ==
7149          map->instance_descriptors()->number_of_descriptors());
7150
7151   Handle<Map> result = CopyDropDescriptors(map);
7152   Handle<Name> name = descriptor->GetKey();
7153
7154   // Ensure there's space for the new descriptor in the shared descriptor array.
7155   if (descriptors->NumberOfSlackDescriptors() == 0) {
7156     int old_size = descriptors->number_of_descriptors();
7157     if (old_size == 0) {
7158       descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
7159     } else {
7160       EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2);
7161       descriptors = handle(map->instance_descriptors());
7162     }
7163   }
7164
7165   {
7166     DisallowHeapAllocation no_gc;
7167     descriptors->Append(descriptor);
7168     result->InitializeDescriptors(*descriptors);
7169   }
7170
7171   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
7172   ConnectTransition(map, result, name, SIMPLE_TRANSITION);
7173
7174   return result;
7175 }
7176
7177
7178 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
7179                             Handle<Name> name, SimpleTransitionFlag flag) {
7180   parent->set_owns_descriptors(false);
7181   if (parent->is_prototype_map()) {
7182     DCHECK(child->is_prototype_map());
7183   } else {
7184     Handle<TransitionArray> transitions =
7185         TransitionArray::CopyInsert(parent, name, child, flag);
7186     parent->set_transitions(*transitions);
7187     child->SetBackPointer(*parent);
7188   }
7189 }
7190
7191
7192 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
7193                                         Handle<DescriptorArray> descriptors,
7194                                         TransitionFlag flag,
7195                                         MaybeHandle<Name> maybe_name,
7196                                         SimpleTransitionFlag simple_flag) {
7197   DCHECK(descriptors->IsSortedNoDuplicates());
7198
7199   Handle<Map> result = CopyDropDescriptors(map);
7200   result->InitializeDescriptors(*descriptors);
7201
7202   if (!map->is_prototype_map()) {
7203     if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) {
7204       Handle<Name> name;
7205       CHECK(maybe_name.ToHandle(&name));
7206       ConnectTransition(map, result, name, simple_flag);
7207     } else {
7208       int length = descriptors->number_of_descriptors();
7209       for (int i = 0; i < length; i++) {
7210         descriptors->SetRepresentation(i, Representation::Tagged());
7211         if (descriptors->GetDetails(i).type() == FIELD) {
7212           descriptors->SetValue(i, HeapType::Any());
7213         }
7214       }
7215     }
7216   }
7217
7218   return result;
7219 }
7220
7221
7222 // Since this method is used to rewrite an existing transition tree, it can
7223 // always insert transitions without checking.
7224 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map,
7225                                         int new_descriptor,
7226                                         Handle<DescriptorArray> descriptors) {
7227   DCHECK(descriptors->IsSortedNoDuplicates());
7228
7229   Handle<Map> result = CopyDropDescriptors(map);
7230
7231   result->InitializeDescriptors(*descriptors);
7232   result->SetNumberOfOwnDescriptors(new_descriptor + 1);
7233
7234   int unused_property_fields = map->unused_property_fields();
7235   if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
7236     unused_property_fields = map->unused_property_fields() - 1;
7237     if (unused_property_fields < 0) {
7238       unused_property_fields += JSObject::kFieldsAdded;
7239     }
7240   }
7241
7242   result->set_unused_property_fields(unused_property_fields);
7243
7244   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
7245   ConnectTransition(map, result, name, SIMPLE_TRANSITION);
7246
7247   return result;
7248 }
7249
7250
7251 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
7252                                     TransitionFlag flag) {
7253   if (flag == INSERT_TRANSITION) {
7254     DCHECK(!map->HasElementsTransition() ||
7255         ((map->elements_transition_map()->elements_kind() ==
7256           DICTIONARY_ELEMENTS ||
7257           IsExternalArrayElementsKind(
7258               map->elements_transition_map()->elements_kind())) &&
7259          (kind == DICTIONARY_ELEMENTS ||
7260           IsExternalArrayElementsKind(kind))));
7261     DCHECK(!IsFastElementsKind(kind) ||
7262            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
7263     DCHECK(kind != map->elements_kind());
7264   }
7265
7266   bool insert_transition =
7267       flag == INSERT_TRANSITION && !map->HasElementsTransition();
7268
7269   if (insert_transition && map->owns_descriptors()) {
7270     // In case the map owned its own descriptors, share the descriptors and
7271     // transfer ownership to the new map.
7272     Handle<Map> new_map = CopyDropDescriptors(map);
7273
7274     ConnectElementsTransition(map, new_map);
7275
7276     new_map->set_elements_kind(kind);
7277     new_map->InitializeDescriptors(map->instance_descriptors());
7278     return new_map;
7279   }
7280
7281   // In case the map did not own its own descriptors, a split is forced by
7282   // copying the map; creating a new descriptor array cell.
7283   // Create a new free-floating map only if we are not allowed to store it.
7284   Handle<Map> new_map = Copy(map);
7285
7286   new_map->set_elements_kind(kind);
7287
7288   if (insert_transition) {
7289     ConnectElementsTransition(map, new_map);
7290   }
7291
7292   return new_map;
7293 }
7294
7295
7296 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
7297   DCHECK(!map->is_observed());
7298
7299   Isolate* isolate = map->GetIsolate();
7300
7301   // In case the map owned its own descriptors, share the descriptors and
7302   // transfer ownership to the new map.
7303   Handle<Map> new_map;
7304   if (map->owns_descriptors()) {
7305     new_map = CopyDropDescriptors(map);
7306   } else {
7307     DCHECK(!map->is_prototype_map());
7308     new_map = Copy(map);
7309   }
7310
7311   new_map->set_is_observed();
7312   if (map->owns_descriptors()) {
7313     new_map->InitializeDescriptors(map->instance_descriptors());
7314   }
7315
7316   Handle<Name> name = isolate->factory()->observed_symbol();
7317   ConnectTransition(map, new_map, name, FULL_TRANSITION);
7318
7319   return new_map;
7320 }
7321
7322
7323 Handle<Map> Map::Copy(Handle<Map> map) {
7324   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7325   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
7326   Handle<DescriptorArray> new_descriptors =
7327       DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
7328   return CopyReplaceDescriptors(
7329       map, new_descriptors, OMIT_TRANSITION, MaybeHandle<Name>());
7330 }
7331
7332
7333 Handle<Map> Map::Create(Handle<JSFunction> constructor,
7334                         int extra_inobject_properties) {
7335   Handle<Map> copy = Copy(handle(constructor->initial_map()));
7336
7337   // Check that we do not overflow the instance size when adding the
7338   // extra inobject properties.
7339   int instance_size_delta = extra_inobject_properties * kPointerSize;
7340   int max_instance_size_delta =
7341       JSObject::kMaxInstanceSize - copy->instance_size();
7342   int max_extra_properties = max_instance_size_delta >> kPointerSizeLog2;
7343
7344   // If the instance size overflows, we allocate as many properties as we can as
7345   // inobject properties.
7346   if (extra_inobject_properties > max_extra_properties) {
7347     instance_size_delta = max_instance_size_delta;
7348     extra_inobject_properties = max_extra_properties;
7349   }
7350
7351   // Adjust the map with the extra inobject properties.
7352   int inobject_properties =
7353       copy->inobject_properties() + extra_inobject_properties;
7354   copy->set_inobject_properties(inobject_properties);
7355   copy->set_unused_property_fields(inobject_properties);
7356   copy->set_instance_size(copy->instance_size() + instance_size_delta);
7357   copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
7358   return copy;
7359 }
7360
7361
7362 Handle<Map> Map::CopyForFreeze(Handle<Map> map) {
7363   int num_descriptors = map->NumberOfOwnDescriptors();
7364   Isolate* isolate = map->GetIsolate();
7365   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
7366       handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN);
7367   Handle<Map> new_map = CopyReplaceDescriptors(
7368       map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol());
7369   new_map->freeze();
7370   new_map->set_is_extensible(false);
7371   new_map->set_elements_kind(DICTIONARY_ELEMENTS);
7372   return new_map;
7373 }
7374
7375
7376 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
7377   PropertyDetails details = GetDetails(descriptor);
7378   switch (details.type()) {
7379     case FIELD:
7380       return value->FitsRepresentation(details.representation()) &&
7381              GetFieldType(descriptor)->NowContains(value);
7382
7383     case CONSTANT:
7384       DCHECK(GetConstant(descriptor) != value ||
7385              value->FitsRepresentation(details.representation()));
7386       return GetConstant(descriptor) == value;
7387
7388     case CALLBACKS:
7389       return false;
7390
7391     case NORMAL:
7392     case INTERCEPTOR:
7393     case HANDLER:
7394     case NONEXISTENT:
7395       break;
7396   }
7397
7398   UNREACHABLE();
7399   return false;
7400 }
7401
7402
7403 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
7404                                         Handle<Object> value) {
7405   // Dictionaries can store any property value.
7406   if (map->is_dictionary_map()) return map;
7407
7408   // Migrate to the newest map before storing the property.
7409   if (map->is_deprecated()) map = Update(map);
7410
7411   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7412
7413   if (descriptors->CanHoldValue(descriptor, *value)) return map;
7414
7415   Isolate* isolate = map->GetIsolate();
7416   Representation representation = value->OptimalRepresentation();
7417   Handle<HeapType> type = value->OptimalType(isolate, representation);
7418
7419   return GeneralizeRepresentation(map, descriptor, representation, type,
7420                                   FORCE_FIELD);
7421 }
7422
7423
7424 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
7425                                           Handle<Object> value,
7426                                           PropertyAttributes attributes,
7427                                           StoreFromKeyed store_mode) {
7428   // Dictionary maps can always have additional data properties.
7429   if (map->is_dictionary_map()) return map;
7430
7431   // Migrate to the newest map before transitioning to the new property.
7432   if (map->is_deprecated()) map = Update(map);
7433
7434   int index = map->SearchTransition(*name);
7435   if (index != TransitionArray::kNotFound) {
7436     Handle<Map> transition(map->GetTransition(index));
7437     int descriptor = transition->LastAdded();
7438
7439     // TODO(verwaest): Handle attributes better.
7440     DescriptorArray* descriptors = transition->instance_descriptors();
7441     if (descriptors->GetDetails(descriptor).attributes() != attributes) {
7442       return CopyGeneralizeAllRepresentations(transition, descriptor,
7443                                               FORCE_FIELD, attributes,
7444                                               "attributes mismatch");
7445     }
7446
7447     return Map::PrepareForDataProperty(transition, descriptor, value);
7448   }
7449
7450   TransitionFlag flag = INSERT_TRANSITION;
7451   MaybeHandle<Map> maybe_map;
7452   if (value->IsJSFunction()) {
7453     maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
7454   } else if (!map->TooManyFastProperties(store_mode)) {
7455     Isolate* isolate = name->GetIsolate();
7456     Representation representation = value->OptimalRepresentation();
7457     Handle<HeapType> type = value->OptimalType(isolate, representation);
7458     maybe_map =
7459         Map::CopyWithField(map, name, type, attributes, representation, flag);
7460   }
7461
7462   Handle<Map> result;
7463   if (!maybe_map.ToHandle(&result)) {
7464     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES);
7465   }
7466
7467   return result;
7468 }
7469
7470
7471 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7472                                    Descriptor* descriptor,
7473                                    TransitionFlag flag) {
7474   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7475
7476   // Ensure the key is unique.
7477   descriptor->KeyToUniqueName();
7478
7479   if (flag == INSERT_TRANSITION &&
7480       map->owns_descriptors() &&
7481       map->CanHaveMoreTransitions()) {
7482     return ShareDescriptor(map, descriptors, descriptor);
7483   }
7484
7485   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7486       descriptors, map->NumberOfOwnDescriptors(), 1);
7487   new_descriptors->Append(descriptor);
7488
7489   return CopyReplaceDescriptors(
7490       map, new_descriptors, flag, descriptor->GetKey(), SIMPLE_TRANSITION);
7491 }
7492
7493
7494 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
7495                                       Descriptor* descriptor,
7496                                       TransitionFlag flag) {
7497   Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
7498
7499   // Ensure the key is unique.
7500   descriptor->KeyToUniqueName();
7501
7502   // We replace the key if it is already present.
7503   int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
7504   if (index != DescriptorArray::kNotFound) {
7505     return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
7506   }
7507   return CopyAddDescriptor(map, descriptor, flag);
7508 }
7509
7510
7511 Handle<DescriptorArray> DescriptorArray::CopyUpTo(
7512     Handle<DescriptorArray> desc,
7513     int enumeration_index,
7514     int slack) {
7515   return DescriptorArray::CopyUpToAddAttributes(
7516       desc, enumeration_index, NONE, slack);
7517 }
7518
7519
7520 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
7521     Handle<DescriptorArray> desc,
7522     int enumeration_index,
7523     PropertyAttributes attributes,
7524     int slack) {
7525   if (enumeration_index + slack == 0) {
7526     return desc->GetIsolate()->factory()->empty_descriptor_array();
7527   }
7528
7529   int size = enumeration_index;
7530
7531   Handle<DescriptorArray> descriptors =
7532       DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
7533   DescriptorArray::WhitenessWitness witness(*descriptors);
7534
7535   if (attributes != NONE) {
7536     for (int i = 0; i < size; ++i) {
7537       Object* value = desc->GetValue(i);
7538       Name* key = desc->GetKey(i);
7539       PropertyDetails details = desc->GetDetails(i);
7540       // Bulk attribute changes never affect private properties.
7541       if (!key->IsSymbol() || !Symbol::cast(key)->is_private()) {
7542         int mask = DONT_DELETE | DONT_ENUM;
7543         // READ_ONLY is an invalid attribute for JS setters/getters.
7544         if (details.type() != CALLBACKS || !value->IsAccessorPair()) {
7545           mask |= READ_ONLY;
7546         }
7547         details = details.CopyAddAttributes(
7548             static_cast<PropertyAttributes>(attributes & mask));
7549       }
7550       Descriptor inner_desc(
7551           handle(key), handle(value, desc->GetIsolate()), details);
7552       descriptors->Set(i, &inner_desc, witness);
7553     }
7554   } else {
7555     for (int i = 0; i < size; ++i) {
7556       descriptors->CopyFrom(i, *desc, witness);
7557     }
7558   }
7559
7560   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
7561
7562   return descriptors;
7563 }
7564
7565
7566 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
7567                                        Handle<DescriptorArray> descriptors,
7568                                        Descriptor* descriptor,
7569                                        int insertion_index,
7570                                        TransitionFlag flag) {
7571   // Ensure the key is unique.
7572   descriptor->KeyToUniqueName();
7573
7574   Handle<Name> key = descriptor->GetKey();
7575   DCHECK(*key == descriptors->GetKey(insertion_index));
7576
7577   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7578       descriptors, map->NumberOfOwnDescriptors());
7579
7580   new_descriptors->Replace(insertion_index, descriptor);
7581
7582   SimpleTransitionFlag simple_flag =
7583       (insertion_index == descriptors->number_of_descriptors() - 1)
7584       ? SIMPLE_TRANSITION
7585       : FULL_TRANSITION;
7586   return CopyReplaceDescriptors(map, new_descriptors, flag, key, simple_flag);
7587 }
7588
7589
7590 void Map::UpdateCodeCache(Handle<Map> map,
7591                           Handle<Name> name,
7592                           Handle<Code> code) {
7593   Isolate* isolate = map->GetIsolate();
7594   HandleScope scope(isolate);
7595   // Allocate the code cache if not present.
7596   if (map->code_cache()->IsFixedArray()) {
7597     Handle<Object> result = isolate->factory()->NewCodeCache();
7598     map->set_code_cache(*result);
7599   }
7600
7601   // Update the code cache.
7602   Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
7603   CodeCache::Update(code_cache, name, code);
7604 }
7605
7606
7607 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
7608   // Do a lookup if a code cache exists.
7609   if (!code_cache()->IsFixedArray()) {
7610     return CodeCache::cast(code_cache())->Lookup(name, flags);
7611   } else {
7612     return GetHeap()->undefined_value();
7613   }
7614 }
7615
7616
7617 int Map::IndexInCodeCache(Object* name, Code* code) {
7618   // Get the internal index if a code cache exists.
7619   if (!code_cache()->IsFixedArray()) {
7620     return CodeCache::cast(code_cache())->GetIndex(name, code);
7621   }
7622   return -1;
7623 }
7624
7625
7626 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7627   // No GC is supposed to happen between a call to IndexInCodeCache and
7628   // RemoveFromCodeCache so the code cache must be there.
7629   DCHECK(!code_cache()->IsFixedArray());
7630   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7631 }
7632
7633
7634 // An iterator over all map transitions in an descriptor array, reusing the
7635 // constructor field of the map while it is running. Negative values in
7636 // the constructor field indicate an active map transition iteration. The
7637 // original constructor is restored after iterating over all entries.
7638 class IntrusiveMapTransitionIterator {
7639  public:
7640   IntrusiveMapTransitionIterator(
7641       Map* map, TransitionArray* transition_array, Object* constructor)
7642       : map_(map),
7643         transition_array_(transition_array),
7644         constructor_(constructor) { }
7645
7646   void StartIfNotStarted() {
7647     DCHECK(!(*IteratorField())->IsSmi() || IsIterating());
7648     if (!(*IteratorField())->IsSmi()) {
7649       DCHECK(*IteratorField() == constructor_);
7650       *IteratorField() = Smi::FromInt(-1);
7651     }
7652   }
7653
7654   bool IsIterating() {
7655     return (*IteratorField())->IsSmi() &&
7656            Smi::cast(*IteratorField())->value() < 0;
7657   }
7658
7659   Map* Next() {
7660     DCHECK(IsIterating());
7661     int value = Smi::cast(*IteratorField())->value();
7662     int index = -value - 1;
7663     int number_of_transitions = transition_array_->number_of_transitions();
7664     while (index < number_of_transitions) {
7665       *IteratorField() = Smi::FromInt(value - 1);
7666       return transition_array_->GetTarget(index);
7667     }
7668
7669     *IteratorField() = constructor_;
7670     return NULL;
7671   }
7672
7673  private:
7674   Object** IteratorField() {
7675     return HeapObject::RawField(map_, Map::kConstructorOffset);
7676   }
7677
7678   Map* map_;
7679   TransitionArray* transition_array_;
7680   Object* constructor_;
7681 };
7682
7683
7684 // An iterator over all prototype transitions, reusing the constructor field
7685 // of the map while it is running.  Positive values in the constructor field
7686 // indicate an active prototype transition iteration. The original constructor
7687 // is restored after iterating over all entries.
7688 class IntrusivePrototypeTransitionIterator {
7689  public:
7690   IntrusivePrototypeTransitionIterator(
7691       Map* map, HeapObject* proto_trans, Object* constructor)
7692       : map_(map), proto_trans_(proto_trans), constructor_(constructor) { }
7693
7694   void StartIfNotStarted() {
7695     if (!(*IteratorField())->IsSmi()) {
7696       DCHECK(*IteratorField() == constructor_);
7697       *IteratorField() = Smi::FromInt(0);
7698     }
7699   }
7700
7701   bool IsIterating() {
7702     return (*IteratorField())->IsSmi() &&
7703            Smi::cast(*IteratorField())->value() >= 0;
7704   }
7705
7706   Map* Next() {
7707     DCHECK(IsIterating());
7708     int transitionNumber = Smi::cast(*IteratorField())->value();
7709     if (transitionNumber < NumberOfTransitions()) {
7710       *IteratorField() = Smi::FromInt(transitionNumber + 1);
7711       return GetTransition(transitionNumber);
7712     }
7713     *IteratorField() = constructor_;
7714     return NULL;
7715   }
7716
7717  private:
7718   Object** IteratorField() {
7719     return HeapObject::RawField(map_, Map::kConstructorOffset);
7720   }
7721
7722   int NumberOfTransitions() {
7723     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7724     Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
7725     return Smi::cast(num)->value();
7726   }
7727
7728   Map* GetTransition(int transitionNumber) {
7729     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7730     return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
7731   }
7732
7733   int IndexFor(int transitionNumber) {
7734     return Map::kProtoTransitionHeaderSize +
7735         Map::kProtoTransitionMapOffset +
7736         transitionNumber * Map::kProtoTransitionElementsPerEntry;
7737   }
7738
7739   Map* map_;
7740   HeapObject* proto_trans_;
7741   Object* constructor_;
7742 };
7743
7744
7745 // To traverse the transition tree iteratively, we have to store two kinds of
7746 // information in a map: The parent map in the traversal and which children of a
7747 // node have already been visited. To do this without additional memory, we
7748 // temporarily reuse two fields with known values:
7749 //
7750 //  (1) The map of the map temporarily holds the parent, and is restored to the
7751 //      meta map afterwards.
7752 //
7753 //  (2) The info which children have already been visited depends on which part
7754 //      of the map we currently iterate. We use the constructor field of the
7755 //      map to store the current index. We can do that because the constructor
7756 //      is the same for all involved maps.
7757 //
7758 //    (a) If we currently follow normal map transitions, we temporarily store
7759 //        the current index in the constructor field, and restore it to the
7760 //        original constructor afterwards. Note that a single descriptor can
7761 //        have 0, 1, or 2 transitions.
7762 //
7763 //    (b) If we currently follow prototype transitions, we temporarily store
7764 //        the current index in the constructor field, and restore it to the
7765 //        original constructor afterwards.
7766 //
7767 // Note that the child iterator is just a concatenation of two iterators: One
7768 // iterating over map transitions and one iterating over prototype transisitons.
7769 class TraversableMap : public Map {
7770  public:
7771   // Record the parent in the traversal within this map. Note that this destroys
7772   // this map's map!
7773   void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
7774
7775   // Reset the current map's map, returning the parent previously stored in it.
7776   TraversableMap* GetAndResetParent() {
7777     TraversableMap* old_parent = static_cast<TraversableMap*>(map());
7778     set_map_no_write_barrier(GetHeap()->meta_map());
7779     return old_parent;
7780   }
7781
7782   // If we have an unvisited child map, return that one and advance. If we have
7783   // none, return NULL and restore the overwritten constructor field.
7784   TraversableMap* ChildIteratorNext(Object* constructor) {
7785     if (!HasTransitionArray()) return NULL;
7786
7787     TransitionArray* transition_array = transitions();
7788     if (transition_array->HasPrototypeTransitions()) {
7789       HeapObject* proto_transitions =
7790           transition_array->GetPrototypeTransitions();
7791       IntrusivePrototypeTransitionIterator proto_iterator(this,
7792                                                           proto_transitions,
7793                                                           constructor);
7794       proto_iterator.StartIfNotStarted();
7795       if (proto_iterator.IsIterating()) {
7796         Map* next = proto_iterator.Next();
7797         if (next != NULL) return static_cast<TraversableMap*>(next);
7798       }
7799     }
7800
7801     IntrusiveMapTransitionIterator transition_iterator(this,
7802                                                        transition_array,
7803                                                        constructor);
7804     transition_iterator.StartIfNotStarted();
7805     if (transition_iterator.IsIterating()) {
7806       Map* next = transition_iterator.Next();
7807       if (next != NULL) return static_cast<TraversableMap*>(next);
7808     }
7809
7810     return NULL;
7811   }
7812 };
7813
7814
7815 // Traverse the transition tree in postorder without using the C++ stack by
7816 // doing pointer reversal.
7817 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
7818   // Make sure that we do not allocate in the callback.
7819   DisallowHeapAllocation no_allocation;
7820
7821   TraversableMap* current = static_cast<TraversableMap*>(this);
7822   // Get the root constructor here to restore it later when finished iterating
7823   // over maps.
7824   Object* root_constructor = constructor();
7825   while (true) {
7826     TraversableMap* child = current->ChildIteratorNext(root_constructor);
7827     if (child != NULL) {
7828       child->SetParent(current);
7829       current = child;
7830     } else {
7831       TraversableMap* parent = current->GetAndResetParent();
7832       callback(current, data);
7833       if (current == this) break;
7834       current = parent;
7835     }
7836   }
7837 }
7838
7839
7840 void CodeCache::Update(
7841     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7842   // The number of monomorphic stubs for normal load/store/call IC's can grow to
7843   // a large number and therefore they need to go into a hash table. They are
7844   // used to load global properties from cells.
7845   if (code->type() == Code::NORMAL) {
7846     // Make sure that a hash table is allocated for the normal load code cache.
7847     if (code_cache->normal_type_cache()->IsUndefined()) {
7848       Handle<Object> result =
7849           CodeCacheHashTable::New(code_cache->GetIsolate(),
7850                                   CodeCacheHashTable::kInitialSize);
7851       code_cache->set_normal_type_cache(*result);
7852     }
7853     UpdateNormalTypeCache(code_cache, name, code);
7854   } else {
7855     DCHECK(code_cache->default_cache()->IsFixedArray());
7856     UpdateDefaultCache(code_cache, name, code);
7857   }
7858 }
7859
7860
7861 void CodeCache::UpdateDefaultCache(
7862     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7863   // When updating the default code cache we disregard the type encoded in the
7864   // flags. This allows call constant stubs to overwrite call field
7865   // stubs, etc.
7866   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7867
7868   // First check whether we can update existing code cache without
7869   // extending it.
7870   Handle<FixedArray> cache = handle(code_cache->default_cache());
7871   int length = cache->length();
7872   {
7873     DisallowHeapAllocation no_alloc;
7874     int deleted_index = -1;
7875     for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7876       Object* key = cache->get(i);
7877       if (key->IsNull()) {
7878         if (deleted_index < 0) deleted_index = i;
7879         continue;
7880       }
7881       if (key->IsUndefined()) {
7882         if (deleted_index >= 0) i = deleted_index;
7883         cache->set(i + kCodeCacheEntryNameOffset, *name);
7884         cache->set(i + kCodeCacheEntryCodeOffset, *code);
7885         return;
7886       }
7887       if (name->Equals(Name::cast(key))) {
7888         Code::Flags found =
7889             Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7890         if (Code::RemoveTypeFromFlags(found) == flags) {
7891           cache->set(i + kCodeCacheEntryCodeOffset, *code);
7892           return;
7893         }
7894       }
7895     }
7896
7897     // Reached the end of the code cache.  If there were deleted
7898     // elements, reuse the space for the first of them.
7899     if (deleted_index >= 0) {
7900       cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
7901       cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
7902       return;
7903     }
7904   }
7905
7906   // Extend the code cache with some new entries (at least one). Must be a
7907   // multiple of the entry size.
7908   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7909   new_length = new_length - new_length % kCodeCacheEntrySize;
7910   DCHECK((new_length % kCodeCacheEntrySize) == 0);
7911   cache = FixedArray::CopySize(cache, new_length);
7912
7913   // Add the (name, code) pair to the new cache.
7914   cache->set(length + kCodeCacheEntryNameOffset, *name);
7915   cache->set(length + kCodeCacheEntryCodeOffset, *code);
7916   code_cache->set_default_cache(*cache);
7917 }
7918
7919
7920 void CodeCache::UpdateNormalTypeCache(
7921     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7922   // Adding a new entry can cause a new cache to be allocated.
7923   Handle<CodeCacheHashTable> cache(
7924       CodeCacheHashTable::cast(code_cache->normal_type_cache()));
7925   Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
7926   code_cache->set_normal_type_cache(*new_cache);
7927 }
7928
7929
7930 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
7931   Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7932   if (result->IsCode()) {
7933     if (Code::cast(result)->flags() == flags) return result;
7934     return GetHeap()->undefined_value();
7935   }
7936   return LookupNormalTypeCache(name, flags);
7937 }
7938
7939
7940 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
7941   FixedArray* cache = default_cache();
7942   int length = cache->length();
7943   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7944     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7945     // Skip deleted elements.
7946     if (key->IsNull()) continue;
7947     if (key->IsUndefined()) return key;
7948     if (name->Equals(Name::cast(key))) {
7949       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
7950       if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
7951         return code;
7952       }
7953     }
7954   }
7955   return GetHeap()->undefined_value();
7956 }
7957
7958
7959 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
7960   if (!normal_type_cache()->IsUndefined()) {
7961     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7962     return cache->Lookup(name, flags);
7963   } else {
7964     return GetHeap()->undefined_value();
7965   }
7966 }
7967
7968
7969 int CodeCache::GetIndex(Object* name, Code* code) {
7970   if (code->type() == Code::NORMAL) {
7971     if (normal_type_cache()->IsUndefined()) return -1;
7972     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7973     return cache->GetIndex(Name::cast(name), code->flags());
7974   }
7975
7976   FixedArray* array = default_cache();
7977   int len = array->length();
7978   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
7979     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
7980   }
7981   return -1;
7982 }
7983
7984
7985 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
7986   if (code->type() == Code::NORMAL) {
7987     DCHECK(!normal_type_cache()->IsUndefined());
7988     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7989     DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
7990     cache->RemoveByIndex(index);
7991   } else {
7992     FixedArray* array = default_cache();
7993     DCHECK(array->length() >= index && array->get(index)->IsCode());
7994     // Use null instead of undefined for deleted elements to distinguish
7995     // deleted elements from unused elements.  This distinction is used
7996     // when looking up in the cache and when updating the cache.
7997     DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
7998     array->set_null(index - 1);  // Name.
7999     array->set_null(index);  // Code.
8000   }
8001 }
8002
8003
8004 // The key in the code cache hash table consists of the property name and the
8005 // code object. The actual match is on the name and the code flags. If a key
8006 // is created using the flags and not a code object it can only be used for
8007 // lookup not to create a new entry.
8008 class CodeCacheHashTableKey : public HashTableKey {
8009  public:
8010   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
8011       : name_(name), flags_(flags), code_() { }
8012
8013   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
8014       : name_(name), flags_(code->flags()), code_(code) { }
8015
8016   bool IsMatch(Object* other) V8_OVERRIDE {
8017     if (!other->IsFixedArray()) return false;
8018     FixedArray* pair = FixedArray::cast(other);
8019     Name* name = Name::cast(pair->get(0));
8020     Code::Flags flags = Code::cast(pair->get(1))->flags();
8021     if (flags != flags_) {
8022       return false;
8023     }
8024     return name_->Equals(name);
8025   }
8026
8027   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
8028     return name->Hash() ^ flags;
8029   }
8030
8031   uint32_t Hash() V8_OVERRIDE { return NameFlagsHashHelper(*name_, flags_); }
8032
8033   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
8034     FixedArray* pair = FixedArray::cast(obj);
8035     Name* name = Name::cast(pair->get(0));
8036     Code* code = Code::cast(pair->get(1));
8037     return NameFlagsHashHelper(name, code->flags());
8038   }
8039
8040   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
8041     Handle<Code> code = code_.ToHandleChecked();
8042     Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
8043     pair->set(0, *name_);
8044     pair->set(1, *code);
8045     return pair;
8046   }
8047
8048  private:
8049   Handle<Name> name_;
8050   Code::Flags flags_;
8051   // TODO(jkummerow): We should be able to get by without this.
8052   MaybeHandle<Code> code_;
8053 };
8054
8055
8056 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
8057   DisallowHeapAllocation no_alloc;
8058   CodeCacheHashTableKey key(handle(name), flags);
8059   int entry = FindEntry(&key);
8060   if (entry == kNotFound) return GetHeap()->undefined_value();
8061   return get(EntryToIndex(entry) + 1);
8062 }
8063
8064
8065 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
8066     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
8067   CodeCacheHashTableKey key(name, code);
8068
8069   Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
8070
8071   int entry = new_cache->FindInsertionEntry(key.Hash());
8072   Handle<Object> k = key.AsHandle(cache->GetIsolate());
8073
8074   new_cache->set(EntryToIndex(entry), *k);
8075   new_cache->set(EntryToIndex(entry) + 1, *code);
8076   new_cache->ElementAdded();
8077   return new_cache;
8078 }
8079
8080
8081 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
8082   DisallowHeapAllocation no_alloc;
8083   CodeCacheHashTableKey key(handle(name), flags);
8084   int entry = FindEntry(&key);
8085   return (entry == kNotFound) ? -1 : entry;
8086 }
8087
8088
8089 void CodeCacheHashTable::RemoveByIndex(int index) {
8090   DCHECK(index >= 0);
8091   Heap* heap = GetHeap();
8092   set(EntryToIndex(index), heap->the_hole_value());
8093   set(EntryToIndex(index) + 1, heap->the_hole_value());
8094   ElementRemoved();
8095 }
8096
8097
8098 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
8099                                   MapHandleList* maps,
8100                                   Code::Flags flags,
8101                                   Handle<Code> code) {
8102   Isolate* isolate = code_cache->GetIsolate();
8103   if (code_cache->cache()->IsUndefined()) {
8104     Handle<PolymorphicCodeCacheHashTable> result =
8105         PolymorphicCodeCacheHashTable::New(
8106             isolate,
8107             PolymorphicCodeCacheHashTable::kInitialSize);
8108     code_cache->set_cache(*result);
8109   } else {
8110     // This entry shouldn't be contained in the cache yet.
8111     DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
8112                ->Lookup(maps, flags)->IsUndefined());
8113   }
8114   Handle<PolymorphicCodeCacheHashTable> hash_table =
8115       handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
8116   Handle<PolymorphicCodeCacheHashTable> new_cache =
8117       PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
8118   code_cache->set_cache(*new_cache);
8119 }
8120
8121
8122 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
8123                                             Code::Flags flags) {
8124   if (!cache()->IsUndefined()) {
8125     PolymorphicCodeCacheHashTable* hash_table =
8126         PolymorphicCodeCacheHashTable::cast(cache());
8127     return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
8128   } else {
8129     return GetIsolate()->factory()->undefined_value();
8130   }
8131 }
8132
8133
8134 // Despite their name, object of this class are not stored in the actual
8135 // hash table; instead they're temporarily used for lookups. It is therefore
8136 // safe to have a weak (non-owning) pointer to a MapList as a member field.
8137 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
8138  public:
8139   // Callers must ensure that |maps| outlives the newly constructed object.
8140   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
8141       : maps_(maps),
8142         code_flags_(code_flags) {}
8143
8144   bool IsMatch(Object* other) V8_OVERRIDE {
8145     MapHandleList other_maps(kDefaultListAllocationSize);
8146     int other_flags;
8147     FromObject(other, &other_flags, &other_maps);
8148     if (code_flags_ != other_flags) return false;
8149     if (maps_->length() != other_maps.length()) return false;
8150     // Compare just the hashes first because it's faster.
8151     int this_hash = MapsHashHelper(maps_, code_flags_);
8152     int other_hash = MapsHashHelper(&other_maps, other_flags);
8153     if (this_hash != other_hash) return false;
8154
8155     // Full comparison: for each map in maps_, look for an equivalent map in
8156     // other_maps. This implementation is slow, but probably good enough for
8157     // now because the lists are short (<= 4 elements currently).
8158     for (int i = 0; i < maps_->length(); ++i) {
8159       bool match_found = false;
8160       for (int j = 0; j < other_maps.length(); ++j) {
8161         if (*(maps_->at(i)) == *(other_maps.at(j))) {
8162           match_found = true;
8163           break;
8164         }
8165       }
8166       if (!match_found) return false;
8167     }
8168     return true;
8169   }
8170
8171   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
8172     uint32_t hash = code_flags;
8173     for (int i = 0; i < maps->length(); ++i) {
8174       hash ^= maps->at(i)->Hash();
8175     }
8176     return hash;
8177   }
8178
8179   uint32_t Hash() V8_OVERRIDE {
8180     return MapsHashHelper(maps_, code_flags_);
8181   }
8182
8183   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
8184     MapHandleList other_maps(kDefaultListAllocationSize);
8185     int other_flags;
8186     FromObject(obj, &other_flags, &other_maps);
8187     return MapsHashHelper(&other_maps, other_flags);
8188   }
8189
8190   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
8191     // The maps in |maps_| must be copied to a newly allocated FixedArray,
8192     // both because the referenced MapList is short-lived, and because C++
8193     // objects can't be stored in the heap anyway.
8194     Handle<FixedArray> list =
8195         isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
8196     list->set(0, Smi::FromInt(code_flags_));
8197     for (int i = 0; i < maps_->length(); ++i) {
8198       list->set(i + 1, *maps_->at(i));
8199     }
8200     return list;
8201   }
8202
8203  private:
8204   static MapHandleList* FromObject(Object* obj,
8205                                    int* code_flags,
8206                                    MapHandleList* maps) {
8207     FixedArray* list = FixedArray::cast(obj);
8208     maps->Rewind(0);
8209     *code_flags = Smi::cast(list->get(0))->value();
8210     for (int i = 1; i < list->length(); ++i) {
8211       maps->Add(Handle<Map>(Map::cast(list->get(i))));
8212     }
8213     return maps;
8214   }
8215
8216   MapHandleList* maps_;  // weak.
8217   int code_flags_;
8218   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
8219 };
8220
8221
8222 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
8223                                               int code_kind) {
8224   DisallowHeapAllocation no_alloc;
8225   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
8226   int entry = FindEntry(&key);
8227   if (entry == kNotFound) return GetHeap()->undefined_value();
8228   return get(EntryToIndex(entry) + 1);
8229 }
8230
8231
8232 Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
8233       Handle<PolymorphicCodeCacheHashTable> hash_table,
8234       MapHandleList* maps,
8235       int code_kind,
8236       Handle<Code> code) {
8237   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
8238   Handle<PolymorphicCodeCacheHashTable> cache =
8239       EnsureCapacity(hash_table, 1, &key);
8240   int entry = cache->FindInsertionEntry(key.Hash());
8241
8242   Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
8243   cache->set(EntryToIndex(entry), *obj);
8244   cache->set(EntryToIndex(entry) + 1, *code);
8245   cache->ElementAdded();
8246   return cache;
8247 }
8248
8249
8250 void FixedArray::Shrink(int new_length) {
8251   DCHECK(0 <= new_length && new_length <= length());
8252   if (new_length < length()) {
8253     GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>(
8254         this, length() - new_length);
8255   }
8256 }
8257
8258
8259 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
8260     Handle<FixedArray> content,
8261     Handle<JSObject> array) {
8262   DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
8263   ElementsAccessor* accessor = array->GetElementsAccessor();
8264   Handle<FixedArray> result;
8265   ASSIGN_RETURN_ON_EXCEPTION(
8266       array->GetIsolate(), result,
8267       accessor->AddElementsToFixedArray(array, array, content),
8268       FixedArray);
8269
8270 #ifdef ENABLE_SLOW_DCHECKS
8271   if (FLAG_enable_slow_asserts) {
8272     DisallowHeapAllocation no_allocation;
8273     for (int i = 0; i < result->length(); i++) {
8274       Object* current = result->get(i);
8275       DCHECK(current->IsNumber() || current->IsName());
8276     }
8277   }
8278 #endif
8279   return result;
8280 }
8281
8282
8283 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
8284                                                 Handle<FixedArray> second) {
8285   ElementsAccessor* accessor = ElementsAccessor::ForArray(second);
8286   Handle<FixedArray> result;
8287   ASSIGN_RETURN_ON_EXCEPTION(
8288       first->GetIsolate(), result,
8289       accessor->AddElementsToFixedArray(
8290           Handle<Object>::null(),     // receiver
8291           Handle<JSObject>::null(),   // holder
8292           first,
8293           Handle<FixedArrayBase>::cast(second)),
8294       FixedArray);
8295
8296 #ifdef ENABLE_SLOW_DCHECKS
8297   if (FLAG_enable_slow_asserts) {
8298     DisallowHeapAllocation no_allocation;
8299     for (int i = 0; i < result->length(); i++) {
8300       Object* current = result->get(i);
8301       DCHECK(current->IsNumber() || current->IsName());
8302     }
8303   }
8304 #endif
8305   return result;
8306 }
8307
8308
8309 Handle<FixedArray> FixedArray::CopySize(
8310     Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
8311   Isolate* isolate = array->GetIsolate();
8312   if (new_length == 0) return isolate->factory()->empty_fixed_array();
8313   Handle<FixedArray> result =
8314       isolate->factory()->NewFixedArray(new_length, pretenure);
8315   // Copy the content
8316   DisallowHeapAllocation no_gc;
8317   int len = array->length();
8318   if (new_length < len) len = new_length;
8319   // We are taking the map from the old fixed array so the map is sure to
8320   // be an immortal immutable object.
8321   result->set_map_no_write_barrier(array->map());
8322   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
8323   for (int i = 0; i < len; i++) {
8324     result->set(i, array->get(i), mode);
8325   }
8326   return result;
8327 }
8328
8329
8330 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
8331   DisallowHeapAllocation no_gc;
8332   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
8333   for (int index = 0; index < len; index++) {
8334     dest->set(dest_pos+index, get(pos+index), mode);
8335   }
8336 }
8337
8338
8339 #ifdef DEBUG
8340 bool FixedArray::IsEqualTo(FixedArray* other) {
8341   if (length() != other->length()) return false;
8342   for (int i = 0 ; i < length(); ++i) {
8343     if (get(i) != other->get(i)) return false;
8344   }
8345   return true;
8346 }
8347 #endif
8348
8349
8350 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
8351                                                   int number_of_descriptors,
8352                                                   int slack) {
8353   DCHECK(0 <= number_of_descriptors);
8354   Factory* factory = isolate->factory();
8355   // Do not use DescriptorArray::cast on incomplete object.
8356   int size = number_of_descriptors + slack;
8357   if (size == 0) return factory->empty_descriptor_array();
8358   // Allocate the array of keys.
8359   Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
8360
8361   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
8362   result->set(kEnumCacheIndex, Smi::FromInt(0));
8363   return Handle<DescriptorArray>::cast(result);
8364 }
8365
8366
8367 void DescriptorArray::ClearEnumCache() {
8368   set(kEnumCacheIndex, Smi::FromInt(0));
8369 }
8370
8371
8372 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
8373   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
8374   Set(index, descriptor);
8375 }
8376
8377
8378 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
8379                                    FixedArray* new_cache,
8380                                    Object* new_index_cache) {
8381   DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
8382   DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
8383   DCHECK(!IsEmpty());
8384   DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
8385   FixedArray::cast(bridge_storage)->
8386     set(kEnumCacheBridgeCacheIndex, new_cache);
8387   FixedArray::cast(bridge_storage)->
8388     set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
8389   set(kEnumCacheIndex, bridge_storage);
8390 }
8391
8392
8393 void DescriptorArray::CopyFrom(int index,
8394                                DescriptorArray* src,
8395                                const WhitenessWitness& witness) {
8396   Object* value = src->GetValue(index);
8397   PropertyDetails details = src->GetDetails(index);
8398   Descriptor desc(handle(src->GetKey(index)),
8399                   handle(value, src->GetIsolate()),
8400                   details);
8401   Set(index, &desc, witness);
8402 }
8403
8404
8405 // We need the whiteness witness since sort will reshuffle the entries in the
8406 // descriptor array. If the descriptor array were to be black, the shuffling
8407 // would move a slot that was already recorded as pointing into an evacuation
8408 // candidate. This would result in missing updates upon evacuation.
8409 void DescriptorArray::Sort() {
8410   // In-place heap sort.
8411   int len = number_of_descriptors();
8412   // Reset sorting since the descriptor array might contain invalid pointers.
8413   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
8414   // Bottom-up max-heap construction.
8415   // Index of the last node with children
8416   const int max_parent_index = (len / 2) - 1;
8417   for (int i = max_parent_index; i >= 0; --i) {
8418     int parent_index = i;
8419     const uint32_t parent_hash = GetSortedKey(i)->Hash();
8420     while (parent_index <= max_parent_index) {
8421       int child_index = 2 * parent_index + 1;
8422       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8423       if (child_index + 1 < len) {
8424         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8425         if (right_child_hash > child_hash) {
8426           child_index++;
8427           child_hash = right_child_hash;
8428         }
8429       }
8430       if (child_hash <= parent_hash) break;
8431       SwapSortedKeys(parent_index, child_index);
8432       // Now element at child_index could be < its children.
8433       parent_index = child_index;  // parent_hash remains correct.
8434     }
8435   }
8436
8437   // Extract elements and create sorted array.
8438   for (int i = len - 1; i > 0; --i) {
8439     // Put max element at the back of the array.
8440     SwapSortedKeys(0, i);
8441     // Shift down the new top element.
8442     int parent_index = 0;
8443     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
8444     const int max_parent_index = (i / 2) - 1;
8445     while (parent_index <= max_parent_index) {
8446       int child_index = parent_index * 2 + 1;
8447       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8448       if (child_index + 1 < i) {
8449         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8450         if (right_child_hash > child_hash) {
8451           child_index++;
8452           child_hash = right_child_hash;
8453         }
8454       }
8455       if (child_hash <= parent_hash) break;
8456       SwapSortedKeys(parent_index, child_index);
8457       parent_index = child_index;
8458     }
8459   }
8460   DCHECK(IsSortedNoDuplicates());
8461 }
8462
8463
8464 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
8465   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
8466   copy->set_getter(pair->getter());
8467   copy->set_setter(pair->setter());
8468   return copy;
8469 }
8470
8471
8472 Object* AccessorPair::GetComponent(AccessorComponent component) {
8473   Object* accessor = get(component);
8474   return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
8475 }
8476
8477
8478 Handle<DeoptimizationInputData> DeoptimizationInputData::New(
8479     Isolate* isolate, int deopt_entry_count, int return_patch_address_count,
8480     PretenureFlag pretenure) {
8481   DCHECK(deopt_entry_count + return_patch_address_count > 0);
8482   Handle<FixedArray> deoptimization_data =
8483       Handle<FixedArray>::cast(isolate->factory()->NewFixedArray(
8484           LengthFor(deopt_entry_count, return_patch_address_count), pretenure));
8485   deoptimization_data->set(kDeoptEntryCountIndex,
8486                            Smi::FromInt(deopt_entry_count));
8487   deoptimization_data->set(kReturnAddressPatchEntryCountIndex,
8488                            Smi::FromInt(return_patch_address_count));
8489   return Handle<DeoptimizationInputData>::cast(deoptimization_data);
8490 }
8491
8492
8493 Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
8494     Isolate* isolate,
8495     int number_of_deopt_points,
8496     PretenureFlag pretenure) {
8497   Handle<FixedArray> result;
8498   if (number_of_deopt_points == 0) {
8499     result = isolate->factory()->empty_fixed_array();
8500   } else {
8501     result = isolate->factory()->NewFixedArray(
8502         LengthOfFixedArray(number_of_deopt_points), pretenure);
8503   }
8504   return Handle<DeoptimizationOutputData>::cast(result);
8505 }
8506
8507
8508 #ifdef DEBUG
8509 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
8510   if (IsEmpty()) return other->IsEmpty();
8511   if (other->IsEmpty()) return false;
8512   if (length() != other->length()) return false;
8513   for (int i = 0; i < length(); ++i) {
8514     if (get(i) != other->get(i)) return false;
8515   }
8516   return true;
8517 }
8518 #endif
8519
8520
8521 bool String::LooksValid() {
8522   if (!GetIsolate()->heap()->Contains(this)) return false;
8523   return true;
8524 }
8525
8526
8527 String::FlatContent String::GetFlatContent() {
8528   DCHECK(!AllowHeapAllocation::IsAllowed());
8529   int length = this->length();
8530   StringShape shape(this);
8531   String* string = this;
8532   int offset = 0;
8533   if (shape.representation_tag() == kConsStringTag) {
8534     ConsString* cons = ConsString::cast(string);
8535     if (cons->second()->length() != 0) {
8536       return FlatContent();
8537     }
8538     string = cons->first();
8539     shape = StringShape(string);
8540   }
8541   if (shape.representation_tag() == kSlicedStringTag) {
8542     SlicedString* slice = SlicedString::cast(string);
8543     offset = slice->offset();
8544     string = slice->parent();
8545     shape = StringShape(string);
8546     DCHECK(shape.representation_tag() != kConsStringTag &&
8547            shape.representation_tag() != kSlicedStringTag);
8548   }
8549   if (shape.encoding_tag() == kOneByteStringTag) {
8550     const uint8_t* start;
8551     if (shape.representation_tag() == kSeqStringTag) {
8552       start = SeqOneByteString::cast(string)->GetChars();
8553     } else {
8554       start = ExternalAsciiString::cast(string)->GetChars();
8555     }
8556     return FlatContent(start + offset, length);
8557   } else {
8558     DCHECK(shape.encoding_tag() == kTwoByteStringTag);
8559     const uc16* start;
8560     if (shape.representation_tag() == kSeqStringTag) {
8561       start = SeqTwoByteString::cast(string)->GetChars();
8562     } else {
8563       start = ExternalTwoByteString::cast(string)->GetChars();
8564     }
8565     return FlatContent(start + offset, length);
8566   }
8567 }
8568
8569
8570 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8571                                           RobustnessFlag robust_flag,
8572                                           int offset,
8573                                           int length,
8574                                           int* length_return) {
8575   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8576     return SmartArrayPointer<char>(NULL);
8577   }
8578   Heap* heap = GetHeap();
8579
8580   // Negative length means the to the end of the string.
8581   if (length < 0) length = kMaxInt - offset;
8582
8583   // Compute the size of the UTF-8 string. Start at the specified offset.
8584   Access<ConsStringIteratorOp> op(
8585       heap->isolate()->objects_string_iterator());
8586   StringCharacterStream stream(this, op.value(), offset);
8587   int character_position = offset;
8588   int utf8_bytes = 0;
8589   int last = unibrow::Utf16::kNoPreviousCharacter;
8590   while (stream.HasMore() && character_position++ < offset + length) {
8591     uint16_t character = stream.GetNext();
8592     utf8_bytes += unibrow::Utf8::Length(character, last);
8593     last = character;
8594   }
8595
8596   if (length_return) {
8597     *length_return = utf8_bytes;
8598   }
8599
8600   char* result = NewArray<char>(utf8_bytes + 1);
8601
8602   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8603   stream.Reset(this, offset);
8604   character_position = offset;
8605   int utf8_byte_position = 0;
8606   last = unibrow::Utf16::kNoPreviousCharacter;
8607   while (stream.HasMore() && character_position++ < offset + length) {
8608     uint16_t character = stream.GetNext();
8609     if (allow_nulls == DISALLOW_NULLS && character == 0) {
8610       character = ' ';
8611     }
8612     utf8_byte_position +=
8613         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8614     last = character;
8615   }
8616   result[utf8_byte_position] = 0;
8617   return SmartArrayPointer<char>(result);
8618 }
8619
8620
8621 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8622                                           RobustnessFlag robust_flag,
8623                                           int* length_return) {
8624   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8625 }
8626
8627
8628 const uc16* String::GetTwoByteData(unsigned start) {
8629   DCHECK(!IsOneByteRepresentationUnderneath());
8630   switch (StringShape(this).representation_tag()) {
8631     case kSeqStringTag:
8632       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8633     case kExternalStringTag:
8634       return ExternalTwoByteString::cast(this)->
8635         ExternalTwoByteStringGetData(start);
8636     case kSlicedStringTag: {
8637       SlicedString* slice = SlicedString::cast(this);
8638       return slice->parent()->GetTwoByteData(start + slice->offset());
8639     }
8640     case kConsStringTag:
8641       UNREACHABLE();
8642       return NULL;
8643   }
8644   UNREACHABLE();
8645   return NULL;
8646 }
8647
8648
8649 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
8650   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8651     return SmartArrayPointer<uc16>();
8652   }
8653   Heap* heap = GetHeap();
8654
8655   Access<ConsStringIteratorOp> op(
8656       heap->isolate()->objects_string_iterator());
8657   StringCharacterStream stream(this, op.value());
8658
8659   uc16* result = NewArray<uc16>(length() + 1);
8660
8661   int i = 0;
8662   while (stream.HasMore()) {
8663     uint16_t character = stream.GetNext();
8664     result[i++] = character;
8665   }
8666   result[i] = 0;
8667   return SmartArrayPointer<uc16>(result);
8668 }
8669
8670
8671 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
8672   return reinterpret_cast<uc16*>(
8673       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8674 }
8675
8676
8677 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8678   Relocatable* current = isolate->relocatable_top();
8679   while (current != NULL) {
8680     current->PostGarbageCollection();
8681     current = current->prev_;
8682   }
8683 }
8684
8685
8686 // Reserve space for statics needing saving and restoring.
8687 int Relocatable::ArchiveSpacePerThread() {
8688   return sizeof(Relocatable*);  // NOLINT
8689 }
8690
8691
8692 // Archive statics that are thread-local.
8693 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8694   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8695   isolate->set_relocatable_top(NULL);
8696   return to + ArchiveSpacePerThread();
8697 }
8698
8699
8700 // Restore statics that are thread-local.
8701 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8702   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8703   return from + ArchiveSpacePerThread();
8704 }
8705
8706
8707 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8708   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8709   Iterate(v, top);
8710   return thread_storage + ArchiveSpacePerThread();
8711 }
8712
8713
8714 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8715   Iterate(v, isolate->relocatable_top());
8716 }
8717
8718
8719 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8720   Relocatable* current = top;
8721   while (current != NULL) {
8722     current->IterateInstance(v);
8723     current = current->prev_;
8724   }
8725 }
8726
8727
8728 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
8729     : Relocatable(isolate),
8730       str_(str.location()),
8731       length_(str->length()) {
8732   PostGarbageCollection();
8733 }
8734
8735
8736 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
8737     : Relocatable(isolate),
8738       str_(0),
8739       is_ascii_(true),
8740       length_(input.length()),
8741       start_(input.start()) { }
8742
8743
8744 void FlatStringReader::PostGarbageCollection() {
8745   if (str_ == NULL) return;
8746   Handle<String> str(str_);
8747   DCHECK(str->IsFlat());
8748   DisallowHeapAllocation no_gc;
8749   // This does not actually prevent the vector from being relocated later.
8750   String::FlatContent content = str->GetFlatContent();
8751   DCHECK(content.IsFlat());
8752   is_ascii_ = content.IsAscii();
8753   if (is_ascii_) {
8754     start_ = content.ToOneByteVector().start();
8755   } else {
8756     start_ = content.ToUC16Vector().start();
8757   }
8758 }
8759
8760
8761 void ConsStringIteratorOp::Initialize(ConsString* cons_string, int offset) {
8762   DCHECK(cons_string != NULL);
8763   root_ = cons_string;
8764   consumed_ = offset;
8765   // Force stack blown condition to trigger restart.
8766   depth_ = 1;
8767   maximum_depth_ = kStackSize + depth_;
8768   DCHECK(StackBlown());
8769 }
8770
8771
8772 String* ConsStringIteratorOp::Continue(int* offset_out) {
8773   DCHECK(depth_ != 0);
8774   DCHECK_EQ(0, *offset_out);
8775   bool blew_stack = StackBlown();
8776   String* string = NULL;
8777   // Get the next leaf if there is one.
8778   if (!blew_stack) string = NextLeaf(&blew_stack);
8779   // Restart search from root.
8780   if (blew_stack) {
8781     DCHECK(string == NULL);
8782     string = Search(offset_out);
8783   }
8784   // Ensure future calls return null immediately.
8785   if (string == NULL) Reset(NULL);
8786   return string;
8787 }
8788
8789
8790 String* ConsStringIteratorOp::Search(int* offset_out) {
8791   ConsString* cons_string = root_;
8792   // Reset the stack, pushing the root string.
8793   depth_ = 1;
8794   maximum_depth_ = 1;
8795   frames_[0] = cons_string;
8796   const int consumed = consumed_;
8797   int offset = 0;
8798   while (true) {
8799     // Loop until the string is found which contains the target offset.
8800     String* string = cons_string->first();
8801     int length = string->length();
8802     int32_t type;
8803     if (consumed < offset + length) {
8804       // Target offset is in the left branch.
8805       // Keep going if we're still in a ConString.
8806       type = string->map()->instance_type();
8807       if ((type & kStringRepresentationMask) == kConsStringTag) {
8808         cons_string = ConsString::cast(string);
8809         PushLeft(cons_string);
8810         continue;
8811       }
8812       // Tell the stack we're done descending.
8813       AdjustMaximumDepth();
8814     } else {
8815       // Descend right.
8816       // Update progress through the string.
8817       offset += length;
8818       // Keep going if we're still in a ConString.
8819       string = cons_string->second();
8820       type = string->map()->instance_type();
8821       if ((type & kStringRepresentationMask) == kConsStringTag) {
8822         cons_string = ConsString::cast(string);
8823         PushRight(cons_string);
8824         continue;
8825       }
8826       // Need this to be updated for the current string.
8827       length = string->length();
8828       // Account for the possibility of an empty right leaf.
8829       // This happens only if we have asked for an offset outside the string.
8830       if (length == 0) {
8831         // Reset so future operations will return null immediately.
8832         Reset(NULL);
8833         return NULL;
8834       }
8835       // Tell the stack we're done descending.
8836       AdjustMaximumDepth();
8837       // Pop stack so next iteration is in correct place.
8838       Pop();
8839     }
8840     DCHECK(length != 0);
8841     // Adjust return values and exit.
8842     consumed_ = offset + length;
8843     *offset_out = consumed - offset;
8844     return string;
8845   }
8846   UNREACHABLE();
8847   return NULL;
8848 }
8849
8850
8851 String* ConsStringIteratorOp::NextLeaf(bool* blew_stack) {
8852   while (true) {
8853     // Tree traversal complete.
8854     if (depth_ == 0) {
8855       *blew_stack = false;
8856       return NULL;
8857     }
8858     // We've lost track of higher nodes.
8859     if (StackBlown()) {
8860       *blew_stack = true;
8861       return NULL;
8862     }
8863     // Go right.
8864     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
8865     String* string = cons_string->second();
8866     int32_t type = string->map()->instance_type();
8867     if ((type & kStringRepresentationMask) != kConsStringTag) {
8868       // Pop stack so next iteration is in correct place.
8869       Pop();
8870       int length = string->length();
8871       // Could be a flattened ConsString.
8872       if (length == 0) continue;
8873       consumed_ += length;
8874       return string;
8875     }
8876     cons_string = ConsString::cast(string);
8877     PushRight(cons_string);
8878     // Need to traverse all the way left.
8879     while (true) {
8880       // Continue left.
8881       string = cons_string->first();
8882       type = string->map()->instance_type();
8883       if ((type & kStringRepresentationMask) != kConsStringTag) {
8884         AdjustMaximumDepth();
8885         int length = string->length();
8886         DCHECK(length != 0);
8887         consumed_ += length;
8888         return string;
8889       }
8890       cons_string = ConsString::cast(string);
8891       PushLeft(cons_string);
8892     }
8893   }
8894   UNREACHABLE();
8895   return NULL;
8896 }
8897
8898
8899 uint16_t ConsString::ConsStringGet(int index) {
8900   DCHECK(index >= 0 && index < this->length());
8901
8902   // Check for a flattened cons string
8903   if (second()->length() == 0) {
8904     String* left = first();
8905     return left->Get(index);
8906   }
8907
8908   String* string = String::cast(this);
8909
8910   while (true) {
8911     if (StringShape(string).IsCons()) {
8912       ConsString* cons_string = ConsString::cast(string);
8913       String* left = cons_string->first();
8914       if (left->length() > index) {
8915         string = left;
8916       } else {
8917         index -= left->length();
8918         string = cons_string->second();
8919       }
8920     } else {
8921       return string->Get(index);
8922     }
8923   }
8924
8925   UNREACHABLE();
8926   return 0;
8927 }
8928
8929
8930 uint16_t SlicedString::SlicedStringGet(int index) {
8931   return parent()->Get(offset() + index);
8932 }
8933
8934
8935 template <typename sinkchar>
8936 void String::WriteToFlat(String* src,
8937                          sinkchar* sink,
8938                          int f,
8939                          int t) {
8940   String* source = src;
8941   int from = f;
8942   int to = t;
8943   while (true) {
8944     DCHECK(0 <= from && from <= to && to <= source->length());
8945     switch (StringShape(source).full_representation_tag()) {
8946       case kOneByteStringTag | kExternalStringTag: {
8947         CopyChars(sink,
8948                   ExternalAsciiString::cast(source)->GetChars() + from,
8949                   to - from);
8950         return;
8951       }
8952       case kTwoByteStringTag | kExternalStringTag: {
8953         const uc16* data =
8954             ExternalTwoByteString::cast(source)->GetChars();
8955         CopyChars(sink,
8956                   data + from,
8957                   to - from);
8958         return;
8959       }
8960       case kOneByteStringTag | kSeqStringTag: {
8961         CopyChars(sink,
8962                   SeqOneByteString::cast(source)->GetChars() + from,
8963                   to - from);
8964         return;
8965       }
8966       case kTwoByteStringTag | kSeqStringTag: {
8967         CopyChars(sink,
8968                   SeqTwoByteString::cast(source)->GetChars() + from,
8969                   to - from);
8970         return;
8971       }
8972       case kOneByteStringTag | kConsStringTag:
8973       case kTwoByteStringTag | kConsStringTag: {
8974         ConsString* cons_string = ConsString::cast(source);
8975         String* first = cons_string->first();
8976         int boundary = first->length();
8977         if (to - boundary >= boundary - from) {
8978           // Right hand side is longer.  Recurse over left.
8979           if (from < boundary) {
8980             WriteToFlat(first, sink, from, boundary);
8981             sink += boundary - from;
8982             from = 0;
8983           } else {
8984             from -= boundary;
8985           }
8986           to -= boundary;
8987           source = cons_string->second();
8988         } else {
8989           // Left hand side is longer.  Recurse over right.
8990           if (to > boundary) {
8991             String* second = cons_string->second();
8992             // When repeatedly appending to a string, we get a cons string that
8993             // is unbalanced to the left, a list, essentially.  We inline the
8994             // common case of sequential ascii right child.
8995             if (to - boundary == 1) {
8996               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
8997             } else if (second->IsSeqOneByteString()) {
8998               CopyChars(sink + boundary - from,
8999                         SeqOneByteString::cast(second)->GetChars(),
9000                         to - boundary);
9001             } else {
9002               WriteToFlat(second,
9003                           sink + boundary - from,
9004                           0,
9005                           to - boundary);
9006             }
9007             to = boundary;
9008           }
9009           source = first;
9010         }
9011         break;
9012       }
9013       case kOneByteStringTag | kSlicedStringTag:
9014       case kTwoByteStringTag | kSlicedStringTag: {
9015         SlicedString* slice = SlicedString::cast(source);
9016         unsigned offset = slice->offset();
9017         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
9018         return;
9019       }
9020     }
9021   }
9022 }
9023
9024
9025
9026 template <typename SourceChar>
9027 static void CalculateLineEndsImpl(Isolate* isolate,
9028                                   List<int>* line_ends,
9029                                   Vector<const SourceChar> src,
9030                                   bool include_ending_line) {
9031   const int src_len = src.length();
9032   StringSearch<uint8_t, SourceChar> search(isolate, STATIC_ASCII_VECTOR("\n"));
9033
9034   // Find and record line ends.
9035   int position = 0;
9036   while (position != -1 && position < src_len) {
9037     position = search.Search(src, position);
9038     if (position != -1) {
9039       line_ends->Add(position);
9040       position++;
9041     } else if (include_ending_line) {
9042       // Even if the last line misses a line end, it is counted.
9043       line_ends->Add(src_len);
9044       return;
9045     }
9046   }
9047 }
9048
9049
9050 Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
9051                                              bool include_ending_line) {
9052   src = Flatten(src);
9053   // Rough estimate of line count based on a roughly estimated average
9054   // length of (unpacked) code.
9055   int line_count_estimate = src->length() >> 4;
9056   List<int> line_ends(line_count_estimate);
9057   Isolate* isolate = src->GetIsolate();
9058   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
9059     // Dispatch on type of strings.
9060     String::FlatContent content = src->GetFlatContent();
9061     DCHECK(content.IsFlat());
9062     if (content.IsAscii()) {
9063       CalculateLineEndsImpl(isolate,
9064                             &line_ends,
9065                             content.ToOneByteVector(),
9066                             include_ending_line);
9067     } else {
9068       CalculateLineEndsImpl(isolate,
9069                             &line_ends,
9070                             content.ToUC16Vector(),
9071                             include_ending_line);
9072     }
9073   }
9074   int line_count = line_ends.length();
9075   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
9076   for (int i = 0; i < line_count; i++) {
9077     array->set(i, Smi::FromInt(line_ends[i]));
9078   }
9079   return array;
9080 }
9081
9082
9083 // Compares the contents of two strings by reading and comparing
9084 // int-sized blocks of characters.
9085 template <typename Char>
9086 static inline bool CompareRawStringContents(const Char* const a,
9087                                             const Char* const b,
9088                                             int length) {
9089   int i = 0;
9090 #ifndef V8_HOST_CAN_READ_UNALIGNED
9091   // If this architecture isn't comfortable reading unaligned ints
9092   // then we have to check that the strings are aligned before
9093   // comparing them blockwise.
9094   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
9095   uintptr_t pa_addr = reinterpret_cast<uintptr_t>(a);
9096   uintptr_t pb_addr = reinterpret_cast<uintptr_t>(b);
9097   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
9098 #endif
9099     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
9100     int endpoint = length - kStepSize;
9101     // Compare blocks until we reach near the end of the string.
9102     for (; i <= endpoint; i += kStepSize) {
9103       uint32_t wa = *reinterpret_cast<const uint32_t*>(a + i);
9104       uint32_t wb = *reinterpret_cast<const uint32_t*>(b + i);
9105       if (wa != wb) {
9106         return false;
9107       }
9108     }
9109 #ifndef V8_HOST_CAN_READ_UNALIGNED
9110   }
9111 #endif
9112   // Compare the remaining characters that didn't fit into a block.
9113   for (; i < length; i++) {
9114     if (a[i] != b[i]) {
9115       return false;
9116     }
9117   }
9118   return true;
9119 }
9120
9121
9122 template<typename Chars1, typename Chars2>
9123 class RawStringComparator : public AllStatic {
9124  public:
9125   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
9126     DCHECK(sizeof(Chars1) != sizeof(Chars2));
9127     for (int i = 0; i < len; i++) {
9128       if (a[i] != b[i]) {
9129         return false;
9130       }
9131     }
9132     return true;
9133   }
9134 };
9135
9136
9137 template<>
9138 class RawStringComparator<uint16_t, uint16_t> {
9139  public:
9140   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
9141     return CompareRawStringContents(a, b, len);
9142   }
9143 };
9144
9145
9146 template<>
9147 class RawStringComparator<uint8_t, uint8_t> {
9148  public:
9149   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
9150     return CompareRawStringContents(a, b, len);
9151   }
9152 };
9153
9154
9155 class StringComparator {
9156   class State {
9157    public:
9158     explicit inline State(ConsStringIteratorOp* op)
9159       : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {}
9160
9161     inline void Init(String* string) {
9162       ConsString* cons_string = String::VisitFlat(this, string);
9163       op_->Reset(cons_string);
9164       if (cons_string != NULL) {
9165         int offset;
9166         string = op_->Next(&offset);
9167         String::VisitFlat(this, string, offset);
9168       }
9169     }
9170
9171     inline void VisitOneByteString(const uint8_t* chars, int length) {
9172       is_one_byte_ = true;
9173       buffer8_ = chars;
9174       length_ = length;
9175     }
9176
9177     inline void VisitTwoByteString(const uint16_t* chars, int length) {
9178       is_one_byte_ = false;
9179       buffer16_ = chars;
9180       length_ = length;
9181     }
9182
9183     void Advance(int consumed) {
9184       DCHECK(consumed <= length_);
9185       // Still in buffer.
9186       if (length_ != consumed) {
9187         if (is_one_byte_) {
9188           buffer8_ += consumed;
9189         } else {
9190           buffer16_ += consumed;
9191         }
9192         length_ -= consumed;
9193         return;
9194       }
9195       // Advance state.
9196       int offset;
9197       String* next = op_->Next(&offset);
9198       DCHECK_EQ(0, offset);
9199       DCHECK(next != NULL);
9200       String::VisitFlat(this, next);
9201     }
9202
9203     ConsStringIteratorOp* const op_;
9204     bool is_one_byte_;
9205     int length_;
9206     union {
9207       const uint8_t* buffer8_;
9208       const uint16_t* buffer16_;
9209     };
9210
9211    private:
9212     DISALLOW_IMPLICIT_CONSTRUCTORS(State);
9213   };
9214
9215  public:
9216   inline StringComparator(ConsStringIteratorOp* op_1,
9217                           ConsStringIteratorOp* op_2)
9218     : state_1_(op_1),
9219       state_2_(op_2) {
9220   }
9221
9222   template<typename Chars1, typename Chars2>
9223   static inline bool Equals(State* state_1, State* state_2, int to_check) {
9224     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
9225     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
9226     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
9227   }
9228
9229   bool Equals(String* string_1, String* string_2) {
9230     int length = string_1->length();
9231     state_1_.Init(string_1);
9232     state_2_.Init(string_2);
9233     while (true) {
9234       int to_check = Min(state_1_.length_, state_2_.length_);
9235       DCHECK(to_check > 0 && to_check <= length);
9236       bool is_equal;
9237       if (state_1_.is_one_byte_) {
9238         if (state_2_.is_one_byte_) {
9239           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
9240         } else {
9241           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
9242         }
9243       } else {
9244         if (state_2_.is_one_byte_) {
9245           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
9246         } else {
9247           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
9248         }
9249       }
9250       // Looping done.
9251       if (!is_equal) return false;
9252       length -= to_check;
9253       // Exit condition. Strings are equal.
9254       if (length == 0) return true;
9255       state_1_.Advance(to_check);
9256       state_2_.Advance(to_check);
9257     }
9258   }
9259
9260  private:
9261   State state_1_;
9262   State state_2_;
9263   DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator);
9264 };
9265
9266
9267 bool String::SlowEquals(String* other) {
9268   DisallowHeapAllocation no_gc;
9269   // Fast check: negative check with lengths.
9270   int len = length();
9271   if (len != other->length()) return false;
9272   if (len == 0) return true;
9273
9274   // Fast check: if hash code is computed for both strings
9275   // a fast negative check can be performed.
9276   if (HasHashCode() && other->HasHashCode()) {
9277 #ifdef ENABLE_SLOW_DCHECKS
9278     if (FLAG_enable_slow_asserts) {
9279       if (Hash() != other->Hash()) {
9280         bool found_difference = false;
9281         for (int i = 0; i < len; i++) {
9282           if (Get(i) != other->Get(i)) {
9283             found_difference = true;
9284             break;
9285           }
9286         }
9287         DCHECK(found_difference);
9288       }
9289     }
9290 #endif
9291     if (Hash() != other->Hash()) return false;
9292   }
9293
9294   // We know the strings are both non-empty. Compare the first chars
9295   // before we try to flatten the strings.
9296   if (this->Get(0) != other->Get(0)) return false;
9297
9298   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
9299     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
9300     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
9301     return CompareRawStringContents(str1, str2, len);
9302   }
9303
9304   Isolate* isolate = GetIsolate();
9305   StringComparator comparator(isolate->objects_string_compare_iterator_a(),
9306                               isolate->objects_string_compare_iterator_b());
9307
9308   return comparator.Equals(this, other);
9309 }
9310
9311
9312 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
9313   // Fast check: negative check with lengths.
9314   int one_length = one->length();
9315   if (one_length != two->length()) return false;
9316   if (one_length == 0) return true;
9317
9318   // Fast check: if hash code is computed for both strings
9319   // a fast negative check can be performed.
9320   if (one->HasHashCode() && two->HasHashCode()) {
9321 #ifdef ENABLE_SLOW_DCHECKS
9322     if (FLAG_enable_slow_asserts) {
9323       if (one->Hash() != two->Hash()) {
9324         bool found_difference = false;
9325         for (int i = 0; i < one_length; i++) {
9326           if (one->Get(i) != two->Get(i)) {
9327             found_difference = true;
9328             break;
9329           }
9330         }
9331         DCHECK(found_difference);
9332       }
9333     }
9334 #endif
9335     if (one->Hash() != two->Hash()) return false;
9336   }
9337
9338   // We know the strings are both non-empty. Compare the first chars
9339   // before we try to flatten the strings.
9340   if (one->Get(0) != two->Get(0)) return false;
9341
9342   one = String::Flatten(one);
9343   two = String::Flatten(two);
9344
9345   DisallowHeapAllocation no_gc;
9346   String::FlatContent flat1 = one->GetFlatContent();
9347   String::FlatContent flat2 = two->GetFlatContent();
9348
9349   if (flat1.IsAscii() && flat2.IsAscii()) {
9350       return CompareRawStringContents(flat1.ToOneByteVector().start(),
9351                                       flat2.ToOneByteVector().start(),
9352                                       one_length);
9353   } else {
9354     for (int i = 0; i < one_length; i++) {
9355       if (flat1.Get(i) != flat2.Get(i)) return false;
9356     }
9357     return true;
9358   }
9359 }
9360
9361
9362 bool String::MarkAsUndetectable() {
9363   if (StringShape(this).IsInternalized()) return false;
9364
9365   Map* map = this->map();
9366   Heap* heap = GetHeap();
9367   if (map == heap->string_map()) {
9368     this->set_map(heap->undetectable_string_map());
9369     return true;
9370   } else if (map == heap->ascii_string_map()) {
9371     this->set_map(heap->undetectable_ascii_string_map());
9372     return true;
9373   }
9374   // Rest cannot be marked as undetectable
9375   return false;
9376 }
9377
9378
9379 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
9380   int slen = length();
9381   // Can't check exact length equality, but we can check bounds.
9382   int str_len = str.length();
9383   if (!allow_prefix_match &&
9384       (str_len < slen ||
9385           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
9386     return false;
9387   }
9388   int i;
9389   unsigned remaining_in_str = static_cast<unsigned>(str_len);
9390   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
9391   for (i = 0; i < slen && remaining_in_str > 0; i++) {
9392     unsigned cursor = 0;
9393     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
9394     DCHECK(cursor > 0 && cursor <= remaining_in_str);
9395     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
9396       if (i > slen - 1) return false;
9397       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
9398       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
9399     } else {
9400       if (Get(i) != r) return false;
9401     }
9402     utf8_data += cursor;
9403     remaining_in_str -= cursor;
9404   }
9405   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
9406 }
9407
9408
9409 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
9410   int slen = length();
9411   if (str.length() != slen) return false;
9412   DisallowHeapAllocation no_gc;
9413   FlatContent content = GetFlatContent();
9414   if (content.IsAscii()) {
9415     return CompareChars(content.ToOneByteVector().start(),
9416                         str.start(), slen) == 0;
9417   }
9418   for (int i = 0; i < slen; i++) {
9419     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
9420   }
9421   return true;
9422 }
9423
9424
9425 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
9426   int slen = length();
9427   if (str.length() != slen) return false;
9428   DisallowHeapAllocation no_gc;
9429   FlatContent content = GetFlatContent();
9430   if (content.IsTwoByte()) {
9431     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
9432   }
9433   for (int i = 0; i < slen; i++) {
9434     if (Get(i) != str[i]) return false;
9435   }
9436   return true;
9437 }
9438
9439
9440 uint32_t String::ComputeAndSetHash() {
9441   // Should only be called if hash code has not yet been computed.
9442   DCHECK(!HasHashCode());
9443
9444   // Store the hash code in the object.
9445   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
9446   set_hash_field(field);
9447
9448   // Check the hash code is there.
9449   DCHECK(HasHashCode());
9450   uint32_t result = field >> kHashShift;
9451   DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
9452   return result;
9453 }
9454
9455
9456 bool String::ComputeArrayIndex(uint32_t* index) {
9457   int length = this->length();
9458   if (length == 0 || length > kMaxArrayIndexSize) return false;
9459   ConsStringIteratorOp op;
9460   StringCharacterStream stream(this, &op);
9461   return StringToArrayIndex(&stream, index);
9462 }
9463
9464
9465 bool String::SlowAsArrayIndex(uint32_t* index) {
9466   if (length() <= kMaxCachedArrayIndexLength) {
9467     Hash();  // force computation of hash code
9468     uint32_t field = hash_field();
9469     if ((field & kIsNotArrayIndexMask) != 0) return false;
9470     // Isolate the array index form the full hash field.
9471     *index = ArrayIndexValueBits::decode(field);
9472     return true;
9473   } else {
9474     return ComputeArrayIndex(index);
9475   }
9476 }
9477
9478
9479 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
9480   int new_size, old_size;
9481   int old_length = string->length();
9482   if (old_length <= new_length) return string;
9483
9484   if (string->IsSeqOneByteString()) {
9485     old_size = SeqOneByteString::SizeFor(old_length);
9486     new_size = SeqOneByteString::SizeFor(new_length);
9487   } else {
9488     DCHECK(string->IsSeqTwoByteString());
9489     old_size = SeqTwoByteString::SizeFor(old_length);
9490     new_size = SeqTwoByteString::SizeFor(new_length);
9491   }
9492
9493   int delta = old_size - new_size;
9494
9495   Address start_of_string = string->address();
9496   DCHECK_OBJECT_ALIGNED(start_of_string);
9497   DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
9498
9499   Heap* heap = string->GetHeap();
9500   NewSpace* newspace = heap->new_space();
9501   if (newspace->Contains(start_of_string) &&
9502       newspace->top() == start_of_string + old_size) {
9503     // Last allocated object in new space.  Simply lower allocation top.
9504     newspace->set_top(start_of_string + new_size);
9505   } else {
9506     // Sizes are pointer size aligned, so that we can use filler objects
9507     // that are a multiple of pointer size.
9508     heap->CreateFillerObjectAt(start_of_string + new_size, delta);
9509   }
9510   heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR);
9511
9512   // We are storing the new length using release store after creating a filler
9513   // for the left-over space to avoid races with the sweeper thread.
9514   string->synchronized_set_length(new_length);
9515
9516   if (new_length == 0) return heap->isolate()->factory()->empty_string();
9517   return string;
9518 }
9519
9520
9521 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
9522   // For array indexes mix the length into the hash as an array index could
9523   // be zero.
9524   DCHECK(length > 0);
9525   DCHECK(length <= String::kMaxArrayIndexSize);
9526   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
9527          (1 << String::kArrayIndexValueBits));
9528
9529   value <<= String::ArrayIndexValueBits::kShift;
9530   value |= length << String::ArrayIndexLengthBits::kShift;
9531
9532   DCHECK((value & String::kIsNotArrayIndexMask) == 0);
9533   DCHECK((length > String::kMaxCachedArrayIndexLength) ||
9534          (value & String::kContainsCachedArrayIndexMask) == 0);
9535   return value;
9536 }
9537
9538
9539 uint32_t StringHasher::GetHashField() {
9540   if (length_ <= String::kMaxHashCalcLength) {
9541     if (is_array_index_) {
9542       return MakeArrayIndexHash(array_index_, length_);
9543     }
9544     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
9545            String::kIsNotArrayIndexMask;
9546   } else {
9547     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
9548   }
9549 }
9550
9551
9552 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
9553                                        uint32_t seed,
9554                                        int* utf16_length_out) {
9555   int vector_length = chars.length();
9556   // Handle some edge cases
9557   if (vector_length <= 1) {
9558     DCHECK(vector_length == 0 ||
9559            static_cast<uint8_t>(chars.start()[0]) <=
9560                unibrow::Utf8::kMaxOneByteChar);
9561     *utf16_length_out = vector_length;
9562     return HashSequentialString(chars.start(), vector_length, seed);
9563   }
9564   // Start with a fake length which won't affect computation.
9565   // It will be updated later.
9566   StringHasher hasher(String::kMaxArrayIndexSize, seed);
9567   unsigned remaining = static_cast<unsigned>(vector_length);
9568   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
9569   int utf16_length = 0;
9570   bool is_index = true;
9571   DCHECK(hasher.is_array_index_);
9572   while (remaining > 0) {
9573     unsigned consumed = 0;
9574     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
9575     DCHECK(consumed > 0 && consumed <= remaining);
9576     stream += consumed;
9577     remaining -= consumed;
9578     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
9579     utf16_length += is_two_characters ? 2 : 1;
9580     // No need to keep hashing. But we do need to calculate utf16_length.
9581     if (utf16_length > String::kMaxHashCalcLength) continue;
9582     if (is_two_characters) {
9583       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
9584       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
9585       hasher.AddCharacter(c1);
9586       hasher.AddCharacter(c2);
9587       if (is_index) is_index = hasher.UpdateIndex(c1);
9588       if (is_index) is_index = hasher.UpdateIndex(c2);
9589     } else {
9590       hasher.AddCharacter(c);
9591       if (is_index) is_index = hasher.UpdateIndex(c);
9592     }
9593   }
9594   *utf16_length_out = static_cast<int>(utf16_length);
9595   // Must set length here so that hash computation is correct.
9596   hasher.length_ = utf16_length;
9597   return hasher.GetHashField();
9598 }
9599
9600
9601 void String::PrintOn(FILE* file) {
9602   int length = this->length();
9603   for (int i = 0; i < length; i++) {
9604     PrintF(file, "%c", Get(i));
9605   }
9606 }
9607
9608
9609 int Map::Hash() {
9610   // For performance reasons we only hash the 3 most variable fields of a map:
9611   // constructor, prototype and bit_field2.
9612
9613   // Shift away the tag.
9614   int hash = (static_cast<uint32_t>(
9615         reinterpret_cast<uintptr_t>(constructor())) >> 2);
9616
9617   // XOR-ing the prototype and constructor directly yields too many zero bits
9618   // when the two pointers are close (which is fairly common).
9619   // To avoid this we shift the prototype 4 bits relatively to the constructor.
9620   hash ^= (static_cast<uint32_t>(
9621         reinterpret_cast<uintptr_t>(prototype())) << 2);
9622
9623   return hash ^ (hash >> 16) ^ bit_field2();
9624 }
9625
9626
9627 static bool CheckEquivalent(Map* first, Map* second) {
9628   return
9629     first->constructor() == second->constructor() &&
9630     first->prototype() == second->prototype() &&
9631     first->instance_type() == second->instance_type() &&
9632     first->bit_field() == second->bit_field() &&
9633     first->bit_field2() == second->bit_field2() &&
9634     first->is_frozen() == second->is_frozen() &&
9635     first->has_instance_call_handler() == second->has_instance_call_handler();
9636 }
9637
9638
9639 bool Map::EquivalentToForTransition(Map* other) {
9640   return CheckEquivalent(this, other);
9641 }
9642
9643
9644 bool Map::EquivalentToForNormalization(Map* other,
9645                                        PropertyNormalizationMode mode) {
9646   int properties = mode == CLEAR_INOBJECT_PROPERTIES
9647       ? 0 : other->inobject_properties();
9648   return CheckEquivalent(this, other) && inobject_properties() == properties;
9649 }
9650
9651
9652 void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) {
9653   // Unfortunately the serializer relies on pointers within an object being
9654   // visited in-order, so we have to iterate both the code and heap pointers in
9655   // the small section before doing so in the extended section.
9656   for (int s = 0; s <= final_section(); ++s) {
9657     LayoutSection section = static_cast<LayoutSection>(s);
9658     ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR,
9659                                           section);
9660     while (!code_iter.is_finished()) {
9661       v->VisitCodeEntry(reinterpret_cast<Address>(
9662           RawFieldOfElementAt(code_iter.next_index())));
9663     }
9664
9665     ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR,
9666                                           section);
9667     while (!heap_iter.is_finished()) {
9668       v->VisitPointer(RawFieldOfElementAt(heap_iter.next_index()));
9669     }
9670   }
9671 }
9672
9673
9674 void ConstantPoolArray::ClearPtrEntries(Isolate* isolate) {
9675   Type type[] = { CODE_PTR, HEAP_PTR };
9676   Address default_value[] = {
9677         isolate->builtins()->builtin(Builtins::kIllegal)->entry(),
9678         reinterpret_cast<Address>(isolate->heap()->undefined_value()) };
9679
9680   for (int i = 0; i < 2; ++i) {
9681     for (int s = 0; s <= final_section(); ++s) {
9682       LayoutSection section = static_cast<LayoutSection>(s);
9683       if (number_of_entries(type[i], section) > 0) {
9684         int offset = OffsetOfElementAt(first_index(type[i], section));
9685         MemsetPointer(
9686           reinterpret_cast<Address*>(HeapObject::RawField(this, offset)),
9687           default_value[i],
9688           number_of_entries(type[i], section));
9689       }
9690     }
9691   }
9692 }
9693
9694
9695 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
9696   // Iterate over all fields in the body but take care in dealing with
9697   // the code entry.
9698   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
9699   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9700   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9701 }
9702
9703
9704 void JSFunction::MarkForOptimization() {
9705   DCHECK(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
9706   DCHECK(!IsOptimized());
9707   DCHECK(shared()->allows_lazy_compilation() ||
9708          code()->optimizable());
9709   DCHECK(!shared()->is_generator());
9710   set_code_no_write_barrier(
9711       GetIsolate()->builtins()->builtin(Builtins::kCompileOptimized));
9712   // No write barrier required, since the builtin is part of the root set.
9713 }
9714
9715
9716 void JSFunction::MarkForConcurrentOptimization() {
9717   DCHECK(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
9718   DCHECK(!IsOptimized());
9719   DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9720   DCHECK(!shared()->is_generator());
9721   DCHECK(GetIsolate()->concurrent_recompilation_enabled());
9722   if (FLAG_trace_concurrent_recompilation) {
9723     PrintF("  ** Marking ");
9724     PrintName();
9725     PrintF(" for concurrent recompilation.\n");
9726   }
9727   set_code_no_write_barrier(
9728       GetIsolate()->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9729   // No write barrier required, since the builtin is part of the root set.
9730 }
9731
9732
9733 void JSFunction::MarkInOptimizationQueue() {
9734   // We can only arrive here via the concurrent-recompilation builtin.  If
9735   // break points were set, the code would point to the lazy-compile builtin.
9736   DCHECK(!GetIsolate()->DebuggerHasBreakPoints());
9737   DCHECK(IsMarkedForConcurrentOptimization() && !IsOptimized());
9738   DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9739   DCHECK(GetIsolate()->concurrent_recompilation_enabled());
9740   if (FLAG_trace_concurrent_recompilation) {
9741     PrintF("  ** Queueing ");
9742     PrintName();
9743     PrintF(" for concurrent recompilation.\n");
9744   }
9745   set_code_no_write_barrier(
9746       GetIsolate()->builtins()->builtin(Builtins::kInOptimizationQueue));
9747   // No write barrier required, since the builtin is part of the root set.
9748 }
9749
9750
9751 void SharedFunctionInfo::AddToOptimizedCodeMap(
9752     Handle<SharedFunctionInfo> shared,
9753     Handle<Context> native_context,
9754     Handle<Code> code,
9755     Handle<FixedArray> literals,
9756     BailoutId osr_ast_id) {
9757   Isolate* isolate = shared->GetIsolate();
9758   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9759   DCHECK(native_context->IsNativeContext());
9760   STATIC_ASSERT(kEntryLength == 4);
9761   Handle<FixedArray> new_code_map;
9762   Handle<Object> value(shared->optimized_code_map(), isolate);
9763   int old_length;
9764   if (value->IsSmi()) {
9765     // No optimized code map.
9766     DCHECK_EQ(0, Smi::cast(*value)->value());
9767     // Create 3 entries per context {context, code, literals}.
9768     new_code_map = isolate->factory()->NewFixedArray(kInitialLength);
9769     old_length = kEntriesStart;
9770   } else {
9771     // Copy old map and append one new entry.
9772     Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value);
9773     DCHECK_EQ(-1, shared->SearchOptimizedCodeMap(*native_context, osr_ast_id));
9774     old_length = old_code_map->length();
9775     new_code_map = FixedArray::CopySize(
9776         old_code_map, old_length + kEntryLength);
9777     // Zap the old map for the sake of the heap verifier.
9778     if (Heap::ShouldZapGarbage()) {
9779       Object** data = old_code_map->data_start();
9780       MemsetPointer(data, isolate->heap()->the_hole_value(), old_length);
9781     }
9782   }
9783   new_code_map->set(old_length + kContextOffset, *native_context);
9784   new_code_map->set(old_length + kCachedCodeOffset, *code);
9785   new_code_map->set(old_length + kLiteralsOffset, *literals);
9786   new_code_map->set(old_length + kOsrAstIdOffset,
9787                     Smi::FromInt(osr_ast_id.ToInt()));
9788
9789 #ifdef DEBUG
9790   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9791     DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext());
9792     DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9793     DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9794            Code::OPTIMIZED_FUNCTION);
9795     DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9796     DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9797   }
9798 #endif
9799   shared->set_optimized_code_map(*new_code_map);
9800 }
9801
9802
9803 FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) {
9804   DCHECK(index > kEntriesStart);
9805   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9806   if (!bound()) {
9807     FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
9808     DCHECK_NE(NULL, cached_literals);
9809     return cached_literals;
9810   }
9811   return NULL;
9812 }
9813
9814
9815 Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) {
9816   DCHECK(index > kEntriesStart);
9817   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9818   Code* code = Code::cast(code_map->get(index));
9819   DCHECK_NE(NULL, code);
9820   return code;
9821 }
9822
9823
9824 void SharedFunctionInfo::ClearOptimizedCodeMap() {
9825   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9826
9827   // If the next map link slot is already used then the function was
9828   // enqueued with code flushing and we remove it now.
9829   if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9830     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
9831     flusher->EvictOptimizedCodeMap(this);
9832   }
9833
9834   DCHECK(code_map->get(kNextMapIndex)->IsUndefined());
9835   set_optimized_code_map(Smi::FromInt(0));
9836 }
9837
9838
9839 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
9840                                                    const char* reason) {
9841   DisallowHeapAllocation no_gc;
9842   if (optimized_code_map()->IsSmi()) return;
9843
9844   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9845   int dst = kEntriesStart;
9846   int length = code_map->length();
9847   for (int src = kEntriesStart; src < length; src += kEntryLength) {
9848     DCHECK(code_map->get(src)->IsNativeContext());
9849     if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9850       // Evict the src entry by not copying it to the dst entry.
9851       if (FLAG_trace_opt) {
9852         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9853         ShortPrint();
9854         BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9855         if (osr.IsNone()) {
9856           PrintF("]\n");
9857         } else {
9858           PrintF(" (osr ast id %d)]\n", osr.ToInt());
9859         }
9860       }
9861     } else {
9862       // Keep the src entry by copying it to the dst entry.
9863       if (dst != src) {
9864         code_map->set(dst + kContextOffset,
9865                       code_map->get(src + kContextOffset));
9866         code_map->set(dst + kCachedCodeOffset,
9867                       code_map->get(src + kCachedCodeOffset));
9868         code_map->set(dst + kLiteralsOffset,
9869                       code_map->get(src + kLiteralsOffset));
9870         code_map->set(dst + kOsrAstIdOffset,
9871                       code_map->get(src + kOsrAstIdOffset));
9872       }
9873       dst += kEntryLength;
9874     }
9875   }
9876   if (dst != length) {
9877     // Always trim even when array is cleared because of heap verifier.
9878     GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>(code_map, length - dst);
9879     if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap();
9880   }
9881 }
9882
9883
9884 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
9885   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9886   DCHECK(shrink_by % kEntryLength == 0);
9887   DCHECK(shrink_by <= code_map->length() - kEntriesStart);
9888   // Always trim even when array is cleared because of heap verifier.
9889   GetHeap()->RightTrimFixedArray<Heap::FROM_GC>(code_map, shrink_by);
9890   if (code_map->length() == kEntriesStart) {
9891     ClearOptimizedCodeMap();
9892   }
9893 }
9894
9895
9896 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
9897                                    PrototypeOptimizationMode mode) {
9898   if (object->IsGlobalObject()) return;
9899   if (object->IsJSGlobalProxy()) return;
9900   if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) {
9901     // First normalize to ensure all JSFunctions are CONSTANT.
9902     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0);
9903   }
9904   if (!object->HasFastProperties()) {
9905     JSObject::MigrateSlowToFast(object, 0);
9906   }
9907   if (mode == FAST_PROTOTYPE && object->HasFastProperties() &&
9908       !object->map()->is_prototype_map()) {
9909     Handle<Map> new_map = Map::Copy(handle(object->map()));
9910     JSObject::MigrateToMap(object, new_map);
9911     object->map()->set_is_prototype_map(true);
9912   }
9913 }
9914
9915
9916 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9917   if (!object->map()->is_prototype_map()) return;
9918   OptimizeAsPrototype(object, FAST_PROTOTYPE);
9919 }
9920
9921
9922 Handle<Object> CacheInitialJSArrayMaps(
9923     Handle<Context> native_context, Handle<Map> initial_map) {
9924   // Replace all of the cached initial array maps in the native context with
9925   // the appropriate transitioned elements kind maps.
9926   Factory* factory = native_context->GetIsolate()->factory();
9927   Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9928       kElementsKindCount, TENURED);
9929
9930   Handle<Map> current_map = initial_map;
9931   ElementsKind kind = current_map->elements_kind();
9932   DCHECK(kind == GetInitialFastElementsKind());
9933   maps->set(kind, *current_map);
9934   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
9935        i < kFastElementsKindCount; ++i) {
9936     Handle<Map> new_map;
9937     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
9938     if (current_map->HasElementsTransition()) {
9939       new_map = handle(current_map->elements_transition_map());
9940       DCHECK(new_map->elements_kind() == next_kind);
9941     } else {
9942       new_map = Map::CopyAsElementsKind(
9943           current_map, next_kind, INSERT_TRANSITION);
9944     }
9945     maps->set(next_kind, *new_map);
9946     current_map = new_map;
9947   }
9948   native_context->set_js_array_maps(*maps);
9949   return initial_map;
9950 }
9951
9952
9953 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
9954                                       Handle<Object> value) {
9955   Isolate* isolate = function->GetIsolate();
9956
9957   DCHECK(value->IsJSReceiver());
9958
9959   // Now some logic for the maps of the objects that are created by using this
9960   // function as a constructor.
9961   if (function->has_initial_map()) {
9962     // If the function has allocated the initial map replace it with a
9963     // copy containing the new prototype.  Also complete any in-object
9964     // slack tracking that is in progress at this point because it is
9965     // still tracking the old copy.
9966     if (function->IsInobjectSlackTrackingInProgress()) {
9967       function->CompleteInobjectSlackTracking();
9968     }
9969
9970     Handle<Map> initial_map(function->initial_map(), isolate);
9971
9972     if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
9973         initial_map->instance_type() == JS_OBJECT_TYPE) {
9974       // Put the value in the initial map field until an initial map is needed.
9975       // At that point, a new initial map is created and the prototype is put
9976       // into the initial map where it belongs.
9977       function->set_prototype_or_initial_map(*value);
9978     } else {
9979       Handle<Map> new_map = Map::Copy(initial_map);
9980       JSFunction::SetInitialMap(function, new_map, value);
9981
9982       // If the function is used as the global Array function, cache the
9983       // initial map (and transitioned versions) in the native context.
9984       Context* native_context = function->context()->native_context();
9985       Object* array_function =
9986           native_context->get(Context::ARRAY_FUNCTION_INDEX);
9987       if (array_function->IsJSFunction() &&
9988           *function == JSFunction::cast(array_function)) {
9989         CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
9990       }
9991     }
9992
9993     // Deoptimize all code that embeds the previous initial map.
9994     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
9995         isolate, DependentCode::kInitialMapChangedGroup);
9996   } else {
9997     // Put the value in the initial map field until an initial map is
9998     // needed.  At that point, a new initial map is created and the
9999     // prototype is put into the initial map where it belongs.
10000     function->set_prototype_or_initial_map(*value);
10001   }
10002   isolate->heap()->ClearInstanceofCache();
10003 }
10004
10005
10006 void JSFunction::SetPrototype(Handle<JSFunction> function,
10007                               Handle<Object> value) {
10008   DCHECK(function->should_have_prototype());
10009   Handle<Object> construct_prototype = value;
10010
10011   // If the value is not a JSReceiver, store the value in the map's
10012   // constructor field so it can be accessed.  Also, set the prototype
10013   // used for constructing objects to the original object prototype.
10014   // See ECMA-262 13.2.2.
10015   if (!value->IsJSReceiver()) {
10016     // Copy the map so this does not affect unrelated functions.
10017     // Remove map transitions because they point to maps with a
10018     // different prototype.
10019     Handle<Map> new_map = Map::Copy(handle(function->map()));
10020
10021     JSObject::MigrateToMap(function, new_map);
10022     new_map->set_constructor(*value);
10023     new_map->set_non_instance_prototype(true);
10024     Isolate* isolate = new_map->GetIsolate();
10025     construct_prototype = handle(
10026         isolate->context()->native_context()->initial_object_prototype(),
10027         isolate);
10028   } else {
10029     function->map()->set_non_instance_prototype(false);
10030   }
10031
10032   return SetInstancePrototype(function, construct_prototype);
10033 }
10034
10035
10036 bool JSFunction::RemovePrototype() {
10037   Context* native_context = context()->native_context();
10038   Map* no_prototype_map = shared()->strict_mode() == SLOPPY
10039       ? native_context->sloppy_function_without_prototype_map()
10040       : native_context->strict_function_without_prototype_map();
10041
10042   if (map() == no_prototype_map) return true;
10043
10044 #ifdef DEBUG
10045   if (map() != (shared()->strict_mode() == SLOPPY
10046                    ? native_context->sloppy_function_map()
10047                    : native_context->strict_function_map())) {
10048     return false;
10049   }
10050 #endif
10051
10052   set_map(no_prototype_map);
10053   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
10054   return true;
10055 }
10056
10057
10058 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
10059                                Handle<Object> prototype) {
10060   if (prototype->IsJSObject()) {
10061     Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype);
10062     JSObject::OptimizeAsPrototype(js_proto, FAST_PROTOTYPE);
10063   }
10064   map->set_prototype(*prototype);
10065   function->set_prototype_or_initial_map(*map);
10066   map->set_constructor(*function);
10067 }
10068
10069
10070 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
10071   if (function->has_initial_map()) return;
10072   Isolate* isolate = function->GetIsolate();
10073
10074   // First create a new map with the size and number of in-object properties
10075   // suggested by the function.
10076   InstanceType instance_type;
10077   int instance_size;
10078   int in_object_properties;
10079   if (function->shared()->is_generator()) {
10080     instance_type = JS_GENERATOR_OBJECT_TYPE;
10081     instance_size = JSGeneratorObject::kSize;
10082     in_object_properties = 0;
10083   } else {
10084     instance_type = JS_OBJECT_TYPE;
10085     instance_size = function->shared()->CalculateInstanceSize();
10086     in_object_properties = function->shared()->CalculateInObjectProperties();
10087   }
10088   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
10089
10090   // Fetch or allocate prototype.
10091   Handle<Object> prototype;
10092   if (function->has_instance_prototype()) {
10093     prototype = handle(function->instance_prototype(), isolate);
10094   } else {
10095     prototype = isolate->factory()->NewFunctionPrototype(function);
10096   }
10097   map->set_inobject_properties(in_object_properties);
10098   map->set_unused_property_fields(in_object_properties);
10099   DCHECK(map->has_fast_object_elements());
10100
10101   // Finally link initial map and constructor function.
10102   JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
10103
10104   if (!function->shared()->is_generator()) {
10105     function->StartInobjectSlackTracking();
10106   }
10107 }
10108
10109
10110 void JSFunction::SetInstanceClassName(String* name) {
10111   shared()->set_instance_class_name(name);
10112 }
10113
10114
10115 void JSFunction::PrintName(FILE* out) {
10116   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
10117   PrintF(out, "%s", name.get());
10118 }
10119
10120
10121 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) {
10122   return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex));
10123 }
10124
10125
10126 // The filter is a pattern that matches function names in this way:
10127 //   "*"      all; the default
10128 //   "-"      all but the top-level function
10129 //   "-name"  all but the function "name"
10130 //   ""       only the top-level function
10131 //   "name"   only the function "name"
10132 //   "name*"  only functions starting with "name"
10133 //   "~"      none; the tilde is not an identifier
10134 bool JSFunction::PassesFilter(const char* raw_filter) {
10135   if (*raw_filter == '*') return true;
10136   String* name = shared()->DebugName();
10137   Vector<const char> filter = CStrVector(raw_filter);
10138   if (filter.length() == 0) return name->length() == 0;
10139   if (filter[0] == '-') {
10140     // Negative filter.
10141     if (filter.length() == 1) {
10142       return (name->length() != 0);
10143     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
10144       return false;
10145     }
10146     if (filter[filter.length() - 1] == '*' &&
10147         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
10148       return false;
10149     }
10150     return true;
10151
10152   } else if (name->IsUtf8EqualTo(filter)) {
10153     return true;
10154   }
10155   if (filter[filter.length() - 1] == '*' &&
10156       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
10157     return true;
10158   }
10159   return false;
10160 }
10161
10162
10163 void Oddball::Initialize(Isolate* isolate,
10164                          Handle<Oddball> oddball,
10165                          const char* to_string,
10166                          Handle<Object> to_number,
10167                          byte kind) {
10168   Handle<String> internalized_to_string =
10169       isolate->factory()->InternalizeUtf8String(to_string);
10170   oddball->set_to_string(*internalized_to_string);
10171   oddball->set_to_number(*to_number);
10172   oddball->set_kind(kind);
10173 }
10174
10175
10176 void Script::InitLineEnds(Handle<Script> script) {
10177   if (!script->line_ends()->IsUndefined()) return;
10178
10179   Isolate* isolate = script->GetIsolate();
10180
10181   if (!script->source()->IsString()) {
10182     DCHECK(script->source()->IsUndefined());
10183     Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
10184     script->set_line_ends(*empty);
10185     DCHECK(script->line_ends()->IsFixedArray());
10186     return;
10187   }
10188
10189   Handle<String> src(String::cast(script->source()), isolate);
10190
10191   Handle<FixedArray> array = String::CalculateLineEnds(src, true);
10192
10193   if (*array != isolate->heap()->empty_fixed_array()) {
10194     array->set_map(isolate->heap()->fixed_cow_array_map());
10195   }
10196
10197   script->set_line_ends(*array);
10198   DCHECK(script->line_ends()->IsFixedArray());
10199 }
10200
10201
10202 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
10203   int line_number = GetLineNumber(script, code_pos);
10204   if (line_number == -1) return -1;
10205
10206   DisallowHeapAllocation no_allocation;
10207   FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
10208   line_number = line_number - script->line_offset()->value();
10209   if (line_number == 0) return code_pos + script->column_offset()->value();
10210   int prev_line_end_pos =
10211       Smi::cast(line_ends_array->get(line_number - 1))->value();
10212   return code_pos - (prev_line_end_pos + 1);
10213 }
10214
10215
10216 int Script::GetLineNumberWithArray(int code_pos) {
10217   DisallowHeapAllocation no_allocation;
10218   DCHECK(line_ends()->IsFixedArray());
10219   FixedArray* line_ends_array = FixedArray::cast(line_ends());
10220   int line_ends_len = line_ends_array->length();
10221   if (line_ends_len == 0) return -1;
10222
10223   if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
10224     return line_offset()->value();
10225   }
10226
10227   int left = 0;
10228   int right = line_ends_len;
10229   while (int half = (right - left) / 2) {
10230     if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
10231       right -= half;
10232     } else {
10233       left += half;
10234     }
10235   }
10236   return right + line_offset()->value();
10237 }
10238
10239
10240 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
10241   InitLineEnds(script);
10242   return script->GetLineNumberWithArray(code_pos);
10243 }
10244
10245
10246 int Script::GetLineNumber(int code_pos) {
10247   DisallowHeapAllocation no_allocation;
10248   if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
10249
10250   // Slow mode: we do not have line_ends. We have to iterate through source.
10251   if (!source()->IsString()) return -1;
10252
10253   String* source_string = String::cast(source());
10254   int line = 0;
10255   int len = source_string->length();
10256   for (int pos = 0; pos < len; pos++) {
10257     if (pos == code_pos) break;
10258     if (source_string->Get(pos) == '\n') line++;
10259   }
10260   return line;
10261 }
10262
10263
10264 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
10265   Isolate* isolate = script->GetIsolate();
10266   Handle<String> name_or_source_url_key =
10267       isolate->factory()->InternalizeOneByteString(
10268           STATIC_ASCII_VECTOR("nameOrSourceURL"));
10269   Handle<JSObject> script_wrapper = Script::GetWrapper(script);
10270   Handle<Object> property = Object::GetProperty(
10271       script_wrapper, name_or_source_url_key).ToHandleChecked();
10272   DCHECK(property->IsJSFunction());
10273   Handle<JSFunction> method = Handle<JSFunction>::cast(property);
10274   Handle<Object> result;
10275   // Do not check against pending exception, since this function may be called
10276   // when an exception has already been pending.
10277   if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
10278     return isolate->factory()->undefined_value();
10279   }
10280   return result;
10281 }
10282
10283
10284 // Wrappers for scripts are kept alive and cached in weak global
10285 // handles referred from foreign objects held by the scripts as long as
10286 // they are used. When they are not used anymore, the garbage
10287 // collector will call the weak callback on the global handle
10288 // associated with the wrapper and get rid of both the wrapper and the
10289 // handle.
10290 static void ClearWrapperCacheWeakCallback(
10291     const v8::WeakCallbackData<v8::Value, void>& data) {
10292   Object** location = reinterpret_cast<Object**>(data.GetParameter());
10293   JSValue* wrapper = JSValue::cast(*location);
10294   Script::cast(wrapper->value())->ClearWrapperCache();
10295 }
10296
10297
10298 void Script::ClearWrapperCache() {
10299   Foreign* foreign = wrapper();
10300   Object** location = reinterpret_cast<Object**>(foreign->foreign_address());
10301   DCHECK_EQ(foreign->foreign_address(), reinterpret_cast<Address>(location));
10302   foreign->set_foreign_address(0);
10303   GlobalHandles::Destroy(location);
10304   GetIsolate()->counters()->script_wrappers()->Decrement();
10305 }
10306
10307
10308 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
10309   if (script->wrapper()->foreign_address() != NULL) {
10310     // Return a handle for the existing script wrapper from the cache.
10311     return Handle<JSValue>(
10312         *reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
10313   }
10314   Isolate* isolate = script->GetIsolate();
10315   // Construct a new script wrapper.
10316   isolate->counters()->script_wrappers()->Increment();
10317   Handle<JSFunction> constructor = isolate->script_function();
10318   Handle<JSValue> result =
10319       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
10320
10321   result->set_value(*script);
10322
10323   // Create a new weak global handle and use it to cache the wrapper
10324   // for future use. The cache will automatically be cleared by the
10325   // garbage collector when it is not used anymore.
10326   Handle<Object> handle = isolate->global_handles()->Create(*result);
10327   GlobalHandles::MakeWeak(handle.location(),
10328                           reinterpret_cast<void*>(handle.location()),
10329                           &ClearWrapperCacheWeakCallback);
10330   script->wrapper()->set_foreign_address(
10331       reinterpret_cast<Address>(handle.location()));
10332   return result;
10333 }
10334
10335
10336 String* SharedFunctionInfo::DebugName() {
10337   Object* n = name();
10338   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
10339   return String::cast(n);
10340 }
10341
10342
10343 bool SharedFunctionInfo::HasSourceCode() const {
10344   return !script()->IsUndefined() &&
10345          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
10346 }
10347
10348
10349 Handle<Object> SharedFunctionInfo::GetSourceCode() {
10350   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
10351   Handle<String> source(String::cast(Script::cast(script())->source()));
10352   return GetIsolate()->factory()->NewSubString(
10353       source, start_position(), end_position());
10354 }
10355
10356
10357 bool SharedFunctionInfo::IsInlineable() {
10358   // Check that the function has a script associated with it.
10359   if (!script()->IsScript()) return false;
10360   if (optimization_disabled()) return false;
10361   // If we never ran this (unlikely) then lets try to optimize it.
10362   if (code()->kind() != Code::FUNCTION) return true;
10363   return code()->optimizable();
10364 }
10365
10366
10367 int SharedFunctionInfo::SourceSize() {
10368   return end_position() - start_position();
10369 }
10370
10371
10372 int SharedFunctionInfo::CalculateInstanceSize() {
10373   int instance_size =
10374       JSObject::kHeaderSize +
10375       expected_nof_properties() * kPointerSize;
10376   if (instance_size > JSObject::kMaxInstanceSize) {
10377     instance_size = JSObject::kMaxInstanceSize;
10378   }
10379   return instance_size;
10380 }
10381
10382
10383 int SharedFunctionInfo::CalculateInObjectProperties() {
10384   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
10385 }
10386
10387
10388 // Output the source code without any allocation in the heap.
10389 OStream& operator<<(OStream& os, const SourceCodeOf& v) {
10390   const SharedFunctionInfo* s = v.value;
10391   // For some native functions there is no source.
10392   if (!s->HasSourceCode()) return os << "<No Source>";
10393
10394   // Get the source for the script which this function came from.
10395   // Don't use String::cast because we don't want more assertion errors while
10396   // we are already creating a stack dump.
10397   String* script_source =
10398       reinterpret_cast<String*>(Script::cast(s->script())->source());
10399
10400   if (!script_source->LooksValid()) return os << "<Invalid Source>";
10401
10402   if (!s->is_toplevel()) {
10403     os << "function ";
10404     Object* name = s->name();
10405     if (name->IsString() && String::cast(name)->length() > 0) {
10406       String::cast(name)->PrintUC16(os);
10407     }
10408   }
10409
10410   int len = s->end_position() - s->start_position();
10411   if (len <= v.max_length || v.max_length < 0) {
10412     script_source->PrintUC16(os, s->start_position(), s->end_position());
10413     return os;
10414   } else {
10415     script_source->PrintUC16(os, s->start_position(),
10416                              s->start_position() + v.max_length);
10417     return os << "...\n";
10418   }
10419 }
10420
10421
10422 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
10423   if (code->instruction_size() != recompiled->instruction_size()) return false;
10424   ByteArray* code_relocation = code->relocation_info();
10425   ByteArray* recompiled_relocation = recompiled->relocation_info();
10426   int length = code_relocation->length();
10427   if (length != recompiled_relocation->length()) return false;
10428   int compare = memcmp(code_relocation->GetDataStartAddress(),
10429                        recompiled_relocation->GetDataStartAddress(),
10430                        length);
10431   return compare == 0;
10432 }
10433
10434
10435 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
10436   DCHECK(!has_deoptimization_support());
10437   DisallowHeapAllocation no_allocation;
10438   Code* code = this->code();
10439   if (IsCodeEquivalent(code, recompiled)) {
10440     // Copy the deoptimization data from the recompiled code.
10441     code->set_deoptimization_data(recompiled->deoptimization_data());
10442     code->set_has_deoptimization_support(true);
10443   } else {
10444     // TODO(3025757): In case the recompiled isn't equivalent to the
10445     // old code, we have to replace it. We should try to avoid this
10446     // altogether because it flushes valuable type feedback by
10447     // effectively resetting all IC state.
10448     ReplaceCode(recompiled);
10449   }
10450   DCHECK(has_deoptimization_support());
10451 }
10452
10453
10454 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
10455   // Disable optimization for the shared function info and mark the
10456   // code as non-optimizable. The marker on the shared function info
10457   // is there because we flush non-optimized code thereby loosing the
10458   // non-optimizable information for the code. When the code is
10459   // regenerated and set on the shared function info it is marked as
10460   // non-optimizable if optimization is disabled for the shared
10461   // function info.
10462   set_optimization_disabled(true);
10463   set_bailout_reason(reason);
10464   // Code should be the lazy compilation stub or else unoptimized.  If the
10465   // latter, disable optimization for the code too.
10466   DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
10467   if (code()->kind() == Code::FUNCTION) {
10468     code()->set_optimizable(false);
10469   }
10470   PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
10471   if (FLAG_trace_opt) {
10472     PrintF("[disabled optimization for ");
10473     ShortPrint();
10474     PrintF(", reason: %s]\n", GetBailoutReason(reason));
10475   }
10476 }
10477
10478
10479 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
10480   DCHECK(!id.IsNone());
10481   Code* unoptimized = code();
10482   DeoptimizationOutputData* data =
10483       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
10484   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
10485   USE(ignore);
10486   return true;  // Return true if there was no DCHECK.
10487 }
10488
10489
10490 void JSFunction::StartInobjectSlackTracking() {
10491   DCHECK(has_initial_map() && !IsInobjectSlackTrackingInProgress());
10492
10493   if (!FLAG_clever_optimizations) return;
10494   Map* map = initial_map();
10495
10496   // Only initiate the tracking the first time.
10497   if (map->done_inobject_slack_tracking()) return;
10498   map->set_done_inobject_slack_tracking(true);
10499
10500   // No tracking during the snapshot construction phase.
10501   Isolate* isolate = GetIsolate();
10502   if (isolate->serializer_enabled()) return;
10503
10504   if (map->unused_property_fields() == 0) return;
10505
10506   map->set_construction_count(kGenerousAllocationCount);
10507 }
10508
10509
10510 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
10511   code()->ClearInlineCaches();
10512   // If we clear ICs, we need to clear the type feedback vector too, since
10513   // CallICs are synced with a feedback vector slot.
10514   ClearTypeFeedbackInfo();
10515   set_ic_age(new_ic_age);
10516   if (code()->kind() == Code::FUNCTION) {
10517     code()->set_profiler_ticks(0);
10518     if (optimization_disabled() &&
10519         opt_count() >= FLAG_max_opt_count) {
10520       // Re-enable optimizations if they were disabled due to opt_count limit.
10521       set_optimization_disabled(false);
10522       code()->set_optimizable(true);
10523     }
10524     set_opt_count(0);
10525     set_deopt_count(0);
10526   }
10527 }
10528
10529
10530 static void GetMinInobjectSlack(Map* map, void* data) {
10531   int slack = map->unused_property_fields();
10532   if (*reinterpret_cast<int*>(data) > slack) {
10533     *reinterpret_cast<int*>(data) = slack;
10534   }
10535 }
10536
10537
10538 static void ShrinkInstanceSize(Map* map, void* data) {
10539   int slack = *reinterpret_cast<int*>(data);
10540   map->set_inobject_properties(map->inobject_properties() - slack);
10541   map->set_unused_property_fields(map->unused_property_fields() - slack);
10542   map->set_instance_size(map->instance_size() - slack * kPointerSize);
10543
10544   // Visitor id might depend on the instance size, recalculate it.
10545   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
10546 }
10547
10548
10549 void JSFunction::CompleteInobjectSlackTracking() {
10550   DCHECK(has_initial_map());
10551   Map* map = initial_map();
10552
10553   DCHECK(map->done_inobject_slack_tracking());
10554   map->set_construction_count(kNoSlackTracking);
10555
10556   int slack = map->unused_property_fields();
10557   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
10558   if (slack != 0) {
10559     // Resize the initial map and all maps in its transition tree.
10560     map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
10561   }
10562 }
10563
10564
10565 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
10566                                                BailoutId osr_ast_id) {
10567   DisallowHeapAllocation no_gc;
10568   DCHECK(native_context->IsNativeContext());
10569   if (!FLAG_cache_optimized_code) return -1;
10570   Object* value = optimized_code_map();
10571   if (!value->IsSmi()) {
10572     FixedArray* optimized_code_map = FixedArray::cast(value);
10573     int length = optimized_code_map->length();
10574     Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
10575     for (int i = kEntriesStart; i < length; i += kEntryLength) {
10576       if (optimized_code_map->get(i + kContextOffset) == native_context &&
10577           optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
10578         return i + kCachedCodeOffset;
10579       }
10580     }
10581     if (FLAG_trace_opt) {
10582       PrintF("[didn't find optimized code in optimized code map for ");
10583       ShortPrint();
10584       PrintF("]\n");
10585     }
10586   }
10587   return -1;
10588 }
10589
10590
10591 #define DECLARE_TAG(ignore1, name, ignore2) name,
10592 const char* const VisitorSynchronization::kTags[
10593     VisitorSynchronization::kNumberOfSyncTags] = {
10594   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10595 };
10596 #undef DECLARE_TAG
10597
10598
10599 #define DECLARE_TAG(ignore1, ignore2, name) name,
10600 const char* const VisitorSynchronization::kTagNames[
10601     VisitorSynchronization::kNumberOfSyncTags] = {
10602   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10603 };
10604 #undef DECLARE_TAG
10605
10606
10607 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10608   DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
10609   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10610   Object* old_target = target;
10611   VisitPointer(&target);
10612   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10613 }
10614
10615
10616 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10617   DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10618   Object* stub = rinfo->code_age_stub();
10619   if (stub) {
10620     VisitPointer(&stub);
10621   }
10622 }
10623
10624
10625 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10626   Object* code = Code::GetObjectFromEntryAddress(entry_address);
10627   Object* old_code = code;
10628   VisitPointer(&code);
10629   if (code != old_code) {
10630     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10631   }
10632 }
10633
10634
10635 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10636   DCHECK(rinfo->rmode() == RelocInfo::CELL);
10637   Object* cell = rinfo->target_cell();
10638   Object* old_cell = cell;
10639   VisitPointer(&cell);
10640   if (cell != old_cell) {
10641     rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10642   }
10643 }
10644
10645
10646 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10647   DCHECK((RelocInfo::IsJSReturn(rinfo->rmode()) &&
10648           rinfo->IsPatchedReturnSequence()) ||
10649          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10650           rinfo->IsPatchedDebugBreakSlotSequence()));
10651   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
10652   Object* old_target = target;
10653   VisitPointer(&target);
10654   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10655 }
10656
10657
10658 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10659   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10660   Object* p = rinfo->target_object();
10661   VisitPointer(&p);
10662 }
10663
10664
10665 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10666   Address p = rinfo->target_reference();
10667   VisitExternalReference(&p);
10668 }
10669
10670
10671 void Code::InvalidateRelocation() {
10672   InvalidateEmbeddedObjects();
10673   set_relocation_info(GetHeap()->empty_byte_array());
10674 }
10675
10676
10677 void Code::InvalidateEmbeddedObjects() {
10678   Object* undefined = GetHeap()->undefined_value();
10679   Cell* undefined_cell = GetHeap()->undefined_cell();
10680   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10681                   RelocInfo::ModeMask(RelocInfo::CELL);
10682   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10683     RelocInfo::Mode mode = it.rinfo()->rmode();
10684     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10685       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10686     } else if (mode == RelocInfo::CELL) {
10687       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10688     }
10689   }
10690 }
10691
10692
10693 void Code::Relocate(intptr_t delta) {
10694   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10695     it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10696   }
10697   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10698 }
10699
10700
10701 void Code::CopyFrom(const CodeDesc& desc) {
10702   DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT);
10703
10704   // copy code
10705   CopyBytes(instruction_start(), desc.buffer,
10706             static_cast<size_t>(desc.instr_size));
10707
10708   // copy reloc info
10709   CopyBytes(relocation_start(),
10710             desc.buffer + desc.buffer_size - desc.reloc_size,
10711             static_cast<size_t>(desc.reloc_size));
10712
10713   // unbox handles and relocate
10714   intptr_t delta = instruction_start() - desc.buffer;
10715   int mode_mask = RelocInfo::kCodeTargetMask |
10716                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10717                   RelocInfo::ModeMask(RelocInfo::CELL) |
10718                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
10719                   RelocInfo::kApplyMask;
10720   // Needed to find target_object and runtime_entry on X64
10721   Assembler* origin = desc.origin;
10722   AllowDeferredHandleDereference embedding_raw_address;
10723   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10724     RelocInfo::Mode mode = it.rinfo()->rmode();
10725     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10726       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10727       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10728     } else if (mode == RelocInfo::CELL) {
10729       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
10730       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10731     } else if (RelocInfo::IsCodeTarget(mode)) {
10732       // rewrite code handles in inline cache targets to direct
10733       // pointers to the first instruction in the code object
10734       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10735       Code* code = Code::cast(*p);
10736       it.rinfo()->set_target_address(code->instruction_start(),
10737                                      SKIP_WRITE_BARRIER,
10738                                      SKIP_ICACHE_FLUSH);
10739     } else if (RelocInfo::IsRuntimeEntry(mode)) {
10740       Address p = it.rinfo()->target_runtime_entry(origin);
10741       it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
10742                                            SKIP_ICACHE_FLUSH);
10743     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10744       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10745       Code* code = Code::cast(*p);
10746       it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
10747     } else {
10748       it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10749     }
10750   }
10751   CpuFeatures::FlushICache(instruction_start(), instruction_size());
10752 }
10753
10754
10755 // Locate the source position which is closest to the address in the code. This
10756 // is using the source position information embedded in the relocation info.
10757 // The position returned is relative to the beginning of the script where the
10758 // source for this function is found.
10759 int Code::SourcePosition(Address pc) {
10760   int distance = kMaxInt;
10761   int position = RelocInfo::kNoPosition;  // Initially no position found.
10762   // Run through all the relocation info to find the best matching source
10763   // position. All the code needs to be considered as the sequence of the
10764   // instructions in the code does not necessarily follow the same order as the
10765   // source.
10766   RelocIterator it(this, RelocInfo::kPositionMask);
10767   while (!it.done()) {
10768     // Only look at positions after the current pc.
10769     if (it.rinfo()->pc() < pc) {
10770       // Get position and distance.
10771
10772       int dist = static_cast<int>(pc - it.rinfo()->pc());
10773       int pos = static_cast<int>(it.rinfo()->data());
10774       // If this position is closer than the current candidate or if it has the
10775       // same distance as the current candidate and the position is higher then
10776       // this position is the new candidate.
10777       if ((dist < distance) ||
10778           (dist == distance && pos > position)) {
10779         position = pos;
10780         distance = dist;
10781       }
10782     }
10783     it.next();
10784   }
10785   return position;
10786 }
10787
10788
10789 // Same as Code::SourcePosition above except it only looks for statement
10790 // positions.
10791 int Code::SourceStatementPosition(Address pc) {
10792   // First find the position as close as possible using all position
10793   // information.
10794   int position = SourcePosition(pc);
10795   // Now find the closest statement position before the position.
10796   int statement_position = 0;
10797   RelocIterator it(this, RelocInfo::kPositionMask);
10798   while (!it.done()) {
10799     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
10800       int p = static_cast<int>(it.rinfo()->data());
10801       if (statement_position < p && p <= position) {
10802         statement_position = p;
10803       }
10804     }
10805     it.next();
10806   }
10807   return statement_position;
10808 }
10809
10810
10811 SafepointEntry Code::GetSafepointEntry(Address pc) {
10812   SafepointTable table(this);
10813   SafepointEntry entry = table.FindEntry(pc);
10814   if (entry.is_valid() || !is_turbofanned()) {
10815     return entry;
10816   }
10817
10818   // If the code is turbofanned, we might be looking for
10819   // an address that was patched by lazy deoptimization.
10820   // In that case look through the patch table, try to
10821   // lookup the original address there, and then use this
10822   // to find the safepoint entry.
10823   DeoptimizationInputData* deopt_data =
10824       DeoptimizationInputData::cast(deoptimization_data());
10825   intptr_t offset = pc - instruction_start();
10826   for (int i = 0; i < deopt_data->ReturnAddressPatchCount(); i++) {
10827     if (deopt_data->PatchedAddressPc(i)->value() == offset) {
10828       int original_offset = deopt_data->ReturnAddressPc(i)->value();
10829       return table.FindEntry(instruction_start() + original_offset);
10830     }
10831   }
10832   return SafepointEntry();
10833 }
10834
10835
10836 Object* Code::FindNthObject(int n, Map* match_map) {
10837   DCHECK(is_inline_cache_stub());
10838   DisallowHeapAllocation no_allocation;
10839   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10840   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10841     RelocInfo* info = it.rinfo();
10842     Object* object = info->target_object();
10843     if (object->IsHeapObject()) {
10844       if (HeapObject::cast(object)->map() == match_map) {
10845         if (--n == 0) return object;
10846       }
10847     }
10848   }
10849   return NULL;
10850 }
10851
10852
10853 AllocationSite* Code::FindFirstAllocationSite() {
10854   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
10855   return (result != NULL) ? AllocationSite::cast(result) : NULL;
10856 }
10857
10858
10859 Map* Code::FindFirstMap() {
10860   Object* result = FindNthObject(1, GetHeap()->meta_map());
10861   return (result != NULL) ? Map::cast(result) : NULL;
10862 }
10863
10864
10865 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
10866   DCHECK(is_inline_cache_stub() || is_handler());
10867   DisallowHeapAllocation no_allocation;
10868   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10869   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
10870   int current_pattern = 0;
10871   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10872     RelocInfo* info = it.rinfo();
10873     Object* object = info->target_object();
10874     if (object->IsHeapObject()) {
10875       Map* map = HeapObject::cast(object)->map();
10876       if (map == *pattern.find_[current_pattern]) {
10877         info->set_target_object(*pattern.replace_[current_pattern]);
10878         if (++current_pattern == pattern.count_) return;
10879       }
10880     }
10881   }
10882   UNREACHABLE();
10883 }
10884
10885
10886 void Code::FindAllMaps(MapHandleList* maps) {
10887   DCHECK(is_inline_cache_stub());
10888   DisallowHeapAllocation no_allocation;
10889   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10890   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10891     RelocInfo* info = it.rinfo();
10892     Object* object = info->target_object();
10893     if (object->IsMap()) maps->Add(handle(Map::cast(object)));
10894   }
10895 }
10896
10897
10898 Code* Code::FindFirstHandler() {
10899   DCHECK(is_inline_cache_stub());
10900   DisallowHeapAllocation no_allocation;
10901   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
10902   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10903     RelocInfo* info = it.rinfo();
10904     Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10905     if (code->kind() == Code::HANDLER) return code;
10906   }
10907   return NULL;
10908 }
10909
10910
10911 bool Code::FindHandlers(CodeHandleList* code_list, int length) {
10912   DCHECK(is_inline_cache_stub());
10913   DisallowHeapAllocation no_allocation;
10914   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
10915   int i = 0;
10916   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10917     if (i == length) return true;
10918     RelocInfo* info = it.rinfo();
10919     Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10920     // IC stubs with handlers never contain non-handler code objects before
10921     // handler targets.
10922     if (code->kind() != Code::HANDLER) break;
10923     code_list->Add(Handle<Code>(code));
10924     i++;
10925   }
10926   return i == length;
10927 }
10928
10929
10930 MaybeHandle<Code> Code::FindHandlerForMap(Map* map) {
10931   DCHECK(is_inline_cache_stub());
10932   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10933              RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10934   bool return_next = false;
10935   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10936     RelocInfo* info = it.rinfo();
10937     if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10938       Object* object = info->target_object();
10939       if (object == map) return_next = true;
10940     } else if (return_next) {
10941       Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10942       DCHECK(code->kind() == Code::HANDLER);
10943       return handle(code);
10944     }
10945   }
10946   return MaybeHandle<Code>();
10947 }
10948
10949
10950 Name* Code::FindFirstName() {
10951   DCHECK(is_inline_cache_stub());
10952   DisallowHeapAllocation no_allocation;
10953   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10954   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10955     RelocInfo* info = it.rinfo();
10956     Object* object = info->target_object();
10957     if (object->IsName()) return Name::cast(object);
10958   }
10959   return NULL;
10960 }
10961
10962
10963 void Code::ClearInlineCaches() {
10964   ClearInlineCaches(NULL);
10965 }
10966
10967
10968 void Code::ClearInlineCaches(Code::Kind kind) {
10969   ClearInlineCaches(&kind);
10970 }
10971
10972
10973 void Code::ClearInlineCaches(Code::Kind* kind) {
10974   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10975              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
10976              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
10977   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10978     RelocInfo* info = it.rinfo();
10979     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10980     if (target->is_inline_cache_stub()) {
10981       if (kind == NULL || *kind == target->kind()) {
10982         IC::Clear(this->GetIsolate(), info->pc(),
10983                   info->host()->constant_pool());
10984       }
10985     }
10986   }
10987 }
10988
10989
10990 void SharedFunctionInfo::ClearTypeFeedbackInfo() {
10991   FixedArray* vector = feedback_vector();
10992   Heap* heap = GetHeap();
10993   int length = vector->length();
10994
10995   for (int i = 0; i < length; i++) {
10996     Object* obj = vector->get(i);
10997     if (obj->IsHeapObject()) {
10998       InstanceType instance_type =
10999           HeapObject::cast(obj)->map()->instance_type();
11000       switch (instance_type) {
11001         case ALLOCATION_SITE_TYPE:
11002           // AllocationSites are not cleared because they do not store
11003           // information that leaks.
11004           break;
11005           // Fall through...
11006         default:
11007           vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap),
11008                       SKIP_WRITE_BARRIER);
11009       }
11010     }
11011   }
11012 }
11013
11014
11015 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
11016   DisallowHeapAllocation no_gc;
11017   DCHECK(kind() == FUNCTION);
11018   BackEdgeTable back_edges(this, &no_gc);
11019   for (uint32_t i = 0; i < back_edges.length(); i++) {
11020     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
11021   }
11022   return BailoutId::None();
11023 }
11024
11025
11026 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
11027   DisallowHeapAllocation no_gc;
11028   DCHECK(kind() == FUNCTION);
11029   BackEdgeTable back_edges(this, &no_gc);
11030   for (uint32_t i = 0; i < back_edges.length(); i++) {
11031     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
11032   }
11033   UNREACHABLE();  // We expect to find the back edge.
11034   return 0;
11035 }
11036
11037
11038 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
11039   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
11040 }
11041
11042
11043 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
11044   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
11045       NO_MARKING_PARITY);
11046 }
11047
11048
11049 static Code::Age EffectiveAge(Code::Age age) {
11050   if (age == Code::kNotExecutedCodeAge) {
11051     // Treat that's never been executed as old immediately.
11052     age = Code::kIsOldCodeAge;
11053   } else if (age == Code::kExecutedOnceCodeAge) {
11054     // Pre-age code that has only been executed once.
11055     age = Code::kPreAgedCodeAge;
11056   }
11057   return age;
11058 }
11059
11060
11061 void Code::MakeOlder(MarkingParity current_parity) {
11062   byte* sequence = FindCodeAgeSequence();
11063   if (sequence != NULL) {
11064     Age age;
11065     MarkingParity code_parity;
11066     Isolate* isolate = GetIsolate();
11067     GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
11068     age = EffectiveAge(age);
11069     if (age != kLastCodeAge && code_parity != current_parity) {
11070       PatchPlatformCodeAge(isolate,
11071                            sequence,
11072                            static_cast<Age>(age + 1),
11073                            current_parity);
11074     }
11075   }
11076 }
11077
11078
11079 bool Code::IsOld() {
11080   return GetAge() >= kIsOldCodeAge;
11081 }
11082
11083
11084 byte* Code::FindCodeAgeSequence() {
11085   return FLAG_age_code &&
11086       prologue_offset() != Code::kPrologueOffsetNotSet &&
11087       (kind() == OPTIMIZED_FUNCTION ||
11088        (kind() == FUNCTION && !has_debug_break_slots()))
11089       ? instruction_start() + prologue_offset()
11090       : NULL;
11091 }
11092
11093
11094 Code::Age Code::GetAge() {
11095   return EffectiveAge(GetRawAge());
11096 }
11097
11098
11099 Code::Age Code::GetRawAge() {
11100   byte* sequence = FindCodeAgeSequence();
11101   if (sequence == NULL) {
11102     return kNoAgeCodeAge;
11103   }
11104   Age age;
11105   MarkingParity parity;
11106   GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
11107   return age;
11108 }
11109
11110
11111 void Code::GetCodeAgeAndParity(Code* code, Age* age,
11112                                MarkingParity* parity) {
11113   Isolate* isolate = code->GetIsolate();
11114   Builtins* builtins = isolate->builtins();
11115   Code* stub = NULL;
11116 #define HANDLE_CODE_AGE(AGE)                                            \
11117   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
11118   if (code == stub) {                                                   \
11119     *age = k##AGE##CodeAge;                                             \
11120     *parity = EVEN_MARKING_PARITY;                                      \
11121     return;                                                             \
11122   }                                                                     \
11123   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
11124   if (code == stub) {                                                   \
11125     *age = k##AGE##CodeAge;                                             \
11126     *parity = ODD_MARKING_PARITY;                                       \
11127     return;                                                             \
11128   }
11129   CODE_AGE_LIST(HANDLE_CODE_AGE)
11130 #undef HANDLE_CODE_AGE
11131   stub = *builtins->MarkCodeAsExecutedOnce();
11132   if (code == stub) {
11133     *age = kNotExecutedCodeAge;
11134     *parity = NO_MARKING_PARITY;
11135     return;
11136   }
11137   stub = *builtins->MarkCodeAsExecutedTwice();
11138   if (code == stub) {
11139     *age = kExecutedOnceCodeAge;
11140     *parity = NO_MARKING_PARITY;
11141     return;
11142   }
11143   UNREACHABLE();
11144 }
11145
11146
11147 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
11148   Builtins* builtins = isolate->builtins();
11149   switch (age) {
11150 #define HANDLE_CODE_AGE(AGE)                                            \
11151     case k##AGE##CodeAge: {                                             \
11152       Code* stub = parity == EVEN_MARKING_PARITY                        \
11153           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
11154           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
11155       return stub;                                                      \
11156     }
11157     CODE_AGE_LIST(HANDLE_CODE_AGE)
11158 #undef HANDLE_CODE_AGE
11159     case kNotExecutedCodeAge: {
11160       DCHECK(parity == NO_MARKING_PARITY);
11161       return *builtins->MarkCodeAsExecutedOnce();
11162     }
11163     case kExecutedOnceCodeAge: {
11164       DCHECK(parity == NO_MARKING_PARITY);
11165       return *builtins->MarkCodeAsExecutedTwice();
11166     }
11167     default:
11168       UNREACHABLE();
11169       break;
11170   }
11171   return NULL;
11172 }
11173
11174
11175 void Code::PrintDeoptLocation(FILE* out, int bailout_id) {
11176   const char* last_comment = NULL;
11177   int mask = RelocInfo::ModeMask(RelocInfo::COMMENT)
11178       | RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
11179   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11180     RelocInfo* info = it.rinfo();
11181     if (info->rmode() == RelocInfo::COMMENT) {
11182       last_comment = reinterpret_cast<const char*>(info->data());
11183     } else if (last_comment != NULL) {
11184       if ((bailout_id == Deoptimizer::GetDeoptimizationId(
11185               GetIsolate(), info->target_address(), Deoptimizer::EAGER)) ||
11186           (bailout_id == Deoptimizer::GetDeoptimizationId(
11187               GetIsolate(), info->target_address(), Deoptimizer::SOFT)) ||
11188           (bailout_id == Deoptimizer::GetDeoptimizationId(
11189               GetIsolate(), info->target_address(), Deoptimizer::LAZY))) {
11190         CHECK(RelocInfo::IsRuntimeEntry(info->rmode()));
11191         PrintF(out, "            %s\n", last_comment);
11192         return;
11193       }
11194     }
11195   }
11196 }
11197
11198
11199 bool Code::CanDeoptAt(Address pc) {
11200   DeoptimizationInputData* deopt_data =
11201       DeoptimizationInputData::cast(deoptimization_data());
11202   Address code_start_address = instruction_start();
11203   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
11204     if (deopt_data->Pc(i)->value() == -1) continue;
11205     Address address = code_start_address + deopt_data->Pc(i)->value();
11206     if (address == pc) return true;
11207   }
11208   return false;
11209 }
11210
11211
11212 // Identify kind of code.
11213 const char* Code::Kind2String(Kind kind) {
11214   switch (kind) {
11215 #define CASE(name) case name: return #name;
11216     CODE_KIND_LIST(CASE)
11217 #undef CASE
11218     case NUMBER_OF_KINDS: break;
11219   }
11220   UNREACHABLE();
11221   return NULL;
11222 }
11223
11224
11225 #ifdef ENABLE_DISASSEMBLER
11226
11227 void DeoptimizationInputData::DeoptimizationInputDataPrint(
11228     OStream& os) {  // NOLINT
11229   disasm::NameConverter converter;
11230   int deopt_count = DeoptCount();
11231   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
11232   if (0 != deopt_count) {
11233     os << " index  ast id    argc     pc";
11234     if (FLAG_print_code_verbose) os << "  commands";
11235     os << "\n";
11236   }
11237   for (int i = 0; i < deopt_count; i++) {
11238     // TODO(svenpanne) Add some basic formatting to our streams.
11239     Vector<char> buf1 = Vector<char>::New(128);
11240     SNPrintF(buf1, "%6d  %6d  %6d %6d", i, AstId(i).ToInt(),
11241              ArgumentsStackHeight(i)->value(), Pc(i)->value());
11242     os << buf1.start();
11243
11244     if (!FLAG_print_code_verbose) {
11245       os << "\n";
11246       continue;
11247     }
11248     // Print details of the frame translation.
11249     int translation_index = TranslationIndex(i)->value();
11250     TranslationIterator iterator(TranslationByteArray(), translation_index);
11251     Translation::Opcode opcode =
11252         static_cast<Translation::Opcode>(iterator.Next());
11253     DCHECK(Translation::BEGIN == opcode);
11254     int frame_count = iterator.Next();
11255     int jsframe_count = iterator.Next();
11256     os << "  " << Translation::StringFor(opcode)
11257        << " {frame count=" << frame_count
11258        << ", js frame count=" << jsframe_count << "}\n";
11259
11260     while (iterator.HasNext() &&
11261            Translation::BEGIN !=
11262            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
11263       Vector<char> buf2 = Vector<char>::New(128);
11264       SNPrintF(buf2, "%27s    %s ", "", Translation::StringFor(opcode));
11265       os << buf2.start();
11266
11267       switch (opcode) {
11268         case Translation::BEGIN:
11269           UNREACHABLE();
11270           break;
11271
11272         case Translation::JS_FRAME: {
11273           int ast_id = iterator.Next();
11274           int function_id = iterator.Next();
11275           unsigned height = iterator.Next();
11276           os << "{ast_id=" << ast_id << ", function=";
11277           if (function_id != Translation::kSelfLiteralId) {
11278             Object* function = LiteralArray()->get(function_id);
11279             os << Brief(JSFunction::cast(function)->shared()->DebugName());
11280           } else {
11281             os << "<self>";
11282           }
11283           os << ", height=" << height << "}";
11284           break;
11285         }
11286
11287         case Translation::COMPILED_STUB_FRAME: {
11288           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
11289           os << "{kind=" << stub_kind << "}";
11290           break;
11291         }
11292
11293         case Translation::ARGUMENTS_ADAPTOR_FRAME:
11294         case Translation::CONSTRUCT_STUB_FRAME: {
11295           int function_id = iterator.Next();
11296           JSFunction* function =
11297               JSFunction::cast(LiteralArray()->get(function_id));
11298           unsigned height = iterator.Next();
11299           os << "{function=" << Brief(function->shared()->DebugName())
11300              << ", height=" << height << "}";
11301           break;
11302         }
11303
11304         case Translation::GETTER_STUB_FRAME:
11305         case Translation::SETTER_STUB_FRAME: {
11306           int function_id = iterator.Next();
11307           JSFunction* function =
11308               JSFunction::cast(LiteralArray()->get(function_id));
11309           os << "{function=" << Brief(function->shared()->DebugName()) << "}";
11310           break;
11311         }
11312
11313         case Translation::REGISTER: {
11314           int reg_code = iterator.Next();
11315           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11316           break;
11317         }
11318
11319         case Translation::INT32_REGISTER: {
11320           int reg_code = iterator.Next();
11321           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
11322           break;
11323         }
11324
11325         case Translation::UINT32_REGISTER: {
11326           int reg_code = iterator.Next();
11327           os << "{input=" << converter.NameOfCPURegister(reg_code)
11328              << " (unsigned)}";
11329           break;
11330         }
11331
11332         case Translation::DOUBLE_REGISTER: {
11333           int reg_code = iterator.Next();
11334           os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
11335              << "}";
11336           break;
11337         }
11338
11339         case Translation::FLOAT32x4_REGISTER: {
11340           int reg_code = iterator.Next();
11341           os << "{input=" << SIMD128Register::AllocationIndexToString(reg_code)
11342              << "}";
11343           break;
11344         }
11345
11346         case Translation::FLOAT64x2_REGISTER: {
11347           int reg_code = iterator.Next();
11348           os << "{input=" << SIMD128Register::AllocationIndexToString(reg_code)
11349              << "}";
11350           break;
11351         }
11352
11353         case Translation::INT32x4_REGISTER: {
11354           int reg_code = iterator.Next();
11355           os << "{input=" << SIMD128Register::AllocationIndexToString(reg_code)
11356              << "}";
11357           break;
11358         }
11359
11360         case Translation::STACK_SLOT: {
11361           int input_slot_index = iterator.Next();
11362           os << "{input=" << input_slot_index << "}";
11363           break;
11364         }
11365
11366         case Translation::INT32_STACK_SLOT: {
11367           int input_slot_index = iterator.Next();
11368           os << "{input=" << input_slot_index << "}";
11369           break;
11370         }
11371
11372         case Translation::UINT32_STACK_SLOT: {
11373           int input_slot_index = iterator.Next();
11374           os << "{input=" << input_slot_index << " (unsigned)}";
11375           break;
11376         }
11377
11378         case Translation::DOUBLE_STACK_SLOT: {
11379           int input_slot_index = iterator.Next();
11380           os << "{input=" << input_slot_index << "}";
11381           break;
11382         }
11383
11384         case Translation::FLOAT32x4_STACK_SLOT: {
11385           int input_slot_index = iterator.Next();
11386           os << "{input=" << input_slot_index << "}";
11387           break;
11388         }
11389
11390         case Translation::FLOAT64x2_STACK_SLOT: {
11391           int input_slot_index = iterator.Next();
11392           os << "{input=" << input_slot_index << "}";
11393           break;
11394         }
11395
11396         case Translation::INT32x4_STACK_SLOT: {
11397           int input_slot_index = iterator.Next();
11398           os << "{input=" << input_slot_index << "}";
11399           break;
11400         }
11401
11402         case Translation::LITERAL: {
11403           unsigned literal_index = iterator.Next();
11404           os << "{literal_id=" << literal_index << "}";
11405           break;
11406         }
11407
11408         case Translation::DUPLICATED_OBJECT: {
11409           int object_index = iterator.Next();
11410           os << "{object_index=" << object_index << "}";
11411           break;
11412         }
11413
11414         case Translation::ARGUMENTS_OBJECT:
11415         case Translation::CAPTURED_OBJECT: {
11416           int args_length = iterator.Next();
11417           os << "{length=" << args_length << "}";
11418           break;
11419         }
11420       }
11421       os << "\n";
11422     }
11423   }
11424
11425   int return_address_patch_count = ReturnAddressPatchCount();
11426   if (return_address_patch_count != 0) {
11427     os << "Return address patch data (count = " << return_address_patch_count
11428        << ")\n";
11429     os << " index    pc  patched_pc\n";
11430   }
11431   for (int i = 0; i < return_address_patch_count; i++) {
11432     Vector<char> buf = Vector<char>::New(128);
11433     SNPrintF(buf, "%6d  %6d  %12d\n", i, ReturnAddressPc(i)->value(),
11434              PatchedAddressPc(i)->value());
11435     os << buf.start();
11436   }
11437 }
11438
11439
11440 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
11441     OStream& os) {  // NOLINT
11442   os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
11443      << ")\n";
11444   if (this->DeoptPoints() == 0) return;
11445
11446   os << "ast id        pc  state\n";
11447   for (int i = 0; i < this->DeoptPoints(); i++) {
11448     int pc_and_state = this->PcAndState(i)->value();
11449     // TODO(svenpanne) Add some basic formatting to our streams.
11450     Vector<char> buf = Vector<char>::New(100);
11451     SNPrintF(buf, "%6d  %8d  %s\n", this->AstId(i).ToInt(),
11452              FullCodeGenerator::PcField::decode(pc_and_state),
11453              FullCodeGenerator::State2String(
11454                  FullCodeGenerator::StateField::decode(pc_and_state)));
11455     os << buf.start();
11456   }
11457 }
11458
11459
11460 const char* Code::ICState2String(InlineCacheState state) {
11461   switch (state) {
11462     case UNINITIALIZED: return "UNINITIALIZED";
11463     case PREMONOMORPHIC: return "PREMONOMORPHIC";
11464     case MONOMORPHIC: return "MONOMORPHIC";
11465     case PROTOTYPE_FAILURE:
11466       return "PROTOTYPE_FAILURE";
11467     case POLYMORPHIC: return "POLYMORPHIC";
11468     case MEGAMORPHIC: return "MEGAMORPHIC";
11469     case GENERIC: return "GENERIC";
11470     case DEBUG_STUB: return "DEBUG_STUB";
11471     case DEFAULT:
11472       return "DEFAULT";
11473   }
11474   UNREACHABLE();
11475   return NULL;
11476 }
11477
11478
11479 const char* Code::StubType2String(StubType type) {
11480   switch (type) {
11481     case NORMAL: return "NORMAL";
11482     case FAST: return "FAST";
11483   }
11484   UNREACHABLE();  // keep the compiler happy
11485   return NULL;
11486 }
11487
11488
11489 void Code::PrintExtraICState(OStream& os,  // NOLINT
11490                              Kind kind, ExtraICState extra) {
11491   os << "extra_ic_state = ";
11492   if ((kind == STORE_IC || kind == KEYED_STORE_IC) && (extra == STRICT)) {
11493     os << "STRICT\n";
11494   } else {
11495     os << extra << "\n";
11496   }
11497 }
11498
11499
11500 void Code::Disassemble(const char* name, OStream& os) {  // NOLINT
11501   os << "kind = " << Kind2String(kind()) << "\n";
11502   if (IsCodeStubOrIC()) {
11503     const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true);
11504     os << "major_key = " << (n == NULL ? "null" : n) << "\n";
11505   }
11506   if (is_inline_cache_stub()) {
11507     os << "ic_state = " << ICState2String(ic_state()) << "\n";
11508     PrintExtraICState(os, kind(), extra_ic_state());
11509     if (ic_state() == MONOMORPHIC) {
11510       os << "type = " << StubType2String(type()) << "\n";
11511     }
11512     if (is_compare_ic_stub()) {
11513       DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
11514       CompareIC::State left_state, right_state, handler_state;
11515       Token::Value op;
11516       ICCompareStub::DecodeKey(stub_key(), &left_state, &right_state,
11517                                &handler_state, &op);
11518       os << "compare_state = " << CompareIC::GetStateName(left_state) << "*"
11519          << CompareIC::GetStateName(right_state) << " -> "
11520          << CompareIC::GetStateName(handler_state) << "\n";
11521       os << "compare_operation = " << Token::Name(op) << "\n";
11522     }
11523   }
11524   if ((name != NULL) && (name[0] != '\0')) {
11525     os << "name = " << name << "\n";
11526   }
11527   if (kind() == OPTIMIZED_FUNCTION) {
11528     os << "stack_slots = " << stack_slots() << "\n";
11529   }
11530
11531   os << "Instructions (size = " << instruction_size() << ")\n";
11532   // TODO(svenpanne) The Disassembler should use streams, too!
11533   Disassembler::Decode(stdout, this);
11534   os << "\n";
11535
11536   if (kind() == FUNCTION) {
11537     DeoptimizationOutputData* data =
11538         DeoptimizationOutputData::cast(this->deoptimization_data());
11539     data->DeoptimizationOutputDataPrint(os);
11540   } else if (kind() == OPTIMIZED_FUNCTION) {
11541     DeoptimizationInputData* data =
11542         DeoptimizationInputData::cast(this->deoptimization_data());
11543     data->DeoptimizationInputDataPrint(os);
11544   }
11545   os << "\n";
11546
11547   if (is_crankshafted()) {
11548     SafepointTable table(this);
11549     os << "Safepoints (size = " << table.size() << ")\n";
11550     for (unsigned i = 0; i < table.length(); i++) {
11551       unsigned pc_offset = table.GetPcOffset(i);
11552       os << (instruction_start() + pc_offset) << "  ";
11553       // TODO(svenpanne) Add some basic formatting to our streams.
11554       Vector<char> buf1 = Vector<char>::New(30);
11555       SNPrintF(buf1, "%4d", pc_offset);
11556       os << buf1.start() << "  ";
11557       table.PrintEntry(i, os);
11558       os << " (sp -> fp)  ";
11559       SafepointEntry entry = table.GetEntry(i);
11560       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
11561         Vector<char> buf2 = Vector<char>::New(30);
11562         SNPrintF(buf2, "%6d", entry.deoptimization_index());
11563         os << buf2.start();
11564       } else {
11565         os << "<none>";
11566       }
11567       if (entry.argument_count() > 0) {
11568         os << " argc: " << entry.argument_count();
11569       }
11570       os << "\n";
11571     }
11572     os << "\n";
11573   } else if (kind() == FUNCTION) {
11574     unsigned offset = back_edge_table_offset();
11575     // If there is no back edge table, the "table start" will be at or after
11576     // (due to alignment) the end of the instruction stream.
11577     if (static_cast<int>(offset) < instruction_size()) {
11578       DisallowHeapAllocation no_gc;
11579       BackEdgeTable back_edges(this, &no_gc);
11580
11581       os << "Back edges (size = " << back_edges.length() << ")\n";
11582       os << "ast_id  pc_offset  loop_depth\n";
11583
11584       for (uint32_t i = 0; i < back_edges.length(); i++) {
11585         Vector<char> buf = Vector<char>::New(100);
11586         SNPrintF(buf, "%6d  %9u  %10u\n", back_edges.ast_id(i).ToInt(),
11587                  back_edges.pc_offset(i), back_edges.loop_depth(i));
11588         os << buf.start();
11589       }
11590
11591       os << "\n";
11592     }
11593 #ifdef OBJECT_PRINT
11594     if (!type_feedback_info()->IsUndefined()) {
11595       OFStream os(stdout);
11596       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
11597       os << "\n";
11598     }
11599 #endif
11600   }
11601
11602   os << "RelocInfo (size = " << relocation_size() << ")\n";
11603   for (RelocIterator it(this); !it.done(); it.next()) {
11604     it.rinfo()->Print(GetIsolate(), os);
11605   }
11606   os << "\n";
11607 }
11608 #endif  // ENABLE_DISASSEMBLER
11609
11610
11611 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
11612     Handle<JSObject> object,
11613     int capacity,
11614     int length,
11615     SetFastElementsCapacitySmiMode smi_mode) {
11616   // We should never end in here with a pixel or external array.
11617   DCHECK(!object->HasExternalArrayElements());
11618
11619   // Allocate a new fast elements backing store.
11620   Handle<FixedArray> new_elements =
11621       object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
11622
11623   ElementsKind elements_kind = object->GetElementsKind();
11624   ElementsKind new_elements_kind;
11625   // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
11626   // or if it's allowed and the old elements array contained only SMIs.
11627   bool has_fast_smi_elements =
11628       (smi_mode == kForceSmiElements) ||
11629       ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements());
11630   if (has_fast_smi_elements) {
11631     if (IsHoleyElementsKind(elements_kind)) {
11632       new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
11633     } else {
11634       new_elements_kind = FAST_SMI_ELEMENTS;
11635     }
11636   } else {
11637     if (IsHoleyElementsKind(elements_kind)) {
11638       new_elements_kind = FAST_HOLEY_ELEMENTS;
11639     } else {
11640       new_elements_kind = FAST_ELEMENTS;
11641     }
11642   }
11643   Handle<FixedArrayBase> old_elements(object->elements());
11644   ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
11645   accessor->CopyElements(object, new_elements, elements_kind);
11646
11647   if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
11648     Handle<Map> new_map = (new_elements_kind != elements_kind)
11649         ? GetElementsTransitionMap(object, new_elements_kind)
11650         : handle(object->map());
11651     JSObject::ValidateElements(object);
11652     JSObject::SetMapAndElements(object, new_map, new_elements);
11653
11654     // Transition through the allocation site as well if present.
11655     JSObject::UpdateAllocationSite(object, new_elements_kind);
11656   } else {
11657     Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11658     parameter_map->set(1, *new_elements);
11659   }
11660
11661   if (FLAG_trace_elements_transitions) {
11662     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11663                             object->GetElementsKind(), new_elements);
11664   }
11665
11666   if (object->IsJSArray()) {
11667     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11668   }
11669   return new_elements;
11670 }
11671
11672
11673 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object,
11674                                                       int capacity,
11675                                                       int length) {
11676   // We should never end in here with a pixel or external array.
11677   DCHECK(!object->HasExternalArrayElements());
11678
11679   Handle<FixedArrayBase> elems =
11680       object->GetIsolate()->factory()->NewFixedDoubleArray(capacity);
11681
11682   ElementsKind elements_kind = object->GetElementsKind();
11683   CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS);
11684   ElementsKind new_elements_kind = elements_kind;
11685   if (IsHoleyElementsKind(elements_kind)) {
11686     new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
11687   } else {
11688     new_elements_kind = FAST_DOUBLE_ELEMENTS;
11689   }
11690
11691   Handle<Map> new_map = GetElementsTransitionMap(object, new_elements_kind);
11692
11693   Handle<FixedArrayBase> old_elements(object->elements());
11694   ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
11695   accessor->CopyElements(object, elems, elements_kind);
11696
11697   JSObject::ValidateElements(object);
11698   JSObject::SetMapAndElements(object, new_map, elems);
11699
11700   if (FLAG_trace_elements_transitions) {
11701     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11702                             object->GetElementsKind(), elems);
11703   }
11704
11705   if (object->IsJSArray()) {
11706     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11707   }
11708 }
11709
11710
11711 // static
11712 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11713   DCHECK(capacity >= 0);
11714   array->GetIsolate()->factory()->NewJSArrayStorage(
11715       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11716 }
11717
11718
11719 void JSArray::Expand(Handle<JSArray> array, int required_size) {
11720   ElementsAccessor* accessor = array->GetElementsAccessor();
11721   accessor->SetCapacityAndLength(array, required_size, required_size);
11722 }
11723
11724
11725 // Returns false if the passed-in index is marked non-configurable,
11726 // which will cause the ES5 truncation operation to halt, and thus
11727 // no further old values need be collected.
11728 static bool GetOldValue(Isolate* isolate,
11729                         Handle<JSObject> object,
11730                         uint32_t index,
11731                         List<Handle<Object> >* old_values,
11732                         List<uint32_t>* indices) {
11733   Maybe<PropertyAttributes> maybe =
11734       JSReceiver::GetOwnElementAttribute(object, index);
11735   DCHECK(maybe.has_value);
11736   DCHECK(maybe.value != ABSENT);
11737   if (maybe.value == DONT_DELETE) return false;
11738   Handle<Object> value;
11739   if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
11740     value = Handle<Object>::cast(isolate->factory()->the_hole_value());
11741   } else {
11742     value = Object::GetElement(isolate, object, index).ToHandleChecked();
11743   }
11744   old_values->Add(value);
11745   indices->Add(index);
11746   return true;
11747 }
11748
11749 static void EnqueueSpliceRecord(Handle<JSArray> object,
11750                                 uint32_t index,
11751                                 Handle<JSArray> deleted,
11752                                 uint32_t add_count) {
11753   Isolate* isolate = object->GetIsolate();
11754   HandleScope scope(isolate);
11755   Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
11756   Handle<Object> add_count_object =
11757       isolate->factory()->NewNumberFromUint(add_count);
11758
11759   Handle<Object> args[] =
11760       { object, index_object, deleted, add_count_object };
11761
11762   Execution::Call(isolate,
11763                   Handle<JSFunction>(isolate->observers_enqueue_splice()),
11764                   isolate->factory()->undefined_value(),
11765                   ARRAY_SIZE(args),
11766                   args).Assert();
11767 }
11768
11769
11770 static void BeginPerformSplice(Handle<JSArray> object) {
11771   Isolate* isolate = object->GetIsolate();
11772   HandleScope scope(isolate);
11773   Handle<Object> args[] = { object };
11774
11775   Execution::Call(isolate,
11776                   Handle<JSFunction>(isolate->observers_begin_perform_splice()),
11777                   isolate->factory()->undefined_value(),
11778                   ARRAY_SIZE(args),
11779                   args).Assert();
11780 }
11781
11782
11783 static void EndPerformSplice(Handle<JSArray> object) {
11784   Isolate* isolate = object->GetIsolate();
11785   HandleScope scope(isolate);
11786   Handle<Object> args[] = { object };
11787
11788   Execution::Call(isolate,
11789                   Handle<JSFunction>(isolate->observers_end_perform_splice()),
11790                   isolate->factory()->undefined_value(),
11791                   ARRAY_SIZE(args),
11792                   args).Assert();
11793 }
11794
11795
11796 MaybeHandle<Object> JSArray::SetElementsLength(
11797     Handle<JSArray> array,
11798     Handle<Object> new_length_handle) {
11799   if (array->HasFastElements()) {
11800     // If the new array won't fit in a some non-trivial fraction of the max old
11801     // space size, then force it to go dictionary mode.
11802     int max_fast_array_size = static_cast<int>(
11803         (array->GetHeap()->MaxOldGenerationSize() / kDoubleSize) / 4);
11804     if (new_length_handle->IsNumber() &&
11805         NumberToInt32(*new_length_handle) >= max_fast_array_size) {
11806       NormalizeElements(array);
11807     }
11808   }
11809
11810   // We should never end in here with a pixel or external array.
11811   DCHECK(array->AllowsSetElementsLength());
11812   if (!array->map()->is_observed()) {
11813     return array->GetElementsAccessor()->SetLength(array, new_length_handle);
11814   }
11815
11816   Isolate* isolate = array->GetIsolate();
11817   List<uint32_t> indices;
11818   List<Handle<Object> > old_values;
11819   Handle<Object> old_length_handle(array->length(), isolate);
11820   uint32_t old_length = 0;
11821   CHECK(old_length_handle->ToArrayIndex(&old_length));
11822   uint32_t new_length = 0;
11823   CHECK(new_length_handle->ToArrayIndex(&new_length));
11824
11825   static const PropertyAttributes kNoAttrFilter = NONE;
11826   int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
11827   if (num_elements > 0) {
11828     if (old_length == static_cast<uint32_t>(num_elements)) {
11829       // Simple case for arrays without holes.
11830       for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
11831         if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
11832       }
11833     } else {
11834       // For sparse arrays, only iterate over existing elements.
11835       // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
11836       // the to-be-removed indices twice.
11837       Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
11838       array->GetOwnElementKeys(*keys, kNoAttrFilter);
11839       while (num_elements-- > 0) {
11840         uint32_t index = NumberToUint32(keys->get(num_elements));
11841         if (index < new_length) break;
11842         if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
11843       }
11844     }
11845   }
11846
11847   Handle<Object> hresult;
11848   ASSIGN_RETURN_ON_EXCEPTION(
11849       isolate, hresult,
11850       array->GetElementsAccessor()->SetLength(array, new_length_handle),
11851       Object);
11852
11853   CHECK(array->length()->ToArrayIndex(&new_length));
11854   if (old_length == new_length) return hresult;
11855
11856   BeginPerformSplice(array);
11857
11858   for (int i = 0; i < indices.length(); ++i) {
11859     // For deletions where the property was an accessor, old_values[i]
11860     // will be the hole, which instructs EnqueueChangeRecord to elide
11861     // the "oldValue" property.
11862     JSObject::EnqueueChangeRecord(
11863         array, "delete", isolate->factory()->Uint32ToString(indices[i]),
11864         old_values[i]);
11865   }
11866   JSObject::EnqueueChangeRecord(
11867       array, "update", isolate->factory()->length_string(),
11868       old_length_handle);
11869
11870   EndPerformSplice(array);
11871
11872   uint32_t index = Min(old_length, new_length);
11873   uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11874   uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11875   Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11876   if (delete_count > 0) {
11877     for (int i = indices.length() - 1; i >= 0; i--) {
11878       // Skip deletions where the property was an accessor, leaving holes
11879       // in the array of old values.
11880       if (old_values[i]->IsTheHole()) continue;
11881       JSObject::SetElement(
11882           deleted, indices[i] - index, old_values[i], NONE, SLOPPY).Assert();
11883     }
11884
11885     SetProperty(deleted, isolate->factory()->length_string(),
11886                 isolate->factory()->NewNumberFromUint(delete_count),
11887                 STRICT).Assert();
11888   }
11889
11890   EnqueueSpliceRecord(array, index, deleted, add_count);
11891
11892   return hresult;
11893 }
11894
11895
11896 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map,
11897                                         Handle<Object> prototype) {
11898   FixedArray* cache = map->GetPrototypeTransitions();
11899   int number_of_transitions = map->NumberOfProtoTransitions();
11900   const int proto_offset =
11901       kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
11902   const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
11903   const int step = kProtoTransitionElementsPerEntry;
11904   for (int i = 0; i < number_of_transitions; i++) {
11905     if (cache->get(proto_offset + i * step) == *prototype) {
11906       Object* result = cache->get(map_offset + i * step);
11907       return Handle<Map>(Map::cast(result));
11908     }
11909   }
11910   return Handle<Map>();
11911 }
11912
11913
11914 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
11915                                         Handle<Object> prototype,
11916                                         Handle<Map> target_map) {
11917   DCHECK(target_map->IsMap());
11918   DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
11919   // Don't cache prototype transition if this map is either shared, or a map of
11920   // a prototype.
11921   if (map->is_prototype_map()) return map;
11922   if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;
11923
11924   const int step = kProtoTransitionElementsPerEntry;
11925   const int header = kProtoTransitionHeaderSize;
11926
11927   Handle<FixedArray> cache(map->GetPrototypeTransitions());
11928   int capacity = (cache->length() - header) / step;
11929   int transitions = map->NumberOfProtoTransitions() + 1;
11930
11931   if (transitions > capacity) {
11932     if (capacity > kMaxCachedPrototypeTransitions) return map;
11933
11934     // Grow array by factor 2 over and above what we need.
11935     cache = FixedArray::CopySize(cache, transitions * 2 * step + header);
11936
11937     SetPrototypeTransitions(map, cache);
11938   }
11939
11940   // Reload number of transitions as GC might shrink them.
11941   int last = map->NumberOfProtoTransitions();
11942   int entry = header + last * step;
11943
11944   cache->set(entry + kProtoTransitionPrototypeOffset, *prototype);
11945   cache->set(entry + kProtoTransitionMapOffset, *target_map);
11946   map->SetNumberOfProtoTransitions(last + 1);
11947
11948   return map;
11949 }
11950
11951
11952 void Map::ZapTransitions() {
11953   TransitionArray* transition_array = transitions();
11954   // TODO(mstarzinger): Temporarily use a slower version instead of the faster
11955   // MemsetPointer to investigate a crasher. Switch back to MemsetPointer.
11956   Object** data = transition_array->data_start();
11957   Object* the_hole = GetHeap()->the_hole_value();
11958   int length = transition_array->length();
11959   for (int i = 0; i < length; i++) {
11960     data[i] = the_hole;
11961   }
11962 }
11963
11964
11965 void Map::ZapPrototypeTransitions() {
11966   FixedArray* proto_transitions = GetPrototypeTransitions();
11967   MemsetPointer(proto_transitions->data_start(),
11968                 GetHeap()->the_hole_value(),
11969                 proto_transitions->length());
11970 }
11971
11972
11973 // static
11974 void Map::AddDependentCompilationInfo(Handle<Map> map,
11975                                       DependentCode::DependencyGroup group,
11976                                       CompilationInfo* info) {
11977   Handle<DependentCode> codes =
11978       DependentCode::Insert(handle(map->dependent_code(), info->isolate()),
11979                             group, info->object_wrapper());
11980   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11981   info->dependencies(group)->Add(map, info->zone());
11982 }
11983
11984
11985 // static
11986 void Map::AddDependentCode(Handle<Map> map,
11987                            DependentCode::DependencyGroup group,
11988                            Handle<Code> code) {
11989   Handle<DependentCode> codes = DependentCode::Insert(
11990       Handle<DependentCode>(map->dependent_code()), group, code);
11991   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11992 }
11993
11994
11995 // static
11996 void Map::AddDependentIC(Handle<Map> map,
11997                          Handle<Code> stub) {
11998   DCHECK(stub->next_code_link()->IsUndefined());
11999   int n = map->dependent_code()->number_of_entries(DependentCode::kWeakICGroup);
12000   if (n == 0) {
12001     // Slow path: insert the head of the list with possible heap allocation.
12002     Map::AddDependentCode(map, DependentCode::kWeakICGroup, stub);
12003   } else {
12004     // Fast path: link the stub to the existing head of the list without any
12005     // heap allocation.
12006     DCHECK(n == 1);
12007     map->dependent_code()->AddToDependentICList(stub);
12008   }
12009 }
12010
12011
12012 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
12013   Recompute(entries);
12014 }
12015
12016
12017 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
12018   start_indexes_[0] = 0;
12019   for (int g = 1; g <= kGroupCount; g++) {
12020     int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
12021     start_indexes_[g] = start_indexes_[g - 1] + count;
12022   }
12023 }
12024
12025
12026 DependentCode* DependentCode::ForObject(Handle<HeapObject> object,
12027                                         DependencyGroup group) {
12028   AllowDeferredHandleDereference dependencies_are_safe;
12029   if (group == DependentCode::kPropertyCellChangedGroup) {
12030     return Handle<PropertyCell>::cast(object)->dependent_code();
12031   } else if (group == DependentCode::kAllocationSiteTenuringChangedGroup ||
12032       group == DependentCode::kAllocationSiteTransitionChangedGroup) {
12033     return Handle<AllocationSite>::cast(object)->dependent_code();
12034   }
12035   return Handle<Map>::cast(object)->dependent_code();
12036 }
12037
12038
12039 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
12040                                             DependencyGroup group,
12041                                             Handle<Object> object) {
12042   GroupStartIndexes starts(*entries);
12043   int start = starts.at(group);
12044   int end = starts.at(group + 1);
12045   int number_of_entries = starts.number_of_entries();
12046   // Check for existing entry to avoid duplicates.
12047   for (int i = start; i < end; i++) {
12048     if (entries->object_at(i) == *object) return entries;
12049   }
12050   if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
12051     int capacity = kCodesStartIndex + number_of_entries + 1;
12052     if (capacity > 5) capacity = capacity * 5 / 4;
12053     Handle<DependentCode> new_entries = Handle<DependentCode>::cast(
12054         FixedArray::CopySize(entries, capacity, TENURED));
12055     // The number of codes can change after GC.
12056     starts.Recompute(*entries);
12057     start = starts.at(group);
12058     end = starts.at(group + 1);
12059     number_of_entries = starts.number_of_entries();
12060     for (int i = 0; i < number_of_entries; i++) {
12061       entries->clear_at(i);
12062     }
12063     // If the old fixed array was empty, we need to reset counters of the
12064     // new array.
12065     if (number_of_entries == 0) {
12066       for (int g = 0; g < kGroupCount; g++) {
12067         new_entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
12068       }
12069     }
12070     entries = new_entries;
12071   }
12072   entries->ExtendGroup(group);
12073   entries->set_object_at(end, *object);
12074   entries->set_number_of_entries(group, end + 1 - start);
12075   return entries;
12076 }
12077
12078
12079 void DependentCode::UpdateToFinishedCode(DependencyGroup group,
12080                                          CompilationInfo* info,
12081                                          Code* code) {
12082   DisallowHeapAllocation no_gc;
12083   AllowDeferredHandleDereference get_object_wrapper;
12084   Foreign* info_wrapper = *info->object_wrapper();
12085   GroupStartIndexes starts(this);
12086   int start = starts.at(group);
12087   int end = starts.at(group + 1);
12088   for (int i = start; i < end; i++) {
12089     if (object_at(i) == info_wrapper) {
12090       set_object_at(i, code);
12091       break;
12092     }
12093   }
12094
12095 #ifdef DEBUG
12096   for (int i = start; i < end; i++) {
12097     DCHECK(is_code_at(i) || compilation_info_at(i) != info);
12098   }
12099 #endif
12100 }
12101
12102
12103 void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
12104                                           CompilationInfo* info) {
12105   DisallowHeapAllocation no_allocation;
12106   AllowDeferredHandleDereference get_object_wrapper;
12107   Foreign* info_wrapper = *info->object_wrapper();
12108   GroupStartIndexes starts(this);
12109   int start = starts.at(group);
12110   int end = starts.at(group + 1);
12111   // Find compilation info wrapper.
12112   int info_pos = -1;
12113   for (int i = start; i < end; i++) {
12114     if (object_at(i) == info_wrapper) {
12115       info_pos = i;
12116       break;
12117     }
12118   }
12119   if (info_pos == -1) return;  // Not found.
12120   int gap = info_pos;
12121   // Use the last of each group to fill the gap in the previous group.
12122   for (int i = group; i < kGroupCount; i++) {
12123     int last_of_group = starts.at(i + 1) - 1;
12124     DCHECK(last_of_group >= gap);
12125     if (last_of_group == gap) continue;
12126     copy(last_of_group, gap);
12127     gap = last_of_group;
12128   }
12129   DCHECK(gap == starts.number_of_entries() - 1);
12130   clear_at(gap);  // Clear last gap.
12131   set_number_of_entries(group, end - start - 1);
12132
12133 #ifdef DEBUG
12134   for (int i = start; i < end - 1; i++) {
12135     DCHECK(is_code_at(i) || compilation_info_at(i) != info);
12136   }
12137 #endif
12138 }
12139
12140
12141 static bool CodeListContains(Object* head, Code* code) {
12142   while (!head->IsUndefined()) {
12143     if (head == code) return true;
12144     head = Code::cast(head)->next_code_link();
12145   }
12146   return false;
12147 }
12148
12149
12150 bool DependentCode::Contains(DependencyGroup group, Code* code) {
12151   GroupStartIndexes starts(this);
12152   int start = starts.at(group);
12153   int end = starts.at(group + 1);
12154   if (group == kWeakICGroup) {
12155     return CodeListContains(object_at(start), code);
12156   }
12157   for (int i = start; i < end; i++) {
12158     if (object_at(i) == code) return true;
12159   }
12160   return false;
12161 }
12162
12163
12164 bool DependentCode::MarkCodeForDeoptimization(
12165     Isolate* isolate,
12166     DependentCode::DependencyGroup group) {
12167   DisallowHeapAllocation no_allocation_scope;
12168   DependentCode::GroupStartIndexes starts(this);
12169   int start = starts.at(group);
12170   int end = starts.at(group + 1);
12171   int code_entries = starts.number_of_entries();
12172   if (start == end) return false;
12173
12174   // Mark all the code that needs to be deoptimized.
12175   bool marked = false;
12176   for (int i = start; i < end; i++) {
12177     if (is_code_at(i)) {
12178       Code* code = code_at(i);
12179       if (!code->marked_for_deoptimization()) {
12180         code->set_marked_for_deoptimization(true);
12181         marked = true;
12182       }
12183     } else {
12184       CompilationInfo* info = compilation_info_at(i);
12185       info->AbortDueToDependencyChange();
12186     }
12187   }
12188   // Compact the array by moving all subsequent groups to fill in the new holes.
12189   for (int src = end, dst = start; src < code_entries; src++, dst++) {
12190     copy(src, dst);
12191   }
12192   // Now the holes are at the end of the array, zap them for heap-verifier.
12193   int removed = end - start;
12194   for (int i = code_entries - removed; i < code_entries; i++) {
12195     clear_at(i);
12196   }
12197   set_number_of_entries(group, 0);
12198   return marked;
12199 }
12200
12201
12202 void DependentCode::DeoptimizeDependentCodeGroup(
12203     Isolate* isolate,
12204     DependentCode::DependencyGroup group) {
12205   DCHECK(AllowCodeDependencyChange::IsAllowed());
12206   DisallowHeapAllocation no_allocation_scope;
12207   bool marked = MarkCodeForDeoptimization(isolate, group);
12208
12209   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
12210 }
12211
12212
12213 void DependentCode::AddToDependentICList(Handle<Code> stub) {
12214   DisallowHeapAllocation no_heap_allocation;
12215   GroupStartIndexes starts(this);
12216   int i = starts.at(kWeakICGroup);
12217   Object* head = object_at(i);
12218   // Try to insert the stub after the head of the list to minimize number of
12219   // writes to the DependentCode array, since a write to the array can make it
12220   // strong if it was alread marked by incremental marker.
12221   if (head->IsCode()) {
12222     stub->set_next_code_link(Code::cast(head)->next_code_link());
12223     Code::cast(head)->set_next_code_link(*stub);
12224   } else {
12225     stub->set_next_code_link(head);
12226     set_object_at(i, *stub);
12227   }
12228 }
12229
12230
12231 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
12232                                        Handle<Object> prototype) {
12233   Handle<Map> new_map = GetPrototypeTransition(map, prototype);
12234   if (new_map.is_null()) {
12235     new_map = Copy(map);
12236     PutPrototypeTransition(map, prototype, new_map);
12237     new_map->set_prototype(*prototype);
12238   }
12239   return new_map;
12240 }
12241
12242
12243 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12244                                            Handle<Object> value,
12245                                            bool from_javascript) {
12246 #ifdef DEBUG
12247   int size = object->Size();
12248 #endif
12249
12250   Isolate* isolate = object->GetIsolate();
12251   Heap* heap = isolate->heap();
12252   // Silently ignore the change if value is not a JSObject or null.
12253   // SpiderMonkey behaves this way.
12254   if (!value->IsJSReceiver() && !value->IsNull()) return value;
12255
12256   // From 8.6.2 Object Internal Methods
12257   // ...
12258   // In addition, if [[Extensible]] is false the value of the [[Class]] and
12259   // [[Prototype]] internal properties of the object may not be modified.
12260   // ...
12261   // Implementation specific extensions that modify [[Class]], [[Prototype]]
12262   // or [[Extensible]] must not violate the invariants defined in the preceding
12263   // paragraph.
12264   if (!object->map()->is_extensible()) {
12265     Handle<Object> args[] = { object };
12266     Handle<Object> error = isolate->factory()->NewTypeError(
12267         "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args)));
12268     return isolate->Throw<Object>(error);
12269   }
12270
12271   // Before we can set the prototype we need to be sure
12272   // prototype cycles are prevented.
12273   // It is sufficient to validate that the receiver is not in the new prototype
12274   // chain.
12275   for (PrototypeIterator iter(isolate, *value,
12276                               PrototypeIterator::START_AT_RECEIVER);
12277        !iter.IsAtEnd(); iter.Advance()) {
12278     if (JSReceiver::cast(iter.GetCurrent()) == *object) {
12279       // Cycle detected.
12280       Handle<Object> error = isolate->factory()->NewError(
12281           "cyclic_proto", HandleVector<Object>(NULL, 0));
12282       return isolate->Throw<Object>(error);
12283     }
12284   }
12285
12286   bool dictionary_elements_in_chain =
12287       object->map()->DictionaryElementsInPrototypeChainOnly();
12288   Handle<JSObject> real_receiver = object;
12289
12290   if (from_javascript) {
12291     // Find the first object in the chain whose prototype object is not
12292     // hidden and set the new prototype on that object.
12293     PrototypeIterator iter(isolate, real_receiver);
12294     while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
12295       real_receiver =
12296           Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
12297       iter.Advance();
12298     }
12299   }
12300
12301   // Set the new prototype of the object.
12302   Handle<Map> map(real_receiver->map());
12303
12304   // Nothing to do if prototype is already set.
12305   if (map->prototype() == *value) return value;
12306
12307   if (value->IsJSObject()) {
12308     PrototypeOptimizationMode mode =
12309         from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
12310     JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value), mode);
12311   }
12312
12313   Handle<Map> new_map = Map::TransitionToPrototype(map, value);
12314   DCHECK(new_map->prototype() == *value);
12315   JSObject::MigrateToMap(real_receiver, new_map);
12316
12317   if (!dictionary_elements_in_chain &&
12318       new_map->DictionaryElementsInPrototypeChainOnly()) {
12319     // If the prototype chain didn't previously have element callbacks, then
12320     // KeyedStoreICs need to be cleared to ensure any that involve this
12321     // map go generic.
12322     object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
12323   }
12324
12325   heap->ClearInstanceofCache();
12326   DCHECK(size == object->Size());
12327   return value;
12328 }
12329
12330
12331 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
12332                                         Arguments* args,
12333                                         uint32_t first_arg,
12334                                         uint32_t arg_count,
12335                                         EnsureElementsMode mode) {
12336   // Elements in |Arguments| are ordered backwards (because they're on the
12337   // stack), but the method that's called here iterates over them in forward
12338   // direction.
12339   return EnsureCanContainElements(
12340       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
12341 }
12342
12343
12344 MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair(
12345     Handle<JSObject> object,
12346     uint32_t index) {
12347   if (object->IsJSGlobalProxy()) {
12348     PrototypeIterator iter(object->GetIsolate(), object);
12349     if (iter.IsAtEnd()) return MaybeHandle<AccessorPair>();
12350     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
12351     return GetOwnElementAccessorPair(
12352         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
12353   }
12354
12355   // Check for lookup interceptor.
12356   if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>();
12357
12358   return object->GetElementsAccessor()->GetAccessorPair(object, object, index);
12359 }
12360
12361
12362 MaybeHandle<Object> JSObject::SetElementWithInterceptor(
12363     Handle<JSObject> object,
12364     uint32_t index,
12365     Handle<Object> value,
12366     PropertyAttributes attributes,
12367     StrictMode strict_mode,
12368     bool check_prototype,
12369     SetPropertyMode set_mode) {
12370   Isolate* isolate = object->GetIsolate();
12371
12372   // Make sure that the top context does not change when doing
12373   // callbacks or interceptor calls.
12374   AssertNoContextChange ncc(isolate);
12375
12376   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
12377   if (!interceptor->setter()->IsUndefined()) {
12378     v8::IndexedPropertySetterCallback setter =
12379         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
12380     LOG(isolate,
12381         ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
12382     PropertyCallbackArguments args(isolate, interceptor->data(), *object,
12383                                    *object);
12384     v8::Handle<v8::Value> result =
12385         args.Call(setter, index, v8::Utils::ToLocal(value));
12386     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12387     if (!result.IsEmpty()) return value;
12388   }
12389
12390   return SetElementWithoutInterceptor(object, index, value, attributes,
12391                                       strict_mode,
12392                                       check_prototype,
12393                                       set_mode);
12394 }
12395
12396
12397 MaybeHandle<Object> JSObject::GetElementWithCallback(
12398     Handle<JSObject> object,
12399     Handle<Object> receiver,
12400     Handle<Object> structure,
12401     uint32_t index,
12402     Handle<Object> holder) {
12403   Isolate* isolate = object->GetIsolate();
12404   DCHECK(!structure->IsForeign());
12405   // api style callbacks.
12406   if (structure->IsExecutableAccessorInfo()) {
12407     Handle<ExecutableAccessorInfo> data =
12408         Handle<ExecutableAccessorInfo>::cast(structure);
12409     Object* fun_obj = data->getter();
12410     v8::AccessorGetterCallback call_fun =
12411         v8::ToCData<v8::AccessorGetterCallback>(fun_obj);
12412     if (call_fun == NULL) return isolate->factory()->undefined_value();
12413     Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder);
12414     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12415     Handle<String> key = isolate->factory()->NumberToString(number);
12416     LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key));
12417     PropertyCallbackArguments
12418         args(isolate, data->data(), *receiver, *holder_handle);
12419     v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
12420     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12421     if (result.IsEmpty()) return isolate->factory()->undefined_value();
12422     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12423     result_internal->VerifyApiCallResultType();
12424     // Rebox handle before return.
12425     return handle(*result_internal, isolate);
12426   }
12427
12428   // __defineGetter__ callback
12429   if (structure->IsAccessorPair()) {
12430     Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
12431                           isolate);
12432     if (getter->IsSpecFunction()) {
12433       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12434       return GetPropertyWithDefinedGetter(
12435           receiver, Handle<JSReceiver>::cast(getter));
12436     }
12437     // Getter is not a function.
12438     return isolate->factory()->undefined_value();
12439   }
12440
12441   if (structure->IsDeclaredAccessorInfo()) {
12442     return GetDeclaredAccessorProperty(
12443         receiver, Handle<DeclaredAccessorInfo>::cast(structure), isolate);
12444   }
12445
12446   UNREACHABLE();
12447   return MaybeHandle<Object>();
12448 }
12449
12450
12451 MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
12452                                                      Handle<Object> structure,
12453                                                      uint32_t index,
12454                                                      Handle<Object> value,
12455                                                      Handle<JSObject> holder,
12456                                                      StrictMode strict_mode) {
12457   Isolate* isolate = object->GetIsolate();
12458
12459   // We should never get here to initialize a const with the hole
12460   // value since a const declaration would conflict with the setter.
12461   DCHECK(!value->IsTheHole());
12462   DCHECK(!structure->IsForeign());
12463   if (structure->IsExecutableAccessorInfo()) {
12464     // api style callbacks
12465     Handle<ExecutableAccessorInfo> data =
12466         Handle<ExecutableAccessorInfo>::cast(structure);
12467     Object* call_obj = data->setter();
12468     v8::AccessorSetterCallback call_fun =
12469         v8::ToCData<v8::AccessorSetterCallback>(call_obj);
12470     if (call_fun == NULL) return value;
12471     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12472     Handle<String> key(isolate->factory()->NumberToString(number));
12473     LOG(isolate, ApiNamedPropertyAccess("store", *object, *key));
12474     PropertyCallbackArguments
12475         args(isolate, data->data(), *object, *holder);
12476     args.Call(call_fun,
12477               v8::Utils::ToLocal(key),
12478               v8::Utils::ToLocal(value));
12479     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12480     return value;
12481   }
12482
12483   if (structure->IsAccessorPair()) {
12484     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
12485     if (setter->IsSpecFunction()) {
12486       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12487       return SetPropertyWithDefinedSetter(
12488           object, Handle<JSReceiver>::cast(setter), value);
12489     } else {
12490       if (strict_mode == SLOPPY) return value;
12491       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
12492       Handle<Object> args[2] = { key, holder };
12493       Handle<Object> error = isolate->factory()->NewTypeError(
12494           "no_setter_in_callback", HandleVector(args, 2));
12495       return isolate->Throw<Object>(error);
12496     }
12497   }
12498
12499   // TODO(dcarney): Handle correctly.
12500   if (structure->IsDeclaredAccessorInfo()) return value;
12501
12502   UNREACHABLE();
12503   return MaybeHandle<Object>();
12504 }
12505
12506
12507 bool JSObject::HasFastArgumentsElements() {
12508   Heap* heap = GetHeap();
12509   if (!elements()->IsFixedArray()) return false;
12510   FixedArray* elements = FixedArray::cast(this->elements());
12511   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12512     return false;
12513   }
12514   FixedArray* arguments = FixedArray::cast(elements->get(1));
12515   return !arguments->IsDictionary();
12516 }
12517
12518
12519 bool JSObject::HasDictionaryArgumentsElements() {
12520   Heap* heap = GetHeap();
12521   if (!elements()->IsFixedArray()) return false;
12522   FixedArray* elements = FixedArray::cast(this->elements());
12523   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12524     return false;
12525   }
12526   FixedArray* arguments = FixedArray::cast(elements->get(1));
12527   return arguments->IsDictionary();
12528 }
12529
12530
12531 // Adding n elements in fast case is O(n*n).
12532 // Note: revisit design to have dual undefined values to capture absent
12533 // elements.
12534 MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
12535                                              uint32_t index,
12536                                              Handle<Object> value,
12537                                              StrictMode strict_mode,
12538                                              bool check_prototype) {
12539   DCHECK(object->HasFastSmiOrObjectElements() ||
12540          object->HasFastArgumentsElements());
12541
12542   Isolate* isolate = object->GetIsolate();
12543
12544   // Array optimizations rely on the prototype lookups of Array objects always
12545   // returning undefined. If there is a store to the initial prototype object,
12546   // make sure all of these optimizations are invalidated.
12547   if (isolate->is_initial_object_prototype(*object) ||
12548       isolate->is_initial_array_prototype(*object)) {
12549     object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate,
12550         DependentCode::kElementsCantBeAddedGroup);
12551   }
12552
12553   Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12554   if (backing_store->map() ==
12555       isolate->heap()->sloppy_arguments_elements_map()) {
12556     backing_store = handle(FixedArray::cast(backing_store->get(1)));
12557   } else {
12558     backing_store = EnsureWritableFastElements(object);
12559   }
12560   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12561
12562   if (check_prototype &&
12563       (index >= capacity || backing_store->get(index)->IsTheHole())) {
12564     bool found;
12565     MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12566         object, index, value, &found, strict_mode);
12567     if (found) return result;
12568   }
12569
12570   uint32_t new_capacity = capacity;
12571   // Check if the length property of this object needs to be updated.
12572   uint32_t array_length = 0;
12573   bool must_update_array_length = false;
12574   bool introduces_holes = true;
12575   if (object->IsJSArray()) {
12576     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12577     introduces_holes = index > array_length;
12578     if (index >= array_length) {
12579       must_update_array_length = true;
12580       array_length = index + 1;
12581     }
12582   } else {
12583     introduces_holes = index >= capacity;
12584   }
12585
12586   // If the array is growing, and it's not growth by a single element at the
12587   // end, make sure that the ElementsKind is HOLEY.
12588   ElementsKind elements_kind = object->GetElementsKind();
12589   if (introduces_holes &&
12590       IsFastElementsKind(elements_kind) &&
12591       !IsFastHoleyElementsKind(elements_kind)) {
12592     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12593     TransitionElementsKind(object, transitioned_kind);
12594   }
12595
12596   // Check if the capacity of the backing store needs to be increased, or if
12597   // a transition to slow elements is necessary.
12598   if (index >= capacity) {
12599     bool convert_to_slow = true;
12600     if ((index - capacity) < kMaxGap) {
12601       new_capacity = NewElementsCapacity(index + 1);
12602       DCHECK(new_capacity > index);
12603       if (!object->ShouldConvertToSlowElements(new_capacity)) {
12604         convert_to_slow = false;
12605       }
12606     }
12607     if (convert_to_slow) {
12608       NormalizeElements(object);
12609       return SetDictionaryElement(object, index, value, NONE, strict_mode,
12610                                   check_prototype);
12611     }
12612   }
12613   // Convert to fast double elements if appropriate.
12614   if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12615     // Consider fixing the boilerplate as well if we have one.
12616     ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
12617         ? FAST_HOLEY_DOUBLE_ELEMENTS
12618         : FAST_DOUBLE_ELEMENTS;
12619
12620     UpdateAllocationSite(object, to_kind);
12621
12622     SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12623     FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12624     JSObject::ValidateElements(object);
12625     return value;
12626   }
12627   // Change elements kind from Smi-only to generic FAST if necessary.
12628   if (object->HasFastSmiElements() && !value->IsSmi()) {
12629     ElementsKind kind = object->HasFastHoleyElements()
12630         ? FAST_HOLEY_ELEMENTS
12631         : FAST_ELEMENTS;
12632
12633     UpdateAllocationSite(object, kind);
12634     Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12635     JSObject::MigrateToMap(object, new_map);
12636     DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12637   }
12638   // Increase backing store capacity if that's been decided previously.
12639   if (new_capacity != capacity) {
12640     SetFastElementsCapacitySmiMode smi_mode =
12641         value->IsSmi() && object->HasFastSmiElements()
12642             ? kAllowSmiElements
12643             : kDontAllowSmiElements;
12644     Handle<FixedArray> new_elements =
12645         SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12646                                          smi_mode);
12647     new_elements->set(index, *value);
12648     JSObject::ValidateElements(object);
12649     return value;
12650   }
12651
12652   // Finally, set the new element and length.
12653   DCHECK(object->elements()->IsFixedArray());
12654   backing_store->set(index, *value);
12655   if (must_update_array_length) {
12656     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12657   }
12658   return value;
12659 }
12660
12661
12662 MaybeHandle<Object> JSObject::SetDictionaryElement(
12663     Handle<JSObject> object,
12664     uint32_t index,
12665     Handle<Object> value,
12666     PropertyAttributes attributes,
12667     StrictMode strict_mode,
12668     bool check_prototype,
12669     SetPropertyMode set_mode) {
12670   DCHECK(object->HasDictionaryElements() ||
12671          object->HasDictionaryArgumentsElements());
12672   Isolate* isolate = object->GetIsolate();
12673
12674   // Insert element in the dictionary.
12675   Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12676   bool is_arguments =
12677       (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12678   Handle<SeededNumberDictionary> dictionary(is_arguments
12679     ? SeededNumberDictionary::cast(elements->get(1))
12680     : SeededNumberDictionary::cast(*elements));
12681
12682   int entry = dictionary->FindEntry(index);
12683   if (entry != SeededNumberDictionary::kNotFound) {
12684     Handle<Object> element(dictionary->ValueAt(entry), isolate);
12685     PropertyDetails details = dictionary->DetailsAt(entry);
12686     if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
12687       return SetElementWithCallback(object, element, index, value, object,
12688                                     strict_mode);
12689     } else {
12690       dictionary->UpdateMaxNumberKey(index);
12691       // If a value has not been initialized we allow writing to it even if it
12692       // is read-only (a declared const that has not been initialized).  If a
12693       // value is being defined we skip attribute checks completely.
12694       if (set_mode == DEFINE_PROPERTY) {
12695         details = PropertyDetails(
12696             attributes, NORMAL, details.dictionary_index());
12697         dictionary->DetailsAtPut(entry, details);
12698       } else if (details.IsReadOnly() && !element->IsTheHole()) {
12699         if (strict_mode == SLOPPY) {
12700           return isolate->factory()->undefined_value();
12701         } else {
12702           Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12703           Handle<Object> args[2] = { number, object };
12704           Handle<Object> error =
12705               isolate->factory()->NewTypeError("strict_read_only_property",
12706                                                HandleVector(args, 2));
12707           return isolate->Throw<Object>(error);
12708         }
12709       }
12710       // Elements of the arguments object in slow mode might be slow aliases.
12711       if (is_arguments && element->IsAliasedArgumentsEntry()) {
12712         Handle<AliasedArgumentsEntry> entry =
12713             Handle<AliasedArgumentsEntry>::cast(element);
12714         Handle<Context> context(Context::cast(elements->get(0)));
12715         int context_index = entry->aliased_context_slot();
12716         DCHECK(!context->get(context_index)->IsTheHole());
12717         context->set(context_index, *value);
12718         // For elements that are still writable we keep slow aliasing.
12719         if (!details.IsReadOnly()) value = element;
12720       }
12721       dictionary->ValueAtPut(entry, *value);
12722     }
12723   } else {
12724     // Index not already used. Look for an accessor in the prototype chain.
12725     // Can cause GC!
12726     if (check_prototype) {
12727       bool found;
12728       MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12729           object, index, value, &found, strict_mode);
12730       if (found) return result;
12731     }
12732
12733     // When we set the is_extensible flag to false we always force the
12734     // element into dictionary mode (and force them to stay there).
12735     if (!object->map()->is_extensible()) {
12736       if (strict_mode == SLOPPY) {
12737         return isolate->factory()->undefined_value();
12738       } else {
12739         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12740         Handle<String> name = isolate->factory()->NumberToString(number);
12741         Handle<Object> args[1] = { name };
12742         Handle<Object> error =
12743             isolate->factory()->NewTypeError("object_not_extensible",
12744                                              HandleVector(args, 1));
12745         return isolate->Throw<Object>(error);
12746       }
12747     }
12748
12749     PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
12750     Handle<SeededNumberDictionary> new_dictionary =
12751         SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
12752                                                details);
12753     if (*dictionary != *new_dictionary) {
12754       if (is_arguments) {
12755         elements->set(1, *new_dictionary);
12756       } else {
12757         object->set_elements(*new_dictionary);
12758       }
12759       dictionary = new_dictionary;
12760     }
12761   }
12762
12763   // Update the array length if this JSObject is an array.
12764   if (object->IsJSArray()) {
12765     JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index,
12766                                           value);
12767   }
12768
12769   // Attempt to put this object back in fast case.
12770   if (object->ShouldConvertToFastElements()) {
12771     uint32_t new_length = 0;
12772     if (object->IsJSArray()) {
12773       CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length));
12774     } else {
12775       new_length = dictionary->max_number_key() + 1;
12776     }
12777     bool has_smi_only_elements = false;
12778     bool should_convert_to_fast_double_elements =
12779         object->ShouldConvertToFastDoubleElements(&has_smi_only_elements);
12780     SetFastElementsCapacitySmiMode smi_mode =
12781         has_smi_only_elements ? kForceSmiElements : kAllowSmiElements;
12782
12783     if (should_convert_to_fast_double_elements) {
12784       SetFastDoubleElementsCapacityAndLength(object, new_length, new_length);
12785     } else {
12786       SetFastElementsCapacityAndLength(object, new_length, new_length,
12787                                        smi_mode);
12788     }
12789     JSObject::ValidateElements(object);
12790 #ifdef DEBUG
12791     if (FLAG_trace_normalization) {
12792       OFStream os(stdout);
12793       os << "Object elements are fast case again:\n";
12794       object->Print(os);
12795     }
12796 #endif
12797   }
12798   return value;
12799 }
12800
12801 MaybeHandle<Object> JSObject::SetFastDoubleElement(
12802     Handle<JSObject> object,
12803     uint32_t index,
12804     Handle<Object> value,
12805     StrictMode strict_mode,
12806     bool check_prototype) {
12807   DCHECK(object->HasFastDoubleElements());
12808
12809   Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12810   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
12811
12812   // If storing to an element that isn't in the array, pass the store request
12813   // up the prototype chain before storing in the receiver's elements.
12814   if (check_prototype &&
12815       (index >= elms_length ||
12816        Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
12817     bool found;
12818     MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12819         object, index, value, &found, strict_mode);
12820     if (found) return result;
12821   }
12822
12823   // If the value object is not a heap number, switch to fast elements and try
12824   // again.
12825   bool value_is_smi = value->IsSmi();
12826   bool introduces_holes = true;
12827   uint32_t length = elms_length;
12828   if (object->IsJSArray()) {
12829     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length));
12830     introduces_holes = index > length;
12831   } else {
12832     introduces_holes = index >= elms_length;
12833   }
12834
12835   if (!value->IsNumber()) {
12836     SetFastElementsCapacityAndLength(object, elms_length, length,
12837                                      kDontAllowSmiElements);
12838     Handle<Object> result;
12839     ASSIGN_RETURN_ON_EXCEPTION(
12840         object->GetIsolate(), result,
12841         SetFastElement(object, index, value, strict_mode, check_prototype),
12842         Object);
12843     JSObject::ValidateElements(object);
12844     return result;
12845   }
12846
12847   double double_value = value_is_smi
12848       ? static_cast<double>(Handle<Smi>::cast(value)->value())
12849       : Handle<HeapNumber>::cast(value)->value();
12850
12851   // If the array is growing, and it's not growth by a single element at the
12852   // end, make sure that the ElementsKind is HOLEY.
12853   ElementsKind elements_kind = object->GetElementsKind();
12854   if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
12855     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12856     TransitionElementsKind(object, transitioned_kind);
12857   }
12858
12859   // Check whether there is extra space in the fixed array.
12860   if (index < elms_length) {
12861     Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
12862     elms->set(index, double_value);
12863     if (object->IsJSArray()) {
12864       // Update the length of the array if needed.
12865       uint32_t array_length = 0;
12866       CHECK(
12867           Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12868       if (index >= array_length) {
12869         Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12870       }
12871     }
12872     return value;
12873   }
12874
12875   // Allow gap in fast case.
12876   if ((index - elms_length) < kMaxGap) {
12877     // Try allocating extra space.
12878     int new_capacity = NewElementsCapacity(index+1);
12879     if (!object->ShouldConvertToSlowElements(new_capacity)) {
12880       DCHECK(static_cast<uint32_t>(new_capacity) > index);
12881       SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
12882       FixedDoubleArray::cast(object->elements())->set(index, double_value);
12883       JSObject::ValidateElements(object);
12884       return value;
12885     }
12886   }
12887
12888   // Otherwise default to slow case.
12889   DCHECK(object->HasFastDoubleElements());
12890   DCHECK(object->map()->has_fast_double_elements());
12891   DCHECK(object->elements()->IsFixedDoubleArray() ||
12892          object->elements()->length() == 0);
12893
12894   NormalizeElements(object);
12895   DCHECK(object->HasDictionaryElements());
12896   return SetElement(object, index, value, NONE, strict_mode, check_prototype);
12897 }
12898
12899
12900 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12901                                            uint32_t index,
12902                                            Handle<Object> value,
12903                                            PropertyAttributes attributes,
12904                                            StrictMode strict_mode) {
12905   if (object->IsJSProxy()) {
12906     return JSProxy::SetElementWithHandler(
12907         Handle<JSProxy>::cast(object), object, index, value, strict_mode);
12908   }
12909   return JSObject::SetElement(
12910       Handle<JSObject>::cast(object), index, value, attributes, strict_mode);
12911 }
12912
12913
12914 MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
12915                                             uint32_t index,
12916                                             Handle<Object> value,
12917                                             StrictMode strict_mode) {
12918   DCHECK(!object->HasExternalArrayElements());
12919   return JSObject::SetElement(object, index, value, NONE, strict_mode, false);
12920 }
12921
12922
12923 MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object,
12924                                          uint32_t index,
12925                                          Handle<Object> value,
12926                                          PropertyAttributes attributes,
12927                                          StrictMode strict_mode,
12928                                          bool check_prototype,
12929                                          SetPropertyMode set_mode) {
12930   Isolate* isolate = object->GetIsolate();
12931
12932   if (object->HasExternalArrayElements() ||
12933       object->HasFixedTypedArrayElements()) {
12934     if (!value->IsNumber() && !value->IsFloat32x4() && !value->IsFloat64x2() &&
12935         !value->IsInt32x4() && !value->IsUndefined()) {
12936       ASSIGN_RETURN_ON_EXCEPTION(
12937           isolate, value,
12938           Execution::ToNumber(isolate, value), Object);
12939     }
12940   }
12941
12942   // Check access rights if needed.
12943   if (object->IsAccessCheckNeeded()) {
12944     if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_SET)) {
12945       isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
12946       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12947       return value;
12948     }
12949   }
12950
12951   if (object->IsJSGlobalProxy()) {
12952     PrototypeIterator iter(isolate, object);
12953     if (iter.IsAtEnd()) return value;
12954     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
12955     return SetElement(
12956         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
12957         value, attributes, strict_mode, check_prototype, set_mode);
12958   }
12959
12960   // Don't allow element properties to be redefined for external arrays.
12961   if ((object->HasExternalArrayElements() ||
12962           object->HasFixedTypedArrayElements()) &&
12963       set_mode == DEFINE_PROPERTY) {
12964     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12965     Handle<Object> args[] = { object, number };
12966     Handle<Object> error = isolate->factory()->NewTypeError(
12967         "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
12968     return isolate->Throw<Object>(error);
12969   }
12970
12971   // Normalize the elements to enable attributes on the property.
12972   if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
12973     Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
12974     // Make sure that we never go back to fast case.
12975     dictionary->set_requires_slow_elements();
12976   }
12977
12978   if (!object->map()->is_observed()) {
12979     return object->HasIndexedInterceptor()
12980       ? SetElementWithInterceptor(object, index, value, attributes,
12981                                   strict_mode, check_prototype, set_mode)
12982       : SetElementWithoutInterceptor(object, index, value, attributes,
12983                                      strict_mode, check_prototype, set_mode);
12984   }
12985
12986   Maybe<PropertyAttributes> maybe =
12987       JSReceiver::GetOwnElementAttribute(object, index);
12988   if (!maybe.has_value) return MaybeHandle<Object>();
12989   PropertyAttributes old_attributes = maybe.value;
12990
12991   Handle<Object> old_value = isolate->factory()->the_hole_value();
12992   Handle<Object> old_length_handle;
12993   Handle<Object> new_length_handle;
12994
12995   if (old_attributes != ABSENT) {
12996     if (GetOwnElementAccessorPair(object, index).is_null()) {
12997       old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
12998     }
12999   } else if (object->IsJSArray()) {
13000     // Store old array length in case adding an element grows the array.
13001     old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13002                                isolate);
13003   }
13004
13005   // Check for lookup interceptor
13006   Handle<Object> result;
13007   ASSIGN_RETURN_ON_EXCEPTION(
13008       isolate, result,
13009       object->HasIndexedInterceptor()
13010           ? SetElementWithInterceptor(
13011               object, index, value, attributes,
13012               strict_mode, check_prototype, set_mode)
13013           : SetElementWithoutInterceptor(
13014               object, index, value, attributes,
13015               strict_mode, check_prototype, set_mode),
13016       Object);
13017
13018   Handle<String> name = isolate->factory()->Uint32ToString(index);
13019   maybe = GetOwnElementAttribute(object, index);
13020   if (!maybe.has_value) return MaybeHandle<Object>();
13021   PropertyAttributes new_attributes = maybe.value;
13022
13023   if (old_attributes == ABSENT) {
13024     if (object->IsJSArray() &&
13025         !old_length_handle->SameValue(
13026             Handle<JSArray>::cast(object)->length())) {
13027       new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13028                                  isolate);
13029       uint32_t old_length = 0;
13030       uint32_t new_length = 0;
13031       CHECK(old_length_handle->ToArrayIndex(&old_length));
13032       CHECK(new_length_handle->ToArrayIndex(&new_length));
13033
13034       BeginPerformSplice(Handle<JSArray>::cast(object));
13035       EnqueueChangeRecord(object, "add", name, old_value);
13036       EnqueueChangeRecord(object, "update", isolate->factory()->length_string(),
13037                           old_length_handle);
13038       EndPerformSplice(Handle<JSArray>::cast(object));
13039       Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
13040       EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length, deleted,
13041                           new_length - old_length);
13042     } else {
13043       EnqueueChangeRecord(object, "add", name, old_value);
13044     }
13045   } else if (old_value->IsTheHole()) {
13046     EnqueueChangeRecord(object, "reconfigure", name, old_value);
13047   } else {
13048     Handle<Object> new_value =
13049         Object::GetElement(isolate, object, index).ToHandleChecked();
13050     bool value_changed = !old_value->SameValue(*new_value);
13051     if (old_attributes != new_attributes) {
13052       if (!value_changed) old_value = isolate->factory()->the_hole_value();
13053       EnqueueChangeRecord(object, "reconfigure", name, old_value);
13054     } else if (value_changed) {
13055       EnqueueChangeRecord(object, "update", name, old_value);
13056     }
13057   }
13058
13059   return result;
13060 }
13061
13062
13063 MaybeHandle<Object> JSObject::SetElementWithoutInterceptor(
13064     Handle<JSObject> object,
13065     uint32_t index,
13066     Handle<Object> value,
13067     PropertyAttributes attributes,
13068     StrictMode strict_mode,
13069     bool check_prototype,
13070     SetPropertyMode set_mode) {
13071   DCHECK(object->HasDictionaryElements() ||
13072          object->HasDictionaryArgumentsElements() ||
13073          (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
13074   Isolate* isolate = object->GetIsolate();
13075   if (FLAG_trace_external_array_abuse &&
13076       IsExternalArrayElementsKind(object->GetElementsKind())) {
13077     CheckArrayAbuse(object, "external elements write", index);
13078   }
13079   if (FLAG_trace_js_array_abuse &&
13080       !IsExternalArrayElementsKind(object->GetElementsKind())) {
13081     if (object->IsJSArray()) {
13082       CheckArrayAbuse(object, "elements write", index, true);
13083     }
13084   }
13085   if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
13086       Handle<JSArray>::cast(object), index)) {
13087     if (strict_mode == SLOPPY) {
13088       return value;
13089     } else {
13090       return JSArray::ReadOnlyLengthError(Handle<JSArray>::cast(object));
13091     }
13092   }
13093   switch (object->GetElementsKind()) {
13094     case FAST_SMI_ELEMENTS:
13095     case FAST_ELEMENTS:
13096     case FAST_HOLEY_SMI_ELEMENTS:
13097     case FAST_HOLEY_ELEMENTS:
13098       return SetFastElement(object, index, value, strict_mode, check_prototype);
13099     case FAST_DOUBLE_ELEMENTS:
13100     case FAST_HOLEY_DOUBLE_ELEMENTS:
13101       return SetFastDoubleElement(object, index, value, strict_mode,
13102                                   check_prototype);
13103
13104 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
13105     case EXTERNAL_##TYPE##_ELEMENTS: {                                        \
13106       Handle<External##Type##Array> array(                                    \
13107           External##Type##Array::cast(object->elements()));                   \
13108       return External##Type##Array::SetValue(array, index, value);            \
13109     }                                                                         \
13110     case TYPE##_ELEMENTS: {                                                   \
13111       Handle<Fixed##Type##Array> array(                                       \
13112           Fixed##Type##Array::cast(object->elements()));                      \
13113       return Fixed##Type##Array::SetValue(array, index, value);               \
13114     }
13115
13116     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13117
13118 #undef TYPED_ARRAY_CASE
13119
13120     case DICTIONARY_ELEMENTS:
13121       return SetDictionaryElement(object, index, value, attributes, strict_mode,
13122                                   check_prototype,
13123                                   set_mode);
13124     case SLOPPY_ARGUMENTS_ELEMENTS: {
13125       Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
13126       uint32_t length = parameter_map->length();
13127       Handle<Object> probe = index < length - 2 ?
13128           Handle<Object>(parameter_map->get(index + 2), isolate) :
13129           Handle<Object>();
13130       if (!probe.is_null() && !probe->IsTheHole()) {
13131         Handle<Context> context(Context::cast(parameter_map->get(0)));
13132         int context_index = Handle<Smi>::cast(probe)->value();
13133         DCHECK(!context->get(context_index)->IsTheHole());
13134         context->set(context_index, *value);
13135         // Redefining attributes of an aliased element destroys fast aliasing.
13136         if (set_mode == SET_PROPERTY || attributes == NONE) return value;
13137         parameter_map->set_the_hole(index + 2);
13138         // For elements that are still writable we re-establish slow aliasing.
13139         if ((attributes & READ_ONLY) == 0) {
13140           value = Handle<Object>::cast(
13141               isolate->factory()->NewAliasedArgumentsEntry(context_index));
13142         }
13143       }
13144       Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
13145       if (arguments->IsDictionary()) {
13146         return SetDictionaryElement(object, index, value, attributes,
13147                                     strict_mode,
13148                                     check_prototype,
13149                                     set_mode);
13150       } else {
13151         return SetFastElement(object, index, value, strict_mode,
13152                               check_prototype);
13153       }
13154     }
13155   }
13156   // All possible cases have been handled above. Add a return to avoid the
13157   // complaints from the compiler.
13158   UNREACHABLE();
13159   return isolate->factory()->null_value();
13160 }
13161
13162
13163 const double AllocationSite::kPretenureRatio = 0.85;
13164
13165
13166 void AllocationSite::ResetPretenureDecision() {
13167   set_pretenure_decision(kUndecided);
13168   set_memento_found_count(0);
13169   set_memento_create_count(0);
13170 }
13171
13172
13173 PretenureFlag AllocationSite::GetPretenureMode() {
13174   PretenureDecision mode = pretenure_decision();
13175   // Zombie objects "decide" to be untenured.
13176   return mode == kTenure ? TENURED : NOT_TENURED;
13177 }
13178
13179
13180 bool AllocationSite::IsNestedSite() {
13181   DCHECK(FLAG_trace_track_allocation_sites);
13182   Object* current = GetHeap()->allocation_sites_list();
13183   while (current->IsAllocationSite()) {
13184     AllocationSite* current_site = AllocationSite::cast(current);
13185     if (current_site->nested_site() == this) {
13186       return true;
13187     }
13188     current = current_site->weak_next();
13189   }
13190   return false;
13191 }
13192
13193
13194 void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
13195                                               ElementsKind to_kind) {
13196   Isolate* isolate = site->GetIsolate();
13197
13198   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
13199     Handle<JSArray> transition_info =
13200         handle(JSArray::cast(site->transition_info()));
13201     ElementsKind kind = transition_info->GetElementsKind();
13202     // if kind is holey ensure that to_kind is as well.
13203     if (IsHoleyElementsKind(kind)) {
13204       to_kind = GetHoleyElementsKind(to_kind);
13205     }
13206     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
13207       // If the array is huge, it's not likely to be defined in a local
13208       // function, so we shouldn't make new instances of it very often.
13209       uint32_t length = 0;
13210       CHECK(transition_info->length()->ToArrayIndex(&length));
13211       if (length <= kMaximumArrayBytesToPretransition) {
13212         if (FLAG_trace_track_allocation_sites) {
13213           bool is_nested = site->IsNestedSite();
13214           PrintF(
13215               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
13216               reinterpret_cast<void*>(*site),
13217               is_nested ? "(nested)" : "",
13218               ElementsKindToString(kind),
13219               ElementsKindToString(to_kind));
13220         }
13221         JSObject::TransitionElementsKind(transition_info, to_kind);
13222         site->dependent_code()->DeoptimizeDependentCodeGroup(
13223             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
13224       }
13225     }
13226   } else {
13227     ElementsKind kind = site->GetElementsKind();
13228     // if kind is holey ensure that to_kind is as well.
13229     if (IsHoleyElementsKind(kind)) {
13230       to_kind = GetHoleyElementsKind(to_kind);
13231     }
13232     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
13233       if (FLAG_trace_track_allocation_sites) {
13234         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
13235                reinterpret_cast<void*>(*site),
13236                ElementsKindToString(kind),
13237                ElementsKindToString(to_kind));
13238       }
13239       site->SetElementsKind(to_kind);
13240       site->dependent_code()->DeoptimizeDependentCodeGroup(
13241           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
13242     }
13243   }
13244 }
13245
13246
13247 // static
13248 void AllocationSite::AddDependentCompilationInfo(Handle<AllocationSite> site,
13249                                                  Reason reason,
13250                                                  CompilationInfo* info) {
13251   DependentCode::DependencyGroup group = site->ToDependencyGroup(reason);
13252   Handle<DependentCode> dep(site->dependent_code());
13253   Handle<DependentCode> codes =
13254       DependentCode::Insert(dep, group, info->object_wrapper());
13255   if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
13256   info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
13257 }
13258
13259
13260 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
13261   switch (decision) {
13262     case kUndecided: return "undecided";
13263     case kDontTenure: return "don't tenure";
13264     case kMaybeTenure: return "maybe tenure";
13265     case kTenure: return "tenure";
13266     case kZombie: return "zombie";
13267     default: UNREACHABLE();
13268   }
13269   return NULL;
13270 }
13271
13272
13273 void JSObject::UpdateAllocationSite(Handle<JSObject> object,
13274                                     ElementsKind to_kind) {
13275   if (!object->IsJSArray()) return;
13276
13277   Heap* heap = object->GetHeap();
13278   if (!heap->InNewSpace(*object)) return;
13279
13280   Handle<AllocationSite> site;
13281   {
13282     DisallowHeapAllocation no_allocation;
13283
13284     AllocationMemento* memento = heap->FindAllocationMemento(*object);
13285     if (memento == NULL) return;
13286
13287     // Walk through to the Allocation Site
13288     site = handle(memento->GetAllocationSite());
13289   }
13290   AllocationSite::DigestTransitionFeedback(site, to_kind);
13291 }
13292
13293
13294 void JSObject::TransitionElementsKind(Handle<JSObject> object,
13295                                       ElementsKind to_kind) {
13296   ElementsKind from_kind = object->map()->elements_kind();
13297
13298   if (IsFastHoleyElementsKind(from_kind)) {
13299     to_kind = GetHoleyElementsKind(to_kind);
13300   }
13301
13302   if (from_kind == to_kind) return;
13303   // Don't update the site if to_kind isn't fast
13304   if (IsFastElementsKind(to_kind)) {
13305     UpdateAllocationSite(object, to_kind);
13306   }
13307
13308   Isolate* isolate = object->GetIsolate();
13309   if (object->elements() == isolate->heap()->empty_fixed_array() ||
13310       (IsFastSmiOrObjectElementsKind(from_kind) &&
13311        IsFastSmiOrObjectElementsKind(to_kind)) ||
13312       (from_kind == FAST_DOUBLE_ELEMENTS &&
13313        to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
13314     DCHECK(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
13315     // No change is needed to the elements() buffer, the transition
13316     // only requires a map change.
13317     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
13318     MigrateToMap(object, new_map);
13319     if (FLAG_trace_elements_transitions) {
13320       Handle<FixedArrayBase> elms(object->elements());
13321       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
13322     }
13323     return;
13324   }
13325
13326   Handle<FixedArrayBase> elms(object->elements());
13327   uint32_t capacity = static_cast<uint32_t>(elms->length());
13328   uint32_t length = capacity;
13329
13330   if (object->IsJSArray()) {
13331     Object* raw_length = Handle<JSArray>::cast(object)->length();
13332     if (raw_length->IsUndefined()) {
13333       // If length is undefined, then JSArray is being initialized and has no
13334       // elements, assume a length of zero.
13335       length = 0;
13336     } else {
13337       CHECK(raw_length->ToArrayIndex(&length));
13338     }
13339   }
13340
13341   if (IsFastSmiElementsKind(from_kind) &&
13342       IsFastDoubleElementsKind(to_kind)) {
13343     SetFastDoubleElementsCapacityAndLength(object, capacity, length);
13344     JSObject::ValidateElements(object);
13345     return;
13346   }
13347
13348   if (IsFastDoubleElementsKind(from_kind) &&
13349       IsFastObjectElementsKind(to_kind)) {
13350     SetFastElementsCapacityAndLength(object, capacity, length,
13351                                      kDontAllowSmiElements);
13352     JSObject::ValidateElements(object);
13353     return;
13354   }
13355
13356   // This method should never be called for any other case than the ones
13357   // handled above.
13358   UNREACHABLE();
13359 }
13360
13361
13362 // static
13363 bool Map::IsValidElementsTransition(ElementsKind from_kind,
13364                                     ElementsKind to_kind) {
13365   // Transitions can't go backwards.
13366   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
13367     return false;
13368   }
13369
13370   // Transitions from HOLEY -> PACKED are not allowed.
13371   return !IsFastHoleyElementsKind(from_kind) ||
13372       IsFastHoleyElementsKind(to_kind);
13373 }
13374
13375
13376 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array,
13377                                            uint32_t index,
13378                                            Handle<Object> value) {
13379   uint32_t old_len = 0;
13380   CHECK(array->length()->ToArrayIndex(&old_len));
13381   // Check to see if we need to update the length. For now, we make
13382   // sure that the length stays within 32-bits (unsigned).
13383   if (index >= old_len && index != 0xffffffff) {
13384     Handle<Object> len = array->GetIsolate()->factory()->NewNumber(
13385         static_cast<double>(index) + 1);
13386     array->set_length(*len);
13387   }
13388 }
13389
13390
13391 bool JSArray::IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map) {
13392     Isolate* isolate = jsarray_map->GetIsolate();
13393     DCHECK(!jsarray_map->is_dictionary_map());
13394     LookupResult lookup(isolate);
13395     Handle<Name> length_string = isolate->factory()->length_string();
13396     jsarray_map->LookupDescriptor(NULL, *length_string, &lookup);
13397     return lookup.IsReadOnly();
13398 }
13399
13400
13401 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
13402                                         uint32_t index) {
13403   uint32_t length = 0;
13404   CHECK(array->length()->ToArrayIndex(&length));
13405   if (length <= index) {
13406     Isolate* isolate = array->GetIsolate();
13407     LookupResult lookup(isolate);
13408     Handle<Name> length_string = isolate->factory()->length_string();
13409     array->LookupOwnRealNamedProperty(length_string, &lookup);
13410     return lookup.IsReadOnly();
13411   }
13412   return false;
13413 }
13414
13415
13416 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
13417   Isolate* isolate = array->GetIsolate();
13418   Handle<Name> length = isolate->factory()->length_string();
13419   Handle<Object> args[2] = { length, array };
13420   Handle<Object> error = isolate->factory()->NewTypeError(
13421       "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
13422   return isolate->Throw<Object>(error);
13423 }
13424
13425
13426 MaybeHandle<Object> JSObject::GetElementWithInterceptor(
13427     Handle<JSObject> object,
13428     Handle<Object> receiver,
13429     uint32_t index) {
13430   Isolate* isolate = object->GetIsolate();
13431
13432   // Make sure that the top context does not change when doing
13433   // callbacks or interceptor calls.
13434   AssertNoContextChange ncc(isolate);
13435
13436   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate);
13437   if (!interceptor->getter()->IsUndefined()) {
13438     v8::IndexedPropertyGetterCallback getter =
13439         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
13440     LOG(isolate,
13441         ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
13442     PropertyCallbackArguments
13443         args(isolate, interceptor->data(), *receiver, *object);
13444     v8::Handle<v8::Value> result = args.Call(getter, index);
13445     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13446     if (!result.IsEmpty()) {
13447       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13448       result_internal->VerifyApiCallResultType();
13449       // Rebox handle before return.
13450       return handle(*result_internal, isolate);
13451     }
13452   }
13453
13454   ElementsAccessor* handler = object->GetElementsAccessor();
13455   Handle<Object> result;
13456   ASSIGN_RETURN_ON_EXCEPTION(
13457       isolate, result, handler->Get(receiver,  object, index),
13458       Object);
13459   if (!result->IsTheHole()) return result;
13460
13461   PrototypeIterator iter(isolate, object);
13462   if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
13463   return Object::GetElementWithReceiver(
13464       isolate, PrototypeIterator::GetCurrent(iter), receiver, index);
13465 }
13466
13467
13468 bool JSObject::HasDenseElements() {
13469   int capacity = 0;
13470   int used = 0;
13471   GetElementsCapacityAndUsage(&capacity, &used);
13472   return (capacity == 0) || (used > (capacity / 2));
13473 }
13474
13475
13476 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
13477   *capacity = 0;
13478   *used = 0;
13479
13480   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
13481   FixedArray* backing_store = NULL;
13482   switch (GetElementsKind()) {
13483     case SLOPPY_ARGUMENTS_ELEMENTS:
13484       backing_store_base =
13485           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
13486       backing_store = FixedArray::cast(backing_store_base);
13487       if (backing_store->IsDictionary()) {
13488         SeededNumberDictionary* dictionary =
13489             SeededNumberDictionary::cast(backing_store);
13490         *capacity = dictionary->Capacity();
13491         *used = dictionary->NumberOfElements();
13492         break;
13493       }
13494       // Fall through.
13495     case FAST_SMI_ELEMENTS:
13496     case FAST_ELEMENTS:
13497       if (IsJSArray()) {
13498         *capacity = backing_store_base->length();
13499         *used = Smi::cast(JSArray::cast(this)->length())->value();
13500         break;
13501       }
13502       // Fall through if packing is not guaranteed.
13503     case FAST_HOLEY_SMI_ELEMENTS:
13504     case FAST_HOLEY_ELEMENTS:
13505       backing_store = FixedArray::cast(backing_store_base);
13506       *capacity = backing_store->length();
13507       for (int i = 0; i < *capacity; ++i) {
13508         if (!backing_store->get(i)->IsTheHole()) ++(*used);
13509       }
13510       break;
13511     case DICTIONARY_ELEMENTS: {
13512       SeededNumberDictionary* dictionary = element_dictionary();
13513       *capacity = dictionary->Capacity();
13514       *used = dictionary->NumberOfElements();
13515       break;
13516     }
13517     case FAST_DOUBLE_ELEMENTS:
13518       if (IsJSArray()) {
13519         *capacity = backing_store_base->length();
13520         *used = Smi::cast(JSArray::cast(this)->length())->value();
13521         break;
13522       }
13523       // Fall through if packing is not guaranteed.
13524     case FAST_HOLEY_DOUBLE_ELEMENTS: {
13525       *capacity = elements()->length();
13526       if (*capacity == 0) break;
13527       FixedDoubleArray * elms = FixedDoubleArray::cast(elements());
13528       for (int i = 0; i < *capacity; i++) {
13529         if (!elms->is_the_hole(i)) ++(*used);
13530       }
13531       break;
13532     }
13533
13534 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
13535     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
13536     case TYPE##_ELEMENTS:                                                    \
13537
13538     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13539 #undef TYPED_ARRAY_CASE
13540     {
13541       // External arrays are considered 100% used.
13542       FixedArrayBase* external_array = FixedArrayBase::cast(elements());
13543       *capacity = external_array->length();
13544       *used = external_array->length();
13545       break;
13546     }
13547   }
13548 }
13549
13550
13551 bool JSObject::WouldConvertToSlowElements(Handle<Object> key) {
13552   uint32_t index;
13553   if (HasFastElements() && key->ToArrayIndex(&index)) {
13554     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
13555     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
13556     if (index >= capacity) {
13557       if ((index - capacity) >= kMaxGap) return true;
13558       uint32_t new_capacity = NewElementsCapacity(index + 1);
13559       return ShouldConvertToSlowElements(new_capacity);
13560     }
13561   }
13562   return false;
13563 }
13564
13565
13566 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
13567   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
13568                 kMaxUncheckedFastElementsLength);
13569   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
13570       (new_capacity <= kMaxUncheckedFastElementsLength &&
13571        GetHeap()->InNewSpace(this))) {
13572     return false;
13573   }
13574   // If the fast-case backing storage takes up roughly three times as
13575   // much space (in machine words) as a dictionary backing storage
13576   // would, the object should have slow elements.
13577   int old_capacity = 0;
13578   int used_elements = 0;
13579   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
13580   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
13581       SeededNumberDictionary::kEntrySize;
13582   return 3 * dictionary_size <= new_capacity;
13583 }
13584
13585
13586 bool JSObject::ShouldConvertToFastElements() {
13587   DCHECK(HasDictionaryElements() || HasDictionaryArgumentsElements());
13588   // If the elements are sparse, we should not go back to fast case.
13589   if (!HasDenseElements()) return false;
13590   // An object requiring access checks is never allowed to have fast
13591   // elements.  If it had fast elements we would skip security checks.
13592   if (IsAccessCheckNeeded()) return false;
13593   // Observed objects may not go to fast mode because they rely on map checks,
13594   // and for fast element accesses we sometimes check element kinds only.
13595   if (map()->is_observed()) return false;
13596
13597   FixedArray* elements = FixedArray::cast(this->elements());
13598   SeededNumberDictionary* dictionary = NULL;
13599   if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) {
13600     dictionary = SeededNumberDictionary::cast(elements->get(1));
13601   } else {
13602     dictionary = SeededNumberDictionary::cast(elements);
13603   }
13604   // If an element has been added at a very high index in the elements
13605   // dictionary, we cannot go back to fast case.
13606   if (dictionary->requires_slow_elements()) return false;
13607   // If the dictionary backing storage takes up roughly half as much
13608   // space (in machine words) as a fast-case backing storage would,
13609   // the object should have fast elements.
13610   uint32_t array_size = 0;
13611   if (IsJSArray()) {
13612     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
13613   } else {
13614     array_size = dictionary->max_number_key();
13615   }
13616   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
13617       SeededNumberDictionary::kEntrySize;
13618   return 2 * dictionary_size >= array_size;
13619 }
13620
13621
13622 bool JSObject::ShouldConvertToFastDoubleElements(
13623     bool* has_smi_only_elements) {
13624   *has_smi_only_elements = false;
13625   if (HasSloppyArgumentsElements()) return false;
13626   if (FLAG_unbox_double_arrays) {
13627     DCHECK(HasDictionaryElements());
13628     SeededNumberDictionary* dictionary = element_dictionary();
13629     bool found_double = false;
13630     for (int i = 0; i < dictionary->Capacity(); i++) {
13631       Object* key = dictionary->KeyAt(i);
13632       if (key->IsNumber()) {
13633         Object* value = dictionary->ValueAt(i);
13634         if (!value->IsNumber()) return false;
13635         if (!value->IsSmi()) {
13636           found_double = true;
13637         }
13638       }
13639     }
13640     *has_smi_only_elements = !found_double;
13641     return found_double;
13642   } else {
13643     return false;
13644   }
13645 }
13646
13647
13648 // Certain compilers request function template instantiation when they
13649 // see the definition of the other template functions in the
13650 // class. This requires us to have the template functions put
13651 // together, so even though this function belongs in objects-debug.cc,
13652 // we keep it here instead to satisfy certain compilers.
13653 #ifdef OBJECT_PRINT
13654 template <typename Derived, typename Shape, typename Key>
13655 void Dictionary<Derived, Shape, Key>::Print(OStream& os) {  // NOLINT
13656   int capacity = DerivedHashTable::Capacity();
13657   for (int i = 0; i < capacity; i++) {
13658     Object* k = DerivedHashTable::KeyAt(i);
13659     if (DerivedHashTable::IsKey(k)) {
13660       os << " ";
13661       if (k->IsString()) {
13662         String::cast(k)->StringPrint(os);
13663       } else {
13664         os << Brief(k);
13665       }
13666       os << ": " << Brief(ValueAt(i)) << "\n";
13667     }
13668   }
13669 }
13670 #endif
13671
13672
13673 template<typename Derived, typename Shape, typename Key>
13674 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
13675   int pos = 0;
13676   int capacity = DerivedHashTable::Capacity();
13677   DisallowHeapAllocation no_gc;
13678   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
13679   for (int i = 0; i < capacity; i++) {
13680     Object* k =  Dictionary::KeyAt(i);
13681     if (Dictionary::IsKey(k)) {
13682       elements->set(pos++, ValueAt(i), mode);
13683     }
13684   }
13685   DCHECK(pos == elements->length());
13686 }
13687
13688
13689 InterceptorInfo* JSObject::GetNamedInterceptor() {
13690   DCHECK(map()->has_named_interceptor());
13691   JSFunction* constructor = JSFunction::cast(map()->constructor());
13692   DCHECK(constructor->shared()->IsApiFunction());
13693   Object* result =
13694       constructor->shared()->get_api_func_data()->named_property_handler();
13695   return InterceptorInfo::cast(result);
13696 }
13697
13698
13699 InterceptorInfo* JSObject::GetIndexedInterceptor() {
13700   DCHECK(map()->has_indexed_interceptor());
13701   JSFunction* constructor = JSFunction::cast(map()->constructor());
13702   DCHECK(constructor->shared()->IsApiFunction());
13703   Object* result =
13704       constructor->shared()->get_api_func_data()->indexed_property_handler();
13705   return InterceptorInfo::cast(result);
13706 }
13707
13708
13709 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(
13710     Handle<JSObject> holder,
13711     Handle<Object> receiver,
13712     Handle<Name> name) {
13713   Isolate* isolate = holder->GetIsolate();
13714
13715   // TODO(rossberg): Support symbols in the API.
13716   if (name->IsSymbol()) return isolate->factory()->undefined_value();
13717
13718   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor(), isolate);
13719   Handle<String> name_string = Handle<String>::cast(name);
13720
13721   if (interceptor->getter()->IsUndefined()) return MaybeHandle<Object>();
13722
13723   v8::NamedPropertyGetterCallback getter =
13724       v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
13725   LOG(isolate,
13726       ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
13727   PropertyCallbackArguments
13728       args(isolate, interceptor->data(), *receiver, *holder);
13729   v8::Handle<v8::Value> result =
13730       args.Call(getter, v8::Utils::ToLocal(name_string));
13731   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13732   if (result.IsEmpty()) return MaybeHandle<Object>();
13733
13734   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13735   result_internal->VerifyApiCallResultType();
13736   // Rebox handle before return
13737   return handle(*result_internal, isolate);
13738 }
13739
13740
13741 // Compute the property keys from the interceptor.
13742 // TODO(rossberg): support symbols in API, and filter here if needed.
13743 MaybeHandle<JSObject> JSObject::GetKeysForNamedInterceptor(
13744     Handle<JSObject> object, Handle<JSReceiver> receiver) {
13745   Isolate* isolate = receiver->GetIsolate();
13746   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
13747   PropertyCallbackArguments
13748       args(isolate, interceptor->data(), *receiver, *object);
13749   v8::Handle<v8::Object> result;
13750   if (!interceptor->enumerator()->IsUndefined()) {
13751     v8::NamedPropertyEnumeratorCallback enum_fun =
13752         v8::ToCData<v8::NamedPropertyEnumeratorCallback>(
13753             interceptor->enumerator());
13754     LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
13755     result = args.Call(enum_fun);
13756   }
13757   if (result.IsEmpty()) return MaybeHandle<JSObject>();
13758 #if ENABLE_EXTRA_CHECKS
13759   CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13760         v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13761 #endif
13762   // Rebox before returning.
13763   return handle(*v8::Utils::OpenHandle(*result), isolate);
13764 }
13765
13766
13767 // Compute the element keys from the interceptor.
13768 MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor(
13769     Handle<JSObject> object, Handle<JSReceiver> receiver) {
13770   Isolate* isolate = receiver->GetIsolate();
13771   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
13772   PropertyCallbackArguments
13773       args(isolate, interceptor->data(), *receiver, *object);
13774   v8::Handle<v8::Object> result;
13775   if (!interceptor->enumerator()->IsUndefined()) {
13776     v8::IndexedPropertyEnumeratorCallback enum_fun =
13777         v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
13778             interceptor->enumerator());
13779     LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
13780     result = args.Call(enum_fun);
13781   }
13782   if (result.IsEmpty()) return MaybeHandle<JSObject>();
13783 #if ENABLE_EXTRA_CHECKS
13784   CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13785         v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13786 #endif
13787   // Rebox before returning.
13788   return handle(*v8::Utils::OpenHandle(*result), isolate);
13789 }
13790
13791
13792 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
13793                                            Handle<Name> key) {
13794   Isolate* isolate = object->GetIsolate();
13795   SealHandleScope shs(isolate);
13796   // Check access rights if needed.
13797   if (object->IsAccessCheckNeeded()) {
13798     if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) {
13799       isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
13800       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>());
13801       return maybe(false);
13802     }
13803   }
13804
13805   LookupResult result(isolate);
13806   object->LookupOwnRealNamedProperty(key, &result);
13807   return maybe(result.IsFound() && !result.IsInterceptor());
13808 }
13809
13810
13811 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
13812                                              uint32_t index) {
13813   Isolate* isolate = object->GetIsolate();
13814   HandleScope scope(isolate);
13815   // Check access rights if needed.
13816   if (object->IsAccessCheckNeeded()) {
13817     if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
13818       isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
13819       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>());
13820       return maybe(false);
13821     }
13822   }
13823
13824   if (object->IsJSGlobalProxy()) {
13825     HandleScope scope(isolate);
13826     PrototypeIterator iter(isolate, object);
13827     if (iter.IsAtEnd()) return maybe(false);
13828     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
13829     return HasRealElementProperty(
13830         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
13831   }
13832
13833   Maybe<PropertyAttributes> result =
13834       GetElementAttributeWithoutInterceptor(object, object, index, false);
13835   if (!result.has_value) return Maybe<bool>();
13836   return maybe(result.value != ABSENT);
13837 }
13838
13839
13840 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
13841                                                    Handle<Name> key) {
13842   Isolate* isolate = object->GetIsolate();
13843   SealHandleScope shs(isolate);
13844   // Check access rights if needed.
13845   if (object->IsAccessCheckNeeded()) {
13846     if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) {
13847       isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
13848       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>());
13849       return maybe(false);
13850     }
13851   }
13852
13853   LookupResult result(isolate);
13854   object->LookupOwnRealNamedProperty(key, &result);
13855   return maybe(result.IsPropertyCallbacks());
13856 }
13857
13858
13859 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) {
13860   if (HasFastProperties()) {
13861     Map* map = this->map();
13862     if (filter == NONE) return map->NumberOfOwnDescriptors();
13863     if (filter & DONT_ENUM) {
13864       int result = map->EnumLength();
13865       if (result != kInvalidEnumCacheSentinel) return result;
13866     }
13867     return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
13868   }
13869   return property_dictionary()->NumberOfElementsFilterAttributes(filter);
13870 }
13871
13872
13873 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
13874   Object* temp = get(i);
13875   set(i, get(j));
13876   set(j, temp);
13877   if (this != numbers) {
13878     temp = numbers->get(i);
13879     numbers->set(i, Smi::cast(numbers->get(j)));
13880     numbers->set(j, Smi::cast(temp));
13881   }
13882 }
13883
13884
13885 static void InsertionSortPairs(FixedArray* content,
13886                                FixedArray* numbers,
13887                                int len) {
13888   for (int i = 1; i < len; i++) {
13889     int j = i;
13890     while (j > 0 &&
13891            (NumberToUint32(numbers->get(j - 1)) >
13892             NumberToUint32(numbers->get(j)))) {
13893       content->SwapPairs(numbers, j - 1, j);
13894       j--;
13895     }
13896   }
13897 }
13898
13899
13900 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
13901   // In-place heap sort.
13902   DCHECK(content->length() == numbers->length());
13903
13904   // Bottom-up max-heap construction.
13905   for (int i = 1; i < len; ++i) {
13906     int child_index = i;
13907     while (child_index > 0) {
13908       int parent_index = ((child_index + 1) >> 1) - 1;
13909       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13910       uint32_t child_value = NumberToUint32(numbers->get(child_index));
13911       if (parent_value < child_value) {
13912         content->SwapPairs(numbers, parent_index, child_index);
13913       } else {
13914         break;
13915       }
13916       child_index = parent_index;
13917     }
13918   }
13919
13920   // Extract elements and create sorted array.
13921   for (int i = len - 1; i > 0; --i) {
13922     // Put max element at the back of the array.
13923     content->SwapPairs(numbers, 0, i);
13924     // Sift down the new top element.
13925     int parent_index = 0;
13926     while (true) {
13927       int child_index = ((parent_index + 1) << 1) - 1;
13928       if (child_index >= i) break;
13929       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
13930       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
13931       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13932       if (child_index + 1 >= i || child1_value > child2_value) {
13933         if (parent_value > child1_value) break;
13934         content->SwapPairs(numbers, parent_index, child_index);
13935         parent_index = child_index;
13936       } else {
13937         if (parent_value > child2_value) break;
13938         content->SwapPairs(numbers, parent_index, child_index + 1);
13939         parent_index = child_index + 1;
13940       }
13941     }
13942   }
13943 }
13944
13945
13946 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
13947 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
13948   DCHECK(this->length() == numbers->length());
13949   // For small arrays, simply use insertion sort.
13950   if (len <= 10) {
13951     InsertionSortPairs(this, numbers, len);
13952     return;
13953   }
13954   // Check the range of indices.
13955   uint32_t min_index = NumberToUint32(numbers->get(0));
13956   uint32_t max_index = min_index;
13957   uint32_t i;
13958   for (i = 1; i < len; i++) {
13959     if (NumberToUint32(numbers->get(i)) < min_index) {
13960       min_index = NumberToUint32(numbers->get(i));
13961     } else if (NumberToUint32(numbers->get(i)) > max_index) {
13962       max_index = NumberToUint32(numbers->get(i));
13963     }
13964   }
13965   if (max_index - min_index + 1 == len) {
13966     // Indices form a contiguous range, unless there are duplicates.
13967     // Do an in-place linear time sort assuming distinct numbers, but
13968     // avoid hanging in case they are not.
13969     for (i = 0; i < len; i++) {
13970       uint32_t p;
13971       uint32_t j = 0;
13972       // While the current element at i is not at its correct position p,
13973       // swap the elements at these two positions.
13974       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
13975              j++ < len) {
13976         SwapPairs(numbers, i, p);
13977       }
13978     }
13979   } else {
13980     HeapSortPairs(this, numbers, len);
13981     return;
13982   }
13983 }
13984
13985
13986 // Fill in the names of own properties into the supplied storage. The main
13987 // purpose of this function is to provide reflection information for the object
13988 // mirrors.
13989 void JSObject::GetOwnPropertyNames(
13990     FixedArray* storage, int index, PropertyAttributes filter) {
13991   DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index));
13992   if (HasFastProperties()) {
13993     int real_size = map()->NumberOfOwnDescriptors();
13994     DescriptorArray* descs = map()->instance_descriptors();
13995     for (int i = 0; i < real_size; i++) {
13996       if ((descs->GetDetails(i).attributes() & filter) == 0 &&
13997           !FilterKey(descs->GetKey(i), filter)) {
13998         storage->set(index++, descs->GetKey(i));
13999       }
14000     }
14001   } else {
14002     property_dictionary()->CopyKeysTo(storage,
14003                                       index,
14004                                       filter,
14005                                       NameDictionary::UNSORTED);
14006   }
14007 }
14008
14009
14010 int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
14011   return GetOwnElementKeys(NULL, filter);
14012 }
14013
14014
14015 int JSObject::NumberOfEnumElements() {
14016   // Fast case for objects with no elements.
14017   if (!IsJSValue() && HasFastObjectElements()) {
14018     uint32_t length = IsJSArray() ?
14019         static_cast<uint32_t>(
14020             Smi::cast(JSArray::cast(this)->length())->value()) :
14021         static_cast<uint32_t>(FixedArray::cast(elements())->length());
14022     if (length == 0) return 0;
14023   }
14024   // Compute the number of enumerable elements.
14025   return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
14026 }
14027
14028
14029 int JSObject::GetOwnElementKeys(FixedArray* storage,
14030                                 PropertyAttributes filter) {
14031   int counter = 0;
14032   switch (GetElementsKind()) {
14033     case FAST_SMI_ELEMENTS:
14034     case FAST_ELEMENTS:
14035     case FAST_HOLEY_SMI_ELEMENTS:
14036     case FAST_HOLEY_ELEMENTS: {
14037       int length = IsJSArray() ?
14038           Smi::cast(JSArray::cast(this)->length())->value() :
14039           FixedArray::cast(elements())->length();
14040       for (int i = 0; i < length; i++) {
14041         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
14042           if (storage != NULL) {
14043             storage->set(counter, Smi::FromInt(i));
14044           }
14045           counter++;
14046         }
14047       }
14048       DCHECK(!storage || storage->length() >= counter);
14049       break;
14050     }
14051     case FAST_DOUBLE_ELEMENTS:
14052     case FAST_HOLEY_DOUBLE_ELEMENTS: {
14053       int length = IsJSArray() ?
14054           Smi::cast(JSArray::cast(this)->length())->value() :
14055           FixedArrayBase::cast(elements())->length();
14056       for (int i = 0; i < length; i++) {
14057         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
14058           if (storage != NULL) {
14059             storage->set(counter, Smi::FromInt(i));
14060           }
14061           counter++;
14062         }
14063       }
14064       DCHECK(!storage || storage->length() >= counter);
14065       break;
14066     }
14067
14068 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
14069     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
14070     case TYPE##_ELEMENTS:                                                    \
14071
14072     TYPED_ARRAYS(TYPED_ARRAY_CASE)
14073 #undef TYPED_ARRAY_CASE
14074     {
14075       int length = FixedArrayBase::cast(elements())->length();
14076       while (counter < length) {
14077         if (storage != NULL) {
14078           storage->set(counter, Smi::FromInt(counter));
14079         }
14080         counter++;
14081       }
14082       DCHECK(!storage || storage->length() >= counter);
14083       break;
14084     }
14085
14086     case DICTIONARY_ELEMENTS: {
14087       if (storage != NULL) {
14088         element_dictionary()->CopyKeysTo(storage,
14089                                          filter,
14090                                          SeededNumberDictionary::SORTED);
14091       }
14092       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
14093       break;
14094     }
14095     case SLOPPY_ARGUMENTS_ELEMENTS: {
14096       FixedArray* parameter_map = FixedArray::cast(elements());
14097       int mapped_length = parameter_map->length() - 2;
14098       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
14099       if (arguments->IsDictionary()) {
14100         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
14101         // will insert in storage starting at index 0.
14102         SeededNumberDictionary* dictionary =
14103             SeededNumberDictionary::cast(arguments);
14104         if (storage != NULL) {
14105           dictionary->CopyKeysTo(
14106               storage, filter, SeededNumberDictionary::UNSORTED);
14107         }
14108         counter += dictionary->NumberOfElementsFilterAttributes(filter);
14109         for (int i = 0; i < mapped_length; ++i) {
14110           if (!parameter_map->get(i + 2)->IsTheHole()) {
14111             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14112             ++counter;
14113           }
14114         }
14115         if (storage != NULL) storage->SortPairs(storage, counter);
14116
14117       } else {
14118         int backing_length = arguments->length();
14119         int i = 0;
14120         for (; i < mapped_length; ++i) {
14121           if (!parameter_map->get(i + 2)->IsTheHole()) {
14122             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14123             ++counter;
14124           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
14125             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14126             ++counter;
14127           }
14128         }
14129         for (; i < backing_length; ++i) {
14130           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14131           ++counter;
14132         }
14133       }
14134       break;
14135     }
14136   }
14137
14138   if (this->IsJSValue()) {
14139     Object* val = JSValue::cast(this)->value();
14140     if (val->IsString()) {
14141       String* str = String::cast(val);
14142       if (storage) {
14143         for (int i = 0; i < str->length(); i++) {
14144           storage->set(counter + i, Smi::FromInt(i));
14145         }
14146       }
14147       counter += str->length();
14148     }
14149   }
14150   DCHECK(!storage || storage->length() == counter);
14151   return counter;
14152 }
14153
14154
14155 int JSObject::GetEnumElementKeys(FixedArray* storage) {
14156   return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
14157 }
14158
14159
14160 // StringSharedKeys are used as keys in the eval cache.
14161 class StringSharedKey : public HashTableKey {
14162  public:
14163   StringSharedKey(Handle<String> source,
14164                   Handle<SharedFunctionInfo> shared,
14165                   StrictMode strict_mode,
14166                   int scope_position)
14167       : source_(source),
14168         shared_(shared),
14169         strict_mode_(strict_mode),
14170         scope_position_(scope_position) { }
14171
14172   bool IsMatch(Object* other) V8_OVERRIDE {
14173     DisallowHeapAllocation no_allocation;
14174     if (!other->IsFixedArray()) return false;
14175     FixedArray* other_array = FixedArray::cast(other);
14176     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
14177     if (shared != *shared_) return false;
14178     int strict_unchecked = Smi::cast(other_array->get(2))->value();
14179     DCHECK(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
14180     StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
14181     if (strict_mode != strict_mode_) return false;
14182     int scope_position = Smi::cast(other_array->get(3))->value();
14183     if (scope_position != scope_position_) return false;
14184     String* source = String::cast(other_array->get(1));
14185     return source->Equals(*source_);
14186   }
14187
14188   static uint32_t StringSharedHashHelper(String* source,
14189                                          SharedFunctionInfo* shared,
14190                                          StrictMode strict_mode,
14191                                          int scope_position) {
14192     uint32_t hash = source->Hash();
14193     if (shared->HasSourceCode()) {
14194       // Instead of using the SharedFunctionInfo pointer in the hash
14195       // code computation, we use a combination of the hash of the
14196       // script source code and the start position of the calling scope.
14197       // We do this to ensure that the cache entries can survive garbage
14198       // collection.
14199       Script* script(Script::cast(shared->script()));
14200       hash ^= String::cast(script->source())->Hash();
14201       if (strict_mode == STRICT) hash ^= 0x8000;
14202       hash += scope_position;
14203     }
14204     return hash;
14205   }
14206
14207   uint32_t Hash() V8_OVERRIDE {
14208     return StringSharedHashHelper(*source_, *shared_, strict_mode_,
14209                                   scope_position_);
14210   }
14211
14212   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
14213     DisallowHeapAllocation no_allocation;
14214     FixedArray* other_array = FixedArray::cast(obj);
14215     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
14216     String* source = String::cast(other_array->get(1));
14217     int strict_unchecked = Smi::cast(other_array->get(2))->value();
14218     DCHECK(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
14219     StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
14220     int scope_position = Smi::cast(other_array->get(3))->value();
14221     return StringSharedHashHelper(
14222         source, shared, strict_mode, scope_position);
14223   }
14224
14225
14226   Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
14227     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
14228     array->set(0, *shared_);
14229     array->set(1, *source_);
14230     array->set(2, Smi::FromInt(strict_mode_));
14231     array->set(3, Smi::FromInt(scope_position_));
14232     return array;
14233   }
14234
14235  private:
14236   Handle<String> source_;
14237   Handle<SharedFunctionInfo> shared_;
14238   StrictMode strict_mode_;
14239   int scope_position_;
14240 };
14241
14242
14243 // RegExpKey carries the source and flags of a regular expression as key.
14244 class RegExpKey : public HashTableKey {
14245  public:
14246   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
14247       : string_(string),
14248         flags_(Smi::FromInt(flags.value())) { }
14249
14250   // Rather than storing the key in the hash table, a pointer to the
14251   // stored value is stored where the key should be.  IsMatch then
14252   // compares the search key to the found object, rather than comparing
14253   // a key to a key.
14254   bool IsMatch(Object* obj) V8_OVERRIDE {
14255     FixedArray* val = FixedArray::cast(obj);
14256     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
14257         && (flags_ == val->get(JSRegExp::kFlagsIndex));
14258   }
14259
14260   uint32_t Hash() V8_OVERRIDE { return RegExpHash(*string_, flags_); }
14261
14262   Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
14263     // Plain hash maps, which is where regexp keys are used, don't
14264     // use this function.
14265     UNREACHABLE();
14266     return MaybeHandle<Object>().ToHandleChecked();
14267   }
14268
14269   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
14270     FixedArray* val = FixedArray::cast(obj);
14271     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
14272                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
14273   }
14274
14275   static uint32_t RegExpHash(String* string, Smi* flags) {
14276     return string->Hash() + flags->value();
14277   }
14278
14279   Handle<String> string_;
14280   Smi* flags_;
14281 };
14282
14283
14284 Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
14285   if (hash_field_ == 0) Hash();
14286   return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
14287 }
14288
14289
14290 Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
14291   if (hash_field_ == 0) Hash();
14292   return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
14293 }
14294
14295
14296 template<>
14297 const uint8_t* SubStringKey<uint8_t>::GetChars() {
14298   return string_->IsSeqOneByteString()
14299       ? SeqOneByteString::cast(*string_)->GetChars()
14300       : ExternalAsciiString::cast(*string_)->GetChars();
14301 }
14302
14303
14304 template<>
14305 const uint16_t* SubStringKey<uint16_t>::GetChars() {
14306   return string_->IsSeqTwoByteString()
14307       ? SeqTwoByteString::cast(*string_)->GetChars()
14308       : ExternalTwoByteString::cast(*string_)->GetChars();
14309 }
14310
14311
14312 template<>
14313 Handle<Object> SubStringKey<uint8_t>::AsHandle(Isolate* isolate) {
14314   if (hash_field_ == 0) Hash();
14315   Vector<const uint8_t> chars(GetChars() + from_, length_);
14316   return isolate->factory()->NewOneByteInternalizedString(chars, hash_field_);
14317 }
14318
14319
14320 template<>
14321 Handle<Object> SubStringKey<uint16_t>::AsHandle(Isolate* isolate) {
14322   if (hash_field_ == 0) Hash();
14323   Vector<const uint16_t> chars(GetChars() + from_, length_);
14324   return isolate->factory()->NewTwoByteInternalizedString(chars, hash_field_);
14325 }
14326
14327
14328 template<>
14329 bool SubStringKey<uint8_t>::IsMatch(Object* string) {
14330   Vector<const uint8_t> chars(GetChars() + from_, length_);
14331   return String::cast(string)->IsOneByteEqualTo(chars);
14332 }
14333
14334
14335 template<>
14336 bool SubStringKey<uint16_t>::IsMatch(Object* string) {
14337   Vector<const uint16_t> chars(GetChars() + from_, length_);
14338   return String::cast(string)->IsTwoByteEqualTo(chars);
14339 }
14340
14341
14342 template class SubStringKey<uint8_t>;
14343 template class SubStringKey<uint16_t>;
14344
14345
14346 // InternalizedStringKey carries a string/internalized-string object as key.
14347 class InternalizedStringKey : public HashTableKey {
14348  public:
14349   explicit InternalizedStringKey(Handle<String> string)
14350       : string_(string) { }
14351
14352   virtual bool IsMatch(Object* string) V8_OVERRIDE {
14353     return String::cast(string)->Equals(*string_);
14354   }
14355
14356   virtual uint32_t Hash() V8_OVERRIDE { return string_->Hash(); }
14357
14358   virtual uint32_t HashForObject(Object* other) V8_OVERRIDE {
14359     return String::cast(other)->Hash();
14360   }
14361
14362   virtual Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
14363     // Internalize the string if possible.
14364     MaybeHandle<Map> maybe_map =
14365         isolate->factory()->InternalizedStringMapForString(string_);
14366     Handle<Map> map;
14367     if (maybe_map.ToHandle(&map)) {
14368       string_->set_map_no_write_barrier(*map);
14369       DCHECK(string_->IsInternalizedString());
14370       return string_;
14371     }
14372     // Otherwise allocate a new internalized string.
14373     return isolate->factory()->NewInternalizedStringImpl(
14374         string_, string_->length(), string_->hash_field());
14375   }
14376
14377   static uint32_t StringHash(Object* obj) {
14378     return String::cast(obj)->Hash();
14379   }
14380
14381   Handle<String> string_;
14382 };
14383
14384
14385 template<typename Derived, typename Shape, typename Key>
14386 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
14387   IteratePointers(v, 0, kElementsStartOffset);
14388 }
14389
14390
14391 template<typename Derived, typename Shape, typename Key>
14392 void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
14393   IteratePointers(v,
14394                   kElementsStartOffset,
14395                   kHeaderSize + length() * kPointerSize);
14396 }
14397
14398
14399 template<typename Derived, typename Shape, typename Key>
14400 Handle<Derived> HashTable<Derived, Shape, Key>::New(
14401     Isolate* isolate,
14402     int at_least_space_for,
14403     MinimumCapacity capacity_option,
14404     PretenureFlag pretenure) {
14405   DCHECK(0 <= at_least_space_for);
14406   DCHECK(!capacity_option || IsPowerOf2(at_least_space_for));
14407   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
14408                      ? at_least_space_for
14409                      : ComputeCapacity(at_least_space_for);
14410   if (capacity > HashTable::kMaxCapacity) {
14411     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
14412   }
14413
14414   Factory* factory = isolate->factory();
14415   int length = EntryToIndex(capacity);
14416   Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
14417   array->set_map_no_write_barrier(*factory->hash_table_map());
14418   Handle<Derived> table = Handle<Derived>::cast(array);
14419
14420   table->SetNumberOfElements(0);
14421   table->SetNumberOfDeletedElements(0);
14422   table->SetCapacity(capacity);
14423   return table;
14424 }
14425
14426
14427 // Find entry for key otherwise return kNotFound.
14428 int NameDictionary::FindEntry(Handle<Name> key) {
14429   if (!key->IsUniqueName()) {
14430     return DerivedHashTable::FindEntry(key);
14431   }
14432
14433   // Optimized for unique names. Knowledge of the key type allows:
14434   // 1. Move the check if the key is unique out of the loop.
14435   // 2. Avoid comparing hash codes in unique-to-unique comparison.
14436   // 3. Detect a case when a dictionary key is not unique but the key is.
14437   //    In case of positive result the dictionary key may be replaced by the
14438   //    internalized string with minimal performance penalty. It gives a chance
14439   //    to perform further lookups in code stubs (and significant performance
14440   //    boost a certain style of code).
14441
14442   // EnsureCapacity will guarantee the hash table is never full.
14443   uint32_t capacity = Capacity();
14444   uint32_t entry = FirstProbe(key->Hash(), capacity);
14445   uint32_t count = 1;
14446
14447   while (true) {
14448     int index = EntryToIndex(entry);
14449     Object* element = get(index);
14450     if (element->IsUndefined()) break;  // Empty entry.
14451     if (*key == element) return entry;
14452     if (!element->IsUniqueName() &&
14453         !element->IsTheHole() &&
14454         Name::cast(element)->Equals(*key)) {
14455       // Replace a key that is a non-internalized string by the equivalent
14456       // internalized string for faster further lookups.
14457       set(index, *key);
14458       return entry;
14459     }
14460     DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
14461     entry = NextProbe(entry, count++, capacity);
14462   }
14463   return kNotFound;
14464 }
14465
14466
14467 template<typename Derived, typename Shape, typename Key>
14468 void HashTable<Derived, Shape, Key>::Rehash(
14469     Handle<Derived> new_table,
14470     Key key) {
14471   DCHECK(NumberOfElements() < new_table->Capacity());
14472
14473   DisallowHeapAllocation no_gc;
14474   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
14475
14476   // Copy prefix to new array.
14477   for (int i = kPrefixStartIndex;
14478        i < kPrefixStartIndex + Shape::kPrefixSize;
14479        i++) {
14480     new_table->set(i, get(i), mode);
14481   }
14482
14483   // Rehash the elements.
14484   int capacity = Capacity();
14485   for (int i = 0; i < capacity; i++) {
14486     uint32_t from_index = EntryToIndex(i);
14487     Object* k = get(from_index);
14488     if (IsKey(k)) {
14489       uint32_t hash = HashTable::HashForObject(key, k);
14490       uint32_t insertion_index =
14491           EntryToIndex(new_table->FindInsertionEntry(hash));
14492       for (int j = 0; j < Shape::kEntrySize; j++) {
14493         new_table->set(insertion_index + j, get(from_index + j), mode);
14494       }
14495     }
14496   }
14497   new_table->SetNumberOfElements(NumberOfElements());
14498   new_table->SetNumberOfDeletedElements(0);
14499 }
14500
14501
14502 template<typename Derived, typename Shape, typename Key>
14503 uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
14504     Key key,
14505     Object* k,
14506     int probe,
14507     uint32_t expected) {
14508   uint32_t hash = HashTable::HashForObject(key, k);
14509   uint32_t capacity = Capacity();
14510   uint32_t entry = FirstProbe(hash, capacity);
14511   for (int i = 1; i < probe; i++) {
14512     if (entry == expected) return expected;
14513     entry = NextProbe(entry, i, capacity);
14514   }
14515   return entry;
14516 }
14517
14518
14519 template<typename Derived, typename Shape, typename Key>
14520 void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
14521                                           uint32_t entry2,
14522                                           WriteBarrierMode mode) {
14523   int index1 = EntryToIndex(entry1);
14524   int index2 = EntryToIndex(entry2);
14525   Object* temp[Shape::kEntrySize];
14526   for (int j = 0; j < Shape::kEntrySize; j++) {
14527     temp[j] = get(index1 + j);
14528   }
14529   for (int j = 0; j < Shape::kEntrySize; j++) {
14530     set(index1 + j, get(index2 + j), mode);
14531   }
14532   for (int j = 0; j < Shape::kEntrySize; j++) {
14533     set(index2 + j, temp[j], mode);
14534   }
14535 }
14536
14537
14538 template<typename Derived, typename Shape, typename Key>
14539 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
14540   DisallowHeapAllocation no_gc;
14541   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
14542   uint32_t capacity = Capacity();
14543   bool done = false;
14544   for (int probe = 1; !done; probe++) {
14545     // All elements at entries given by one of the first _probe_ probes
14546     // are placed correctly. Other elements might need to be moved.
14547     done = true;
14548     for (uint32_t current = 0; current < capacity; current++) {
14549       Object* current_key = get(EntryToIndex(current));
14550       if (IsKey(current_key)) {
14551         uint32_t target = EntryForProbe(key, current_key, probe, current);
14552         if (current == target) continue;
14553         Object* target_key = get(EntryToIndex(target));
14554         if (!IsKey(target_key) ||
14555             EntryForProbe(key, target_key, probe, target) != target) {
14556           // Put the current element into the correct position.
14557           Swap(current, target, mode);
14558           // The other element will be processed on the next iteration.
14559           current--;
14560         } else {
14561           // The place for the current element is occupied. Leave the element
14562           // for the next probe.
14563           done = false;
14564         }
14565       }
14566     }
14567   }
14568 }
14569
14570
14571 template<typename Derived, typename Shape, typename Key>
14572 Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
14573     Handle<Derived> table,
14574     int n,
14575     Key key,
14576     PretenureFlag pretenure) {
14577   Isolate* isolate = table->GetIsolate();
14578   int capacity = table->Capacity();
14579   int nof = table->NumberOfElements() + n;
14580   int nod = table->NumberOfDeletedElements();
14581   // Return if:
14582   //   50% is still free after adding n elements and
14583   //   at most 50% of the free elements are deleted elements.
14584   if (nod <= (capacity - nof) >> 1) {
14585     int needed_free = nof >> 1;
14586     if (nof + needed_free <= capacity) return table;
14587   }
14588
14589   const int kMinCapacityForPretenure = 256;
14590   bool should_pretenure = pretenure == TENURED ||
14591       ((capacity > kMinCapacityForPretenure) &&
14592           !isolate->heap()->InNewSpace(*table));
14593   Handle<Derived> new_table = HashTable::New(
14594       isolate,
14595       nof * 2,
14596       USE_DEFAULT_MINIMUM_CAPACITY,
14597       should_pretenure ? TENURED : NOT_TENURED);
14598
14599   table->Rehash(new_table, key);
14600   return new_table;
14601 }
14602
14603
14604 template<typename Derived, typename Shape, typename Key>
14605 Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
14606                                                        Key key) {
14607   int capacity = table->Capacity();
14608   int nof = table->NumberOfElements();
14609
14610   // Shrink to fit the number of elements if only a quarter of the
14611   // capacity is filled with elements.
14612   if (nof > (capacity >> 2)) return table;
14613   // Allocate a new dictionary with room for at least the current
14614   // number of elements. The allocation method will make sure that
14615   // there is extra room in the dictionary for additions. Don't go
14616   // lower than room for 16 elements.
14617   int at_least_room_for = nof;
14618   if (at_least_room_for < 16) return table;
14619
14620   Isolate* isolate = table->GetIsolate();
14621   const int kMinCapacityForPretenure = 256;
14622   bool pretenure =
14623       (at_least_room_for > kMinCapacityForPretenure) &&
14624       !isolate->heap()->InNewSpace(*table);
14625   Handle<Derived> new_table = HashTable::New(
14626       isolate,
14627       at_least_room_for,
14628       USE_DEFAULT_MINIMUM_CAPACITY,
14629       pretenure ? TENURED : NOT_TENURED);
14630
14631   table->Rehash(new_table, key);
14632   return new_table;
14633 }
14634
14635
14636 template<typename Derived, typename Shape, typename Key>
14637 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
14638   uint32_t capacity = Capacity();
14639   uint32_t entry = FirstProbe(hash, capacity);
14640   uint32_t count = 1;
14641   // EnsureCapacity will guarantee the hash table is never full.
14642   while (true) {
14643     Object* element = KeyAt(entry);
14644     if (element->IsUndefined() || element->IsTheHole()) break;
14645     entry = NextProbe(entry, count++, capacity);
14646   }
14647   return entry;
14648 }
14649
14650
14651 // Force instantiation of template instances class.
14652 // Please note this list is compiler dependent.
14653
14654 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
14655
14656 template class HashTable<CompilationCacheTable,
14657                          CompilationCacheShape,
14658                          HashTableKey*>;
14659
14660 template class HashTable<MapCache, MapCacheShape, HashTableKey*>;
14661
14662 template class HashTable<ObjectHashTable,
14663                          ObjectHashTableShape,
14664                          Handle<Object> >;
14665
14666 template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
14667
14668 template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
14669
14670 template class Dictionary<SeededNumberDictionary,
14671                           SeededNumberDictionaryShape,
14672                           uint32_t>;
14673
14674 template class Dictionary<UnseededNumberDictionary,
14675                           UnseededNumberDictionaryShape,
14676                           uint32_t>;
14677
14678 template Handle<SeededNumberDictionary>
14679 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14680     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14681
14682 template Handle<UnseededNumberDictionary>
14683 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14684     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14685
14686 template Handle<NameDictionary>
14687 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14688     New(Isolate*, int n, PretenureFlag pretenure);
14689
14690 template Handle<SeededNumberDictionary>
14691 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14692     AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
14693
14694 template Handle<UnseededNumberDictionary>
14695 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14696     AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
14697
14698 template Object*
14699 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14700     SlowReverseLookup(Object* value);
14701
14702 template Object*
14703 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14704     SlowReverseLookup(Object* value);
14705
14706 template void
14707 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14708     CopyKeysTo(
14709         FixedArray*,
14710         PropertyAttributes,
14711         Dictionary<SeededNumberDictionary,
14712                    SeededNumberDictionaryShape,
14713                    uint32_t>::SortMode);
14714
14715 template Handle<Object>
14716 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
14717     Handle<NameDictionary>, int, JSObject::DeleteMode);
14718
14719 template Handle<Object>
14720 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14721     DeleteProperty(Handle<SeededNumberDictionary>, int, JSObject::DeleteMode);
14722
14723 template Handle<NameDictionary>
14724 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14725     New(Isolate*, int, MinimumCapacity, PretenureFlag);
14726
14727 template Handle<NameDictionary>
14728 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14729     Shrink(Handle<NameDictionary>, Handle<Name>);
14730
14731 template Handle<SeededNumberDictionary>
14732 HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14733     Shrink(Handle<SeededNumberDictionary>, uint32_t);
14734
14735 template void Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14736     CopyKeysTo(
14737         FixedArray*,
14738         int,
14739         PropertyAttributes,
14740         Dictionary<
14741             NameDictionary, NameDictionaryShape, Handle<Name> >::SortMode);
14742
14743 template int
14744 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14745     NumberOfElementsFilterAttributes(PropertyAttributes);
14746
14747 template Handle<NameDictionary>
14748 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
14749     Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
14750
14751 template void
14752 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14753     GenerateNewEnumerationIndices(Handle<NameDictionary>);
14754
14755 template int
14756 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14757     NumberOfElementsFilterAttributes(PropertyAttributes);
14758
14759 template Handle<SeededNumberDictionary>
14760 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14761     Add(Handle<SeededNumberDictionary>,
14762         uint32_t,
14763         Handle<Object>,
14764         PropertyDetails);
14765
14766 template Handle<UnseededNumberDictionary>
14767 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14768     Add(Handle<UnseededNumberDictionary>,
14769         uint32_t,
14770         Handle<Object>,
14771         PropertyDetails);
14772
14773 template Handle<SeededNumberDictionary>
14774 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14775     EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
14776
14777 template Handle<UnseededNumberDictionary>
14778 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14779     EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
14780
14781 template Handle<NameDictionary>
14782 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14783     EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
14784
14785 template
14786 int Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14787     NumberOfEnumElements();
14788
14789 template
14790 int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14791     NumberOfEnumElements();
14792
14793 template
14794 int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14795     FindEntry(uint32_t);
14796
14797
14798 Handle<Object> JSObject::PrepareSlowElementsForSort(
14799     Handle<JSObject> object, uint32_t limit) {
14800   DCHECK(object->HasDictionaryElements());
14801   Isolate* isolate = object->GetIsolate();
14802   // Must stay in dictionary mode, either because of requires_slow_elements,
14803   // or because we are not going to sort (and therefore compact) all of the
14804   // elements.
14805   Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
14806   Handle<SeededNumberDictionary> new_dict =
14807       SeededNumberDictionary::New(isolate, dict->NumberOfElements());
14808
14809   uint32_t pos = 0;
14810   uint32_t undefs = 0;
14811   int capacity = dict->Capacity();
14812   Handle<Smi> bailout(Smi::FromInt(-1), isolate);
14813   // Entry to the new dictionary does not cause it to grow, as we have
14814   // allocated one that is large enough for all entries.
14815   DisallowHeapAllocation no_gc;
14816   for (int i = 0; i < capacity; i++) {
14817     Object* k = dict->KeyAt(i);
14818     if (!dict->IsKey(k)) continue;
14819
14820     DCHECK(k->IsNumber());
14821     DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
14822     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
14823     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
14824
14825     HandleScope scope(isolate);
14826     Handle<Object> value(dict->ValueAt(i), isolate);
14827     PropertyDetails details = dict->DetailsAt(i);
14828     if (details.type() == CALLBACKS || details.IsReadOnly()) {
14829       // Bail out and do the sorting of undefineds and array holes in JS.
14830       // Also bail out if the element is not supposed to be moved.
14831       return bailout;
14832     }
14833
14834     uint32_t key = NumberToUint32(k);
14835     if (key < limit) {
14836       if (value->IsUndefined()) {
14837         undefs++;
14838       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14839         // Adding an entry with the key beyond smi-range requires
14840         // allocation. Bailout.
14841         return bailout;
14842       } else {
14843         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14844             new_dict, pos, value, details);
14845         DCHECK(result.is_identical_to(new_dict));
14846         USE(result);
14847         pos++;
14848       }
14849     } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
14850       // Adding an entry with the key beyond smi-range requires
14851       // allocation. Bailout.
14852       return bailout;
14853     } else {
14854       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14855           new_dict, key, value, details);
14856       DCHECK(result.is_identical_to(new_dict));
14857       USE(result);
14858     }
14859   }
14860
14861   uint32_t result = pos;
14862   PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0);
14863   while (undefs > 0) {
14864     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14865       // Adding an entry with the key beyond smi-range requires
14866       // allocation. Bailout.
14867       return bailout;
14868     }
14869     HandleScope scope(isolate);
14870     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14871         new_dict, pos, isolate->factory()->undefined_value(), no_details);
14872     DCHECK(result.is_identical_to(new_dict));
14873     USE(result);
14874     pos++;
14875     undefs--;
14876   }
14877
14878   object->set_elements(*new_dict);
14879
14880   AllowHeapAllocation allocate_return_value;
14881   return isolate->factory()->NewNumberFromUint(result);
14882 }
14883
14884
14885 // Collects all defined (non-hole) and non-undefined (array) elements at
14886 // the start of the elements array.
14887 // If the object is in dictionary mode, it is converted to fast elements
14888 // mode.
14889 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
14890                                                 uint32_t limit) {
14891   Isolate* isolate = object->GetIsolate();
14892   if (object->HasSloppyArgumentsElements() ||
14893       object->map()->is_observed()) {
14894     return handle(Smi::FromInt(-1), isolate);
14895   }
14896
14897   if (object->HasDictionaryElements()) {
14898     // Convert to fast elements containing only the existing properties.
14899     // Ordering is irrelevant, since we are going to sort anyway.
14900     Handle<SeededNumberDictionary> dict(object->element_dictionary());
14901     if (object->IsJSArray() || dict->requires_slow_elements() ||
14902         dict->max_number_key() >= limit) {
14903       return JSObject::PrepareSlowElementsForSort(object, limit);
14904     }
14905     // Convert to fast elements.
14906
14907     Handle<Map> new_map =
14908         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
14909
14910     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
14911         NOT_TENURED: TENURED;
14912     Handle<FixedArray> fast_elements =
14913         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
14914     dict->CopyValuesTo(*fast_elements);
14915     JSObject::ValidateElements(object);
14916
14917     JSObject::SetMapAndElements(object, new_map, fast_elements);
14918   } else if (object->HasExternalArrayElements() ||
14919              object->HasFixedTypedArrayElements()) {
14920     // Typed arrays cannot have holes or undefined elements.
14921     return handle(Smi::FromInt(
14922         FixedArrayBase::cast(object->elements())->length()), isolate);
14923   } else if (!object->HasFastDoubleElements()) {
14924     EnsureWritableFastElements(object);
14925   }
14926   DCHECK(object->HasFastSmiOrObjectElements() ||
14927          object->HasFastDoubleElements());
14928
14929   // Collect holes at the end, undefined before that and the rest at the
14930   // start, and return the number of non-hole, non-undefined values.
14931
14932   Handle<FixedArrayBase> elements_base(object->elements());
14933   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
14934   if (limit > elements_length) {
14935     limit = elements_length ;
14936   }
14937   if (limit == 0) {
14938     return handle(Smi::FromInt(0), isolate);
14939   }
14940
14941   uint32_t result = 0;
14942   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
14943     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
14944     // Split elements into defined and the_hole, in that order.
14945     unsigned int holes = limit;
14946     // Assume most arrays contain no holes and undefined values, so minimize the
14947     // number of stores of non-undefined, non-the-hole values.
14948     for (unsigned int i = 0; i < holes; i++) {
14949       if (elements->is_the_hole(i)) {
14950         holes--;
14951       } else {
14952         continue;
14953       }
14954       // Position i needs to be filled.
14955       while (holes > i) {
14956         if (elements->is_the_hole(holes)) {
14957           holes--;
14958         } else {
14959           elements->set(i, elements->get_scalar(holes));
14960           break;
14961         }
14962       }
14963     }
14964     result = holes;
14965     while (holes < limit) {
14966       elements->set_the_hole(holes);
14967       holes++;
14968     }
14969   } else {
14970     FixedArray* elements = FixedArray::cast(*elements_base);
14971     DisallowHeapAllocation no_gc;
14972
14973     // Split elements into defined, undefined and the_hole, in that order.  Only
14974     // count locations for undefined and the hole, and fill them afterwards.
14975     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
14976     unsigned int undefs = limit;
14977     unsigned int holes = limit;
14978     // Assume most arrays contain no holes and undefined values, so minimize the
14979     // number of stores of non-undefined, non-the-hole values.
14980     for (unsigned int i = 0; i < undefs; i++) {
14981       Object* current = elements->get(i);
14982       if (current->IsTheHole()) {
14983         holes--;
14984         undefs--;
14985       } else if (current->IsUndefined()) {
14986         undefs--;
14987       } else {
14988         continue;
14989       }
14990       // Position i needs to be filled.
14991       while (undefs > i) {
14992         current = elements->get(undefs);
14993         if (current->IsTheHole()) {
14994           holes--;
14995           undefs--;
14996         } else if (current->IsUndefined()) {
14997           undefs--;
14998         } else {
14999           elements->set(i, current, write_barrier);
15000           break;
15001         }
15002       }
15003     }
15004     result = undefs;
15005     while (undefs < holes) {
15006       elements->set_undefined(undefs);
15007       undefs++;
15008     }
15009     while (holes < limit) {
15010       elements->set_the_hole(holes);
15011       holes++;
15012     }
15013   }
15014
15015   return isolate->factory()->NewNumberFromUint(result);
15016 }
15017
15018
15019 ExternalArrayType JSTypedArray::type() {
15020   switch (elements()->map()->instance_type()) {
15021 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
15022     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
15023     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
15024       return kExternal##Type##Array;
15025
15026     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
15027 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
15028
15029     default:
15030       UNREACHABLE();
15031       return static_cast<ExternalArrayType>(-1);
15032   }
15033 }
15034
15035
15036 size_t JSTypedArray::element_size() {
15037   switch (elements()->map()->instance_type()) {
15038 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)          \
15039     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
15040       return size;
15041
15042     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
15043 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
15044
15045     default:
15046       UNREACHABLE();
15047       return 0;
15048   }
15049 }
15050
15051
15052 Handle<Object> ExternalUint8ClampedArray::SetValue(
15053     Handle<ExternalUint8ClampedArray> array,
15054     uint32_t index,
15055     Handle<Object> value) {
15056   uint8_t clamped_value = 0;
15057   if (index < static_cast<uint32_t>(array->length())) {
15058     if (value->IsSmi()) {
15059       int int_value = Handle<Smi>::cast(value)->value();
15060       if (int_value < 0) {
15061         clamped_value = 0;
15062       } else if (int_value > 255) {
15063         clamped_value = 255;
15064       } else {
15065         clamped_value = static_cast<uint8_t>(int_value);
15066       }
15067     } else if (value->IsHeapNumber()) {
15068       double double_value = Handle<HeapNumber>::cast(value)->value();
15069       if (!(double_value > 0)) {
15070         // NaN and less than zero clamp to zero.
15071         clamped_value = 0;
15072       } else if (double_value > 255) {
15073         // Greater than 255 clamp to 255.
15074         clamped_value = 255;
15075       } else {
15076         // Other doubles are rounded to the nearest integer.
15077         clamped_value = static_cast<uint8_t>(lrint(double_value));
15078       }
15079     } else {
15080       // Clamp undefined to zero (default). All other types have been
15081       // converted to a number type further up in the call chain.
15082       DCHECK(value->IsUndefined());
15083     }
15084     array->set(index, clamped_value);
15085   }
15086   return handle(Smi::FromInt(clamped_value), array->GetIsolate());
15087 }
15088
15089
15090 template<typename ExternalArrayClass, typename ValueType>
15091 static Handle<Object> ExternalArrayIntSetter(
15092     Isolate* isolate,
15093     Handle<ExternalArrayClass> receiver,
15094     uint32_t index,
15095     Handle<Object> value) {
15096   ValueType cast_value = 0;
15097   if (index < static_cast<uint32_t>(receiver->length())) {
15098     if (value->IsSmi()) {
15099       int int_value = Handle<Smi>::cast(value)->value();
15100       cast_value = static_cast<ValueType>(int_value);
15101     } else if (value->IsHeapNumber()) {
15102       double double_value = Handle<HeapNumber>::cast(value)->value();
15103       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
15104     } else {
15105       // Clamp undefined to zero (default). All other types have been
15106       // converted to a number type further up in the call chain.
15107       DCHECK(value->IsUndefined());
15108     }
15109     receiver->set(index, cast_value);
15110   }
15111   return isolate->factory()->NewNumberFromInt(cast_value);
15112 }
15113
15114
15115 Handle<Object> ExternalInt8Array::SetValue(Handle<ExternalInt8Array> array,
15116                                            uint32_t index,
15117                                            Handle<Object> value) {
15118   return ExternalArrayIntSetter<ExternalInt8Array, int8_t>(
15119       array->GetIsolate(), array, index, value);
15120 }
15121
15122
15123 Handle<Object> ExternalUint8Array::SetValue(Handle<ExternalUint8Array> array,
15124                                             uint32_t index,
15125                                             Handle<Object> value) {
15126   return ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(
15127       array->GetIsolate(), array, index, value);
15128 }
15129
15130
15131 Handle<Object> ExternalInt16Array::SetValue(Handle<ExternalInt16Array> array,
15132                                             uint32_t index,
15133                                             Handle<Object> value) {
15134   return ExternalArrayIntSetter<ExternalInt16Array, int16_t>(
15135       array->GetIsolate(), array, index, value);
15136 }
15137
15138
15139 Handle<Object> ExternalUint16Array::SetValue(Handle<ExternalUint16Array> array,
15140                                              uint32_t index,
15141                                              Handle<Object> value) {
15142   return ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(
15143       array->GetIsolate(), array, index, value);
15144 }
15145
15146
15147 Handle<Object> ExternalInt32Array::SetValue(Handle<ExternalInt32Array> array,
15148                                             uint32_t index,
15149                                             Handle<Object> value) {
15150   return ExternalArrayIntSetter<ExternalInt32Array, int32_t>(
15151       array->GetIsolate(), array, index, value);
15152 }
15153
15154
15155 Handle<Object> ExternalUint32Array::SetValue(
15156     Handle<ExternalUint32Array> array,
15157     uint32_t index,
15158     Handle<Object> value) {
15159   uint32_t cast_value = 0;
15160   if (index < static_cast<uint32_t>(array->length())) {
15161     if (value->IsSmi()) {
15162       int int_value = Handle<Smi>::cast(value)->value();
15163       cast_value = static_cast<uint32_t>(int_value);
15164     } else if (value->IsHeapNumber()) {
15165       double double_value = Handle<HeapNumber>::cast(value)->value();
15166       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
15167     } else {
15168       // Clamp undefined to zero (default). All other types have been
15169       // converted to a number type further up in the call chain.
15170       DCHECK(value->IsUndefined());
15171     }
15172     array->set(index, cast_value);
15173   }
15174   return array->GetIsolate()->factory()->NewNumberFromUint(cast_value);
15175 }
15176
15177
15178 Handle<Object> ExternalFloat32Array::SetValue(
15179     Handle<ExternalFloat32Array> array,
15180     uint32_t index,
15181     Handle<Object> value) {
15182   float cast_value = static_cast<float>(base::OS::nan_value());
15183   if (index < static_cast<uint32_t>(array->length())) {
15184     if (value->IsSmi()) {
15185       int int_value = Handle<Smi>::cast(value)->value();
15186       cast_value = static_cast<float>(int_value);
15187     } else if (value->IsHeapNumber()) {
15188       double double_value = Handle<HeapNumber>::cast(value)->value();
15189       cast_value = static_cast<float>(double_value);
15190     } else {
15191       // Clamp undefined to NaN (default). All other types have been
15192       // converted to a number type further up in the call chain.
15193       DCHECK(value->IsUndefined());
15194     }
15195     array->set(index, cast_value);
15196   }
15197   return array->GetIsolate()->factory()->NewNumber(cast_value);
15198 }
15199
15200
15201 Handle<Object> ExternalFloat64Array::SetValue(
15202     Handle<ExternalFloat64Array> array,
15203     uint32_t index,
15204     Handle<Object> value) {
15205   double double_value = base::OS::nan_value();
15206   if (index < static_cast<uint32_t>(array->length())) {
15207     if (value->IsNumber()) {
15208       double_value = value->Number();
15209     } else {
15210       // Clamp undefined to NaN (default). All other types have been
15211       // converted to a number type further up in the call chain.
15212       DCHECK(value->IsUndefined());
15213     }
15214     array->set(index, double_value);
15215   }
15216   return array->GetIsolate()->factory()->NewNumber(double_value);
15217 }
15218
15219
15220 Handle<Object> ExternalFloat32x4Array::SetValue(
15221     Handle<ExternalFloat32x4Array> array,
15222     uint32_t index,
15223     Handle<Object> value) {
15224   float32x4_value_t cast_value;
15225   cast_value.storage[0] = static_cast<float>(base::OS::nan_value());
15226   cast_value.storage[1] = static_cast<float>(base::OS::nan_value());
15227   cast_value.storage[2] = static_cast<float>(base::OS::nan_value());
15228   cast_value.storage[3] = static_cast<float>(base::OS::nan_value());
15229   if (index < static_cast<uint32_t>(array->length())) {
15230     if (value->IsFloat32x4()) {
15231       cast_value = Handle<Float32x4>::cast(value)->get();
15232     } else {
15233       // Clamp undefined to NaN (default). All other types have been
15234       // converted to a number type further up in the call chain.
15235       DCHECK(value->IsUndefined());
15236     }
15237     array->set(index, cast_value);
15238   }
15239   return array->GetIsolate()->factory()->NewFloat32x4(cast_value);
15240 }
15241
15242
15243 Handle<Object> ExternalInt32x4Array::SetValue(
15244     Handle<ExternalInt32x4Array> array, uint32_t index, Handle<Object> value) {
15245   int32x4_value_t cast_value;
15246   cast_value.storage[0] = 0;
15247   cast_value.storage[1] = 0;
15248   cast_value.storage[2] = 0;
15249   cast_value.storage[3] = 0;
15250   if (index < static_cast<uint32_t>(array->length())) {
15251     if (value->IsInt32x4()) {
15252       cast_value = Handle<Int32x4>::cast(value)->get();
15253     } else {
15254       // Clamp undefined to zero (default). All other types have been
15255       // converted to a number type further up in the call chain.
15256       DCHECK(value->IsUndefined());
15257     }
15258     array->set(index, cast_value);
15259   }
15260   return array->GetIsolate()->factory()->NewInt32x4(cast_value);
15261 }
15262
15263
15264 Handle<Object> ExternalFloat64x2Array::SetValue(
15265     Handle<ExternalFloat64x2Array> array,
15266     uint32_t index,
15267     Handle<Object> value) {
15268   float64x2_value_t cast_value;
15269   cast_value.storage[0] = base::OS::nan_value();
15270   cast_value.storage[1] = base::OS::nan_value();
15271   if (index < static_cast<uint32_t>(array->length())) {
15272     if (value->IsFloat64x2()) {
15273       cast_value = Handle<Float64x2>::cast(value)->get();
15274     } else {
15275       // Clamp undefined to NaN (default). All other types have been
15276       // converted to a number type further up in the call chain.
15277       DCHECK(value->IsUndefined());
15278     }
15279     array->set(index, cast_value);
15280   }
15281   return array->GetIsolate()->factory()->NewFloat64x2(cast_value);
15282 }
15283
15284
15285 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
15286   DCHECK(!HasFastProperties());
15287   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
15288   return PropertyCell::cast(value);
15289 }
15290
15291
15292 Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell(
15293     Handle<JSGlobalObject> global,
15294     Handle<Name> name) {
15295   DCHECK(!global->HasFastProperties());
15296   int entry = global->property_dictionary()->FindEntry(name);
15297   if (entry == NameDictionary::kNotFound) {
15298     Isolate* isolate = global->GetIsolate();
15299     Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(
15300         isolate->factory()->the_hole_value());
15301     PropertyDetails details(NONE, NORMAL, 0);
15302     details = details.AsDeleted();
15303     Handle<NameDictionary> dictionary = NameDictionary::Add(
15304         handle(global->property_dictionary()), name, cell, details);
15305     global->set_properties(*dictionary);
15306     return cell;
15307   } else {
15308     Object* value = global->property_dictionary()->ValueAt(entry);
15309     DCHECK(value->IsPropertyCell());
15310     return handle(PropertyCell::cast(value));
15311   }
15312 }
15313
15314
15315 // This class is used for looking up two character strings in the string table.
15316 // If we don't have a hit we don't want to waste much time so we unroll the
15317 // string hash calculation loop here for speed.  Doesn't work if the two
15318 // characters form a decimal integer, since such strings have a different hash
15319 // algorithm.
15320 class TwoCharHashTableKey : public HashTableKey {
15321  public:
15322   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
15323     : c1_(c1), c2_(c2) {
15324     // Char 1.
15325     uint32_t hash = seed;
15326     hash += c1;
15327     hash += hash << 10;
15328     hash ^= hash >> 6;
15329     // Char 2.
15330     hash += c2;
15331     hash += hash << 10;
15332     hash ^= hash >> 6;
15333     // GetHash.
15334     hash += hash << 3;
15335     hash ^= hash >> 11;
15336     hash += hash << 15;
15337     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
15338     hash_ = hash;
15339 #ifdef DEBUG
15340     // If this assert fails then we failed to reproduce the two-character
15341     // version of the string hashing algorithm above.  One reason could be
15342     // that we were passed two digits as characters, since the hash
15343     // algorithm is different in that case.
15344     uint16_t chars[2] = {c1, c2};
15345     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
15346     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
15347     DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
15348 #endif
15349   }
15350
15351   bool IsMatch(Object* o) V8_OVERRIDE {
15352     if (!o->IsString()) return false;
15353     String* other = String::cast(o);
15354     if (other->length() != 2) return false;
15355     if (other->Get(0) != c1_) return false;
15356     return other->Get(1) == c2_;
15357   }
15358
15359   uint32_t Hash() V8_OVERRIDE { return hash_; }
15360   uint32_t HashForObject(Object* key) V8_OVERRIDE {
15361     if (!key->IsString()) return 0;
15362     return String::cast(key)->Hash();
15363   }
15364
15365   Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
15366     // The TwoCharHashTableKey is only used for looking in the string
15367     // table, not for adding to it.
15368     UNREACHABLE();
15369     return MaybeHandle<Object>().ToHandleChecked();
15370   }
15371
15372  private:
15373   uint16_t c1_;
15374   uint16_t c2_;
15375   uint32_t hash_;
15376 };
15377
15378
15379 MaybeHandle<String> StringTable::InternalizeStringIfExists(
15380     Isolate* isolate,
15381     Handle<String> string) {
15382   if (string->IsInternalizedString()) {
15383     return string;
15384   }
15385   return LookupStringIfExists(isolate, string);
15386 }
15387
15388
15389 MaybeHandle<String> StringTable::LookupStringIfExists(
15390     Isolate* isolate,
15391     Handle<String> string) {
15392   Handle<StringTable> string_table = isolate->factory()->string_table();
15393   InternalizedStringKey key(string);
15394   int entry = string_table->FindEntry(&key);
15395   if (entry == kNotFound) {
15396     return MaybeHandle<String>();
15397   } else {
15398     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
15399     DCHECK(StringShape(*result).IsInternalized());
15400     return result;
15401   }
15402 }
15403
15404
15405 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
15406     Isolate* isolate,
15407     uint16_t c1,
15408     uint16_t c2) {
15409   Handle<StringTable> string_table = isolate->factory()->string_table();
15410   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
15411   int entry = string_table->FindEntry(&key);
15412   if (entry == kNotFound) {
15413     return MaybeHandle<String>();
15414   } else {
15415     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
15416     DCHECK(StringShape(*result).IsInternalized());
15417     return result;
15418   }
15419 }
15420
15421
15422 Handle<String> StringTable::LookupString(Isolate* isolate,
15423                                          Handle<String> string) {
15424   InternalizedStringKey key(string);
15425   return LookupKey(isolate, &key);
15426 }
15427
15428
15429 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
15430   Handle<StringTable> table = isolate->factory()->string_table();
15431   int entry = table->FindEntry(key);
15432
15433   // String already in table.
15434   if (entry != kNotFound) {
15435     return handle(String::cast(table->KeyAt(entry)), isolate);
15436   }
15437
15438   // Adding new string. Grow table if needed.
15439   table = StringTable::EnsureCapacity(table, 1, key);
15440
15441   // Create string object.
15442   Handle<Object> string = key->AsHandle(isolate);
15443   // There must be no attempts to internalize strings that could throw
15444   // InvalidStringLength error.
15445   CHECK(!string.is_null());
15446
15447   // Add the new string and return it along with the string table.
15448   entry = table->FindInsertionEntry(key->Hash());
15449   table->set(EntryToIndex(entry), *string);
15450   table->ElementAdded();
15451
15452   isolate->factory()->set_string_table(table);
15453   return Handle<String>::cast(string);
15454 }
15455
15456
15457 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
15458                                              Handle<Context> context) {
15459   Isolate* isolate = GetIsolate();
15460   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15461   StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
15462                       RelocInfo::kNoPosition);
15463   int entry = FindEntry(&key);
15464   if (entry == kNotFound) return isolate->factory()->undefined_value();
15465   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15466 }
15467
15468
15469 Handle<Object> CompilationCacheTable::LookupEval(Handle<String> src,
15470                                                  Handle<Context> context,
15471                                                  StrictMode strict_mode,
15472                                                  int scope_position) {
15473   Isolate* isolate = GetIsolate();
15474   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15475   StringSharedKey key(src, shared, strict_mode, scope_position);
15476   int entry = FindEntry(&key);
15477   if (entry == kNotFound) return isolate->factory()->undefined_value();
15478   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15479 }
15480
15481
15482 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
15483                                                    JSRegExp::Flags flags) {
15484   Isolate* isolate = GetIsolate();
15485   DisallowHeapAllocation no_allocation;
15486   RegExpKey key(src, flags);
15487   int entry = FindEntry(&key);
15488   if (entry == kNotFound) return isolate->factory()->undefined_value();
15489   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15490 }
15491
15492
15493 Handle<CompilationCacheTable> CompilationCacheTable::Put(
15494     Handle<CompilationCacheTable> cache, Handle<String> src,
15495     Handle<Context> context, Handle<Object> value) {
15496   Isolate* isolate = cache->GetIsolate();
15497   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15498   StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
15499                       RelocInfo::kNoPosition);
15500   cache = EnsureCapacity(cache, 1, &key);
15501   Handle<Object> k = key.AsHandle(isolate);
15502   int entry = cache->FindInsertionEntry(key.Hash());
15503   cache->set(EntryToIndex(entry), *k);
15504   cache->set(EntryToIndex(entry) + 1, *value);
15505   cache->ElementAdded();
15506   return cache;
15507 }
15508
15509
15510 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
15511     Handle<CompilationCacheTable> cache, Handle<String> src,
15512     Handle<Context> context, Handle<SharedFunctionInfo> value,
15513     int scope_position) {
15514   Isolate* isolate = cache->GetIsolate();
15515   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15516   StringSharedKey key(src, shared, value->strict_mode(), scope_position);
15517   cache = EnsureCapacity(cache, 1, &key);
15518   Handle<Object> k = key.AsHandle(isolate);
15519   int entry = cache->FindInsertionEntry(key.Hash());
15520   cache->set(EntryToIndex(entry), *k);
15521   cache->set(EntryToIndex(entry) + 1, *value);
15522   cache->ElementAdded();
15523   return cache;
15524 }
15525
15526
15527 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
15528       Handle<CompilationCacheTable> cache, Handle<String> src,
15529       JSRegExp::Flags flags, Handle<FixedArray> value) {
15530   RegExpKey key(src, flags);
15531   cache = EnsureCapacity(cache, 1, &key);
15532   int entry = cache->FindInsertionEntry(key.Hash());
15533   // We store the value in the key slot, and compare the search key
15534   // to the stored value with a custon IsMatch function during lookups.
15535   cache->set(EntryToIndex(entry), *value);
15536   cache->set(EntryToIndex(entry) + 1, *value);
15537   cache->ElementAdded();
15538   return cache;
15539 }
15540
15541
15542 void CompilationCacheTable::Remove(Object* value) {
15543   DisallowHeapAllocation no_allocation;
15544   Object* the_hole_value = GetHeap()->the_hole_value();
15545   for (int entry = 0, size = Capacity(); entry < size; entry++) {
15546     int entry_index = EntryToIndex(entry);
15547     int value_index = entry_index + 1;
15548     if (get(value_index) == value) {
15549       NoWriteBarrierSet(this, entry_index, the_hole_value);
15550       NoWriteBarrierSet(this, value_index, the_hole_value);
15551       ElementRemoved();
15552     }
15553   }
15554   return;
15555 }
15556
15557
15558 // StringsKey used for HashTable where key is array of internalized strings.
15559 class StringsKey : public HashTableKey {
15560  public:
15561   explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
15562
15563   bool IsMatch(Object* strings) V8_OVERRIDE {
15564     FixedArray* o = FixedArray::cast(strings);
15565     int len = strings_->length();
15566     if (o->length() != len) return false;
15567     for (int i = 0; i < len; i++) {
15568       if (o->get(i) != strings_->get(i)) return false;
15569     }
15570     return true;
15571   }
15572
15573   uint32_t Hash() V8_OVERRIDE { return HashForObject(*strings_); }
15574
15575   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
15576     FixedArray* strings = FixedArray::cast(obj);
15577     int len = strings->length();
15578     uint32_t hash = 0;
15579     for (int i = 0; i < len; i++) {
15580       hash ^= String::cast(strings->get(i))->Hash();
15581     }
15582     return hash;
15583   }
15584
15585   Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE { return strings_; }
15586
15587  private:
15588   Handle<FixedArray> strings_;
15589 };
15590
15591
15592 Object* MapCache::Lookup(FixedArray* array) {
15593   DisallowHeapAllocation no_alloc;
15594   StringsKey key(handle(array));
15595   int entry = FindEntry(&key);
15596   if (entry == kNotFound) return GetHeap()->undefined_value();
15597   return get(EntryToIndex(entry) + 1);
15598 }
15599
15600
15601 Handle<MapCache> MapCache::Put(
15602     Handle<MapCache> map_cache, Handle<FixedArray> array, Handle<Map> value) {
15603   StringsKey key(array);
15604
15605   Handle<MapCache> new_cache = EnsureCapacity(map_cache, 1, &key);
15606   int entry = new_cache->FindInsertionEntry(key.Hash());
15607   new_cache->set(EntryToIndex(entry), *array);
15608   new_cache->set(EntryToIndex(entry) + 1, *value);
15609   new_cache->ElementAdded();
15610   return new_cache;
15611 }
15612
15613
15614 template<typename Derived, typename Shape, typename Key>
15615 Handle<Derived> Dictionary<Derived, Shape, Key>::New(
15616     Isolate* isolate,
15617     int at_least_space_for,
15618     PretenureFlag pretenure) {
15619   DCHECK(0 <= at_least_space_for);
15620   Handle<Derived> dict = DerivedHashTable::New(isolate,
15621                                                at_least_space_for,
15622                                                USE_DEFAULT_MINIMUM_CAPACITY,
15623                                                pretenure);
15624
15625   // Initialize the next enumeration index.
15626   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
15627   return dict;
15628 }
15629
15630
15631 template<typename Derived, typename Shape, typename Key>
15632 void Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
15633     Handle<Derived> dictionary) {
15634   Factory* factory = dictionary->GetIsolate()->factory();
15635   int length = dictionary->NumberOfElements();
15636
15637   // Allocate and initialize iteration order array.
15638   Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
15639   for (int i = 0; i < length; i++) {
15640     iteration_order->set(i, Smi::FromInt(i));
15641   }
15642
15643   // Allocate array with enumeration order.
15644   Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
15645
15646   // Fill the enumeration order array with property details.
15647   int capacity = dictionary->Capacity();
15648   int pos = 0;
15649   for (int i = 0; i < capacity; i++) {
15650     if (dictionary->IsKey(dictionary->KeyAt(i))) {
15651       int index = dictionary->DetailsAt(i).dictionary_index();
15652       enumeration_order->set(pos++, Smi::FromInt(index));
15653     }
15654   }
15655
15656   // Sort the arrays wrt. enumeration order.
15657   iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
15658
15659   // Overwrite the enumeration_order with the enumeration indices.
15660   for (int i = 0; i < length; i++) {
15661     int index = Smi::cast(iteration_order->get(i))->value();
15662     int enum_index = PropertyDetails::kInitialIndex + i;
15663     enumeration_order->set(index, Smi::FromInt(enum_index));
15664   }
15665
15666   // Update the dictionary with new indices.
15667   capacity = dictionary->Capacity();
15668   pos = 0;
15669   for (int i = 0; i < capacity; i++) {
15670     if (dictionary->IsKey(dictionary->KeyAt(i))) {
15671       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
15672       PropertyDetails details = dictionary->DetailsAt(i);
15673       PropertyDetails new_details = PropertyDetails(
15674           details.attributes(), details.type(), enum_index);
15675       dictionary->DetailsAtPut(i, new_details);
15676     }
15677   }
15678
15679   // Set the next enumeration index.
15680   dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
15681 }
15682
15683
15684 template<typename Derived, typename Shape, typename Key>
15685 Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
15686     Handle<Derived> dictionary, int n, Key key) {
15687   // Check whether there are enough enumeration indices to add n elements.
15688   if (Shape::kIsEnumerable &&
15689       !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
15690     // If not, we generate new indices for the properties.
15691     GenerateNewEnumerationIndices(dictionary);
15692   }
15693   return DerivedHashTable::EnsureCapacity(dictionary, n, key);
15694 }
15695
15696
15697 template<typename Derived, typename Shape, typename Key>
15698 Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
15699     Handle<Derived> dictionary,
15700     int entry,
15701     JSObject::DeleteMode mode) {
15702   Factory* factory = dictionary->GetIsolate()->factory();
15703   PropertyDetails details = dictionary->DetailsAt(entry);
15704   // Ignore attributes if forcing a deletion.
15705   if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
15706     return factory->false_value();
15707   }
15708
15709   dictionary->SetEntry(
15710       entry, factory->the_hole_value(), factory->the_hole_value());
15711   dictionary->ElementRemoved();
15712   return factory->true_value();
15713 }
15714
15715
15716 template<typename Derived, typename Shape, typename Key>
15717 Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
15718     Handle<Derived> dictionary, Key key, Handle<Object> value) {
15719   int entry = dictionary->FindEntry(key);
15720
15721   // If the entry is present set the value;
15722   if (entry != Dictionary::kNotFound) {
15723     dictionary->ValueAtPut(entry, *value);
15724     return dictionary;
15725   }
15726
15727   // Check whether the dictionary should be extended.
15728   dictionary = EnsureCapacity(dictionary, 1, key);
15729 #ifdef DEBUG
15730   USE(Shape::AsHandle(dictionary->GetIsolate(), key));
15731 #endif
15732   PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
15733
15734   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15735   return dictionary;
15736 }
15737
15738
15739 template<typename Derived, typename Shape, typename Key>
15740 Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
15741     Handle<Derived> dictionary,
15742     Key key,
15743     Handle<Object> value,
15744     PropertyDetails details) {
15745   // Valdate key is absent.
15746   SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
15747   // Check whether the dictionary should be extended.
15748   dictionary = EnsureCapacity(dictionary, 1, key);
15749
15750   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15751   return dictionary;
15752 }
15753
15754
15755 // Add a key, value pair to the dictionary.
15756 template<typename Derived, typename Shape, typename Key>
15757 void Dictionary<Derived, Shape, Key>::AddEntry(
15758     Handle<Derived> dictionary,
15759     Key key,
15760     Handle<Object> value,
15761     PropertyDetails details,
15762     uint32_t hash) {
15763   // Compute the key object.
15764   Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
15765
15766   uint32_t entry = dictionary->FindInsertionEntry(hash);
15767   // Insert element at empty or deleted entry
15768   if (!details.IsDeleted() &&
15769       details.dictionary_index() == 0 &&
15770       Shape::kIsEnumerable) {
15771     // Assign an enumeration index to the property and update
15772     // SetNextEnumerationIndex.
15773     int index = dictionary->NextEnumerationIndex();
15774     details = PropertyDetails(details.attributes(), details.type(), index);
15775     dictionary->SetNextEnumerationIndex(index + 1);
15776   }
15777   dictionary->SetEntry(entry, k, value, details);
15778   DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
15779           dictionary->KeyAt(entry)->IsName()));
15780   dictionary->ElementAdded();
15781 }
15782
15783
15784 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
15785   DisallowHeapAllocation no_allocation;
15786   // If the dictionary requires slow elements an element has already
15787   // been added at a high index.
15788   if (requires_slow_elements()) return;
15789   // Check if this index is high enough that we should require slow
15790   // elements.
15791   if (key > kRequiresSlowElementsLimit) {
15792     set_requires_slow_elements();
15793     return;
15794   }
15795   // Update max key value.
15796   Object* max_index_object = get(kMaxNumberKeyIndex);
15797   if (!max_index_object->IsSmi() || max_number_key() < key) {
15798     FixedArray::set(kMaxNumberKeyIndex,
15799                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
15800   }
15801 }
15802
15803
15804 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
15805     Handle<SeededNumberDictionary> dictionary,
15806     uint32_t key,
15807     Handle<Object> value,
15808     PropertyDetails details) {
15809   dictionary->UpdateMaxNumberKey(key);
15810   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
15811   return Add(dictionary, key, value, details);
15812 }
15813
15814
15815 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
15816     Handle<UnseededNumberDictionary> dictionary,
15817     uint32_t key,
15818     Handle<Object> value) {
15819   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
15820   return Add(dictionary, key, value, PropertyDetails(NONE, NORMAL, 0));
15821 }
15822
15823
15824 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
15825     Handle<SeededNumberDictionary> dictionary,
15826     uint32_t key,
15827     Handle<Object> value) {
15828   dictionary->UpdateMaxNumberKey(key);
15829   return AtPut(dictionary, key, value);
15830 }
15831
15832
15833 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
15834     Handle<UnseededNumberDictionary> dictionary,
15835     uint32_t key,
15836     Handle<Object> value) {
15837   return AtPut(dictionary, key, value);
15838 }
15839
15840
15841 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
15842     Handle<SeededNumberDictionary> dictionary,
15843     uint32_t key,
15844     Handle<Object> value,
15845     PropertyDetails details) {
15846   int entry = dictionary->FindEntry(key);
15847   if (entry == kNotFound) {
15848     return AddNumberEntry(dictionary, key, value, details);
15849   }
15850   // Preserve enumeration index.
15851   details = PropertyDetails(details.attributes(),
15852                             details.type(),
15853                             dictionary->DetailsAt(entry).dictionary_index());
15854   Handle<Object> object_key =
15855       SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15856   dictionary->SetEntry(entry, object_key, value, details);
15857   return dictionary;
15858 }
15859
15860
15861 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
15862     Handle<UnseededNumberDictionary> dictionary,
15863     uint32_t key,
15864     Handle<Object> value) {
15865   int entry = dictionary->FindEntry(key);
15866   if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
15867   Handle<Object> object_key =
15868       UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15869   dictionary->SetEntry(entry, object_key, value);
15870   return dictionary;
15871 }
15872
15873
15874
15875 template<typename Derived, typename Shape, typename Key>
15876 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
15877     PropertyAttributes filter) {
15878   int capacity = DerivedHashTable::Capacity();
15879   int result = 0;
15880   for (int i = 0; i < capacity; i++) {
15881     Object* k = DerivedHashTable::KeyAt(i);
15882     if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15883       PropertyDetails details = DetailsAt(i);
15884       if (details.IsDeleted()) continue;
15885       PropertyAttributes attr = details.attributes();
15886       if ((attr & filter) == 0) result++;
15887     }
15888   }
15889   return result;
15890 }
15891
15892
15893 template<typename Derived, typename Shape, typename Key>
15894 int Dictionary<Derived, Shape, Key>::NumberOfEnumElements() {
15895   return NumberOfElementsFilterAttributes(
15896       static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC));
15897 }
15898
15899
15900 template<typename Derived, typename Shape, typename Key>
15901 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
15902     FixedArray* storage,
15903     PropertyAttributes filter,
15904     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
15905   DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
15906   int capacity = DerivedHashTable::Capacity();
15907   int index = 0;
15908   for (int i = 0; i < capacity; i++) {
15909      Object* k = DerivedHashTable::KeyAt(i);
15910      if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15911        PropertyDetails details = DetailsAt(i);
15912        if (details.IsDeleted()) continue;
15913        PropertyAttributes attr = details.attributes();
15914        if ((attr & filter) == 0) storage->set(index++, k);
15915      }
15916   }
15917   if (sort_mode == Dictionary::SORTED) {
15918     storage->SortPairs(storage, index);
15919   }
15920   DCHECK(storage->length() >= index);
15921 }
15922
15923
15924 struct EnumIndexComparator {
15925   explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { }
15926   bool operator() (Smi* a, Smi* b) {
15927     PropertyDetails da(dict->DetailsAt(a->value()));
15928     PropertyDetails db(dict->DetailsAt(b->value()));
15929     return da.dictionary_index() < db.dictionary_index();
15930   }
15931   NameDictionary* dict;
15932 };
15933
15934
15935 void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
15936   int length = storage->length();
15937   int capacity = Capacity();
15938   int properties = 0;
15939   for (int i = 0; i < capacity; i++) {
15940      Object* k = KeyAt(i);
15941      if (IsKey(k) && !k->IsSymbol()) {
15942        PropertyDetails details = DetailsAt(i);
15943        if (details.IsDeleted() || details.IsDontEnum()) continue;
15944        storage->set(properties, Smi::FromInt(i));
15945        properties++;
15946        if (properties == length) break;
15947      }
15948   }
15949   CHECK_EQ(length, properties);
15950   EnumIndexComparator cmp(this);
15951   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
15952   std::sort(start, start + length, cmp);
15953   for (int i = 0; i < length; i++) {
15954     int index = Smi::cast(storage->get(i))->value();
15955     storage->set(i, KeyAt(index));
15956   }
15957 }
15958
15959
15960 template<typename Derived, typename Shape, typename Key>
15961 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
15962     FixedArray* storage,
15963     int index,
15964     PropertyAttributes filter,
15965     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
15966   DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
15967   int capacity = DerivedHashTable::Capacity();
15968   for (int i = 0; i < capacity; i++) {
15969     Object* k = DerivedHashTable::KeyAt(i);
15970     if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15971       PropertyDetails details = DetailsAt(i);
15972       if (details.IsDeleted()) continue;
15973       PropertyAttributes attr = details.attributes();
15974       if ((attr & filter) == 0) storage->set(index++, k);
15975     }
15976   }
15977   if (sort_mode == Dictionary::SORTED) {
15978     storage->SortPairs(storage, index);
15979   }
15980   DCHECK(storage->length() >= index);
15981 }
15982
15983
15984 // Backwards lookup (slow).
15985 template<typename Derived, typename Shape, typename Key>
15986 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
15987   int capacity = DerivedHashTable::Capacity();
15988   for (int i = 0; i < capacity; i++) {
15989     Object* k =  DerivedHashTable::KeyAt(i);
15990     if (Dictionary::IsKey(k)) {
15991       Object* e = ValueAt(i);
15992       if (e->IsPropertyCell()) {
15993         e = PropertyCell::cast(e)->value();
15994       }
15995       if (e == value) return k;
15996     }
15997   }
15998   Heap* heap = Dictionary::GetHeap();
15999   return heap->undefined_value();
16000 }
16001
16002
16003 Object* ObjectHashTable::Lookup(Handle<Object> key) {
16004   DisallowHeapAllocation no_gc;
16005   DCHECK(IsKey(*key));
16006
16007   // If the object does not have an identity hash, it was never used as a key.
16008   Object* hash = key->GetHash();
16009   if (hash->IsUndefined()) {
16010     return GetHeap()->the_hole_value();
16011   }
16012   int entry = FindEntry(key);
16013   if (entry == kNotFound) return GetHeap()->the_hole_value();
16014   return get(EntryToIndex(entry) + 1);
16015 }
16016
16017
16018 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
16019                                              Handle<Object> key,
16020                                              Handle<Object> value) {
16021   DCHECK(table->IsKey(*key));
16022   DCHECK(!value->IsTheHole());
16023
16024   Isolate* isolate = table->GetIsolate();
16025
16026   // Make sure the key object has an identity hash code.
16027   Handle<Smi> hash = Object::GetOrCreateHash(isolate, key);
16028
16029   int entry = table->FindEntry(key);
16030
16031   // Key is already in table, just overwrite value.
16032   if (entry != kNotFound) {
16033     table->set(EntryToIndex(entry) + 1, *value);
16034     return table;
16035   }
16036
16037   // Check whether the hash table should be extended.
16038   table = EnsureCapacity(table, 1, key);
16039   table->AddEntry(table->FindInsertionEntry(hash->value()),
16040                   *key,
16041                   *value);
16042   return table;
16043 }
16044
16045
16046 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
16047                                                 Handle<Object> key,
16048                                                 bool* was_present) {
16049   DCHECK(table->IsKey(*key));
16050
16051   Object* hash = key->GetHash();
16052   if (hash->IsUndefined()) {
16053     *was_present = false;
16054     return table;
16055   }
16056
16057   int entry = table->FindEntry(key);
16058   if (entry == kNotFound) {
16059     *was_present = false;
16060     return table;
16061   }
16062
16063   *was_present = true;
16064   table->RemoveEntry(entry);
16065   return Shrink(table, key);
16066 }
16067
16068
16069 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
16070   set(EntryToIndex(entry), key);
16071   set(EntryToIndex(entry) + 1, value);
16072   ElementAdded();
16073 }
16074
16075
16076 void ObjectHashTable::RemoveEntry(int entry) {
16077   set_the_hole(EntryToIndex(entry));
16078   set_the_hole(EntryToIndex(entry) + 1);
16079   ElementRemoved();
16080 }
16081
16082
16083 Object* WeakHashTable::Lookup(Handle<Object> key) {
16084   DisallowHeapAllocation no_gc;
16085   DCHECK(IsKey(*key));
16086   int entry = FindEntry(key);
16087   if (entry == kNotFound) return GetHeap()->the_hole_value();
16088   return get(EntryToValueIndex(entry));
16089 }
16090
16091
16092 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
16093                                          Handle<Object> key,
16094                                          Handle<Object> value) {
16095   DCHECK(table->IsKey(*key));
16096   int entry = table->FindEntry(key);
16097   // Key is already in table, just overwrite value.
16098   if (entry != kNotFound) {
16099     // TODO(ulan): Skipping write barrier is a temporary solution to avoid
16100     // memory leaks. Remove this once we have special visitor for weak fixed
16101     // arrays.
16102     table->set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
16103     return table;
16104   }
16105
16106   // Check whether the hash table should be extended.
16107   table = EnsureCapacity(table, 1, key, TENURED);
16108
16109   table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key, value);
16110   return table;
16111 }
16112
16113
16114 void WeakHashTable::AddEntry(int entry,
16115                              Handle<Object> key,
16116                              Handle<Object> value) {
16117   DisallowHeapAllocation no_allocation;
16118   // TODO(ulan): Skipping write barrier is a temporary solution to avoid
16119   // memory leaks. Remove this once we have special visitor for weak fixed
16120   // arrays.
16121   set(EntryToIndex(entry), *key, SKIP_WRITE_BARRIER);
16122   set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
16123   ElementAdded();
16124 }
16125
16126
16127 template<class Derived, class Iterator, int entrysize>
16128 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
16129     Isolate* isolate, int capacity, PretenureFlag pretenure) {
16130   // Capacity must be a power of two, since we depend on being able
16131   // to divide and multiple by 2 (kLoadFactor) to derive capacity
16132   // from number of buckets. If we decide to change kLoadFactor
16133   // to something other than 2, capacity should be stored as another
16134   // field of this object.
16135   capacity = RoundUpToPowerOf2(Max(kMinCapacity, capacity));
16136   if (capacity > kMaxCapacity) {
16137     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
16138   }
16139   int num_buckets = capacity / kLoadFactor;
16140   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
16141       kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
16142   backing_store->set_map_no_write_barrier(
16143       isolate->heap()->ordered_hash_table_map());
16144   Handle<Derived> table = Handle<Derived>::cast(backing_store);
16145   for (int i = 0; i < num_buckets; ++i) {
16146     table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
16147   }
16148   table->SetNumberOfBuckets(num_buckets);
16149   table->SetNumberOfElements(0);
16150   table->SetNumberOfDeletedElements(0);
16151   return table;
16152 }
16153
16154
16155 template<class Derived, class Iterator, int entrysize>
16156 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
16157     Handle<Derived> table) {
16158   DCHECK(!table->IsObsolete());
16159
16160   int nof = table->NumberOfElements();
16161   int nod = table->NumberOfDeletedElements();
16162   int capacity = table->Capacity();
16163   if ((nof + nod) < capacity) return table;
16164   // Don't need to grow if we can simply clear out deleted entries instead.
16165   // Note that we can't compact in place, though, so we always allocate
16166   // a new table.
16167   return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
16168 }
16169
16170
16171 template<class Derived, class Iterator, int entrysize>
16172 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
16173     Handle<Derived> table) {
16174   DCHECK(!table->IsObsolete());
16175
16176   int nof = table->NumberOfElements();
16177   int capacity = table->Capacity();
16178   if (nof >= (capacity >> 2)) return table;
16179   return Rehash(table, capacity / 2);
16180 }
16181
16182
16183 template<class Derived, class Iterator, int entrysize>
16184 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
16185     Handle<Derived> table) {
16186   DCHECK(!table->IsObsolete());
16187
16188   Handle<Derived> new_table =
16189       Allocate(table->GetIsolate(),
16190                kMinCapacity,
16191                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
16192
16193   table->SetNextTable(*new_table);
16194   table->SetNumberOfDeletedElements(-1);
16195
16196   return new_table;
16197 }
16198
16199
16200 template<class Derived, class Iterator, int entrysize>
16201 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Remove(
16202     Handle<Derived> table, Handle<Object> key, bool* was_present) {
16203   int entry = table->FindEntry(key);
16204   if (entry == kNotFound) {
16205     *was_present = false;
16206     return table;
16207   }
16208   *was_present = true;
16209   table->RemoveEntry(entry);
16210   return Shrink(table);
16211 }
16212
16213
16214 template<class Derived, class Iterator, int entrysize>
16215 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
16216     Handle<Derived> table, int new_capacity) {
16217   DCHECK(!table->IsObsolete());
16218
16219   Handle<Derived> new_table =
16220       Allocate(table->GetIsolate(),
16221                new_capacity,
16222                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
16223   int nof = table->NumberOfElements();
16224   int nod = table->NumberOfDeletedElements();
16225   int new_buckets = new_table->NumberOfBuckets();
16226   int new_entry = 0;
16227   int removed_holes_index = 0;
16228
16229   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
16230     Object* key = table->KeyAt(old_entry);
16231     if (key->IsTheHole()) {
16232       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
16233       continue;
16234     }
16235
16236     Object* hash = key->GetHash();
16237     int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
16238     Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
16239     new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
16240     int new_index = new_table->EntryToIndex(new_entry);
16241     int old_index = table->EntryToIndex(old_entry);
16242     for (int i = 0; i < entrysize; ++i) {
16243       Object* value = table->get(old_index + i);
16244       new_table->set(new_index + i, value);
16245     }
16246     new_table->set(new_index + kChainOffset, chain_entry);
16247     ++new_entry;
16248   }
16249
16250   DCHECK_EQ(nod, removed_holes_index);
16251
16252   new_table->SetNumberOfElements(nof);
16253   table->SetNextTable(*new_table);
16254
16255   return new_table;
16256 }
16257
16258
16259 template <class Derived, class Iterator, int entrysize>
16260 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(
16261     Handle<Object> key, int hash) {
16262   DCHECK(!IsObsolete());
16263
16264   DisallowHeapAllocation no_gc;
16265   DCHECK(!key->IsTheHole());
16266   for (int entry = HashToEntry(hash); entry != kNotFound;
16267        entry = ChainAt(entry)) {
16268     Object* candidate = KeyAt(entry);
16269     if (candidate->SameValueZero(*key))
16270       return entry;
16271   }
16272   return kNotFound;
16273 }
16274
16275
16276 template <class Derived, class Iterator, int entrysize>
16277 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(
16278     Handle<Object> key) {
16279   DisallowHeapAllocation no_gc;
16280   Object* hash = key->GetHash();
16281   if (!hash->IsSmi()) return kNotFound;
16282   return FindEntry(key, Smi::cast(hash)->value());
16283 }
16284
16285
16286 template <class Derived, class Iterator, int entrysize>
16287 int OrderedHashTable<Derived, Iterator, entrysize>::AddEntry(int hash) {
16288   DCHECK(!IsObsolete());
16289
16290   int entry = UsedCapacity();
16291   int bucket = HashToBucket(hash);
16292   int index = EntryToIndex(entry);
16293   Object* chain_entry = get(kHashTableStartIndex + bucket);
16294   set(kHashTableStartIndex + bucket, Smi::FromInt(entry));
16295   set(index + kChainOffset, chain_entry);
16296   SetNumberOfElements(NumberOfElements() + 1);
16297   return index;
16298 }
16299
16300
16301 template<class Derived, class Iterator, int entrysize>
16302 void OrderedHashTable<Derived, Iterator, entrysize>::RemoveEntry(int entry) {
16303   DCHECK(!IsObsolete());
16304
16305   int index = EntryToIndex(entry);
16306   for (int i = 0; i < entrysize; ++i) {
16307     set_the_hole(index + i);
16308   }
16309   SetNumberOfElements(NumberOfElements() - 1);
16310   SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
16311 }
16312
16313
16314 template Handle<OrderedHashSet>
16315 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
16316     Isolate* isolate, int capacity, PretenureFlag pretenure);
16317
16318 template Handle<OrderedHashSet>
16319 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
16320     Handle<OrderedHashSet> table);
16321
16322 template Handle<OrderedHashSet>
16323 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
16324     Handle<OrderedHashSet> table);
16325
16326 template Handle<OrderedHashSet>
16327 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
16328     Handle<OrderedHashSet> table);
16329
16330 template Handle<OrderedHashSet>
16331 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Remove(
16332     Handle<OrderedHashSet> table, Handle<Object> key, bool* was_present);
16333
16334 template int OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(
16335     Handle<Object> key, int hash);
16336 template int OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(
16337     Handle<Object> key);
16338
16339 template int
16340 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::AddEntry(int hash);
16341
16342 template void
16343 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::RemoveEntry(int entry);
16344
16345
16346 template Handle<OrderedHashMap>
16347 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
16348     Isolate* isolate, int capacity, PretenureFlag pretenure);
16349
16350 template Handle<OrderedHashMap>
16351 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
16352     Handle<OrderedHashMap> table);
16353
16354 template Handle<OrderedHashMap>
16355 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
16356     Handle<OrderedHashMap> table);
16357
16358 template Handle<OrderedHashMap>
16359 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
16360     Handle<OrderedHashMap> table);
16361
16362 template Handle<OrderedHashMap>
16363 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Remove(
16364     Handle<OrderedHashMap> table, Handle<Object> key, bool* was_present);
16365
16366 template int OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(
16367     Handle<Object> key, int hash);
16368 template int OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(
16369     Handle<Object> key);
16370
16371 template int
16372 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::AddEntry(int hash);
16373
16374 template void
16375 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::RemoveEntry(int entry);
16376
16377
16378 bool OrderedHashSet::Contains(Handle<Object> key) {
16379   return FindEntry(key) != kNotFound;
16380 }
16381
16382
16383 Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
16384                                            Handle<Object> key) {
16385   int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
16386   if (table->FindEntry(key, hash) != kNotFound) return table;
16387
16388   table = EnsureGrowable(table);
16389
16390   int index = table->AddEntry(hash);
16391   table->set(index, *key);
16392   return table;
16393 }
16394
16395
16396 Object* OrderedHashMap::Lookup(Handle<Object> key) {
16397   DisallowHeapAllocation no_gc;
16398   int entry = FindEntry(key);
16399   if (entry == kNotFound) return GetHeap()->the_hole_value();
16400   return ValueAt(entry);
16401 }
16402
16403
16404 Handle<OrderedHashMap> OrderedHashMap::Put(Handle<OrderedHashMap> table,
16405                                            Handle<Object> key,
16406                                            Handle<Object> value) {
16407   DCHECK(!key->IsTheHole());
16408
16409   int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
16410   int entry = table->FindEntry(key, hash);
16411
16412   if (entry != kNotFound) {
16413     table->set(table->EntryToIndex(entry) + kValueOffset, *value);
16414     return table;
16415   }
16416
16417   table = EnsureGrowable(table);
16418
16419   int index = table->AddEntry(hash);
16420   table->set(index, *key);
16421   table->set(index + kValueOffset, *value);
16422   return table;
16423 }
16424
16425
16426 template<class Derived, class TableType>
16427 void OrderedHashTableIterator<Derived, TableType>::Transition() {
16428   DisallowHeapAllocation no_allocation;
16429   TableType* table = TableType::cast(this->table());
16430   if (!table->IsObsolete()) return;
16431
16432   int index = Smi::cast(this->index())->value();
16433   while (table->IsObsolete()) {
16434     TableType* next_table = table->NextTable();
16435
16436     if (index > 0) {
16437       int nod = table->NumberOfDeletedElements();
16438
16439       // When we clear the table we set the number of deleted elements to -1.
16440       if (nod == -1) {
16441         index = 0;
16442       } else {
16443         int old_index = index;
16444         for (int i = 0; i < nod; ++i) {
16445           int removed_index = table->RemovedIndexAt(i);
16446           if (removed_index >= old_index) break;
16447           --index;
16448         }
16449       }
16450     }
16451
16452     table = next_table;
16453   }
16454
16455   set_table(table);
16456   set_index(Smi::FromInt(index));
16457 }
16458
16459
16460 template<class Derived, class TableType>
16461 bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
16462   DisallowHeapAllocation no_allocation;
16463   if (this->table()->IsUndefined()) return false;
16464
16465   Transition();
16466
16467   TableType* table = TableType::cast(this->table());
16468   int index = Smi::cast(this->index())->value();
16469   int used_capacity = table->UsedCapacity();
16470
16471   while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
16472     index++;
16473   }
16474
16475   set_index(Smi::FromInt(index));
16476
16477   if (index < used_capacity) return true;
16478
16479   set_table(GetHeap()->undefined_value());
16480   return false;
16481 }
16482
16483
16484 template<class Derived, class TableType>
16485 Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
16486   DisallowHeapAllocation no_allocation;
16487   if (HasMore()) {
16488     FixedArray* array = FixedArray::cast(value_array->elements());
16489     static_cast<Derived*>(this)->PopulateValueArray(array);
16490     MoveNext();
16491     return kind();
16492   }
16493   return Smi::FromInt(0);
16494 }
16495
16496
16497 template Smi*
16498 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
16499     JSArray* value_array);
16500
16501 template bool
16502 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
16503
16504 template void
16505 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
16506
16507 template Object*
16508 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
16509
16510 template void
16511 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
16512
16513
16514 template Smi*
16515 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
16516     JSArray* value_array);
16517
16518 template bool
16519 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
16520
16521 template void
16522 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
16523
16524 template Object*
16525 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
16526
16527 template void
16528 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
16529
16530
16531 DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator(
16532     DeclaredAccessorDescriptor* descriptor)
16533     : array_(descriptor->serialized_data()->GetDataStartAddress()),
16534       length_(descriptor->serialized_data()->length()),
16535       offset_(0) {
16536 }
16537
16538
16539 const DeclaredAccessorDescriptorData*
16540   DeclaredAccessorDescriptorIterator::Next() {
16541   DCHECK(offset_ < length_);
16542   uint8_t* ptr = &array_[offset_];
16543   DCHECK(reinterpret_cast<uintptr_t>(ptr) % sizeof(uintptr_t) == 0);
16544   const DeclaredAccessorDescriptorData* data =
16545       reinterpret_cast<const DeclaredAccessorDescriptorData*>(ptr);
16546   offset_ += sizeof(*data);
16547   DCHECK(offset_ <= length_);
16548   return data;
16549 }
16550
16551
16552 Handle<DeclaredAccessorDescriptor> DeclaredAccessorDescriptor::Create(
16553     Isolate* isolate,
16554     const DeclaredAccessorDescriptorData& descriptor,
16555     Handle<DeclaredAccessorDescriptor> previous) {
16556   int previous_length =
16557       previous.is_null() ? 0 : previous->serialized_data()->length();
16558   int length = sizeof(descriptor) + previous_length;
16559   Handle<ByteArray> serialized_descriptor =
16560       isolate->factory()->NewByteArray(length);
16561   Handle<DeclaredAccessorDescriptor> value =
16562       isolate->factory()->NewDeclaredAccessorDescriptor();
16563   value->set_serialized_data(*serialized_descriptor);
16564   // Copy in the data.
16565   {
16566     DisallowHeapAllocation no_allocation;
16567     uint8_t* array = serialized_descriptor->GetDataStartAddress();
16568     if (previous_length != 0) {
16569       uint8_t* previous_array =
16570           previous->serialized_data()->GetDataStartAddress();
16571       MemCopy(array, previous_array, previous_length);
16572       array += previous_length;
16573     }
16574     DCHECK(reinterpret_cast<uintptr_t>(array) % sizeof(uintptr_t) == 0);
16575     DeclaredAccessorDescriptorData* data =
16576         reinterpret_cast<DeclaredAccessorDescriptorData*>(array);
16577     *data = descriptor;
16578   }
16579   return value;
16580 }
16581
16582
16583 // Check if there is a break point at this code position.
16584 bool DebugInfo::HasBreakPoint(int code_position) {
16585   // Get the break point info object for this code position.
16586   Object* break_point_info = GetBreakPointInfo(code_position);
16587
16588   // If there is no break point info object or no break points in the break
16589   // point info object there is no break point at this code position.
16590   if (break_point_info->IsUndefined()) return false;
16591   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
16592 }
16593
16594
16595 // Get the break point info object for this code position.
16596 Object* DebugInfo::GetBreakPointInfo(int code_position) {
16597   // Find the index of the break point info object for this code position.
16598   int index = GetBreakPointInfoIndex(code_position);
16599
16600   // Return the break point info object if any.
16601   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
16602   return BreakPointInfo::cast(break_points()->get(index));
16603 }
16604
16605
16606 // Clear a break point at the specified code position.
16607 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
16608                                 int code_position,
16609                                 Handle<Object> break_point_object) {
16610   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16611                                   debug_info->GetIsolate());
16612   if (break_point_info->IsUndefined()) return;
16613   BreakPointInfo::ClearBreakPoint(
16614       Handle<BreakPointInfo>::cast(break_point_info),
16615       break_point_object);
16616 }
16617
16618
16619 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
16620                               int code_position,
16621                               int source_position,
16622                               int statement_position,
16623                               Handle<Object> break_point_object) {
16624   Isolate* isolate = debug_info->GetIsolate();
16625   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16626                                   isolate);
16627   if (!break_point_info->IsUndefined()) {
16628     BreakPointInfo::SetBreakPoint(
16629         Handle<BreakPointInfo>::cast(break_point_info),
16630         break_point_object);
16631     return;
16632   }
16633
16634   // Adding a new break point for a code position which did not have any
16635   // break points before. Try to find a free slot.
16636   int index = kNoBreakPointInfo;
16637   for (int i = 0; i < debug_info->break_points()->length(); i++) {
16638     if (debug_info->break_points()->get(i)->IsUndefined()) {
16639       index = i;
16640       break;
16641     }
16642   }
16643   if (index == kNoBreakPointInfo) {
16644     // No free slot - extend break point info array.
16645     Handle<FixedArray> old_break_points =
16646         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
16647     Handle<FixedArray> new_break_points =
16648         isolate->factory()->NewFixedArray(
16649             old_break_points->length() +
16650             DebugInfo::kEstimatedNofBreakPointsInFunction);
16651
16652     debug_info->set_break_points(*new_break_points);
16653     for (int i = 0; i < old_break_points->length(); i++) {
16654       new_break_points->set(i, old_break_points->get(i));
16655     }
16656     index = old_break_points->length();
16657   }
16658   DCHECK(index != kNoBreakPointInfo);
16659
16660   // Allocate new BreakPointInfo object and set the break point.
16661   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
16662       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
16663   new_break_point_info->set_code_position(Smi::FromInt(code_position));
16664   new_break_point_info->set_source_position(Smi::FromInt(source_position));
16665   new_break_point_info->
16666       set_statement_position(Smi::FromInt(statement_position));
16667   new_break_point_info->set_break_point_objects(
16668       isolate->heap()->undefined_value());
16669   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
16670   debug_info->break_points()->set(index, *new_break_point_info);
16671 }
16672
16673
16674 // Get the break point objects for a code position.
16675 Object* DebugInfo::GetBreakPointObjects(int code_position) {
16676   Object* break_point_info = GetBreakPointInfo(code_position);
16677   if (break_point_info->IsUndefined()) {
16678     return GetHeap()->undefined_value();
16679   }
16680   return BreakPointInfo::cast(break_point_info)->break_point_objects();
16681 }
16682
16683
16684 // Get the total number of break points.
16685 int DebugInfo::GetBreakPointCount() {
16686   if (break_points()->IsUndefined()) return 0;
16687   int count = 0;
16688   for (int i = 0; i < break_points()->length(); i++) {
16689     if (!break_points()->get(i)->IsUndefined()) {
16690       BreakPointInfo* break_point_info =
16691           BreakPointInfo::cast(break_points()->get(i));
16692       count += break_point_info->GetBreakPointCount();
16693     }
16694   }
16695   return count;
16696 }
16697
16698
16699 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
16700                                       Handle<Object> break_point_object) {
16701   Heap* heap = debug_info->GetHeap();
16702   if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
16703   for (int i = 0; i < debug_info->break_points()->length(); i++) {
16704     if (!debug_info->break_points()->get(i)->IsUndefined()) {
16705       Handle<BreakPointInfo> break_point_info =
16706           Handle<BreakPointInfo>(BreakPointInfo::cast(
16707               debug_info->break_points()->get(i)));
16708       if (BreakPointInfo::HasBreakPointObject(break_point_info,
16709                                               break_point_object)) {
16710         return *break_point_info;
16711       }
16712     }
16713   }
16714   return heap->undefined_value();
16715 }
16716
16717
16718 // Find the index of the break point info object for the specified code
16719 // position.
16720 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
16721   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
16722   for (int i = 0; i < break_points()->length(); i++) {
16723     if (!break_points()->get(i)->IsUndefined()) {
16724       BreakPointInfo* break_point_info =
16725           BreakPointInfo::cast(break_points()->get(i));
16726       if (break_point_info->code_position()->value() == code_position) {
16727         return i;
16728       }
16729     }
16730   }
16731   return kNoBreakPointInfo;
16732 }
16733
16734
16735 // Remove the specified break point object.
16736 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
16737                                      Handle<Object> break_point_object) {
16738   Isolate* isolate = break_point_info->GetIsolate();
16739   // If there are no break points just ignore.
16740   if (break_point_info->break_point_objects()->IsUndefined()) return;
16741   // If there is a single break point clear it if it is the same.
16742   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16743     if (break_point_info->break_point_objects() == *break_point_object) {
16744       break_point_info->set_break_point_objects(
16745           isolate->heap()->undefined_value());
16746     }
16747     return;
16748   }
16749   // If there are multiple break points shrink the array
16750   DCHECK(break_point_info->break_point_objects()->IsFixedArray());
16751   Handle<FixedArray> old_array =
16752       Handle<FixedArray>(
16753           FixedArray::cast(break_point_info->break_point_objects()));
16754   Handle<FixedArray> new_array =
16755       isolate->factory()->NewFixedArray(old_array->length() - 1);
16756   int found_count = 0;
16757   for (int i = 0; i < old_array->length(); i++) {
16758     if (old_array->get(i) == *break_point_object) {
16759       DCHECK(found_count == 0);
16760       found_count++;
16761     } else {
16762       new_array->set(i - found_count, old_array->get(i));
16763     }
16764   }
16765   // If the break point was found in the list change it.
16766   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
16767 }
16768
16769
16770 // Add the specified break point object.
16771 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
16772                                    Handle<Object> break_point_object) {
16773   Isolate* isolate = break_point_info->GetIsolate();
16774
16775   // If there was no break point objects before just set it.
16776   if (break_point_info->break_point_objects()->IsUndefined()) {
16777     break_point_info->set_break_point_objects(*break_point_object);
16778     return;
16779   }
16780   // If the break point object is the same as before just ignore.
16781   if (break_point_info->break_point_objects() == *break_point_object) return;
16782   // If there was one break point object before replace with array.
16783   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16784     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
16785     array->set(0, break_point_info->break_point_objects());
16786     array->set(1, *break_point_object);
16787     break_point_info->set_break_point_objects(*array);
16788     return;
16789   }
16790   // If there was more than one break point before extend array.
16791   Handle<FixedArray> old_array =
16792       Handle<FixedArray>(
16793           FixedArray::cast(break_point_info->break_point_objects()));
16794   Handle<FixedArray> new_array =
16795       isolate->factory()->NewFixedArray(old_array->length() + 1);
16796   for (int i = 0; i < old_array->length(); i++) {
16797     // If the break point was there before just ignore.
16798     if (old_array->get(i) == *break_point_object) return;
16799     new_array->set(i, old_array->get(i));
16800   }
16801   // Add the new break point.
16802   new_array->set(old_array->length(), *break_point_object);
16803   break_point_info->set_break_point_objects(*new_array);
16804 }
16805
16806
16807 bool BreakPointInfo::HasBreakPointObject(
16808     Handle<BreakPointInfo> break_point_info,
16809     Handle<Object> break_point_object) {
16810   // No break point.
16811   if (break_point_info->break_point_objects()->IsUndefined()) return false;
16812   // Single break point.
16813   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16814     return break_point_info->break_point_objects() == *break_point_object;
16815   }
16816   // Multiple break points.
16817   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
16818   for (int i = 0; i < array->length(); i++) {
16819     if (array->get(i) == *break_point_object) {
16820       return true;
16821     }
16822   }
16823   return false;
16824 }
16825
16826
16827 // Get the number of break points.
16828 int BreakPointInfo::GetBreakPointCount() {
16829   // No break point.
16830   if (break_point_objects()->IsUndefined()) return 0;
16831   // Single break point.
16832   if (!break_point_objects()->IsFixedArray()) return 1;
16833   // Multiple break points.
16834   return FixedArray::cast(break_point_objects())->length();
16835 }
16836
16837
16838 Object* JSDate::GetField(Object* object, Smi* index) {
16839   return JSDate::cast(object)->DoGetField(
16840       static_cast<FieldIndex>(index->value()));
16841 }
16842
16843
16844 Object* JSDate::DoGetField(FieldIndex index) {
16845   DCHECK(index != kDateValue);
16846
16847   DateCache* date_cache = GetIsolate()->date_cache();
16848
16849   if (index < kFirstUncachedField) {
16850     Object* stamp = cache_stamp();
16851     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
16852       // Since the stamp is not NaN, the value is also not NaN.
16853       int64_t local_time_ms =
16854           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
16855       SetCachedFields(local_time_ms, date_cache);
16856     }
16857     switch (index) {
16858       case kYear: return year();
16859       case kMonth: return month();
16860       case kDay: return day();
16861       case kWeekday: return weekday();
16862       case kHour: return hour();
16863       case kMinute: return min();
16864       case kSecond: return sec();
16865       default: UNREACHABLE();
16866     }
16867   }
16868
16869   if (index >= kFirstUTCField) {
16870     return GetUTCField(index, value()->Number(), date_cache);
16871   }
16872
16873   double time = value()->Number();
16874   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
16875
16876   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
16877   int days = DateCache::DaysFromTime(local_time_ms);
16878
16879   if (index == kDays) return Smi::FromInt(days);
16880
16881   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16882   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
16883   DCHECK(index == kTimeInDay);
16884   return Smi::FromInt(time_in_day_ms);
16885 }
16886
16887
16888 Object* JSDate::GetUTCField(FieldIndex index,
16889                             double value,
16890                             DateCache* date_cache) {
16891   DCHECK(index >= kFirstUTCField);
16892
16893   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
16894
16895   int64_t time_ms = static_cast<int64_t>(value);
16896
16897   if (index == kTimezoneOffset) {
16898     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
16899   }
16900
16901   int days = DateCache::DaysFromTime(time_ms);
16902
16903   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
16904
16905   if (index <= kDayUTC) {
16906     int year, month, day;
16907     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16908     if (index == kYearUTC) return Smi::FromInt(year);
16909     if (index == kMonthUTC) return Smi::FromInt(month);
16910     DCHECK(index == kDayUTC);
16911     return Smi::FromInt(day);
16912   }
16913
16914   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
16915   switch (index) {
16916     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
16917     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
16918     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
16919     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
16920     case kDaysUTC: return Smi::FromInt(days);
16921     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
16922     default: UNREACHABLE();
16923   }
16924
16925   UNREACHABLE();
16926   return NULL;
16927 }
16928
16929
16930 void JSDate::SetValue(Object* value, bool is_value_nan) {
16931   set_value(value);
16932   if (is_value_nan) {
16933     HeapNumber* nan = GetIsolate()->heap()->nan_value();
16934     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
16935     set_year(nan, SKIP_WRITE_BARRIER);
16936     set_month(nan, SKIP_WRITE_BARRIER);
16937     set_day(nan, SKIP_WRITE_BARRIER);
16938     set_hour(nan, SKIP_WRITE_BARRIER);
16939     set_min(nan, SKIP_WRITE_BARRIER);
16940     set_sec(nan, SKIP_WRITE_BARRIER);
16941     set_weekday(nan, SKIP_WRITE_BARRIER);
16942   } else {
16943     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
16944   }
16945 }
16946
16947
16948 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
16949   int days = DateCache::DaysFromTime(local_time_ms);
16950   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16951   int year, month, day;
16952   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16953   int weekday = date_cache->Weekday(days);
16954   int hour = time_in_day_ms / (60 * 60 * 1000);
16955   int min = (time_in_day_ms / (60 * 1000)) % 60;
16956   int sec = (time_in_day_ms / 1000) % 60;
16957   set_cache_stamp(date_cache->stamp());
16958   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
16959   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
16960   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
16961   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
16962   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
16963   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
16964   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
16965 }
16966
16967
16968 void JSArrayBuffer::Neuter() {
16969   DCHECK(is_external());
16970   set_backing_store(NULL);
16971   set_byte_length(Smi::FromInt(0));
16972 }
16973
16974
16975 void JSArrayBufferView::NeuterView() {
16976   set_byte_offset(Smi::FromInt(0));
16977   set_byte_length(Smi::FromInt(0));
16978 }
16979
16980
16981 void JSDataView::Neuter() {
16982   NeuterView();
16983 }
16984
16985
16986 void JSTypedArray::Neuter() {
16987   NeuterView();
16988   set_length(Smi::FromInt(0));
16989   set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
16990 }
16991
16992
16993 static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) {
16994   switch (elements_kind) {
16995 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
16996     case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
16997
16998     TYPED_ARRAYS(TYPED_ARRAY_CASE)
16999 #undef TYPED_ARRAY_CASE
17000
17001     default:
17002       UNREACHABLE();
17003       return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
17004   }
17005 }
17006
17007
17008 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
17009     Handle<JSTypedArray> typed_array) {
17010
17011   Handle<Map> map(typed_array->map());
17012   Isolate* isolate = typed_array->GetIsolate();
17013
17014   DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
17015
17016   Handle<Map> new_map = Map::TransitionElementsTo(
17017           map,
17018           FixedToExternalElementsKind(map->elements_kind()));
17019
17020   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
17021   Handle<FixedTypedArrayBase> fixed_typed_array(
17022       FixedTypedArrayBase::cast(typed_array->elements()));
17023   Runtime::SetupArrayBufferAllocatingData(isolate, buffer,
17024       fixed_typed_array->DataSize(), false);
17025   memcpy(buffer->backing_store(),
17026          fixed_typed_array->DataPtr(),
17027          fixed_typed_array->DataSize());
17028   Handle<ExternalArray> new_elements =
17029       isolate->factory()->NewExternalArray(
17030           fixed_typed_array->length(), typed_array->type(),
17031           static_cast<uint8_t*>(buffer->backing_store()));
17032
17033   buffer->set_weak_first_view(*typed_array);
17034   DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value());
17035   typed_array->set_buffer(*buffer);
17036   JSObject::SetMapAndElements(typed_array, new_map, new_elements);
17037
17038   return buffer;
17039 }
17040
17041
17042 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
17043   Handle<Object> result(buffer(), GetIsolate());
17044   if (*result != Smi::FromInt(0)) {
17045     DCHECK(IsExternalArrayElementsKind(map()->elements_kind()));
17046     return Handle<JSArrayBuffer>::cast(result);
17047   }
17048   Handle<JSTypedArray> self(this);
17049   return MaterializeArrayBuffer(self);
17050 }
17051
17052
17053 HeapType* PropertyCell::type() {
17054   return static_cast<HeapType*>(type_raw());
17055 }
17056
17057
17058 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) {
17059   DCHECK(IsPropertyCell());
17060   set_type_raw(type, ignored);
17061 }
17062
17063
17064 Handle<HeapType> PropertyCell::UpdatedType(Handle<PropertyCell> cell,
17065                                            Handle<Object> value) {
17066   Isolate* isolate = cell->GetIsolate();
17067   Handle<HeapType> old_type(cell->type(), isolate);
17068   Handle<HeapType> new_type = HeapType::Constant(value, isolate);
17069
17070   if (new_type->Is(old_type)) return old_type;
17071
17072   cell->dependent_code()->DeoptimizeDependentCodeGroup(
17073       isolate, DependentCode::kPropertyCellChangedGroup);
17074
17075   if (old_type->Is(HeapType::None()) || old_type->Is(HeapType::Undefined())) {
17076     return new_type;
17077   }
17078
17079   return HeapType::Any(isolate);
17080 }
17081
17082
17083 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell,
17084                                      Handle<Object> value) {
17085   cell->set_value(*value);
17086   if (!HeapType::Any()->Is(cell->type())) {
17087     Handle<HeapType> new_type = UpdatedType(cell, value);
17088     cell->set_type(*new_type);
17089   }
17090 }
17091
17092
17093 // static
17094 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell,
17095                                                CompilationInfo* info) {
17096   Handle<DependentCode> codes =
17097       DependentCode::Insert(handle(cell->dependent_code(), info->isolate()),
17098                             DependentCode::kPropertyCellChangedGroup,
17099                             info->object_wrapper());
17100   if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
17101   info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
17102       cell, info->zone());
17103 }
17104
17105
17106 const char* GetBailoutReason(BailoutReason reason) {
17107   DCHECK(reason < kLastErrorMessage);
17108 #define ERROR_MESSAGES_TEXTS(C, T) T,
17109   static const char* error_messages_[] = {
17110       ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
17111   };
17112 #undef ERROR_MESSAGES_TEXTS
17113   return error_messages_[reason];
17114 }
17115
17116
17117 } }  // namespace v8::internal