Upstream version 9.37.195.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/codegen.h"
13 #include "src/code-stubs.h"
14 #include "src/cpu-profiler.h"
15 #include "src/debug.h"
16 #include "src/deoptimizer.h"
17 #include "src/date.h"
18 #include "src/elements.h"
19 #include "src/execution.h"
20 #include "src/field-index.h"
21 #include "src/field-index-inl.h"
22 #include "src/full-codegen.h"
23 #include "src/hydrogen.h"
24 #include "src/isolate-inl.h"
25 #include "src/log.h"
26 #include "src/lookup.h"
27 #include "src/objects-inl.h"
28 #include "src/objects-visiting-inl.h"
29 #include "src/macro-assembler.h"
30 #include "src/mark-compact.h"
31 #include "src/safepoint-table.h"
32 #include "src/string-search.h"
33 #include "src/string-stream.h"
34 #include "src/utils.h"
35
36 #ifdef ENABLE_DISASSEMBLER
37 #include "src/disasm.h"
38 #include "src/disassembler.h"
39 #endif
40
41 namespace v8 {
42 namespace internal {
43
44 Handle<HeapType> Object::OptimalType(Isolate* isolate,
45                                      Representation representation) {
46   if (representation.IsNone()) return HeapType::None(isolate);
47   if (FLAG_track_field_types) {
48     if (representation.IsHeapObject() && IsHeapObject()) {
49       // We can track only JavaScript objects with stable maps.
50       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
51       if (map->is_stable() &&
52           map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
53           map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
54         return HeapType::Class(map, isolate);
55       }
56     }
57   }
58   return HeapType::Any(isolate);
59 }
60
61
62 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
63                                          Handle<Object> object,
64                                          Handle<Context> native_context) {
65   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
66   Handle<JSFunction> constructor;
67   if (object->IsNumber()) {
68     constructor = handle(native_context->number_function(), isolate);
69   } else if (object->IsBoolean()) {
70     constructor = handle(native_context->boolean_function(), isolate);
71   } else if (object->IsString()) {
72     constructor = handle(native_context->string_function(), isolate);
73   } else if (object->IsSymbol()) {
74     constructor = handle(native_context->symbol_function(), isolate);
75   } else {
76     return MaybeHandle<JSReceiver>();
77   }
78   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
79   Handle<JSValue>::cast(result)->set_value(*object);
80   return result;
81 }
82
83
84 bool Object::BooleanValue() {
85   if (IsBoolean()) return IsTrue();
86   if (IsSmi()) return Smi::cast(this)->value() != 0;
87   if (IsUndefined() || IsNull()) return false;
88   if (IsUndetectableObject()) return false;   // Undetectable object is false.
89   if (IsString()) return String::cast(this)->length() != 0;
90   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
91   return true;
92 }
93
94
95 bool Object::IsCallable() {
96   Object* fun = this;
97   while (fun->IsJSFunctionProxy()) {
98     fun = JSFunctionProxy::cast(fun)->call_trap();
99   }
100   return fun->IsJSFunction() ||
101          (fun->IsHeapObject() &&
102           HeapObject::cast(fun)->map()->has_instance_call_handler());
103 }
104
105
106 void Object::Lookup(Handle<Name> name, LookupResult* result) {
107   DisallowHeapAllocation no_gc;
108   Object* holder = NULL;
109   if (IsJSReceiver()) {
110     holder = this;
111   } else {
112     Context* native_context = result->isolate()->context()->native_context();
113     if (IsNumber()) {
114       holder = native_context->number_function()->instance_prototype();
115     } else if (IsString()) {
116       holder = native_context->string_function()->instance_prototype();
117     } else if (IsSymbol()) {
118       holder = native_context->symbol_function()->instance_prototype();
119     } else if (IsBoolean()) {
120       holder = native_context->boolean_function()->instance_prototype();
121     } else {
122       result->isolate()->PushStackTraceAndDie(
123           0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001);
124     }
125   }
126   ASSERT(holder != NULL);  // Cannot handle null or undefined.
127   JSReceiver::cast(holder)->Lookup(name, result);
128 }
129
130
131 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
132   for (; it->IsFound(); it->Next()) {
133     switch (it->state()) {
134       case LookupIterator::NOT_FOUND:
135         UNREACHABLE();
136       case LookupIterator::JSPROXY:
137         return JSProxy::GetPropertyWithHandler(
138             it->GetJSProxy(), it->GetReceiver(), it->name());
139       case LookupIterator::INTERCEPTOR: {
140         MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithInterceptor(
141             it->GetHolder(), it->GetReceiver(), it->name());
142         if (!maybe_result.is_null()) return maybe_result;
143         if (it->isolate()->has_pending_exception()) return maybe_result;
144         break;
145       }
146       case LookupIterator::ACCESS_CHECK:
147         if (it->HasAccess(v8::ACCESS_GET)) break;
148         return JSObject::GetPropertyWithFailedAccessCheck(it);
149       case LookupIterator::PROPERTY:
150         if (it->HasProperty()) {
151           switch (it->property_kind()) {
152             case LookupIterator::ACCESSOR:
153               return GetPropertyWithAccessor(
154                   it->GetReceiver(), it->name(),
155                   it->GetHolder(), it->GetAccessors());
156             case LookupIterator::DATA:
157               return it->GetDataValue();
158           }
159         }
160         break;
161     }
162   }
163   return it->factory()->undefined_value();
164 }
165
166
167 bool Object::ToInt32(int32_t* value) {
168   if (IsSmi()) {
169     *value = Smi::cast(this)->value();
170     return true;
171   }
172   if (IsHeapNumber()) {
173     double num = HeapNumber::cast(this)->value();
174     if (FastI2D(FastD2I(num)) == num) {
175       *value = FastD2I(num);
176       return true;
177     }
178   }
179   return false;
180 }
181
182
183 bool Object::ToUint32(uint32_t* value) {
184   if (IsSmi()) {
185     int num = Smi::cast(this)->value();
186     if (num >= 0) {
187       *value = static_cast<uint32_t>(num);
188       return true;
189     }
190   }
191   if (IsHeapNumber()) {
192     double num = HeapNumber::cast(this)->value();
193     if (num >= 0 && FastUI2D(FastD2UI(num)) == num) {
194       *value = FastD2UI(num);
195       return true;
196     }
197   }
198   return false;
199 }
200
201
202 bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
203   if (!object->IsHeapObject()) return false;
204   return IsTemplateFor(HeapObject::cast(object)->map());
205 }
206
207
208 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
209   // There is a constraint on the object; check.
210   if (!map->IsJSObjectMap()) return false;
211   // Fetch the constructor function of the object.
212   Object* cons_obj = map->constructor();
213   if (!cons_obj->IsJSFunction()) return false;
214   JSFunction* fun = JSFunction::cast(cons_obj);
215   // Iterate through the chain of inheriting function templates to
216   // see if the required one occurs.
217   for (Object* type = fun->shared()->function_data();
218        type->IsFunctionTemplateInfo();
219        type = FunctionTemplateInfo::cast(type)->parent_template()) {
220     if (type == this) return true;
221   }
222   // Didn't find the required type in the inheritance chain.
223   return false;
224 }
225
226
227 template<typename To>
228 static inline To* CheckedCast(void *from) {
229   uintptr_t temp = reinterpret_cast<uintptr_t>(from);
230   ASSERT(temp % sizeof(To) == 0);
231   return reinterpret_cast<To*>(temp);
232 }
233
234
235 static Handle<Object> PerformCompare(const BitmaskCompareDescriptor& descriptor,
236                                      char* ptr,
237                                      Isolate* isolate) {
238   uint32_t bitmask = descriptor.bitmask;
239   uint32_t compare_value = descriptor.compare_value;
240   uint32_t value;
241   switch (descriptor.size) {
242     case 1:
243       value = static_cast<uint32_t>(*CheckedCast<uint8_t>(ptr));
244       compare_value &= 0xff;
245       bitmask &= 0xff;
246       break;
247     case 2:
248       value = static_cast<uint32_t>(*CheckedCast<uint16_t>(ptr));
249       compare_value &= 0xffff;
250       bitmask &= 0xffff;
251       break;
252     case 4:
253       value = *CheckedCast<uint32_t>(ptr);
254       break;
255     default:
256       UNREACHABLE();
257       return isolate->factory()->undefined_value();
258   }
259   return isolate->factory()->ToBoolean(
260       (bitmask & value) == (bitmask & compare_value));
261 }
262
263
264 static Handle<Object> PerformCompare(const PointerCompareDescriptor& descriptor,
265                                      char* ptr,
266                                      Isolate* isolate) {
267   uintptr_t compare_value =
268       reinterpret_cast<uintptr_t>(descriptor.compare_value);
269   uintptr_t value = *CheckedCast<uintptr_t>(ptr);
270   return isolate->factory()->ToBoolean(compare_value == value);
271 }
272
273
274 static Handle<Object> GetPrimitiveValue(
275     const PrimitiveValueDescriptor& descriptor,
276     char* ptr,
277     Isolate* isolate) {
278   int32_t int32_value = 0;
279   switch (descriptor.data_type) {
280     case kDescriptorInt8Type:
281       int32_value = *CheckedCast<int8_t>(ptr);
282       break;
283     case kDescriptorUint8Type:
284       int32_value = *CheckedCast<uint8_t>(ptr);
285       break;
286     case kDescriptorInt16Type:
287       int32_value = *CheckedCast<int16_t>(ptr);
288       break;
289     case kDescriptorUint16Type:
290       int32_value = *CheckedCast<uint16_t>(ptr);
291       break;
292     case kDescriptorInt32Type:
293       int32_value = *CheckedCast<int32_t>(ptr);
294       break;
295     case kDescriptorUint32Type: {
296       uint32_t value = *CheckedCast<uint32_t>(ptr);
297       AllowHeapAllocation allow_gc;
298       return isolate->factory()->NewNumberFromUint(value);
299     }
300     case kDescriptorBoolType: {
301       uint8_t byte = *CheckedCast<uint8_t>(ptr);
302       return isolate->factory()->ToBoolean(
303           byte & (0x1 << descriptor.bool_offset));
304     }
305     case kDescriptorFloatType: {
306       float value = *CheckedCast<float>(ptr);
307       AllowHeapAllocation allow_gc;
308       return isolate->factory()->NewNumber(value);
309     }
310     case kDescriptorDoubleType: {
311       double value = *CheckedCast<double>(ptr);
312       AllowHeapAllocation allow_gc;
313       return isolate->factory()->NewNumber(value);
314     }
315   }
316   AllowHeapAllocation allow_gc;
317   return isolate->factory()->NewNumberFromInt(int32_value);
318 }
319
320
321 static Handle<Object> GetDeclaredAccessorProperty(
322     Handle<Object> receiver,
323     Handle<DeclaredAccessorInfo> info,
324     Isolate* isolate) {
325   DisallowHeapAllocation no_gc;
326   char* current = reinterpret_cast<char*>(*receiver);
327   DeclaredAccessorDescriptorIterator iterator(info->descriptor());
328   while (true) {
329     const DeclaredAccessorDescriptorData* data = iterator.Next();
330     switch (data->type) {
331       case kDescriptorReturnObject: {
332         ASSERT(iterator.Complete());
333         current = *CheckedCast<char*>(current);
334         return handle(*CheckedCast<Object*>(current), isolate);
335       }
336       case kDescriptorPointerDereference:
337         ASSERT(!iterator.Complete());
338         current = *reinterpret_cast<char**>(current);
339         break;
340       case kDescriptorPointerShift:
341         ASSERT(!iterator.Complete());
342         current += data->pointer_shift_descriptor.byte_offset;
343         break;
344       case kDescriptorObjectDereference: {
345         ASSERT(!iterator.Complete());
346         Object* object = CheckedCast<Object>(current);
347         int field = data->object_dereference_descriptor.internal_field;
348         Object* smi = JSObject::cast(object)->GetInternalField(field);
349         ASSERT(smi->IsSmi());
350         current = reinterpret_cast<char*>(smi);
351         break;
352       }
353       case kDescriptorBitmaskCompare:
354         ASSERT(iterator.Complete());
355         return PerformCompare(data->bitmask_compare_descriptor,
356                               current,
357                               isolate);
358       case kDescriptorPointerCompare:
359         ASSERT(iterator.Complete());
360         return PerformCompare(data->pointer_compare_descriptor,
361                               current,
362                               isolate);
363       case kDescriptorPrimitiveValue:
364         ASSERT(iterator.Complete());
365         return GetPrimitiveValue(data->primitive_value_descriptor,
366                                  current,
367                                  isolate);
368     }
369   }
370   UNREACHABLE();
371   return isolate->factory()->undefined_value();
372 }
373
374
375 Handle<FixedArray> JSObject::EnsureWritableFastElements(
376     Handle<JSObject> object) {
377   ASSERT(object->HasFastSmiOrObjectElements());
378   Isolate* isolate = object->GetIsolate();
379   Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
380   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
381   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
382       elems, isolate->factory()->fixed_array_map());
383   object->set_elements(*writable_elems);
384   isolate->counters()->cow_arrays_converted()->Increment();
385   return writable_elems;
386 }
387
388
389 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
390                                                     Handle<Object> receiver,
391                                                     Handle<Name> name) {
392   Isolate* isolate = proxy->GetIsolate();
393
394   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
395   if (name->IsSymbol()) return isolate->factory()->undefined_value();
396
397   Handle<Object> args[] = { receiver, name };
398   return CallTrap(
399       proxy, "get",  isolate->derived_get_trap(), ARRAY_SIZE(args), args);
400 }
401
402
403 MaybeHandle<Object> Object::GetPropertyWithAccessor(Handle<Object> receiver,
404                                                     Handle<Name> name,
405                                                     Handle<JSObject> holder,
406                                                     Handle<Object> structure) {
407   Isolate* isolate = name->GetIsolate();
408   ASSERT(!structure->IsForeign());
409   // api style callbacks.
410   if (structure->IsAccessorInfo()) {
411     Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure);
412     if (!accessor_info->IsCompatibleReceiver(*receiver)) {
413       Handle<Object> args[2] = { name, receiver };
414       Handle<Object> error =
415           isolate->factory()->NewTypeError("incompatible_method_receiver",
416                                            HandleVector(args,
417                                                         ARRAY_SIZE(args)));
418       return isolate->Throw<Object>(error);
419     }
420     // TODO(rossberg): Handling symbols in the API requires changing the API,
421     // so we do not support it for now.
422     if (name->IsSymbol()) return isolate->factory()->undefined_value();
423     if (structure->IsDeclaredAccessorInfo()) {
424       return GetDeclaredAccessorProperty(
425           receiver,
426           Handle<DeclaredAccessorInfo>::cast(structure),
427           isolate);
428     }
429
430     Handle<ExecutableAccessorInfo> data =
431         Handle<ExecutableAccessorInfo>::cast(structure);
432     v8::AccessorGetterCallback call_fun =
433         v8::ToCData<v8::AccessorGetterCallback>(data->getter());
434     if (call_fun == NULL) return isolate->factory()->undefined_value();
435
436     Handle<String> key = Handle<String>::cast(name);
437     LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
438     PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
439     v8::Handle<v8::Value> result =
440         args.Call(call_fun, v8::Utils::ToLocal(key));
441     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
442     if (result.IsEmpty()) {
443       return isolate->factory()->undefined_value();
444     }
445     Handle<Object> return_value = v8::Utils::OpenHandle(*result);
446     return_value->VerifyApiCallResultType();
447     // Rebox handle before return.
448     return handle(*return_value, isolate);
449   }
450
451   // __defineGetter__ callback
452   Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
453                         isolate);
454   if (getter->IsSpecFunction()) {
455     // TODO(rossberg): nicer would be to cast to some JSCallable here...
456     return Object::GetPropertyWithDefinedGetter(
457         receiver, Handle<JSReceiver>::cast(getter));
458   }
459   // Getter is not a function.
460   return isolate->factory()->undefined_value();
461 }
462
463
464 MaybeHandle<Object> Object::SetPropertyWithCallback(Handle<Object> receiver,
465                                                     Handle<Name> name,
466                                                     Handle<Object> value,
467                                                     Handle<JSObject> holder,
468                                                     Handle<Object> structure,
469                                                     StrictMode strict_mode) {
470   Isolate* isolate = name->GetIsolate();
471
472   // We should never get here to initialize a const with the hole
473   // value since a const declaration would conflict with the setter.
474   ASSERT(!value->IsTheHole());
475   ASSERT(!structure->IsForeign());
476   if (structure->IsExecutableAccessorInfo()) {
477     // api style callbacks
478     ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure);
479     if (!data->IsCompatibleReceiver(*receiver)) {
480       Handle<Object> args[2] = { name, receiver };
481       Handle<Object> error =
482           isolate->factory()->NewTypeError("incompatible_method_receiver",
483                                            HandleVector(args,
484                                                         ARRAY_SIZE(args)));
485       return isolate->Throw<Object>(error);
486     }
487     // TODO(rossberg): Support symbols in the API.
488     if (name->IsSymbol()) return value;
489     Object* call_obj = data->setter();
490     v8::AccessorSetterCallback call_fun =
491         v8::ToCData<v8::AccessorSetterCallback>(call_obj);
492     if (call_fun == NULL) return value;
493     Handle<String> key = Handle<String>::cast(name);
494     LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
495     PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
496     args.Call(call_fun,
497               v8::Utils::ToLocal(key),
498               v8::Utils::ToLocal(value));
499     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
500     return value;
501   }
502
503   if (structure->IsAccessorPair()) {
504     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
505     if (setter->IsSpecFunction()) {
506       // TODO(rossberg): nicer would be to cast to some JSCallable here...
507       return SetPropertyWithDefinedSetter(
508           receiver, Handle<JSReceiver>::cast(setter), value);
509     } else {
510       if (strict_mode == SLOPPY) return value;
511       Handle<Object> args[2] = { name, holder };
512       Handle<Object> error =
513           isolate->factory()->NewTypeError("no_setter_in_callback",
514                                            HandleVector(args, 2));
515       return isolate->Throw<Object>(error);
516     }
517   }
518
519   // TODO(dcarney): Handle correctly.
520   if (structure->IsDeclaredAccessorInfo()) {
521     return value;
522   }
523
524   UNREACHABLE();
525   return MaybeHandle<Object>();
526 }
527
528
529 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
530     Handle<Object> receiver,
531     Handle<JSReceiver> getter) {
532   Isolate* isolate = getter->GetIsolate();
533   Debug* debug = isolate->debug();
534   // Handle stepping into a getter if step into is active.
535   // TODO(rossberg): should this apply to getters that are function proxies?
536   if (debug->StepInActive() && getter->IsJSFunction()) {
537     debug->HandleStepIn(
538         Handle<JSFunction>::cast(getter), Handle<Object>::null(), 0, false);
539   }
540
541   return Execution::Call(isolate, getter, receiver, 0, NULL, true);
542 }
543
544
545 MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
546     Handle<Object> receiver,
547     Handle<JSReceiver> setter,
548     Handle<Object> value) {
549   Isolate* isolate = setter->GetIsolate();
550
551   Debug* debug = isolate->debug();
552   // Handle stepping into a setter if step into is active.
553   // TODO(rossberg): should this apply to getters that are function proxies?
554   if (debug->StepInActive() && setter->IsJSFunction()) {
555     debug->HandleStepIn(
556         Handle<JSFunction>::cast(setter), Handle<Object>::null(), 0, false);
557   }
558
559   Handle<Object> argv[] = { value };
560   RETURN_ON_EXCEPTION(
561       isolate,
562       Execution::Call(isolate, setter, receiver, ARRAY_SIZE(argv), argv),
563       Object);
564   return value;
565 }
566
567
568 static bool FindAllCanReadHolder(LookupIterator* it) {
569   it->skip_interceptor();
570   it->skip_access_check();
571   for (; it->IsFound(); it->Next()) {
572     if (it->state() == LookupIterator::PROPERTY &&
573         it->HasProperty() &&
574         it->property_kind() == LookupIterator::ACCESSOR) {
575       Handle<Object> accessors = it->GetAccessors();
576       if (accessors->IsAccessorInfo()) {
577         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
578       } else if (accessors->IsAccessorPair()) {
579         if (AccessorPair::cast(*accessors)->all_can_read()) return true;
580       }
581     }
582   }
583   return false;
584 }
585
586
587 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
588     LookupIterator* it) {
589   Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder());
590   if (FindAllCanReadHolder(it)) {
591     return GetPropertyWithAccessor(
592         it->GetReceiver(), it->name(), it->GetHolder(), it->GetAccessors());
593   }
594   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET);
595   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
596   return it->factory()->undefined_value();
597 }
598
599
600 PropertyAttributes JSObject::GetPropertyAttributesWithFailedAccessCheck(
601     LookupIterator* it) {
602   Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder());
603   if (FindAllCanReadHolder(it)) return it->property_details().attributes();
604   it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
605   // TODO(yangguo): Issue 3269, check for scheduled exception missing?
606   return ABSENT;
607 }
608
609
610 static bool FindAllCanWriteHolder(LookupResult* result,
611                                   Handle<Name> name,
612                                   bool check_prototype) {
613   if (result->IsInterceptor()) {
614     result->holder()->LookupOwnRealNamedProperty(name, result);
615   }
616
617   while (result->IsProperty()) {
618     if (result->type() == CALLBACKS) {
619       Object* callback_obj = result->GetCallbackObject();
620       if (callback_obj->IsAccessorInfo()) {
621         if (AccessorInfo::cast(callback_obj)->all_can_write()) return true;
622       } else if (callback_obj->IsAccessorPair()) {
623         if (AccessorPair::cast(callback_obj)->all_can_write()) return true;
624       }
625     }
626     if (!check_prototype) break;
627     result->holder()->LookupRealNamedPropertyInPrototypes(name, result);
628   }
629   return false;
630 }
631
632
633 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
634     Handle<JSObject> object,
635     LookupResult* result,
636     Handle<Name> name,
637     Handle<Object> value,
638     bool check_prototype,
639     StrictMode strict_mode) {
640   if (check_prototype && !result->IsProperty()) {
641     object->LookupRealNamedPropertyInPrototypes(name, result);
642   }
643
644   if (FindAllCanWriteHolder(result, name, check_prototype)) {
645     Handle<JSObject> holder(result->holder());
646     Handle<Object> callbacks(result->GetCallbackObject(), result->isolate());
647     return SetPropertyWithCallback(
648         object, name, value, holder, callbacks, strict_mode);
649   }
650
651   Isolate* isolate = object->GetIsolate();
652   isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
653   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
654   return value;
655 }
656
657
658 Object* JSObject::GetNormalizedProperty(const LookupResult* result) {
659   ASSERT(!HasFastProperties());
660   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
661   if (IsGlobalObject()) {
662     value = PropertyCell::cast(value)->value();
663   }
664   ASSERT(!value->IsPropertyCell() && !value->IsCell());
665   return value;
666 }
667
668
669 Handle<Object> JSObject::GetNormalizedProperty(Handle<JSObject> object,
670                                                const LookupResult* result) {
671   ASSERT(!object->HasFastProperties());
672   Isolate* isolate = object->GetIsolate();
673   Handle<Object> value(object->property_dictionary()->ValueAt(
674       result->GetDictionaryEntry()), isolate);
675   if (object->IsGlobalObject()) {
676     value = Handle<Object>(Handle<PropertyCell>::cast(value)->value(), isolate);
677   }
678   ASSERT(!value->IsPropertyCell() && !value->IsCell());
679   return value;
680 }
681
682
683 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
684                                      const LookupResult* result,
685                                      Handle<Object> value) {
686   ASSERT(!object->HasFastProperties());
687   NameDictionary* property_dictionary = object->property_dictionary();
688   if (object->IsGlobalObject()) {
689     Handle<PropertyCell> cell(PropertyCell::cast(
690         property_dictionary->ValueAt(result->GetDictionaryEntry())));
691     PropertyCell::SetValueInferType(cell, value);
692   } else {
693     property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value);
694   }
695 }
696
697
698 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
699                                      Handle<Name> name,
700                                      Handle<Object> value,
701                                      PropertyDetails details) {
702   ASSERT(!object->HasFastProperties());
703   Handle<NameDictionary> property_dictionary(object->property_dictionary());
704
705   if (!name->IsUniqueName()) {
706     name = object->GetIsolate()->factory()->InternalizeString(
707         Handle<String>::cast(name));
708   }
709
710   int entry = property_dictionary->FindEntry(name);
711   if (entry == NameDictionary::kNotFound) {
712     Handle<Object> store_value = value;
713     if (object->IsGlobalObject()) {
714       store_value = object->GetIsolate()->factory()->NewPropertyCell(value);
715     }
716
717     property_dictionary = NameDictionary::Add(
718         property_dictionary, name, store_value, details);
719     object->set_properties(*property_dictionary);
720     return;
721   }
722
723   PropertyDetails original_details = property_dictionary->DetailsAt(entry);
724   int enumeration_index;
725   // Preserve the enumeration index unless the property was deleted.
726   if (original_details.IsDeleted()) {
727     enumeration_index = property_dictionary->NextEnumerationIndex();
728     property_dictionary->SetNextEnumerationIndex(enumeration_index + 1);
729   } else {
730     enumeration_index = original_details.dictionary_index();
731     ASSERT(enumeration_index > 0);
732   }
733
734   details = PropertyDetails(
735       details.attributes(), details.type(), enumeration_index);
736
737   if (object->IsGlobalObject()) {
738     Handle<PropertyCell> cell(
739         PropertyCell::cast(property_dictionary->ValueAt(entry)));
740     PropertyCell::SetValueInferType(cell, value);
741     // Please note we have to update the property details.
742     property_dictionary->DetailsAtPut(entry, details);
743   } else {
744     property_dictionary->SetEntry(entry, name, value, details);
745   }
746 }
747
748
749 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
750                                                   Handle<Name> name,
751                                                   DeleteMode mode) {
752   ASSERT(!object->HasFastProperties());
753   Isolate* isolate = object->GetIsolate();
754   Handle<NameDictionary> dictionary(object->property_dictionary());
755   int entry = dictionary->FindEntry(name);
756   if (entry != NameDictionary::kNotFound) {
757     // If we have a global object set the cell to the hole.
758     if (object->IsGlobalObject()) {
759       PropertyDetails details = dictionary->DetailsAt(entry);
760       if (details.IsDontDelete()) {
761         if (mode != FORCE_DELETION) return isolate->factory()->false_value();
762         // When forced to delete global properties, we have to make a
763         // map change to invalidate any ICs that think they can load
764         // from the DontDelete cell without checking if it contains
765         // the hole value.
766         Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
767         ASSERT(new_map->is_dictionary_map());
768         object->set_map(*new_map);
769       }
770       Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
771       Handle<Object> value = isolate->factory()->the_hole_value();
772       PropertyCell::SetValueInferType(cell, value);
773       dictionary->DetailsAtPut(entry, details.AsDeleted());
774     } else {
775       Handle<Object> deleted(
776           NameDictionary::DeleteProperty(dictionary, entry, mode));
777       if (*deleted == isolate->heap()->true_value()) {
778         Handle<NameDictionary> new_properties =
779             NameDictionary::Shrink(dictionary, name);
780         object->set_properties(*new_properties);
781       }
782       return deleted;
783     }
784   }
785   return isolate->factory()->true_value();
786 }
787
788
789 bool JSObject::IsDirty() {
790   Object* cons_obj = map()->constructor();
791   if (!cons_obj->IsJSFunction())
792     return true;
793   JSFunction* fun = JSFunction::cast(cons_obj);
794   if (!fun->shared()->IsApiFunction())
795     return true;
796   // If the object is fully fast case and has the same map it was
797   // created with then no changes can have been made to it.
798   return map() != fun->initial_map()
799       || !HasFastObjectElements()
800       || !HasFastProperties();
801 }
802
803
804 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
805                                                    Handle<Object> object,
806                                                    Handle<Object> receiver,
807                                                    uint32_t index) {
808   Handle<Object> holder;
809
810   // Iterate up the prototype chain until an element is found or the null
811   // prototype is encountered.
812   for (holder = object;
813        !holder->IsNull();
814        holder = Handle<Object>(holder->GetPrototype(isolate), isolate)) {
815     if (!holder->IsJSObject()) {
816       Context* native_context = isolate->context()->native_context();
817       if (holder->IsNumber()) {
818         holder = Handle<Object>(
819             native_context->number_function()->instance_prototype(), isolate);
820       } else if (holder->IsString()) {
821         holder = Handle<Object>(
822             native_context->string_function()->instance_prototype(), isolate);
823       } else if (holder->IsSymbol()) {
824         holder = Handle<Object>(
825             native_context->symbol_function()->instance_prototype(), isolate);
826       } else if (holder->IsBoolean()) {
827         holder = Handle<Object>(
828             native_context->boolean_function()->instance_prototype(), isolate);
829       } else if (holder->IsJSProxy()) {
830         return JSProxy::GetElementWithHandler(
831             Handle<JSProxy>::cast(holder), receiver, index);
832       } else {
833         // Undefined and null have no indexed properties.
834         ASSERT(holder->IsUndefined() || holder->IsNull());
835         return isolate->factory()->undefined_value();
836       }
837     }
838
839     // Inline the case for JSObjects. Doing so significantly improves the
840     // performance of fetching elements where checking the prototype chain is
841     // necessary.
842     Handle<JSObject> js_object = Handle<JSObject>::cast(holder);
843
844     // Check access rights if needed.
845     if (js_object->IsAccessCheckNeeded()) {
846       if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
847         isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
848         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
849         return isolate->factory()->undefined_value();
850       }
851     }
852
853     if (js_object->HasIndexedInterceptor()) {
854       return JSObject::GetElementWithInterceptor(js_object, receiver, index);
855     }
856
857     if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
858       Handle<Object> result;
859       ASSIGN_RETURN_ON_EXCEPTION(
860           isolate, result,
861           js_object->GetElementsAccessor()->Get(receiver, js_object, index),
862           Object);
863       if (!result->IsTheHole()) return result;
864     }
865   }
866
867   return isolate->factory()->undefined_value();
868 }
869
870
871 Object* Object::GetPrototype(Isolate* isolate) {
872   DisallowHeapAllocation no_alloc;
873   if (IsSmi()) {
874     Context* context = isolate->context()->native_context();
875     return context->number_function()->instance_prototype();
876   }
877
878   HeapObject* heap_object = HeapObject::cast(this);
879
880   // The object is either a number, a string, a boolean,
881   // a real JS object, or a Harmony proxy.
882   if (heap_object->IsJSReceiver()) {
883     return heap_object->map()->prototype();
884   }
885   Context* context = isolate->context()->native_context();
886
887   if (heap_object->IsHeapNumber()) {
888     return context->number_function()->instance_prototype();
889   }
890   if (heap_object->IsString()) {
891     return context->string_function()->instance_prototype();
892   }
893   if (heap_object->IsSymbol()) {
894     return context->symbol_function()->instance_prototype();
895   }
896   if (heap_object->IsBoolean()) {
897     return context->boolean_function()->instance_prototype();
898   } else {
899     return isolate->heap()->null_value();
900   }
901 }
902
903
904 Handle<Object> Object::GetPrototype(Isolate* isolate,
905                                     Handle<Object> object) {
906   return handle(object->GetPrototype(isolate), isolate);
907 }
908
909
910 Object* Object::GetHash() {
911   // The object is either a number, a name, an odd-ball,
912   // a real JS object, or a Harmony proxy.
913   if (IsNumber()) {
914     uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
915     return Smi::FromInt(hash & Smi::kMaxValue);
916   }
917   if (IsName()) {
918     uint32_t hash = Name::cast(this)->Hash();
919     return Smi::FromInt(hash);
920   }
921   if (IsOddball()) {
922     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
923     return Smi::FromInt(hash);
924   }
925
926   ASSERT(IsJSReceiver());
927   return JSReceiver::cast(this)->GetIdentityHash();
928 }
929
930
931 Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
932   Handle<Object> hash(object->GetHash(), isolate);
933   if (hash->IsSmi()) return Handle<Smi>::cast(hash);
934
935   ASSERT(object->IsJSReceiver());
936   return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
937 }
938
939
940 bool Object::SameValue(Object* other) {
941   if (other == this) return true;
942
943   // The object is either a number, a name, an odd-ball,
944   // a real JS object, or a Harmony proxy.
945   if (IsNumber() && other->IsNumber()) {
946     double this_value = Number();
947     double other_value = other->Number();
948     bool equal = this_value == other_value;
949     // SameValue(NaN, NaN) is true.
950     if (!equal) return std::isnan(this_value) && std::isnan(other_value);
951     // SameValue(0.0, -0.0) is false.
952     return (this_value != 0) || ((1 / this_value) == (1 / other_value));
953   }
954   if (IsString() && other->IsString()) {
955     return String::cast(this)->Equals(String::cast(other));
956   }
957   return false;
958 }
959
960
961 bool Object::SameValueZero(Object* other) {
962   if (other == this) return true;
963
964   // The object is either a number, a name, an odd-ball,
965   // a real JS object, or a Harmony proxy.
966   if (IsNumber() && other->IsNumber()) {
967     double this_value = Number();
968     double other_value = other->Number();
969     // +0 == -0 is true
970     return this_value == other_value
971         || (std::isnan(this_value) && std::isnan(other_value));
972   }
973   if (IsString() && other->IsString()) {
974     return String::cast(this)->Equals(String::cast(other));
975   }
976   return false;
977 }
978
979
980 void Object::ShortPrint(FILE* out) {
981   HeapStringAllocator allocator;
982   StringStream accumulator(&allocator);
983   ShortPrint(&accumulator);
984   accumulator.OutputToFile(out);
985 }
986
987
988 void Object::ShortPrint(StringStream* accumulator) {
989   if (IsSmi()) {
990     Smi::cast(this)->SmiPrint(accumulator);
991   } else {
992     HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
993   }
994 }
995
996
997 void Smi::SmiPrint(FILE* out) {
998   PrintF(out, "%d", value());
999 }
1000
1001
1002 void Smi::SmiPrint(StringStream* accumulator) {
1003   accumulator->Add("%d", value());
1004 }
1005
1006
1007 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
1008 // English?  Returns false for non-ASCII or words that don't start with
1009 // a capital letter.  The a/an rule follows pronunciation in English.
1010 // We don't use the BBC's overcorrect "an historic occasion" though if
1011 // you speak a dialect you may well say "an 'istoric occasion".
1012 static bool AnWord(String* str) {
1013   if (str->length() == 0) return false;  // A nothing.
1014   int c0 = str->Get(0);
1015   int c1 = str->length() > 1 ? str->Get(1) : 0;
1016   if (c0 == 'U') {
1017     if (c1 > 'Z') {
1018       return true;  // An Umpire, but a UTF8String, a U.
1019     }
1020   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
1021     return true;    // An Ape, an ABCBook.
1022   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
1023            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
1024             c0 == 'S' || c0 == 'X')) {
1025     return true;    // An MP3File, an M.
1026   }
1027   return false;
1028 }
1029
1030
1031 Handle<String> String::SlowFlatten(Handle<ConsString> cons,
1032                                    PretenureFlag pretenure) {
1033   ASSERT(AllowHeapAllocation::IsAllowed());
1034   ASSERT(cons->second()->length() != 0);
1035   Isolate* isolate = cons->GetIsolate();
1036   int length = cons->length();
1037   PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
1038                                                             : TENURED;
1039   Handle<SeqString> result;
1040   if (cons->IsOneByteRepresentation()) {
1041     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
1042         length, tenure).ToHandleChecked();
1043     DisallowHeapAllocation no_gc;
1044     WriteToFlat(*cons, flat->GetChars(), 0, length);
1045     result = flat;
1046   } else {
1047     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
1048         length, tenure).ToHandleChecked();
1049     DisallowHeapAllocation no_gc;
1050     WriteToFlat(*cons, flat->GetChars(), 0, length);
1051     result = flat;
1052   }
1053   cons->set_first(*result);
1054   cons->set_second(isolate->heap()->empty_string());
1055   ASSERT(result->IsFlat());
1056   return result;
1057 }
1058
1059
1060
1061 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
1062   // Externalizing twice leaks the external resource, so it's
1063   // prohibited by the API.
1064   ASSERT(!this->IsExternalString());
1065 #ifdef ENABLE_SLOW_ASSERTS
1066   if (FLAG_enable_slow_asserts) {
1067     // Assert that the resource and the string are equivalent.
1068     ASSERT(static_cast<size_t>(this->length()) == resource->length());
1069     ScopedVector<uc16> smart_chars(this->length());
1070     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1071     ASSERT(memcmp(smart_chars.start(),
1072                   resource->data(),
1073                   resource->length() * sizeof(smart_chars[0])) == 0);
1074   }
1075 #endif  // DEBUG
1076   Heap* heap = GetHeap();
1077   int size = this->Size();  // Byte size of the original string.
1078   if (size < ExternalString::kShortSize) {
1079     return false;
1080   }
1081   bool is_ascii = this->IsOneByteRepresentation();
1082   bool is_internalized = this->IsInternalizedString();
1083
1084   // Morph the string to an external string by replacing the map and
1085   // reinitializing the fields.  This won't work if
1086   // - the space the existing string occupies is too small for a regular
1087   //   external string.
1088   // - the existing string is in old pointer space and the backing store of
1089   //   the external string is not aligned.  The GC cannot deal with a field
1090   //   containing a possibly unaligned address to outside of V8's heap.
1091   // In either case we resort to a short external string instead, omitting
1092   // the field caching the address of the backing store.  When we encounter
1093   // short external strings in generated code, we need to bailout to runtime.
1094   Map* new_map;
1095   if (size < ExternalString::kSize ||
1096       heap->old_pointer_space()->Contains(this)) {
1097     new_map = is_internalized
1098         ? (is_ascii
1099             ? heap->
1100                 short_external_internalized_string_with_one_byte_data_map()
1101             : heap->short_external_internalized_string_map())
1102         : (is_ascii
1103             ? heap->short_external_string_with_one_byte_data_map()
1104             : heap->short_external_string_map());
1105   } else {
1106     new_map = is_internalized
1107         ? (is_ascii
1108             ? heap->external_internalized_string_with_one_byte_data_map()
1109             : heap->external_internalized_string_map())
1110         : (is_ascii
1111             ? heap->external_string_with_one_byte_data_map()
1112             : heap->external_string_map());
1113   }
1114
1115   // Byte size of the external String object.
1116   int new_size = this->SizeFromMap(new_map);
1117   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1118
1119   // We are storing the new map using release store after creating a filler for
1120   // the left-over space to avoid races with the sweeper thread.
1121   this->synchronized_set_map(new_map);
1122
1123   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
1124   self->set_resource(resource);
1125   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1126
1127   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1128   return true;
1129 }
1130
1131
1132 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
1133 #ifdef ENABLE_SLOW_ASSERTS
1134   if (FLAG_enable_slow_asserts) {
1135     // Assert that the resource and the string are equivalent.
1136     ASSERT(static_cast<size_t>(this->length()) == resource->length());
1137     if (this->IsTwoByteRepresentation()) {
1138       ScopedVector<uint16_t> smart_chars(this->length());
1139       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1140       ASSERT(String::IsOneByte(smart_chars.start(), this->length()));
1141     }
1142     ScopedVector<char> smart_chars(this->length());
1143     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1144     ASSERT(memcmp(smart_chars.start(),
1145                   resource->data(),
1146                   resource->length() * sizeof(smart_chars[0])) == 0);
1147   }
1148 #endif  // DEBUG
1149   Heap* heap = GetHeap();
1150   int size = this->Size();  // Byte size of the original string.
1151   if (size < ExternalString::kShortSize) {
1152     return false;
1153   }
1154   bool is_internalized = this->IsInternalizedString();
1155
1156   // Morph the string to an external string by replacing the map and
1157   // reinitializing the fields.  This won't work if
1158   // - the space the existing string occupies is too small for a regular
1159   //   external string.
1160   // - the existing string is in old pointer space and the backing store of
1161   //   the external string is not aligned.  The GC cannot deal with a field
1162   //   containing a possibly unaligned address to outside of V8's heap.
1163   // In either case we resort to a short external string instead, omitting
1164   // the field caching the address of the backing store.  When we encounter
1165   // short external strings in generated code, we need to bailout to runtime.
1166   Map* new_map;
1167   if (size < ExternalString::kSize ||
1168       heap->old_pointer_space()->Contains(this)) {
1169     new_map = is_internalized
1170         ? heap->short_external_ascii_internalized_string_map()
1171         : heap->short_external_ascii_string_map();
1172   } else {
1173     new_map = is_internalized
1174         ? heap->external_ascii_internalized_string_map()
1175         : heap->external_ascii_string_map();
1176   }
1177
1178   // Byte size of the external String object.
1179   int new_size = this->SizeFromMap(new_map);
1180   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1181
1182   // We are storing the new map using release store after creating a filler for
1183   // the left-over space to avoid races with the sweeper thread.
1184   this->synchronized_set_map(new_map);
1185
1186   ExternalAsciiString* self = ExternalAsciiString::cast(this);
1187   self->set_resource(resource);
1188   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1189
1190   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1191   return true;
1192 }
1193
1194
1195 void String::StringShortPrint(StringStream* accumulator) {
1196   int len = length();
1197   if (len > kMaxShortPrintLength) {
1198     accumulator->Add("<Very long string[%u]>", len);
1199     return;
1200   }
1201
1202   if (!LooksValid()) {
1203     accumulator->Add("<Invalid String>");
1204     return;
1205   }
1206
1207   ConsStringIteratorOp op;
1208   StringCharacterStream stream(this, &op);
1209
1210   bool truncated = false;
1211   if (len > kMaxShortPrintLength) {
1212     len = kMaxShortPrintLength;
1213     truncated = true;
1214   }
1215   bool ascii = true;
1216   for (int i = 0; i < len; i++) {
1217     uint16_t c = stream.GetNext();
1218
1219     if (c < 32 || c >= 127) {
1220       ascii = false;
1221     }
1222   }
1223   stream.Reset(this);
1224   if (ascii) {
1225     accumulator->Add("<String[%u]: ", length());
1226     for (int i = 0; i < len; i++) {
1227       accumulator->Put(static_cast<char>(stream.GetNext()));
1228     }
1229     accumulator->Put('>');
1230   } else {
1231     // Backslash indicates that the string contains control
1232     // characters and that backslashes are therefore escaped.
1233     accumulator->Add("<String[%u]\\: ", length());
1234     for (int i = 0; i < len; i++) {
1235       uint16_t c = stream.GetNext();
1236       if (c == '\n') {
1237         accumulator->Add("\\n");
1238       } else if (c == '\r') {
1239         accumulator->Add("\\r");
1240       } else if (c == '\\') {
1241         accumulator->Add("\\\\");
1242       } else if (c < 32 || c > 126) {
1243         accumulator->Add("\\x%02x", c);
1244       } else {
1245         accumulator->Put(static_cast<char>(c));
1246       }
1247     }
1248     if (truncated) {
1249       accumulator->Put('.');
1250       accumulator->Put('.');
1251       accumulator->Put('.');
1252     }
1253     accumulator->Put('>');
1254   }
1255   return;
1256 }
1257
1258
1259 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1260   switch (map()->instance_type()) {
1261     case JS_ARRAY_TYPE: {
1262       double length = JSArray::cast(this)->length()->IsUndefined()
1263           ? 0
1264           : JSArray::cast(this)->length()->Number();
1265       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1266       break;
1267     }
1268     case JS_WEAK_MAP_TYPE: {
1269       accumulator->Add("<JS WeakMap>");
1270       break;
1271     }
1272     case JS_WEAK_SET_TYPE: {
1273       accumulator->Add("<JS WeakSet>");
1274       break;
1275     }
1276     case JS_REGEXP_TYPE: {
1277       accumulator->Add("<JS RegExp>");
1278       break;
1279     }
1280     case JS_FUNCTION_TYPE: {
1281       JSFunction* function = JSFunction::cast(this);
1282       Object* fun_name = function->shared()->DebugName();
1283       bool printed = false;
1284       if (fun_name->IsString()) {
1285         String* str = String::cast(fun_name);
1286         if (str->length() > 0) {
1287           accumulator->Add("<JS Function ");
1288           accumulator->Put(str);
1289           printed = true;
1290         }
1291       }
1292       if (!printed) {
1293         accumulator->Add("<JS Function");
1294       }
1295       accumulator->Add(" (SharedFunctionInfo %p)",
1296                        reinterpret_cast<void*>(function->shared()));
1297       accumulator->Put('>');
1298       break;
1299     }
1300     case JS_GENERATOR_OBJECT_TYPE: {
1301       accumulator->Add("<JS Generator>");
1302       break;
1303     }
1304     case JS_MODULE_TYPE: {
1305       accumulator->Add("<JS Module>");
1306       break;
1307     }
1308     // All other JSObjects are rather similar to each other (JSObject,
1309     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1310     default: {
1311       Map* map_of_this = map();
1312       Heap* heap = GetHeap();
1313       Object* constructor = map_of_this->constructor();
1314       bool printed = false;
1315       if (constructor->IsHeapObject() &&
1316           !heap->Contains(HeapObject::cast(constructor))) {
1317         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1318       } else {
1319         bool global_object = IsJSGlobalProxy();
1320         if (constructor->IsJSFunction()) {
1321           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1322             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1323           } else {
1324             Object* constructor_name =
1325                 JSFunction::cast(constructor)->shared()->name();
1326             if (constructor_name->IsString()) {
1327               String* str = String::cast(constructor_name);
1328               if (str->length() > 0) {
1329                 bool vowel = AnWord(str);
1330                 accumulator->Add("<%sa%s ",
1331                        global_object ? "Global Object: " : "",
1332                        vowel ? "n" : "");
1333                 accumulator->Put(str);
1334                 accumulator->Add(" with %smap %p",
1335                     map_of_this->is_deprecated() ? "deprecated " : "",
1336                     map_of_this);
1337                 printed = true;
1338               }
1339             }
1340           }
1341         }
1342         if (!printed) {
1343           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1344         }
1345       }
1346       if (IsJSValue()) {
1347         accumulator->Add(" value = ");
1348         JSValue::cast(this)->value()->ShortPrint(accumulator);
1349       }
1350       accumulator->Put('>');
1351       break;
1352     }
1353   }
1354 }
1355
1356
1357 void JSObject::PrintElementsTransition(
1358     FILE* file, Handle<JSObject> object,
1359     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
1360     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
1361   if (from_kind != to_kind) {
1362     PrintF(file, "elements transition [");
1363     PrintElementsKind(file, from_kind);
1364     PrintF(file, " -> ");
1365     PrintElementsKind(file, to_kind);
1366     PrintF(file, "] in ");
1367     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
1368     PrintF(file, " for ");
1369     object->ShortPrint(file);
1370     PrintF(file, " from ");
1371     from_elements->ShortPrint(file);
1372     PrintF(file, " to ");
1373     to_elements->ShortPrint(file);
1374     PrintF(file, "\n");
1375   }
1376 }
1377
1378
1379 void Map::PrintGeneralization(FILE* file,
1380                               const char* reason,
1381                               int modify_index,
1382                               int split,
1383                               int descriptors,
1384                               bool constant_to_field,
1385                               Representation old_representation,
1386                               Representation new_representation,
1387                               HeapType* old_field_type,
1388                               HeapType* new_field_type) {
1389   PrintF(file, "[generalizing ");
1390   constructor_name()->PrintOn(file);
1391   PrintF(file, "] ");
1392   Name* name = instance_descriptors()->GetKey(modify_index);
1393   if (name->IsString()) {
1394     String::cast(name)->PrintOn(file);
1395   } else {
1396     PrintF(file, "{symbol %p}", static_cast<void*>(name));
1397   }
1398   PrintF(file, ":");
1399   if (constant_to_field) {
1400     PrintF(file, "c");
1401   } else {
1402     PrintF(file, "%s", old_representation.Mnemonic());
1403     PrintF(file, "{");
1404     old_field_type->TypePrint(file, HeapType::SEMANTIC_DIM);
1405     PrintF(file, "}");
1406   }
1407   PrintF(file, "->%s", new_representation.Mnemonic());
1408   PrintF(file, "{");
1409   new_field_type->TypePrint(file, HeapType::SEMANTIC_DIM);
1410   PrintF(file, "}");
1411   PrintF(file, " (");
1412   if (strlen(reason) > 0) {
1413     PrintF(file, "%s", reason);
1414   } else {
1415     PrintF(file, "+%i maps", descriptors - split);
1416   }
1417   PrintF(file, ") [");
1418   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1419   PrintF(file, "]\n");
1420 }
1421
1422
1423 void JSObject::PrintInstanceMigration(FILE* file,
1424                                       Map* original_map,
1425                                       Map* new_map) {
1426   PrintF(file, "[migrating ");
1427   map()->constructor_name()->PrintOn(file);
1428   PrintF(file, "] ");
1429   DescriptorArray* o = original_map->instance_descriptors();
1430   DescriptorArray* n = new_map->instance_descriptors();
1431   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
1432     Representation o_r = o->GetDetails(i).representation();
1433     Representation n_r = n->GetDetails(i).representation();
1434     if (!o_r.Equals(n_r)) {
1435       String::cast(o->GetKey(i))->PrintOn(file);
1436       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
1437     } else if (o->GetDetails(i).type() == CONSTANT &&
1438                n->GetDetails(i).type() == FIELD) {
1439       Name* name = o->GetKey(i);
1440       if (name->IsString()) {
1441         String::cast(name)->PrintOn(file);
1442       } else {
1443         PrintF(file, "{symbol %p}", static_cast<void*>(name));
1444       }
1445       PrintF(file, " ");
1446     }
1447   }
1448   PrintF(file, "\n");
1449 }
1450
1451
1452 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
1453   Heap* heap = GetHeap();
1454   if (!heap->Contains(this)) {
1455     accumulator->Add("!!!INVALID POINTER!!!");
1456     return;
1457   }
1458   if (!heap->Contains(map())) {
1459     accumulator->Add("!!!INVALID MAP!!!");
1460     return;
1461   }
1462
1463   accumulator->Add("%p ", this);
1464
1465   if (IsString()) {
1466     String::cast(this)->StringShortPrint(accumulator);
1467     return;
1468   }
1469   if (IsJSObject()) {
1470     JSObject::cast(this)->JSObjectShortPrint(accumulator);
1471     return;
1472   }
1473   switch (map()->instance_type()) {
1474     case MAP_TYPE:
1475       accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind());
1476       break;
1477     case FIXED_ARRAY_TYPE:
1478       accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
1479       break;
1480     case FIXED_DOUBLE_ARRAY_TYPE:
1481       accumulator->Add("<FixedDoubleArray[%u]>",
1482                        FixedDoubleArray::cast(this)->length());
1483       break;
1484     case BYTE_ARRAY_TYPE:
1485       accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
1486       break;
1487     case FREE_SPACE_TYPE:
1488       accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size());
1489       break;
1490 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                 \
1491     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
1492       accumulator->Add("<External" #Type "Array[%u]>",                         \
1493                        External##Type##Array::cast(this)->length());           \
1494       break;                                                                   \
1495     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
1496       accumulator->Add("<Fixed" #Type "Array[%u]>",                            \
1497                        Fixed##Type##Array::cast(this)->length());              \
1498       break;
1499
1500     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1501 #undef TYPED_ARRAY_SHORT_PRINT
1502
1503     case SHARED_FUNCTION_INFO_TYPE: {
1504       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
1505       SmartArrayPointer<char> debug_name =
1506           shared->DebugName()->ToCString();
1507       if (debug_name[0] != 0) {
1508         accumulator->Add("<SharedFunctionInfo %s>", debug_name.get());
1509       } else {
1510         accumulator->Add("<SharedFunctionInfo>");
1511       }
1512       break;
1513     }
1514     case JS_MESSAGE_OBJECT_TYPE:
1515       accumulator->Add("<JSMessageObject>");
1516       break;
1517 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1518   case NAME##_TYPE:                        \
1519     accumulator->Put('<');                 \
1520     accumulator->Add(#Name);               \
1521     accumulator->Put('>');                 \
1522     break;
1523   STRUCT_LIST(MAKE_STRUCT_CASE)
1524 #undef MAKE_STRUCT_CASE
1525     case CODE_TYPE:
1526       accumulator->Add("<Code>");
1527       break;
1528     case ODDBALL_TYPE: {
1529       if (IsUndefined())
1530         accumulator->Add("<undefined>");
1531       else if (IsTheHole())
1532         accumulator->Add("<the hole>");
1533       else if (IsNull())
1534         accumulator->Add("<null>");
1535       else if (IsTrue())
1536         accumulator->Add("<true>");
1537       else if (IsFalse())
1538         accumulator->Add("<false>");
1539       else
1540         accumulator->Add("<Odd Oddball>");
1541       break;
1542     }
1543     case SYMBOL_TYPE: {
1544       Symbol* symbol = Symbol::cast(this);
1545       accumulator->Add("<Symbol: %d", symbol->Hash());
1546       if (!symbol->name()->IsUndefined()) {
1547         accumulator->Add(" ");
1548         String::cast(symbol->name())->StringShortPrint(accumulator);
1549       }
1550       accumulator->Add(">");
1551       break;
1552     }
1553     case HEAP_NUMBER_TYPE:
1554       accumulator->Add("<Number: ");
1555       HeapNumber::cast(this)->HeapNumberPrint(accumulator);
1556       accumulator->Put('>');
1557       break;
1558     case FLOAT32x4_TYPE:
1559       accumulator->Add("<Float32x4: ");
1560       Float32x4::cast(this)->Float32x4Print(accumulator);
1561       accumulator->Put('>');
1562       break;
1563     case FLOAT64x2_TYPE:
1564       accumulator->Add("<Float64x2: ");
1565       Float64x2::cast(this)->Float64x2Print(accumulator);
1566       accumulator->Put('>');
1567       break;
1568     case INT32x4_TYPE:
1569       accumulator->Add("<Int32x4: ");
1570       Int32x4::cast(this)->Int32x4Print(accumulator);
1571       accumulator->Put('>');
1572       break;
1573     case JS_PROXY_TYPE:
1574       accumulator->Add("<JSProxy>");
1575       break;
1576     case JS_FUNCTION_PROXY_TYPE:
1577       accumulator->Add("<JSFunctionProxy>");
1578       break;
1579     case FOREIGN_TYPE:
1580       accumulator->Add("<Foreign>");
1581       break;
1582     case CELL_TYPE:
1583       accumulator->Add("Cell for ");
1584       Cell::cast(this)->value()->ShortPrint(accumulator);
1585       break;
1586     case PROPERTY_CELL_TYPE:
1587       accumulator->Add("PropertyCell for ");
1588       PropertyCell::cast(this)->value()->ShortPrint(accumulator);
1589       break;
1590     default:
1591       accumulator->Add("<Other heap object (%d)>", map()->instance_type());
1592       break;
1593   }
1594 }
1595
1596
1597 void HeapObject::Iterate(ObjectVisitor* v) {
1598   // Handle header
1599   IteratePointer(v, kMapOffset);
1600   // Handle object body
1601   Map* m = map();
1602   IterateBody(m->instance_type(), SizeFromMap(m), v);
1603 }
1604
1605
1606 void HeapObject::IterateBody(InstanceType type, int object_size,
1607                              ObjectVisitor* v) {
1608   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1609   // During GC, the map pointer field is encoded.
1610   if (type < FIRST_NONSTRING_TYPE) {
1611     switch (type & kStringRepresentationMask) {
1612       case kSeqStringTag:
1613         break;
1614       case kConsStringTag:
1615         ConsString::BodyDescriptor::IterateBody(this, v);
1616         break;
1617       case kSlicedStringTag:
1618         SlicedString::BodyDescriptor::IterateBody(this, v);
1619         break;
1620       case kExternalStringTag:
1621         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1622           reinterpret_cast<ExternalAsciiString*>(this)->
1623               ExternalAsciiStringIterateBody(v);
1624         } else {
1625           reinterpret_cast<ExternalTwoByteString*>(this)->
1626               ExternalTwoByteStringIterateBody(v);
1627         }
1628         break;
1629     }
1630     return;
1631   }
1632
1633   switch (type) {
1634     case FIXED_ARRAY_TYPE:
1635       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1636       break;
1637     case CONSTANT_POOL_ARRAY_TYPE:
1638       reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v);
1639       break;
1640     case FIXED_DOUBLE_ARRAY_TYPE:
1641       break;
1642     case FLOAT32x4_TYPE:
1643     case FLOAT64x2_TYPE:
1644     case INT32x4_TYPE:
1645       break;
1646     case JS_OBJECT_TYPE:
1647     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1648     case JS_GENERATOR_OBJECT_TYPE:
1649     case JS_MODULE_TYPE:
1650     case JS_VALUE_TYPE:
1651     case JS_DATE_TYPE:
1652     case JS_ARRAY_TYPE:
1653     case JS_ARRAY_BUFFER_TYPE:
1654     case JS_TYPED_ARRAY_TYPE:
1655     case JS_DATA_VIEW_TYPE:
1656     case JS_SET_TYPE:
1657     case JS_MAP_TYPE:
1658     case JS_SET_ITERATOR_TYPE:
1659     case JS_MAP_ITERATOR_TYPE:
1660     case JS_WEAK_MAP_TYPE:
1661     case JS_WEAK_SET_TYPE:
1662     case JS_REGEXP_TYPE:
1663     case JS_GLOBAL_PROXY_TYPE:
1664     case JS_GLOBAL_OBJECT_TYPE:
1665     case JS_BUILTINS_OBJECT_TYPE:
1666     case JS_MESSAGE_OBJECT_TYPE:
1667       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1668       break;
1669     case JS_FUNCTION_TYPE:
1670       reinterpret_cast<JSFunction*>(this)
1671           ->JSFunctionIterateBody(object_size, v);
1672       break;
1673     case ODDBALL_TYPE:
1674       Oddball::BodyDescriptor::IterateBody(this, v);
1675       break;
1676     case JS_PROXY_TYPE:
1677       JSProxy::BodyDescriptor::IterateBody(this, v);
1678       break;
1679     case JS_FUNCTION_PROXY_TYPE:
1680       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1681       break;
1682     case FOREIGN_TYPE:
1683       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1684       break;
1685     case MAP_TYPE:
1686       Map::BodyDescriptor::IterateBody(this, v);
1687       break;
1688     case CODE_TYPE:
1689       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1690       break;
1691     case CELL_TYPE:
1692       Cell::BodyDescriptor::IterateBody(this, v);
1693       break;
1694     case PROPERTY_CELL_TYPE:
1695       PropertyCell::BodyDescriptor::IterateBody(this, v);
1696       break;
1697     case SYMBOL_TYPE:
1698       Symbol::BodyDescriptor::IterateBody(this, v);
1699       break;
1700
1701     case HEAP_NUMBER_TYPE:
1702     case FILLER_TYPE:
1703     case BYTE_ARRAY_TYPE:
1704     case FREE_SPACE_TYPE:
1705       break;
1706
1707 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
1708     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
1709     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
1710       break;
1711
1712     TYPED_ARRAYS(TYPED_ARRAY_CASE)
1713 #undef TYPED_ARRAY_CASE
1714
1715     case SHARED_FUNCTION_INFO_TYPE: {
1716       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1717       break;
1718     }
1719
1720 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1721         case NAME##_TYPE:
1722       STRUCT_LIST(MAKE_STRUCT_CASE)
1723 #undef MAKE_STRUCT_CASE
1724       if (type == ALLOCATION_SITE_TYPE) {
1725         AllocationSite::BodyDescriptor::IterateBody(this, v);
1726       } else {
1727         StructBodyDescriptor::IterateBody(this, object_size, v);
1728       }
1729       break;
1730     default:
1731       PrintF("Unknown type: %d\n", type);
1732       UNREACHABLE();
1733   }
1734 }
1735
1736
1737 bool HeapNumber::HeapNumberBooleanValue() {
1738   // NaN, +0, and -0 should return the false object
1739 #if __BYTE_ORDER == __LITTLE_ENDIAN
1740   union IeeeDoubleLittleEndianArchType u;
1741 #elif __BYTE_ORDER == __BIG_ENDIAN
1742   union IeeeDoubleBigEndianArchType u;
1743 #endif
1744   u.d = value();
1745   if (u.bits.exp == 2047) {
1746     // Detect NaN for IEEE double precision floating point.
1747     if ((u.bits.man_low | u.bits.man_high) != 0) return false;
1748   }
1749   if (u.bits.exp == 0) {
1750     // Detect +0, and -0 for IEEE double precision floating point.
1751     if ((u.bits.man_low | u.bits.man_high) == 0) return false;
1752   }
1753   return true;
1754 }
1755
1756
1757 void HeapNumber::HeapNumberPrint(FILE* out) {
1758   PrintF(out, "%.16g", Number());
1759 }
1760
1761
1762 void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
1763   // The Windows version of vsnprintf can allocate when printing a %g string
1764   // into a buffer that may not be big enough.  We don't want random memory
1765   // allocation when producing post-crash stack traces, so we print into a
1766   // buffer that is plenty big enough for any floating point number, then
1767   // print that using vsnprintf (which may truncate but never allocate if
1768   // there is no more space in the buffer).
1769   EmbeddedVector<char, 100> buffer;
1770   SNPrintF(buffer, "%.16g", Number());
1771   accumulator->Add("%s", buffer.start());
1772 }
1773
1774
1775 void Float32x4::Float32x4Print(FILE* out) {
1776   PrintF(out, "%.16g %.16g %.16g %.16g", x(), y(), z(), w());
1777 }
1778
1779
1780 void Float32x4::Float32x4Print(StringStream* accumulator) {
1781   // The Windows version of vsnprintf can allocate when printing a %g string
1782   // into a buffer that may not be big enough.  We don't want random memory
1783   // allocation when producing post-crash stack traces, so we print into a
1784   // buffer that is plenty big enough for any floating point number, then
1785   // print that using vsnprintf (which may truncate but never allocate if
1786   // there is no more space in the buffer).
1787   EmbeddedVector<char, 100> buffer;
1788   SNPrintF(buffer, "%.16g %.16g %.16g %.16g", x(), y(), z(), w());
1789   accumulator->Add("%s", buffer.start());
1790 }
1791
1792
1793 void Int32x4::Int32x4Print(FILE* out) {
1794   PrintF(out, "%u %u %u %u", x(), y(), z(), w());
1795 }
1796
1797
1798 void Int32x4::Int32x4Print(StringStream* accumulator) {
1799   // The Windows version of vsnprintf can allocate when printing a %g string
1800   // into a buffer that may not be big enough.  We don't want random memory
1801   // allocation when producing post-crash stack traces, so we print into a
1802   // buffer that is plenty big enough for any floating point number, then
1803   // print that using vsnprintf (which may truncate but never allocate if
1804   // there is no more space in the buffer).
1805   EmbeddedVector<char, 100> buffer;
1806   SNPrintF(buffer, "%u %u %u %u", x(), y(), z(), w());
1807   accumulator->Add("%s", buffer.start());
1808 }
1809
1810
1811 void Float64x2::Float64x2Print(FILE* out) {
1812   PrintF(out, "%.16g %.16g", x(), y());
1813 }
1814
1815
1816 void Float64x2::Float64x2Print(StringStream* accumulator) {
1817   // The Windows version of vsnprintf can allocate when printing a %g string
1818   // into a buffer that may not be big enough.  We don't want random memory
1819   // allocation when producing post-crash stack traces, so we print into a
1820   // buffer that is plenty big enough for any floating point number, then
1821   // print that using vsnprintf (which may truncate but never allocate if
1822   // there is no more space in the buffer).
1823   EmbeddedVector<char, 100> buffer;
1824   SNPrintF(buffer, "%.16g %.16g", x(), y());
1825   accumulator->Add("%s", buffer.start());
1826 }
1827
1828
1829 String* JSReceiver::class_name() {
1830   if (IsJSFunction() && IsJSFunctionProxy()) {
1831     return GetHeap()->function_class_string();
1832   }
1833   if (map()->constructor()->IsJSFunction()) {
1834     JSFunction* constructor = JSFunction::cast(map()->constructor());
1835     return String::cast(constructor->shared()->instance_class_name());
1836   }
1837   // If the constructor is not present, return "Object".
1838   return GetHeap()->Object_string();
1839 }
1840
1841
1842 String* Map::constructor_name() {
1843   if (constructor()->IsJSFunction()) {
1844     JSFunction* constructor = JSFunction::cast(this->constructor());
1845     String* name = String::cast(constructor->shared()->name());
1846     if (name->length() > 0) return name;
1847     String* inferred_name = constructor->shared()->inferred_name();
1848     if (inferred_name->length() > 0) return inferred_name;
1849     Object* proto = prototype();
1850     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1851   }
1852   // TODO(rossberg): what about proxies?
1853   // If the constructor is not present, return "Object".
1854   return GetHeap()->Object_string();
1855 }
1856
1857
1858 String* JSReceiver::constructor_name() {
1859   return map()->constructor_name();
1860 }
1861
1862
1863 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
1864                                     Handle<Name> name,
1865                                     Handle<HeapType> type,
1866                                     PropertyAttributes attributes,
1867                                     Representation representation,
1868                                     TransitionFlag flag) {
1869   ASSERT(DescriptorArray::kNotFound ==
1870          map->instance_descriptors()->Search(
1871              *name, map->NumberOfOwnDescriptors()));
1872
1873   // Ensure the descriptor array does not get too big.
1874   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1875     return MaybeHandle<Map>();
1876   }
1877
1878   Isolate* isolate = map->GetIsolate();
1879
1880   // Compute the new index for new field.
1881   int index = map->NextFreePropertyIndex();
1882
1883   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1884     representation = Representation::Tagged();
1885     type = HeapType::Any(isolate);
1886   }
1887
1888   FieldDescriptor new_field_desc(name, index, type, attributes, representation);
1889   Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1890   int unused_property_fields = new_map->unused_property_fields() - 1;
1891   if (unused_property_fields < 0) {
1892     unused_property_fields += JSObject::kFieldsAdded;
1893   }
1894   new_map->set_unused_property_fields(unused_property_fields);
1895   return new_map;
1896 }
1897
1898
1899 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1900                                        Handle<Name> name,
1901                                        Handle<Object> constant,
1902                                        PropertyAttributes attributes,
1903                                        TransitionFlag flag) {
1904   // Ensure the descriptor array does not get too big.
1905   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1906     return MaybeHandle<Map>();
1907   }
1908
1909   // Allocate new instance descriptors with (name, constant) added.
1910   ConstantDescriptor new_constant_desc(name, constant, attributes);
1911   return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1912 }
1913
1914
1915 void JSObject::AddFastProperty(Handle<JSObject> object,
1916                                Handle<Name> name,
1917                                Handle<Object> value,
1918                                PropertyAttributes attributes,
1919                                StoreFromKeyed store_mode,
1920                                ValueType value_type,
1921                                TransitionFlag flag) {
1922   ASSERT(!object->IsJSGlobalProxy());
1923
1924   MaybeHandle<Map> maybe_map;
1925   if (value->IsJSFunction()) {
1926     maybe_map = Map::CopyWithConstant(
1927         handle(object->map()), name, value, attributes, flag);
1928   } else if (!object->TooManyFastProperties(store_mode)) {
1929     Isolate* isolate = object->GetIsolate();
1930     Representation representation = value->OptimalRepresentation(value_type);
1931     maybe_map = Map::CopyWithField(
1932         handle(object->map(), isolate), name,
1933         value->OptimalType(isolate, representation),
1934         attributes, representation, flag);
1935   }
1936
1937   Handle<Map> new_map;
1938   if (!maybe_map.ToHandle(&new_map)) {
1939     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
1940     return;
1941   }
1942
1943   JSObject::MigrateToNewProperty(object, new_map, value);
1944 }
1945
1946
1947 void JSObject::AddSlowProperty(Handle<JSObject> object,
1948                                Handle<Name> name,
1949                                Handle<Object> value,
1950                                PropertyAttributes attributes) {
1951   ASSERT(!object->HasFastProperties());
1952   Isolate* isolate = object->GetIsolate();
1953   Handle<NameDictionary> dict(object->property_dictionary());
1954   if (object->IsGlobalObject()) {
1955     // In case name is an orphaned property reuse the cell.
1956     int entry = dict->FindEntry(name);
1957     if (entry != NameDictionary::kNotFound) {
1958       Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry)));
1959       PropertyCell::SetValueInferType(cell, value);
1960       // Assign an enumeration index to the property and update
1961       // SetNextEnumerationIndex.
1962       int index = dict->NextEnumerationIndex();
1963       PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
1964       dict->SetNextEnumerationIndex(index + 1);
1965       dict->SetEntry(entry, name, cell, details);
1966       return;
1967     }
1968     Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value);
1969     PropertyCell::SetValueInferType(cell, value);
1970     value = cell;
1971   }
1972   PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
1973   Handle<NameDictionary> result =
1974       NameDictionary::Add(dict, name, value, details);
1975   if (*dict != *result) object->set_properties(*result);
1976 }
1977
1978
1979 MaybeHandle<Object> JSObject::AddProperty(
1980     Handle<JSObject> object,
1981     Handle<Name> name,
1982     Handle<Object> value,
1983     PropertyAttributes attributes,
1984     StrictMode strict_mode,
1985     JSReceiver::StoreFromKeyed store_mode,
1986     ExtensibilityCheck extensibility_check,
1987     ValueType value_type,
1988     StoreMode mode,
1989     TransitionFlag transition_flag) {
1990   ASSERT(!object->IsJSGlobalProxy());
1991   Isolate* isolate = object->GetIsolate();
1992
1993   if (!name->IsUniqueName()) {
1994     name = isolate->factory()->InternalizeString(
1995         Handle<String>::cast(name));
1996   }
1997
1998   if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
1999       !object->map()->is_extensible()) {
2000     if (strict_mode == SLOPPY) {
2001       return value;
2002     } else {
2003       Handle<Object> args[1] = { name };
2004       Handle<Object> error = isolate->factory()->NewTypeError(
2005           "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
2006       return isolate->Throw<Object>(error);
2007     }
2008   }
2009
2010   if (object->HasFastProperties()) {
2011     AddFastProperty(object, name, value, attributes, store_mode,
2012                     value_type, transition_flag);
2013   }
2014
2015   if (!object->HasFastProperties()) {
2016     AddSlowProperty(object, name, value, attributes);
2017   }
2018
2019   if (object->map()->is_observed() &&
2020       *name != isolate->heap()->hidden_string()) {
2021     Handle<Object> old_value = isolate->factory()->the_hole_value();
2022     EnqueueChangeRecord(object, "add", name, old_value);
2023   }
2024
2025   return value;
2026 }
2027
2028
2029 Context* JSObject::GetCreationContext() {
2030   Object* constructor = this->map()->constructor();
2031   JSFunction* function;
2032   if (!constructor->IsJSFunction()) {
2033     // Functions have null as a constructor,
2034     // but any JSFunction knows its context immediately.
2035     function = JSFunction::cast(this);
2036   } else {
2037     function = JSFunction::cast(constructor);
2038   }
2039
2040   return function->context()->native_context();
2041 }
2042
2043
2044 void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
2045                                    const char* type_str,
2046                                    Handle<Name> name,
2047                                    Handle<Object> old_value) {
2048   ASSERT(!object->IsJSGlobalProxy());
2049   ASSERT(!object->IsJSGlobalObject());
2050   Isolate* isolate = object->GetIsolate();
2051   HandleScope scope(isolate);
2052   Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
2053   Handle<Object> args[] = { type, object, name, old_value };
2054   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
2055
2056   Execution::Call(isolate,
2057                   Handle<JSFunction>(isolate->observers_notify_change()),
2058                   isolate->factory()->undefined_value(),
2059                   argc, args).Assert();
2060 }
2061
2062
2063 MaybeHandle<Object> JSObject::SetPropertyPostInterceptor(
2064     Handle<JSObject> object,
2065     Handle<Name> name,
2066     Handle<Object> value,
2067     PropertyAttributes attributes,
2068     StrictMode strict_mode) {
2069   // Check own property, ignore interceptor.
2070   Isolate* isolate = object->GetIsolate();
2071   LookupResult result(isolate);
2072   object->LookupOwnRealNamedProperty(name, &result);
2073   if (!result.IsFound()) {
2074     object->map()->LookupTransition(*object, *name, &result);
2075   }
2076   return SetPropertyForResult(object, &result, name, value, attributes,
2077                               strict_mode, MAY_BE_STORE_FROM_KEYED);
2078 }
2079
2080
2081 static void ReplaceSlowProperty(Handle<JSObject> object,
2082                                 Handle<Name> name,
2083                                 Handle<Object> value,
2084                                 PropertyAttributes attributes) {
2085   NameDictionary* dictionary = object->property_dictionary();
2086   int old_index = dictionary->FindEntry(name);
2087   int new_enumeration_index = 0;  // 0 means "Use the next available index."
2088   if (old_index != -1) {
2089     // All calls to ReplaceSlowProperty have had all transitions removed.
2090     new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index();
2091   }
2092
2093   PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
2094   JSObject::SetNormalizedProperty(object, name, value, new_details);
2095 }
2096
2097
2098 const char* Representation::Mnemonic() const {
2099   switch (kind_) {
2100     case kNone: return "v";
2101     case kTagged: return "t";
2102     case kSmi: return "s";
2103     case kDouble: return "d";
2104     case kFloat32x4: return "float32x4";
2105     case kFloat64x2: return "float64x2";
2106     case kInt32x4: return "int32x44";
2107     case kInteger32: return "i";
2108     case kHeapObject: return "h";
2109     case kExternal: return "x";
2110     default:
2111       UNREACHABLE();
2112       return NULL;
2113   }
2114 }
2115
2116
2117 static void ZapEndOfFixedArray(Address new_end, int to_trim) {
2118   // If we are doing a big trim in old space then we zap the space.
2119   Object** zap = reinterpret_cast<Object**>(new_end);
2120   zap++;  // Header of filler must be at least one word so skip that.
2121   for (int i = 1; i < to_trim; i++) {
2122     *zap++ = Smi::FromInt(0);
2123   }
2124 }
2125
2126
2127 template<Heap::InvocationMode mode>
2128 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
2129   ASSERT(elms->map() != heap->fixed_cow_array_map());
2130   // For now this trick is only applied to fixed arrays in new and paged space.
2131   ASSERT(!heap->lo_space()->Contains(elms));
2132
2133   const int len = elms->length();
2134
2135   ASSERT(to_trim < len);
2136
2137   Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
2138
2139   if (mode != Heap::FROM_GC || Heap::ShouldZapGarbage()) {
2140     ZapEndOfFixedArray(new_end, to_trim);
2141   }
2142
2143   int size_delta = to_trim * kPointerSize;
2144
2145   // Technically in new space this write might be omitted (except for
2146   // debug mode which iterates through the heap), but to play safer
2147   // we still do it.
2148   heap->CreateFillerObjectAt(new_end, size_delta);
2149
2150   // We are storing the new length using release store after creating a filler
2151   // for the left-over space to avoid races with the sweeper thread.
2152   elms->synchronized_set_length(len - to_trim);
2153
2154   heap->AdjustLiveBytes(elms->address(), -size_delta, mode);
2155
2156   // The array may not be moved during GC,
2157   // and size has to be adjusted nevertheless.
2158   HeapProfiler* profiler = heap->isolate()->heap_profiler();
2159   if (profiler->is_tracking_allocations()) {
2160     profiler->UpdateObjectSizeEvent(elms->address(), elms->Size());
2161   }
2162 }
2163
2164
2165 bool Map::InstancesNeedRewriting(Map* target,
2166                                  int target_number_of_fields,
2167                                  int target_inobject,
2168                                  int target_unused) {
2169   // If fields were added (or removed), rewrite the instance.
2170   int number_of_fields = NumberOfFields();
2171   ASSERT(target_number_of_fields >= number_of_fields);
2172   if (target_number_of_fields != number_of_fields) return true;
2173
2174   // If smi descriptors were replaced by double descriptors, rewrite.
2175   DescriptorArray* old_desc = instance_descriptors();
2176   DescriptorArray* new_desc = target->instance_descriptors();
2177   int limit = NumberOfOwnDescriptors();
2178   for (int i = 0; i < limit; i++) {
2179     if (new_desc->GetDetails(i).representation().IsDouble() &&
2180         !old_desc->GetDetails(i).representation().IsDouble()) {
2181       return true;
2182     }
2183   }
2184
2185   // If no fields were added, and no inobject properties were removed, setting
2186   // the map is sufficient.
2187   if (target_inobject == inobject_properties()) return false;
2188   // In-object slack tracking may have reduced the object size of the new map.
2189   // In that case, succeed if all existing fields were inobject, and they still
2190   // fit within the new inobject size.
2191   ASSERT(target_inobject < inobject_properties());
2192   if (target_number_of_fields <= target_inobject) {
2193     ASSERT(target_number_of_fields + target_unused == target_inobject);
2194     return false;
2195   }
2196   // Otherwise, properties will need to be moved to the backing store.
2197   return true;
2198 }
2199
2200
2201 Handle<TransitionArray> Map::SetElementsTransitionMap(
2202     Handle<Map> map, Handle<Map> transitioned_map) {
2203   Handle<TransitionArray> transitions = TransitionArray::CopyInsert(
2204       map,
2205       map->GetIsolate()->factory()->elements_transition_symbol(),
2206       transitioned_map,
2207       FULL_TRANSITION);
2208   map->set_transitions(*transitions);
2209   return transitions;
2210 }
2211
2212
2213 // To migrate an instance to a map:
2214 // - First check whether the instance needs to be rewritten. If not, simply
2215 //   change the map.
2216 // - Otherwise, allocate a fixed array large enough to hold all fields, in
2217 //   addition to unused space.
2218 // - Copy all existing properties in, in the following order: backing store
2219 //   properties, unused fields, inobject properties.
2220 // - If all allocation succeeded, commit the state atomically:
2221 //   * Copy inobject properties from the backing store back into the object.
2222 //   * Trim the difference in instance size of the object. This also cleanly
2223 //     frees inobject properties that moved to the backing store.
2224 //   * If there are properties left in the backing store, trim of the space used
2225 //     to temporarily store the inobject properties.
2226 //   * If there are properties left in the backing store, install the backing
2227 //     store.
2228 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
2229   Isolate* isolate = object->GetIsolate();
2230   Handle<Map> old_map(object->map());
2231   int number_of_fields = new_map->NumberOfFields();
2232   int inobject = new_map->inobject_properties();
2233   int unused = new_map->unused_property_fields();
2234
2235   // Nothing to do if no functions were converted to fields and no smis were
2236   // converted to doubles.
2237   if (!old_map->InstancesNeedRewriting(
2238           *new_map, number_of_fields, inobject, unused)) {
2239     // Writing the new map here does not require synchronization since it does
2240     // not change the actual object size.
2241     object->synchronized_set_map(*new_map);
2242     return;
2243   }
2244
2245   int total_size = number_of_fields + unused;
2246   int external = total_size - inobject;
2247   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
2248
2249   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
2250   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
2251   int old_nof = old_map->NumberOfOwnDescriptors();
2252   int new_nof = new_map->NumberOfOwnDescriptors();
2253
2254   // This method only supports generalizing instances to at least the same
2255   // number of properties.
2256   ASSERT(old_nof <= new_nof);
2257
2258   for (int i = 0; i < old_nof; i++) {
2259     PropertyDetails details = new_descriptors->GetDetails(i);
2260     if (details.type() != FIELD) continue;
2261     PropertyDetails old_details = old_descriptors->GetDetails(i);
2262     if (old_details.type() == CALLBACKS) {
2263       ASSERT(details.representation().IsTagged());
2264       continue;
2265     }
2266     ASSERT(old_details.type() == CONSTANT ||
2267            old_details.type() == FIELD);
2268     Object* raw_value = old_details.type() == CONSTANT
2269         ? old_descriptors->GetValue(i)
2270         : object->RawFastPropertyAt(FieldIndex::ForDescriptor(*old_map, i));
2271     Handle<Object> value(raw_value, isolate);
2272     if (!old_details.representation().IsDouble() &&
2273         details.representation().IsDouble()) {
2274       if (old_details.representation().IsNone()) {
2275         value = handle(Smi::FromInt(0), isolate);
2276       }
2277       value = Object::NewStorageFor(isolate, value, details.representation());
2278     }
2279     ASSERT(!(details.representation().IsDouble() && value->IsSmi()));
2280     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2281     if (target_index < 0) target_index += total_size;
2282     array->set(target_index, *value);
2283   }
2284
2285   for (int i = old_nof; i < new_nof; i++) {
2286     PropertyDetails details = new_descriptors->GetDetails(i);
2287     if (details.type() != FIELD) continue;
2288     Handle<Object> value;
2289     if (details.representation().IsDouble()) {
2290       value = isolate->factory()->NewHeapNumber(0);
2291     } else {
2292       value = isolate->factory()->uninitialized_value();
2293     }
2294     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2295     if (target_index < 0) target_index += total_size;
2296     array->set(target_index, *value);
2297   }
2298
2299   // From here on we cannot fail and we shouldn't GC anymore.
2300   DisallowHeapAllocation no_allocation;
2301
2302   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2303   // avoid overwriting |one_pointer_filler_map|.
2304   int limit = Min(inobject, number_of_fields);
2305   for (int i = 0; i < limit; i++) {
2306     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
2307     object->FastPropertyAtPut(index, array->get(external + i));
2308   }
2309
2310   // Create filler object past the new instance size.
2311   int new_instance_size = new_map->instance_size();
2312   int instance_size_delta = old_map->instance_size() - new_instance_size;
2313   ASSERT(instance_size_delta >= 0);
2314   Address address = object->address() + new_instance_size;
2315
2316   // The trimming is performed on a newly allocated object, which is on a
2317   // fresly allocated page or on an already swept page. Hence, the sweeper
2318   // thread can not get confused with the filler creation. No synchronization
2319   // needed.
2320   isolate->heap()->CreateFillerObjectAt(address, instance_size_delta);
2321
2322   // If there are properties in the new backing store, trim it to the correct
2323   // size and install the backing store into the object.
2324   if (external > 0) {
2325     RightTrimFixedArray<Heap::FROM_MUTATOR>(isolate->heap(), *array, inobject);
2326     object->set_properties(*array);
2327   }
2328
2329   // The trimming is performed on a newly allocated object, which is on a
2330   // fresly allocated page or on an already swept page. Hence, the sweeper
2331   // thread can not get confused with the filler creation. No synchronization
2332   // needed.
2333   object->set_map(*new_map);
2334 }
2335
2336
2337 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object,
2338                                              int modify_index,
2339                                              Representation new_representation,
2340                                              Handle<HeapType> new_field_type,
2341                                              StoreMode store_mode) {
2342   Handle<Map> new_map = Map::GeneralizeRepresentation(
2343       handle(object->map()), modify_index, new_representation,
2344       new_field_type, store_mode);
2345   if (object->map() == *new_map) return;
2346   return MigrateToMap(object, new_map);
2347 }
2348
2349
2350 int Map::NumberOfFields() {
2351   DescriptorArray* descriptors = instance_descriptors();
2352   int result = 0;
2353   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2354     if (descriptors->GetDetails(i).type() == FIELD) result++;
2355   }
2356   return result;
2357 }
2358
2359
2360 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
2361                                                   int modify_index,
2362                                                   StoreMode store_mode,
2363                                                   PropertyAttributes attributes,
2364                                                   const char* reason) {
2365   Isolate* isolate = map->GetIsolate();
2366   Handle<Map> new_map = Copy(map);
2367
2368   DescriptorArray* descriptors = new_map->instance_descriptors();
2369   int length = descriptors->number_of_descriptors();
2370   for (int i = 0; i < length; i++) {
2371     descriptors->SetRepresentation(i, Representation::Tagged());
2372     if (descriptors->GetDetails(i).type() == FIELD) {
2373       descriptors->SetValue(i, HeapType::Any());
2374     }
2375   }
2376
2377   // Unless the instance is being migrated, ensure that modify_index is a field.
2378   PropertyDetails details = descriptors->GetDetails(modify_index);
2379   if (store_mode == FORCE_FIELD && details.type() != FIELD) {
2380     FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
2381                       new_map->NumberOfFields(),
2382                       attributes,
2383                       Representation::Tagged());
2384     descriptors->Replace(modify_index, &d);
2385     int unused_property_fields = new_map->unused_property_fields() - 1;
2386     if (unused_property_fields < 0) {
2387       unused_property_fields += JSObject::kFieldsAdded;
2388     }
2389     new_map->set_unused_property_fields(unused_property_fields);
2390   }
2391
2392   if (FLAG_trace_generalization) {
2393     HeapType* field_type = (details.type() == FIELD)
2394         ? map->instance_descriptors()->GetFieldType(modify_index)
2395         : NULL;
2396     map->PrintGeneralization(stdout, reason, modify_index,
2397                         new_map->NumberOfOwnDescriptors(),
2398                         new_map->NumberOfOwnDescriptors(),
2399                         details.type() == CONSTANT && store_mode == FORCE_FIELD,
2400                         details.representation(), Representation::Tagged(),
2401                         field_type, HeapType::Any());
2402   }
2403   return new_map;
2404 }
2405
2406
2407 // static
2408 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
2409                                                   int modify_index,
2410                                                   StoreMode store_mode,
2411                                                   const char* reason) {
2412   PropertyDetails details =
2413       map->instance_descriptors()->GetDetails(modify_index);
2414   return CopyGeneralizeAllRepresentations(map, modify_index, store_mode,
2415                                           details.attributes(), reason);
2416 }
2417
2418
2419 void Map::DeprecateTransitionTree() {
2420   if (is_deprecated()) return;
2421   if (HasTransitionArray()) {
2422     TransitionArray* transitions = this->transitions();
2423     for (int i = 0; i < transitions->number_of_transitions(); i++) {
2424       transitions->GetTarget(i)->DeprecateTransitionTree();
2425     }
2426   }
2427   deprecate();
2428   dependent_code()->DeoptimizeDependentCodeGroup(
2429       GetIsolate(), DependentCode::kTransitionGroup);
2430   NotifyLeafMapLayoutChange();
2431 }
2432
2433
2434 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2435 // the current instance_descriptors to ensure proper sharing of descriptor
2436 // arrays.
2437 void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors) {
2438   if (HasTransitionArray()) {
2439     TransitionArray* transitions = this->transitions();
2440     int transition = transitions->Search(key);
2441     if (transition != TransitionArray::kNotFound) {
2442       transitions->GetTarget(transition)->DeprecateTransitionTree();
2443     }
2444   }
2445
2446   // Don't overwrite the empty descriptor array.
2447   if (NumberOfOwnDescriptors() == 0) return;
2448
2449   DescriptorArray* to_replace = instance_descriptors();
2450   Map* current = this;
2451   GetHeap()->incremental_marking()->RecordWrites(to_replace);
2452   while (current->instance_descriptors() == to_replace) {
2453     current->SetEnumLength(kInvalidEnumCacheSentinel);
2454     current->set_instance_descriptors(new_descriptors);
2455     Object* next = current->GetBackPointer();
2456     if (next->IsUndefined()) break;
2457     current = Map::cast(next);
2458   }
2459
2460   set_owns_descriptors(false);
2461 }
2462
2463
2464 Map* Map::FindRootMap() {
2465   Map* result = this;
2466   while (true) {
2467     Object* back = result->GetBackPointer();
2468     if (back->IsUndefined()) return result;
2469     result = Map::cast(back);
2470   }
2471 }
2472
2473
2474 Map* Map::FindLastMatchMap(int verbatim,
2475                            int length,
2476                            DescriptorArray* descriptors) {
2477   DisallowHeapAllocation no_allocation;
2478
2479   // This can only be called on roots of transition trees.
2480   ASSERT(GetBackPointer()->IsUndefined());
2481
2482   Map* current = this;
2483
2484   for (int i = verbatim; i < length; i++) {
2485     if (!current->HasTransitionArray()) break;
2486     Name* name = descriptors->GetKey(i);
2487     TransitionArray* transitions = current->transitions();
2488     int transition = transitions->Search(name);
2489     if (transition == TransitionArray::kNotFound) break;
2490
2491     Map* next = transitions->GetTarget(transition);
2492     DescriptorArray* next_descriptors = next->instance_descriptors();
2493
2494     PropertyDetails details = descriptors->GetDetails(i);
2495     PropertyDetails next_details = next_descriptors->GetDetails(i);
2496     if (details.type() != next_details.type()) break;
2497     if (details.attributes() != next_details.attributes()) break;
2498     if (!details.representation().Equals(next_details.representation())) break;
2499     if (next_details.type() == FIELD) {
2500       if (!descriptors->GetFieldType(i)->NowIs(
2501               next_descriptors->GetFieldType(i))) break;
2502     } else {
2503       if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break;
2504     }
2505
2506     current = next;
2507   }
2508   return current;
2509 }
2510
2511
2512 Map* Map::FindFieldOwner(int descriptor) {
2513   DisallowHeapAllocation no_allocation;
2514   ASSERT_EQ(FIELD, instance_descriptors()->GetDetails(descriptor).type());
2515   Map* result = this;
2516   while (true) {
2517     Object* back = result->GetBackPointer();
2518     if (back->IsUndefined()) break;
2519     Map* parent = Map::cast(back);
2520     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
2521     result = parent;
2522   }
2523   return result;
2524 }
2525
2526
2527 void Map::UpdateDescriptor(int descriptor_number, Descriptor* desc) {
2528   DisallowHeapAllocation no_allocation;
2529   if (HasTransitionArray()) {
2530     TransitionArray* transitions = this->transitions();
2531     for (int i = 0; i < transitions->number_of_transitions(); ++i) {
2532       transitions->GetTarget(i)->UpdateDescriptor(descriptor_number, desc);
2533     }
2534   }
2535   instance_descriptors()->Replace(descriptor_number, desc);;
2536 }
2537
2538
2539 // static
2540 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
2541                                           Handle<HeapType> type2,
2542                                           Isolate* isolate) {
2543   static const int kMaxClassesPerFieldType = 5;
2544   if (type1->NowIs(type2)) return type2;
2545   if (type2->NowIs(type1)) return type1;
2546   if (type1->NowStable() && type2->NowStable()) {
2547     Handle<HeapType> type = HeapType::Union(type1, type2, isolate);
2548     if (type->NumClasses() <= kMaxClassesPerFieldType) {
2549       ASSERT(type->NowStable());
2550       ASSERT(type1->NowIs(type));
2551       ASSERT(type2->NowIs(type));
2552       return type;
2553     }
2554   }
2555   return HeapType::Any(isolate);
2556 }
2557
2558
2559 // static
2560 void Map::GeneralizeFieldType(Handle<Map> map,
2561                               int modify_index,
2562                               Handle<HeapType> new_field_type) {
2563   Isolate* isolate = map->GetIsolate();
2564
2565   // Check if we actually need to generalize the field type at all.
2566   Handle<HeapType> old_field_type(
2567       map->instance_descriptors()->GetFieldType(modify_index), isolate);
2568   if (new_field_type->NowIs(old_field_type)) {
2569     ASSERT(Map::GeneralizeFieldType(old_field_type,
2570                                     new_field_type,
2571                                     isolate)->NowIs(old_field_type));
2572     return;
2573   }
2574
2575   // Determine the field owner.
2576   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
2577   Handle<DescriptorArray> descriptors(
2578       field_owner->instance_descriptors(), isolate);
2579   ASSERT_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
2580
2581   // Determine the generalized new field type.
2582   new_field_type = Map::GeneralizeFieldType(
2583       old_field_type, new_field_type, isolate);
2584
2585   PropertyDetails details = descriptors->GetDetails(modify_index);
2586   FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
2587                     descriptors->GetFieldIndex(modify_index),
2588                     new_field_type,
2589                     details.attributes(),
2590                     details.representation());
2591   field_owner->UpdateDescriptor(modify_index, &d);
2592   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
2593       isolate, DependentCode::kFieldTypeGroup);
2594
2595   if (FLAG_trace_generalization) {
2596     map->PrintGeneralization(
2597         stdout, "field type generalization",
2598         modify_index, map->NumberOfOwnDescriptors(),
2599         map->NumberOfOwnDescriptors(), false,
2600         details.representation(), details.representation(),
2601         *old_field_type, *new_field_type);
2602   }
2603 }
2604
2605
2606 // Generalize the representation of the descriptor at |modify_index|.
2607 // This method rewrites the transition tree to reflect the new change. To avoid
2608 // high degrees over polymorphism, and to stabilize quickly, on every rewrite
2609 // the new type is deduced by merging the current type with any potential new
2610 // (partial) version of the type in the transition tree.
2611 // To do this, on each rewrite:
2612 // - Search the root of the transition tree using FindRootMap.
2613 // - Find |target_map|, the newest matching version of this map using the keys
2614 //   in the |old_map|'s descriptor array to walk the transition tree.
2615 // - Merge/generalize the descriptor array of the |old_map| and |target_map|.
2616 // - Generalize the |modify_index| descriptor using |new_representation| and
2617 //   |new_field_type|.
2618 // - Walk the tree again starting from the root towards |target_map|. Stop at
2619 //   |split_map|, the first map who's descriptor array does not match the merged
2620 //   descriptor array.
2621 // - If |target_map| == |split_map|, |target_map| is in the expected state.
2622 //   Return it.
2623 // - Otherwise, invalidate the outdated transition target from |target_map|, and
2624 //   replace its transition tree with a new branch for the updated descriptors.
2625 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
2626                                           int modify_index,
2627                                           Representation new_representation,
2628                                           Handle<HeapType> new_field_type,
2629                                           StoreMode store_mode) {
2630   Isolate* isolate = old_map->GetIsolate();
2631
2632   Handle<DescriptorArray> old_descriptors(
2633       old_map->instance_descriptors(), isolate);
2634   int old_nof = old_map->NumberOfOwnDescriptors();
2635   PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2636   Representation old_representation = old_details.representation();
2637
2638   // It's fine to transition from None to anything but double without any
2639   // modification to the object, because the default uninitialized value for
2640   // representation None can be overwritten by both smi and tagged values.
2641   // Doubles, however, would require a box allocation.
2642   if (old_representation.IsNone() &&
2643       !new_representation.IsNone() &&
2644       !new_representation.IsDouble()) {
2645     ASSERT(old_details.type() == FIELD);
2646     ASSERT(old_descriptors->GetFieldType(modify_index)->NowIs(
2647             HeapType::None()));
2648     if (FLAG_trace_generalization) {
2649       old_map->PrintGeneralization(
2650           stdout, "uninitialized field",
2651           modify_index, old_map->NumberOfOwnDescriptors(),
2652           old_map->NumberOfOwnDescriptors(), false,
2653           old_representation, new_representation,
2654           old_descriptors->GetFieldType(modify_index), *new_field_type);
2655     }
2656     old_descriptors->SetRepresentation(modify_index, new_representation);
2657     old_descriptors->SetValue(modify_index, *new_field_type);
2658     return old_map;
2659   }
2660
2661   // Check the state of the root map.
2662   Handle<Map> root_map(old_map->FindRootMap(), isolate);
2663   if (!old_map->EquivalentToForTransition(*root_map)) {
2664     return CopyGeneralizeAllRepresentations(
2665         old_map, modify_index, store_mode, "not equivalent");
2666   }
2667   int root_nof = root_map->NumberOfOwnDescriptors();
2668   if (modify_index < root_nof) {
2669     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2670     if ((old_details.type() != FIELD && store_mode == FORCE_FIELD) ||
2671         (old_details.type() == FIELD &&
2672          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
2673           !new_representation.fits_into(old_details.representation())))) {
2674       return CopyGeneralizeAllRepresentations(
2675           old_map, modify_index, store_mode, "root modification");
2676     }
2677   }
2678
2679   Handle<Map> target_map = root_map;
2680   for (int i = root_nof; i < old_nof; ++i) {
2681     int j = target_map->SearchTransition(old_descriptors->GetKey(i));
2682     if (j == TransitionArray::kNotFound) break;
2683     Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
2684     Handle<DescriptorArray> tmp_descriptors = handle(
2685         tmp_map->instance_descriptors(), isolate);
2686
2687     // Check if target map is incompatible.
2688     PropertyDetails old_details = old_descriptors->GetDetails(i);
2689     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2690     PropertyType old_type = old_details.type();
2691     PropertyType tmp_type = tmp_details.type();
2692     if (tmp_details.attributes() != old_details.attributes() ||
2693         ((tmp_type == CALLBACKS || old_type == CALLBACKS) &&
2694          (tmp_type != old_type ||
2695           tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) {
2696       return CopyGeneralizeAllRepresentations(
2697           old_map, modify_index, store_mode, "incompatible");
2698     }
2699     Representation old_representation = old_details.representation();
2700     Representation tmp_representation = tmp_details.representation();
2701     if (!old_representation.fits_into(tmp_representation) ||
2702         (!new_representation.fits_into(tmp_representation) &&
2703          modify_index == i)) {
2704       break;
2705     }
2706     if (tmp_type == FIELD) {
2707       // Generalize the field type as necessary.
2708       Handle<HeapType> old_field_type = (old_type == FIELD)
2709           ? handle(old_descriptors->GetFieldType(i), isolate)
2710           : old_descriptors->GetValue(i)->OptimalType(
2711               isolate, tmp_representation);
2712       if (modify_index == i) {
2713         old_field_type = GeneralizeFieldType(
2714             new_field_type, old_field_type, isolate);
2715       }
2716       GeneralizeFieldType(tmp_map, i, old_field_type);
2717     } else if (tmp_type == CONSTANT) {
2718       if (old_type != CONSTANT ||
2719           old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) {
2720         break;
2721       }
2722     } else {
2723       ASSERT_EQ(tmp_type, old_type);
2724       ASSERT_EQ(tmp_descriptors->GetValue(i), old_descriptors->GetValue(i));
2725     }
2726     target_map = tmp_map;
2727   }
2728
2729   // Directly change the map if the target map is more general.
2730   Handle<DescriptorArray> target_descriptors(
2731       target_map->instance_descriptors(), isolate);
2732   int target_nof = target_map->NumberOfOwnDescriptors();
2733   if (target_nof == old_nof &&
2734       (store_mode != FORCE_FIELD ||
2735        target_descriptors->GetDetails(modify_index).type() == FIELD)) {
2736     ASSERT(modify_index < target_nof);
2737     ASSERT(new_representation.fits_into(
2738             target_descriptors->GetDetails(modify_index).representation()));
2739     ASSERT(target_descriptors->GetDetails(modify_index).type() != FIELD ||
2740            new_field_type->NowIs(
2741                target_descriptors->GetFieldType(modify_index)));
2742     return target_map;
2743   }
2744
2745   // Find the last compatible target map in the transition tree.
2746   for (int i = target_nof; i < old_nof; ++i) {
2747     int j = target_map->SearchTransition(old_descriptors->GetKey(i));
2748     if (j == TransitionArray::kNotFound) break;
2749     Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
2750     Handle<DescriptorArray> tmp_descriptors(
2751         tmp_map->instance_descriptors(), isolate);
2752
2753     // Check if target map is compatible.
2754     PropertyDetails old_details = old_descriptors->GetDetails(i);
2755     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2756     if (tmp_details.attributes() != old_details.attributes() ||
2757         ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) &&
2758          (tmp_details.type() != old_details.type() ||
2759           tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) {
2760       return CopyGeneralizeAllRepresentations(
2761           old_map, modify_index, store_mode, "incompatible");
2762     }
2763     target_map = tmp_map;
2764   }
2765   target_nof = target_map->NumberOfOwnDescriptors();
2766   target_descriptors = handle(target_map->instance_descriptors(), isolate);
2767
2768   // Allocate a new descriptor array large enough to hold the required
2769   // descriptors, with minimally the exact same size as the old descriptor
2770   // array.
2771   int new_slack = Max(
2772       old_nof, old_descriptors->number_of_descriptors()) - old_nof;
2773   Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
2774       isolate, old_nof, new_slack);
2775   ASSERT(new_descriptors->length() > target_descriptors->length() ||
2776          new_descriptors->NumberOfSlackDescriptors() > 0 ||
2777          new_descriptors->number_of_descriptors() ==
2778          old_descriptors->number_of_descriptors());
2779   ASSERT(new_descriptors->number_of_descriptors() == old_nof);
2780
2781   // 0 -> |root_nof|
2782   int current_offset = 0;
2783   for (int i = 0; i < root_nof; ++i) {
2784     PropertyDetails old_details = old_descriptors->GetDetails(i);
2785     if (old_details.type() == FIELD) current_offset++;
2786     Descriptor d(handle(old_descriptors->GetKey(i), isolate),
2787                  handle(old_descriptors->GetValue(i), isolate),
2788                  old_details);
2789     new_descriptors->Set(i, &d);
2790   }
2791
2792   // |root_nof| -> |target_nof|
2793   for (int i = root_nof; i < target_nof; ++i) {
2794     Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
2795     PropertyDetails old_details = old_descriptors->GetDetails(i);
2796     PropertyDetails target_details = target_descriptors->GetDetails(i);
2797     target_details = target_details.CopyWithRepresentation(
2798         old_details.representation().generalize(
2799             target_details.representation()));
2800     if (modify_index == i) {
2801       target_details = target_details.CopyWithRepresentation(
2802           new_representation.generalize(target_details.representation()));
2803     }
2804     ASSERT_EQ(old_details.attributes(), target_details.attributes());
2805     if (old_details.type() == FIELD ||
2806         target_details.type() == FIELD ||
2807         (modify_index == i && store_mode == FORCE_FIELD) ||
2808         (target_descriptors->GetValue(i) != old_descriptors->GetValue(i))) {
2809       Handle<HeapType> old_field_type = (old_details.type() == FIELD)
2810           ? handle(old_descriptors->GetFieldType(i), isolate)
2811           : old_descriptors->GetValue(i)->OptimalType(
2812               isolate, target_details.representation());
2813       Handle<HeapType> target_field_type = (target_details.type() == FIELD)
2814           ? handle(target_descriptors->GetFieldType(i), isolate)
2815           : target_descriptors->GetValue(i)->OptimalType(
2816               isolate, target_details.representation());
2817       target_field_type = GeneralizeFieldType(
2818           target_field_type, old_field_type, isolate);
2819       if (modify_index == i) {
2820         target_field_type = GeneralizeFieldType(
2821             target_field_type, new_field_type, isolate);
2822       }
2823       FieldDescriptor d(target_key,
2824                         current_offset++,
2825                         target_field_type,
2826                         target_details.attributes(),
2827                         target_details.representation());
2828       new_descriptors->Set(i, &d);
2829     } else {
2830       ASSERT_NE(FIELD, target_details.type());
2831       Descriptor d(target_key,
2832                    handle(target_descriptors->GetValue(i), isolate),
2833                    target_details);
2834       new_descriptors->Set(i, &d);
2835     }
2836   }
2837
2838   // |target_nof| -> |old_nof|
2839   for (int i = target_nof; i < old_nof; ++i) {
2840     PropertyDetails old_details = old_descriptors->GetDetails(i);
2841     Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
2842     if (modify_index == i) {
2843       old_details = old_details.CopyWithRepresentation(
2844           new_representation.generalize(old_details.representation()));
2845     }
2846     if (old_details.type() == FIELD) {
2847       Handle<HeapType> old_field_type(
2848           old_descriptors->GetFieldType(i), isolate);
2849       if (modify_index == i) {
2850         old_field_type = GeneralizeFieldType(
2851             old_field_type, new_field_type, isolate);
2852       }
2853       FieldDescriptor d(old_key,
2854                         current_offset++,
2855                         old_field_type,
2856                         old_details.attributes(),
2857                         old_details.representation());
2858       new_descriptors->Set(i, &d);
2859     } else {
2860       ASSERT(old_details.type() == CONSTANT || old_details.type() == CALLBACKS);
2861       if (modify_index == i && store_mode == FORCE_FIELD) {
2862         FieldDescriptor d(old_key,
2863                           current_offset++,
2864                           GeneralizeFieldType(
2865                               old_descriptors->GetValue(i)->OptimalType(
2866                                   isolate, old_details.representation()),
2867                               new_field_type, isolate),
2868                           old_details.attributes(),
2869                           old_details.representation());
2870         new_descriptors->Set(i, &d);
2871       } else {
2872         ASSERT_NE(FIELD, old_details.type());
2873         Descriptor d(old_key,
2874                      handle(old_descriptors->GetValue(i), isolate),
2875                      old_details);
2876         new_descriptors->Set(i, &d);
2877       }
2878     }
2879   }
2880
2881   new_descriptors->Sort();
2882
2883   ASSERT(store_mode != FORCE_FIELD ||
2884          new_descriptors->GetDetails(modify_index).type() == FIELD);
2885
2886   Handle<Map> split_map(root_map->FindLastMatchMap(
2887           root_nof, old_nof, *new_descriptors), isolate);
2888   int split_nof = split_map->NumberOfOwnDescriptors();
2889   ASSERT_NE(old_nof, split_nof);
2890
2891   split_map->DeprecateTarget(
2892       old_descriptors->GetKey(split_nof), *new_descriptors);
2893
2894   if (FLAG_trace_generalization) {
2895     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2896     PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
2897     Handle<HeapType> old_field_type = (old_details.type() == FIELD)
2898         ? handle(old_descriptors->GetFieldType(modify_index), isolate)
2899         : HeapType::Constant(handle(old_descriptors->GetValue(modify_index),
2900                                     isolate), isolate);
2901     Handle<HeapType> new_field_type = (new_details.type() == FIELD)
2902         ? handle(new_descriptors->GetFieldType(modify_index), isolate)
2903         : HeapType::Constant(handle(new_descriptors->GetValue(modify_index),
2904                                     isolate), isolate);
2905     old_map->PrintGeneralization(
2906         stdout, "", modify_index, split_nof, old_nof,
2907         old_details.type() == CONSTANT && store_mode == FORCE_FIELD,
2908         old_details.representation(), new_details.representation(),
2909         *old_field_type, *new_field_type);
2910   }
2911
2912   // Add missing transitions.
2913   Handle<Map> new_map = split_map;
2914   for (int i = split_nof; i < old_nof; ++i) {
2915     new_map = CopyInstallDescriptors(new_map, i, new_descriptors);
2916   }
2917   new_map->set_owns_descriptors(true);
2918   return new_map;
2919 }
2920
2921
2922 // Generalize the representation of all FIELD descriptors.
2923 Handle<Map> Map::GeneralizeAllFieldRepresentations(
2924     Handle<Map> map) {
2925   Handle<DescriptorArray> descriptors(map->instance_descriptors());
2926   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
2927     if (descriptors->GetDetails(i).type() == FIELD) {
2928       map = GeneralizeRepresentation(map, i, Representation::Tagged(),
2929                                      HeapType::Any(map->GetIsolate()),
2930                                      FORCE_FIELD);
2931     }
2932   }
2933   return map;
2934 }
2935
2936
2937 // static
2938 MaybeHandle<Map> Map::CurrentMapForDeprecated(Handle<Map> map) {
2939   Handle<Map> proto_map(map);
2940   while (proto_map->prototype()->IsJSObject()) {
2941     Handle<JSObject> holder(JSObject::cast(proto_map->prototype()));
2942     proto_map = Handle<Map>(holder->map());
2943     if (proto_map->is_deprecated() && JSObject::TryMigrateInstance(holder)) {
2944       proto_map = Handle<Map>(holder->map());
2945     }
2946   }
2947   return CurrentMapForDeprecatedInternal(map);
2948 }
2949
2950
2951 // static
2952 MaybeHandle<Map> Map::CurrentMapForDeprecatedInternal(Handle<Map> old_map) {
2953   DisallowHeapAllocation no_allocation;
2954   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
2955
2956   if (!old_map->is_deprecated()) return old_map;
2957
2958   // Check the state of the root map.
2959   Map* root_map = old_map->FindRootMap();
2960   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
2961   int root_nof = root_map->NumberOfOwnDescriptors();
2962
2963   int old_nof = old_map->NumberOfOwnDescriptors();
2964   DescriptorArray* old_descriptors = old_map->instance_descriptors();
2965
2966   Map* new_map = root_map;
2967   for (int i = root_nof; i < old_nof; ++i) {
2968     int j = new_map->SearchTransition(old_descriptors->GetKey(i));
2969     if (j == TransitionArray::kNotFound) return MaybeHandle<Map>();
2970     new_map = new_map->GetTransition(j);
2971     DescriptorArray* new_descriptors = new_map->instance_descriptors();
2972
2973     PropertyDetails new_details = new_descriptors->GetDetails(i);
2974     PropertyDetails old_details = old_descriptors->GetDetails(i);
2975     if (old_details.attributes() != new_details.attributes() ||
2976         !old_details.representation().fits_into(new_details.representation())) {
2977       return MaybeHandle<Map>();
2978     }
2979     PropertyType new_type = new_details.type();
2980     PropertyType old_type = old_details.type();
2981     Object* new_value = new_descriptors->GetValue(i);
2982     Object* old_value = old_descriptors->GetValue(i);
2983     switch (new_type) {
2984       case FIELD:
2985         if ((old_type == FIELD &&
2986              !HeapType::cast(old_value)->NowIs(HeapType::cast(new_value))) ||
2987             (old_type == CONSTANT &&
2988              !HeapType::cast(new_value)->NowContains(old_value)) ||
2989             (old_type == CALLBACKS &&
2990              !HeapType::Any()->Is(HeapType::cast(new_value)))) {
2991           return MaybeHandle<Map>();
2992         }
2993         break;
2994
2995       case CONSTANT:
2996       case CALLBACKS:
2997         if (old_type != new_type || old_value != new_value) {
2998           return MaybeHandle<Map>();
2999         }
3000         break;
3001
3002       case NORMAL:
3003       case HANDLER:
3004       case INTERCEPTOR:
3005       case NONEXISTENT:
3006         UNREACHABLE();
3007     }
3008   }
3009   if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
3010   return handle(new_map);
3011 }
3012
3013
3014 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(
3015     Handle<JSObject> object,
3016     Handle<Name> name,
3017     Handle<Object> value,
3018     PropertyAttributes attributes,
3019     StrictMode strict_mode) {
3020   // TODO(rossberg): Support symbols in the API.
3021   if (name->IsSymbol()) return value;
3022   Isolate* isolate = object->GetIsolate();
3023   Handle<String> name_string = Handle<String>::cast(name);
3024   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
3025   if (!interceptor->setter()->IsUndefined()) {
3026     LOG(isolate,
3027         ApiNamedPropertyAccess("interceptor-named-set", *object, *name));
3028     PropertyCallbackArguments args(
3029         isolate, interceptor->data(), *object, *object);
3030     v8::NamedPropertySetterCallback setter =
3031         v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter());
3032     Handle<Object> value_unhole = value->IsTheHole()
3033         ? Handle<Object>(isolate->factory()->undefined_value()) : value;
3034     v8::Handle<v8::Value> result = args.Call(setter,
3035                                              v8::Utils::ToLocal(name_string),
3036                                              v8::Utils::ToLocal(value_unhole));
3037     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3038     if (!result.IsEmpty()) return value;
3039   }
3040   return SetPropertyPostInterceptor(
3041       object, name, value, attributes, strict_mode);
3042 }
3043
3044
3045 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
3046                                             Handle<Name> name,
3047                                             Handle<Object> value,
3048                                             PropertyAttributes attributes,
3049                                             StrictMode strict_mode,
3050                                             StoreFromKeyed store_mode) {
3051   LookupResult result(object->GetIsolate());
3052   object->LookupOwn(name, &result, true);
3053   if (!result.IsFound()) {
3054     object->map()->LookupTransition(JSObject::cast(*object), *name, &result);
3055   }
3056   return SetProperty(object, &result, name, value, attributes, strict_mode,
3057                      store_mode);
3058 }
3059
3060
3061 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3062     Handle<JSObject> object,
3063     uint32_t index,
3064     Handle<Object> value,
3065     bool* found,
3066     StrictMode strict_mode) {
3067   Isolate *isolate = object->GetIsolate();
3068   for (Handle<Object> proto = handle(object->GetPrototype(), isolate);
3069        !proto->IsNull();
3070        proto = handle(proto->GetPrototype(isolate), isolate)) {
3071     if (proto->IsJSProxy()) {
3072       return JSProxy::SetPropertyViaPrototypesWithHandler(
3073           Handle<JSProxy>::cast(proto),
3074           object,
3075           isolate->factory()->Uint32ToString(index),  // name
3076           value,
3077           NONE,
3078           strict_mode,
3079           found);
3080     }
3081     Handle<JSObject> js_proto = Handle<JSObject>::cast(proto);
3082     if (!js_proto->HasDictionaryElements()) {
3083       continue;
3084     }
3085     Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
3086     int entry = dictionary->FindEntry(index);
3087     if (entry != SeededNumberDictionary::kNotFound) {
3088       PropertyDetails details = dictionary->DetailsAt(entry);
3089       if (details.type() == CALLBACKS) {
3090         *found = true;
3091         Handle<Object> structure(dictionary->ValueAt(entry), isolate);
3092         return SetElementWithCallback(object, structure, index, value, js_proto,
3093                                       strict_mode);
3094       }
3095     }
3096   }
3097   *found = false;
3098   return isolate->factory()->the_hole_value();
3099 }
3100
3101
3102 MaybeHandle<Object> JSObject::SetPropertyViaPrototypes(
3103     Handle<JSObject> object,
3104     Handle<Name> name,
3105     Handle<Object> value,
3106     PropertyAttributes attributes,
3107     StrictMode strict_mode,
3108     bool* done) {
3109   Isolate* isolate = object->GetIsolate();
3110
3111   *done = false;
3112   // We could not find an own property, so let's check whether there is an
3113   // accessor that wants to handle the property, or whether the property is
3114   // read-only on the prototype chain.
3115   LookupResult result(isolate);
3116   object->LookupRealNamedPropertyInPrototypes(name, &result);
3117   if (result.IsFound()) {
3118     switch (result.type()) {
3119       case NORMAL:
3120       case FIELD:
3121       case CONSTANT:
3122         *done = result.IsReadOnly();
3123         break;
3124       case INTERCEPTOR: {
3125         LookupIterator it(object, name, handle(result.holder()));
3126         PropertyAttributes attr = GetPropertyAttributes(&it);
3127         *done = !!(attr & READ_ONLY);
3128         break;
3129       }
3130       case CALLBACKS: {
3131         *done = true;
3132         if (!result.IsReadOnly()) {
3133           Handle<Object> callback_object(result.GetCallbackObject(), isolate);
3134           return SetPropertyWithCallback(object, name, value,
3135                                          handle(result.holder()),
3136                                          callback_object, strict_mode);
3137         }
3138         break;
3139       }
3140       case HANDLER: {
3141         Handle<JSProxy> proxy(result.proxy());
3142         return JSProxy::SetPropertyViaPrototypesWithHandler(
3143             proxy, object, name, value, attributes, strict_mode, done);
3144       }
3145       case NONEXISTENT:
3146         UNREACHABLE();
3147         break;
3148     }
3149   }
3150
3151   // If we get here with *done true, we have encountered a read-only property.
3152   if (*done) {
3153     if (strict_mode == SLOPPY) return value;
3154     Handle<Object> args[] = { name, object };
3155     Handle<Object> error = isolate->factory()->NewTypeError(
3156         "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3157     return isolate->Throw<Object>(error);
3158   }
3159   return isolate->factory()->the_hole_value();
3160 }
3161
3162
3163 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3164   // Only supports adding slack to owned descriptors.
3165   ASSERT(map->owns_descriptors());
3166
3167   Handle<DescriptorArray> descriptors(map->instance_descriptors());
3168   int old_size = map->NumberOfOwnDescriptors();
3169   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3170
3171   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3172       descriptors, old_size, slack);
3173
3174   if (old_size == 0) {
3175     map->set_instance_descriptors(*new_descriptors);
3176     return;
3177   }
3178
3179   // If the source descriptors had an enum cache we copy it. This ensures
3180   // that the maps to which we push the new descriptor array back can rely
3181   // on a cache always being available once it is set. If the map has more
3182   // enumerated descriptors than available in the original cache, the cache
3183   // will be lazily replaced by the extended cache when needed.
3184   if (descriptors->HasEnumCache()) {
3185     new_descriptors->CopyEnumCacheFrom(*descriptors);
3186   }
3187
3188   // Replace descriptors by new_descriptors in all maps that share it.
3189   map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
3190
3191   Map* walk_map;
3192   for (Object* current = map->GetBackPointer();
3193        !current->IsUndefined();
3194        current = walk_map->GetBackPointer()) {
3195     walk_map = Map::cast(current);
3196     if (walk_map->instance_descriptors() != *descriptors) break;
3197     walk_map->set_instance_descriptors(*new_descriptors);
3198   }
3199
3200   map->set_instance_descriptors(*new_descriptors);
3201 }
3202
3203
3204 template<class T>
3205 static int AppendUniqueCallbacks(NeanderArray* callbacks,
3206                                  Handle<typename T::Array> array,
3207                                  int valid_descriptors) {
3208   int nof_callbacks = callbacks->length();
3209
3210   Isolate* isolate = array->GetIsolate();
3211   // Ensure the keys are unique names before writing them into the
3212   // instance descriptor. Since it may cause a GC, it has to be done before we
3213   // temporarily put the heap in an invalid state while appending descriptors.
3214   for (int i = 0; i < nof_callbacks; ++i) {
3215     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3216     if (entry->name()->IsUniqueName()) continue;
3217     Handle<String> key =
3218         isolate->factory()->InternalizeString(
3219             Handle<String>(String::cast(entry->name())));
3220     entry->set_name(*key);
3221   }
3222
3223   // Fill in new callback descriptors.  Process the callbacks from
3224   // back to front so that the last callback with a given name takes
3225   // precedence over previously added callbacks with that name.
3226   for (int i = nof_callbacks - 1; i >= 0; i--) {
3227     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3228     Handle<Name> key(Name::cast(entry->name()));
3229     // Check if a descriptor with this name already exists before writing.
3230     if (!T::Contains(key, entry, valid_descriptors, array)) {
3231       T::Insert(key, entry, valid_descriptors, array);
3232       valid_descriptors++;
3233     }
3234   }
3235
3236   return valid_descriptors;
3237 }
3238
3239 struct DescriptorArrayAppender {
3240   typedef DescriptorArray Array;
3241   static bool Contains(Handle<Name> key,
3242                        Handle<AccessorInfo> entry,
3243                        int valid_descriptors,
3244                        Handle<DescriptorArray> array) {
3245     DisallowHeapAllocation no_gc;
3246     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
3247   }
3248   static void Insert(Handle<Name> key,
3249                      Handle<AccessorInfo> entry,
3250                      int valid_descriptors,
3251                      Handle<DescriptorArray> array) {
3252     DisallowHeapAllocation no_gc;
3253     CallbacksDescriptor desc(key, entry, entry->property_attributes());
3254     array->Append(&desc);
3255   }
3256 };
3257
3258
3259 struct FixedArrayAppender {
3260   typedef FixedArray Array;
3261   static bool Contains(Handle<Name> key,
3262                        Handle<AccessorInfo> entry,
3263                        int valid_descriptors,
3264                        Handle<FixedArray> array) {
3265     for (int i = 0; i < valid_descriptors; i++) {
3266       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
3267     }
3268     return false;
3269   }
3270   static void Insert(Handle<Name> key,
3271                      Handle<AccessorInfo> entry,
3272                      int valid_descriptors,
3273                      Handle<FixedArray> array) {
3274     DisallowHeapAllocation no_gc;
3275     array->set(valid_descriptors, *entry);
3276   }
3277 };
3278
3279
3280 void Map::AppendCallbackDescriptors(Handle<Map> map,
3281                                     Handle<Object> descriptors) {
3282   int nof = map->NumberOfOwnDescriptors();
3283   Handle<DescriptorArray> array(map->instance_descriptors());
3284   NeanderArray callbacks(descriptors);
3285   ASSERT(array->NumberOfSlackDescriptors() >= callbacks.length());
3286   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3287   map->SetNumberOfOwnDescriptors(nof);
3288 }
3289
3290
3291 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
3292                                Handle<FixedArray> array,
3293                                int valid_descriptors) {
3294   NeanderArray callbacks(descriptors);
3295   ASSERT(array->length() >= callbacks.length() + valid_descriptors);
3296   return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3297                                                    array,
3298                                                    valid_descriptors);
3299 }
3300
3301
3302 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
3303   ASSERT(!map.is_null());
3304   for (int i = 0; i < maps->length(); ++i) {
3305     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
3306   }
3307   return false;
3308 }
3309
3310
3311 template <class T>
3312 static Handle<T> MaybeNull(T* p) {
3313   if (p == NULL) return Handle<T>::null();
3314   return Handle<T>(p);
3315 }
3316
3317
3318 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
3319   ElementsKind kind = elements_kind();
3320   Handle<Map> transitioned_map = Handle<Map>::null();
3321   Handle<Map> current_map(this);
3322   bool packed = IsFastPackedElementsKind(kind);
3323   if (IsTransitionableFastElementsKind(kind)) {
3324     while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
3325       kind = GetNextMoreGeneralFastElementsKind(kind, false);
3326       Handle<Map> maybe_transitioned_map =
3327           MaybeNull(current_map->LookupElementsTransitionMap(kind));
3328       if (maybe_transitioned_map.is_null()) break;
3329       if (ContainsMap(candidates, maybe_transitioned_map) &&
3330           (packed || !IsFastPackedElementsKind(kind))) {
3331         transitioned_map = maybe_transitioned_map;
3332         if (!IsFastPackedElementsKind(kind)) packed = false;
3333       }
3334       current_map = maybe_transitioned_map;
3335     }
3336   }
3337   return transitioned_map;
3338 }
3339
3340
3341 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
3342   Map* current_map = map;
3343   int target_kind =
3344       IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
3345       ? to_kind
3346       : TERMINAL_FAST_ELEMENTS_KIND;
3347
3348   // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
3349   // allows to change elements from arbitrary kind to any ExternalArray
3350   // elements kind. Satisfy its requirements, checking whether we already
3351   // have the cached transition.
3352   if (IsExternalArrayElementsKind(to_kind) &&
3353       !IsFixedTypedArrayElementsKind(map->elements_kind())) {
3354     if (map->HasElementsTransition()) {
3355         Map* next_map = map->elements_transition_map();
3356         if (next_map->elements_kind() == to_kind) return next_map;
3357     }
3358     return map;
3359   }
3360
3361   ElementsKind kind = map->elements_kind();
3362   while (kind != target_kind) {
3363     kind = GetNextTransitionElementsKind(kind);
3364     if (!current_map->HasElementsTransition()) return current_map;
3365     current_map = current_map->elements_transition_map();
3366   }
3367
3368   if (to_kind != kind && current_map->HasElementsTransition()) {
3369     ASSERT(to_kind == DICTIONARY_ELEMENTS);
3370     Map* next_map = current_map->elements_transition_map();
3371     if (next_map->elements_kind() == to_kind) return next_map;
3372   }
3373
3374   ASSERT(current_map->elements_kind() == target_kind);
3375   return current_map;
3376 }
3377
3378
3379 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3380   Map* to_map = FindClosestElementsTransition(this, to_kind);
3381   if (to_map->elements_kind() == to_kind) return to_map;
3382   return NULL;
3383 }
3384
3385
3386 bool Map::IsMapInArrayPrototypeChain() {
3387   Isolate* isolate = GetIsolate();
3388   if (isolate->initial_array_prototype()->map() == this) {
3389     return true;
3390   }
3391
3392   if (isolate->initial_object_prototype()->map() == this) {
3393     return true;
3394   }
3395
3396   return false;
3397 }
3398
3399
3400 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
3401                                                  ElementsKind to_kind) {
3402   ASSERT(IsTransitionElementsKind(map->elements_kind()));
3403
3404   Handle<Map> current_map = map;
3405
3406   ElementsKind kind = map->elements_kind();
3407   while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3408     kind = GetNextTransitionElementsKind(kind);
3409     current_map = Map::CopyAsElementsKind(
3410         current_map, kind, INSERT_TRANSITION);
3411   }
3412
3413   // In case we are exiting the fast elements kind system, just add the map in
3414   // the end.
3415   if (kind != to_kind) {
3416     current_map = Map::CopyAsElementsKind(
3417         current_map, to_kind, INSERT_TRANSITION);
3418   }
3419
3420   ASSERT(current_map->elements_kind() == to_kind);
3421   return current_map;
3422 }
3423
3424
3425 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
3426                                       ElementsKind to_kind) {
3427   ElementsKind from_kind = map->elements_kind();
3428   if (from_kind == to_kind) return map;
3429
3430   Isolate* isolate = map->GetIsolate();
3431   Context* native_context = isolate->context()->native_context();
3432   Object* maybe_array_maps = native_context->js_array_maps();
3433   if (maybe_array_maps->IsFixedArray()) {
3434     DisallowHeapAllocation no_gc;
3435     FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
3436     if (array_maps->get(from_kind) == *map) {
3437       Object* maybe_transitioned_map = array_maps->get(to_kind);
3438       if (maybe_transitioned_map->IsMap()) {
3439         return handle(Map::cast(maybe_transitioned_map));
3440       }
3441     }
3442   }
3443
3444   return TransitionElementsToSlow(map, to_kind);
3445 }
3446
3447
3448 Handle<Map> Map::TransitionElementsToSlow(Handle<Map> map,
3449                                           ElementsKind to_kind) {
3450   ElementsKind from_kind = map->elements_kind();
3451
3452   if (from_kind == to_kind) {
3453     return map;
3454   }
3455
3456   bool allow_store_transition =
3457       // Only remember the map transition if there is not an already existing
3458       // non-matching element transition.
3459       !map->IsUndefined() && !map->is_shared() &&
3460       IsTransitionElementsKind(from_kind);
3461
3462   // Only store fast element maps in ascending generality.
3463   if (IsFastElementsKind(to_kind)) {
3464     allow_store_transition &=
3465         IsTransitionableFastElementsKind(from_kind) &&
3466         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3467   }
3468
3469   if (!allow_store_transition) {
3470     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
3471   }
3472
3473   return Map::AsElementsKind(map, to_kind);
3474 }
3475
3476
3477 // static
3478 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
3479   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
3480
3481   if (closest_map->elements_kind() == kind) {
3482     return closest_map;
3483   }
3484
3485   return AddMissingElementsTransitions(closest_map, kind);
3486 }
3487
3488
3489 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
3490                                                ElementsKind to_kind) {
3491   Handle<Map> map(object->map());
3492   return Map::TransitionElementsTo(map, to_kind);
3493 }
3494
3495
3496 void JSObject::LookupOwnRealNamedProperty(Handle<Name> name,
3497                                           LookupResult* result) {
3498   DisallowHeapAllocation no_gc;
3499   if (IsJSGlobalProxy()) {
3500     Object* proto = GetPrototype();
3501     if (proto->IsNull()) return result->NotFound();
3502     ASSERT(proto->IsJSGlobalObject());
3503     return JSObject::cast(proto)->LookupOwnRealNamedProperty(name, result);
3504   }
3505
3506   if (HasFastProperties()) {
3507     map()->LookupDescriptor(this, *name, result);
3508     // A property or a map transition was found. We return all of these result
3509     // types because LookupOwnRealNamedProperty is used when setting
3510     // properties where map transitions are handled.
3511     ASSERT(!result->IsFound() ||
3512            (result->holder() == this && result->IsFastPropertyType()));
3513     // Disallow caching for uninitialized constants. These can only
3514     // occur as fields.
3515     if (result->IsField() &&
3516         result->IsReadOnly() &&
3517         RawFastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
3518       result->DisallowCaching();
3519     }
3520     return;
3521   }
3522
3523   int entry = property_dictionary()->FindEntry(name);
3524   if (entry != NameDictionary::kNotFound) {
3525     Object* value = property_dictionary()->ValueAt(entry);
3526     if (IsGlobalObject()) {
3527       PropertyDetails d = property_dictionary()->DetailsAt(entry);
3528       if (d.IsDeleted()) {
3529         result->NotFound();
3530         return;
3531       }
3532       value = PropertyCell::cast(value)->value();
3533     }
3534     // Make sure to disallow caching for uninitialized constants
3535     // found in the dictionary-mode objects.
3536     if (value->IsTheHole()) result->DisallowCaching();
3537     result->DictionaryResult(this, entry);
3538     return;
3539   }
3540
3541   result->NotFound();
3542 }
3543
3544
3545 void JSObject::LookupRealNamedProperty(Handle<Name> name,
3546                                        LookupResult* result) {
3547   DisallowHeapAllocation no_gc;
3548   LookupOwnRealNamedProperty(name, result);
3549   if (result->IsFound()) return;
3550
3551   LookupRealNamedPropertyInPrototypes(name, result);
3552 }
3553
3554
3555 void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name,
3556                                                    LookupResult* result) {
3557   DisallowHeapAllocation no_gc;
3558   Isolate* isolate = GetIsolate();
3559   Heap* heap = isolate->heap();
3560   for (Object* pt = GetPrototype();
3561        pt != heap->null_value();
3562        pt = pt->GetPrototype(isolate)) {
3563     if (pt->IsJSProxy()) {
3564       return result->HandlerResult(JSProxy::cast(pt));
3565     }
3566     JSObject::cast(pt)->LookupOwnRealNamedProperty(name, result);
3567     ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
3568     if (result->IsFound()) return;
3569   }
3570   result->NotFound();
3571 }
3572
3573
3574 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
3575                                             LookupResult* result,
3576                                             Handle<Name> key,
3577                                             Handle<Object> value,
3578                                             PropertyAttributes attributes,
3579                                             StrictMode strict_mode,
3580                                             StoreFromKeyed store_mode) {
3581   if (result->IsHandler()) {
3582     return JSProxy::SetPropertyWithHandler(handle(result->proxy()),
3583         object, key, value, attributes, strict_mode);
3584   } else {
3585     return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object),
3586         result, key, value, attributes, strict_mode, store_mode);
3587   }
3588 }
3589
3590
3591 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) {
3592   Isolate* isolate = proxy->GetIsolate();
3593
3594   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3595   if (name->IsSymbol()) return false;
3596
3597   Handle<Object> args[] = { name };
3598   Handle<Object> result;
3599   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3600       isolate, result,
3601       CallTrap(proxy,
3602                "has",
3603                isolate->derived_has_trap(),
3604                ARRAY_SIZE(args),
3605                args),
3606       false);
3607
3608   return result->BooleanValue();
3609 }
3610
3611
3612 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(
3613     Handle<JSProxy> proxy,
3614     Handle<JSReceiver> receiver,
3615     Handle<Name> name,
3616     Handle<Object> value,
3617     PropertyAttributes attributes,
3618     StrictMode strict_mode) {
3619   Isolate* isolate = proxy->GetIsolate();
3620
3621   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3622   if (name->IsSymbol()) return value;
3623
3624   Handle<Object> args[] = { receiver, name, value };
3625   RETURN_ON_EXCEPTION(
3626       isolate,
3627       CallTrap(proxy,
3628                "set",
3629                isolate->derived_set_trap(),
3630                ARRAY_SIZE(args),
3631                args),
3632       Object);
3633
3634   return value;
3635 }
3636
3637
3638 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3639     Handle<JSProxy> proxy,
3640     Handle<JSReceiver> receiver,
3641     Handle<Name> name,
3642     Handle<Object> value,
3643     PropertyAttributes attributes,
3644     StrictMode strict_mode,
3645     bool* done) {
3646   Isolate* isolate = proxy->GetIsolate();
3647   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy.
3648
3649   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3650   if (name->IsSymbol()) {
3651     *done = false;
3652     return isolate->factory()->the_hole_value();
3653   }
3654
3655   *done = true;  // except where redefined...
3656   Handle<Object> args[] = { name };
3657   Handle<Object> result;
3658   ASSIGN_RETURN_ON_EXCEPTION(
3659       isolate, result,
3660       CallTrap(proxy,
3661                "getPropertyDescriptor",
3662                Handle<Object>(),
3663                ARRAY_SIZE(args),
3664                args),
3665       Object);
3666
3667   if (result->IsUndefined()) {
3668     *done = false;
3669     return isolate->factory()->the_hole_value();
3670   }
3671
3672   // Emulate [[GetProperty]] semantics for proxies.
3673   Handle<Object> argv[] = { result };
3674   Handle<Object> desc;
3675   ASSIGN_RETURN_ON_EXCEPTION(
3676       isolate, desc,
3677       Execution::Call(isolate,
3678                       isolate->to_complete_property_descriptor(),
3679                       result,
3680                       ARRAY_SIZE(argv),
3681                       argv),
3682       Object);
3683
3684   // [[GetProperty]] requires to check that all properties are configurable.
3685   Handle<String> configurable_name =
3686       isolate->factory()->InternalizeOneByteString(
3687           STATIC_ASCII_VECTOR("configurable_"));
3688   Handle<Object> configurable =
3689       Object::GetProperty(desc, configurable_name).ToHandleChecked();
3690   ASSERT(configurable->IsBoolean());
3691   if (configurable->IsFalse()) {
3692     Handle<String> trap =
3693         isolate->factory()->InternalizeOneByteString(
3694             STATIC_ASCII_VECTOR("getPropertyDescriptor"));
3695     Handle<Object> args[] = { handler, trap, name };
3696     Handle<Object> error = isolate->factory()->NewTypeError(
3697         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
3698     return isolate->Throw<Object>(error);
3699   }
3700   ASSERT(configurable->IsTrue());
3701
3702   // Check for DataDescriptor.
3703   Handle<String> hasWritable_name =
3704       isolate->factory()->InternalizeOneByteString(
3705           STATIC_ASCII_VECTOR("hasWritable_"));
3706   Handle<Object> hasWritable =
3707       Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
3708   ASSERT(hasWritable->IsBoolean());
3709   if (hasWritable->IsTrue()) {
3710     Handle<String> writable_name =
3711         isolate->factory()->InternalizeOneByteString(
3712             STATIC_ASCII_VECTOR("writable_"));
3713     Handle<Object> writable =
3714         Object::GetProperty(desc, writable_name).ToHandleChecked();
3715     ASSERT(writable->IsBoolean());
3716     *done = writable->IsFalse();
3717     if (!*done) return isolate->factory()->the_hole_value();
3718     if (strict_mode == SLOPPY) return value;
3719     Handle<Object> args[] = { name, receiver };
3720     Handle<Object> error = isolate->factory()->NewTypeError(
3721         "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3722     return isolate->Throw<Object>(error);
3723   }
3724
3725   // We have an AccessorDescriptor.
3726   Handle<String> set_name = isolate->factory()->InternalizeOneByteString(
3727       STATIC_ASCII_VECTOR("set_"));
3728   Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
3729   if (!setter->IsUndefined()) {
3730     // TODO(rossberg): nicer would be to cast to some JSCallable here...
3731     return SetPropertyWithDefinedSetter(
3732         receiver, Handle<JSReceiver>::cast(setter), value);
3733   }
3734
3735   if (strict_mode == SLOPPY) return value;
3736   Handle<Object> args2[] = { name, proxy };
3737   Handle<Object> error = isolate->factory()->NewTypeError(
3738       "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
3739   return isolate->Throw<Object>(error);
3740 }
3741
3742
3743 MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
3744     Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) {
3745   Isolate* isolate = proxy->GetIsolate();
3746
3747   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3748   if (name->IsSymbol()) return isolate->factory()->false_value();
3749
3750   Handle<Object> args[] = { name };
3751   Handle<Object> result;
3752   ASSIGN_RETURN_ON_EXCEPTION(
3753       isolate, result,
3754       CallTrap(proxy,
3755                "delete",
3756                Handle<Object>(),
3757                ARRAY_SIZE(args),
3758                args),
3759       Object);
3760
3761   bool result_bool = result->BooleanValue();
3762   if (mode == STRICT_DELETION && !result_bool) {
3763     Handle<Object> handler(proxy->handler(), isolate);
3764     Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
3765         STATIC_ASCII_VECTOR("delete"));
3766     Handle<Object> args[] = { handler, trap_name };
3767     Handle<Object> error = isolate->factory()->NewTypeError(
3768         "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
3769     return isolate->Throw<Object>(error);
3770   }
3771   return isolate->factory()->ToBoolean(result_bool);
3772 }
3773
3774
3775 MaybeHandle<Object> JSProxy::DeleteElementWithHandler(
3776     Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) {
3777   Isolate* isolate = proxy->GetIsolate();
3778   Handle<String> name = isolate->factory()->Uint32ToString(index);
3779   return JSProxy::DeletePropertyWithHandler(proxy, name, mode);
3780 }
3781
3782
3783 PropertyAttributes JSProxy::GetPropertyAttributesWithHandler(
3784     Handle<JSProxy> proxy,
3785     Handle<Object> receiver,
3786     Handle<Name> name) {
3787   Isolate* isolate = proxy->GetIsolate();
3788   HandleScope scope(isolate);
3789
3790   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3791   if (name->IsSymbol()) return ABSENT;
3792
3793   Handle<Object> args[] = { name };
3794   Handle<Object> result;
3795   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3796       isolate, result,
3797       proxy->CallTrap(proxy,
3798                       "getPropertyDescriptor",
3799                       Handle<Object>(),
3800                       ARRAY_SIZE(args),
3801                       args),
3802       NONE);
3803
3804   if (result->IsUndefined()) return ABSENT;
3805
3806   Handle<Object> argv[] = { result };
3807   Handle<Object> desc;
3808   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3809       isolate, desc,
3810       Execution::Call(isolate,
3811                       isolate->to_complete_property_descriptor(),
3812                       result,
3813                       ARRAY_SIZE(argv),
3814                       argv),
3815       NONE);
3816
3817   // Convert result to PropertyAttributes.
3818   Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3819       STATIC_ASCII_VECTOR("enumerable_"));
3820   Handle<Object> enumerable;
3821   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3822       isolate, enumerable, Object::GetProperty(desc, enum_n), NONE);
3823   Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
3824       STATIC_ASCII_VECTOR("configurable_"));
3825   Handle<Object> configurable;
3826   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3827       isolate, configurable, Object::GetProperty(desc, conf_n), NONE);
3828   Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
3829       STATIC_ASCII_VECTOR("writable_"));
3830   Handle<Object> writable;
3831   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3832       isolate, writable, Object::GetProperty(desc, writ_n), NONE);
3833   if (!writable->BooleanValue()) {
3834     Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
3835         STATIC_ASCII_VECTOR("set_"));
3836     Handle<Object> setter;
3837     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3838         isolate, setter, Object::GetProperty(desc, set_n), NONE);
3839     writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
3840   }
3841
3842   if (configurable->IsFalse()) {
3843     Handle<Object> handler(proxy->handler(), isolate);
3844     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3845         STATIC_ASCII_VECTOR("getPropertyDescriptor"));
3846     Handle<Object> args[] = { handler, trap, name };
3847     Handle<Object> error = isolate->factory()->NewTypeError(
3848         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
3849     isolate->Throw(*error);
3850     return NONE;
3851   }
3852
3853   int attributes = NONE;
3854   if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
3855   if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
3856   if (!writable->BooleanValue()) attributes |= READ_ONLY;
3857   return static_cast<PropertyAttributes>(attributes);
3858 }
3859
3860
3861 PropertyAttributes JSProxy::GetElementAttributeWithHandler(
3862     Handle<JSProxy> proxy,
3863     Handle<JSReceiver> receiver,
3864     uint32_t index) {
3865   Isolate* isolate = proxy->GetIsolate();
3866   Handle<String> name = isolate->factory()->Uint32ToString(index);
3867   return GetPropertyAttributesWithHandler(proxy, receiver, name);
3868 }
3869
3870
3871 void JSProxy::Fix(Handle<JSProxy> proxy) {
3872   Isolate* isolate = proxy->GetIsolate();
3873
3874   // Save identity hash.
3875   Handle<Object> hash(proxy->GetIdentityHash(), isolate);
3876
3877   if (proxy->IsJSFunctionProxy()) {
3878     isolate->factory()->BecomeJSFunction(proxy);
3879     // Code will be set on the JavaScript side.
3880   } else {
3881     isolate->factory()->BecomeJSObject(proxy);
3882   }
3883   ASSERT(proxy->IsJSObject());
3884
3885   // Inherit identity, if it was present.
3886   if (hash->IsSmi()) {
3887     JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
3888                               Handle<Smi>::cast(hash));
3889   }
3890 }
3891
3892
3893 MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
3894                                       const char* name,
3895                                       Handle<Object> derived,
3896                                       int argc,
3897                                       Handle<Object> argv[]) {
3898   Isolate* isolate = proxy->GetIsolate();
3899   Handle<Object> handler(proxy->handler(), isolate);
3900
3901   Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
3902   Handle<Object> trap;
3903   ASSIGN_RETURN_ON_EXCEPTION(
3904       isolate, trap,
3905       Object::GetPropertyOrElement(handler, trap_name),
3906       Object);
3907
3908   if (trap->IsUndefined()) {
3909     if (derived.is_null()) {
3910       Handle<Object> args[] = { handler, trap_name };
3911       Handle<Object> error = isolate->factory()->NewTypeError(
3912         "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
3913       return isolate->Throw<Object>(error);
3914     }
3915     trap = Handle<Object>(derived);
3916   }
3917
3918   return Execution::Call(isolate, trap, handler, argc, argv);
3919 }
3920
3921
3922 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
3923   ASSERT(object->map()->inobject_properties() == map->inobject_properties());
3924   ElementsKind obj_kind = object->map()->elements_kind();
3925   ElementsKind map_kind = map->elements_kind();
3926   if (map_kind != obj_kind) {
3927     ElementsKind to_kind = map_kind;
3928     if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
3929         IsDictionaryElementsKind(obj_kind)) {
3930       to_kind = obj_kind;
3931     }
3932     if (IsDictionaryElementsKind(to_kind)) {
3933       NormalizeElements(object);
3934     } else {
3935       TransitionElementsKind(object, to_kind);
3936     }
3937     map = Map::AsElementsKind(map, to_kind);
3938   }
3939   JSObject::MigrateToMap(object, map);
3940 }
3941
3942
3943 void JSObject::MigrateInstance(Handle<JSObject> object) {
3944   // Converting any field to the most specific type will cause the
3945   // GeneralizeFieldRepresentation algorithm to create the most general existing
3946   // transition that matches the object. This achieves what is needed.
3947   Handle<Map> original_map(object->map());
3948   GeneralizeFieldRepresentation(
3949       object, 0, Representation::None(),
3950       HeapType::None(object->GetIsolate()),
3951       ALLOW_AS_CONSTANT);
3952   object->map()->set_migration_target(true);
3953   if (FLAG_trace_migration) {
3954     object->PrintInstanceMigration(stdout, *original_map, object->map());
3955   }
3956 }
3957
3958
3959 // static
3960 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
3961   Isolate* isolate = object->GetIsolate();
3962   DisallowDeoptimization no_deoptimization(isolate);
3963   Handle<Map> original_map(object->map(), isolate);
3964   Handle<Map> new_map;
3965   if (!Map::CurrentMapForDeprecatedInternal(original_map).ToHandle(&new_map)) {
3966     return false;
3967   }
3968   JSObject::MigrateToMap(object, new_map);
3969   if (FLAG_trace_migration) {
3970     object->PrintInstanceMigration(stdout, *original_map, object->map());
3971   }
3972   return true;
3973 }
3974
3975
3976 MaybeHandle<Object> JSObject::SetPropertyUsingTransition(
3977     Handle<JSObject> object,
3978     LookupResult* lookup,
3979     Handle<Name> name,
3980     Handle<Object> value,
3981     PropertyAttributes attributes) {
3982   Handle<Map> transition_map(lookup->GetTransitionTarget());
3983   int descriptor = transition_map->LastAdded();
3984
3985   Handle<DescriptorArray> descriptors(transition_map->instance_descriptors());
3986   PropertyDetails details = descriptors->GetDetails(descriptor);
3987
3988   if (details.type() == CALLBACKS || attributes != details.attributes()) {
3989     // AddProperty will either normalize the object, or create a new fast copy
3990     // of the map. If we get a fast copy of the map, all field representations
3991     // will be tagged since the transition is omitted.
3992     return JSObject::AddProperty(
3993         object, name, value, attributes, SLOPPY,
3994         JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED,
3995         JSReceiver::OMIT_EXTENSIBILITY_CHECK,
3996         JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION);
3997   }
3998
3999   // Keep the target CONSTANT if the same value is stored.
4000   // TODO(verwaest): Also support keeping the placeholder
4001   // (value->IsUninitialized) as constant.
4002   if (!lookup->CanHoldValue(value)) {
4003     Representation field_representation = value->OptimalRepresentation();
4004     Handle<HeapType> field_type = value->OptimalType(
4005         lookup->isolate(), field_representation);
4006     transition_map = Map::GeneralizeRepresentation(
4007         transition_map, descriptor,
4008         field_representation, field_type, FORCE_FIELD);
4009   }
4010
4011   JSObject::MigrateToNewProperty(object, transition_map, value);
4012   return value;
4013 }
4014
4015
4016 void JSObject::MigrateToNewProperty(Handle<JSObject> object,
4017                                     Handle<Map> map,
4018                                     Handle<Object> value) {
4019   JSObject::MigrateToMap(object, map);
4020   if (map->GetLastDescriptorDetails().type() != FIELD) return;
4021   object->WriteToField(map->LastAdded(), *value);
4022 }
4023
4024
4025 void JSObject::WriteToField(int descriptor, Object* value) {
4026   DisallowHeapAllocation no_gc;
4027
4028   DescriptorArray* desc = map()->instance_descriptors();
4029   PropertyDetails details = desc->GetDetails(descriptor);
4030
4031   ASSERT(details.type() == FIELD);
4032
4033   FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
4034   if (details.representation().IsDouble()) {
4035     // Nothing more to be done.
4036     if (value->IsUninitialized()) return;
4037     HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
4038     box->set_value(value->Number());
4039   } else {
4040     FastPropertyAtPut(index, value);
4041   }
4042 }
4043
4044
4045 static void SetPropertyToField(LookupResult* lookup,
4046                                Handle<Object> value) {
4047   if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) {
4048     Representation field_representation = value->OptimalRepresentation();
4049     Handle<HeapType> field_type = value->OptimalType(
4050         lookup->isolate(), field_representation);
4051     JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()),
4052                                             lookup->GetDescriptorIndex(),
4053                                             field_representation, field_type,
4054                                             FORCE_FIELD);
4055   }
4056   lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value);
4057 }
4058
4059
4060 static void ConvertAndSetOwnProperty(LookupResult* lookup,
4061                                      Handle<Name> name,
4062                                      Handle<Object> value,
4063                                      PropertyAttributes attributes) {
4064   Handle<JSObject> object(lookup->holder());
4065   if (object->TooManyFastProperties()) {
4066     JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
4067   }
4068
4069   if (!object->HasFastProperties()) {
4070     ReplaceSlowProperty(object, name, value, attributes);
4071     return;
4072   }
4073
4074   int descriptor_index = lookup->GetDescriptorIndex();
4075   if (lookup->GetAttributes() == attributes) {
4076     JSObject::GeneralizeFieldRepresentation(
4077         object, descriptor_index, Representation::Tagged(),
4078         HeapType::Any(lookup->isolate()), FORCE_FIELD);
4079   } else {
4080     Handle<Map> old_map(object->map());
4081     Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map,
4082         descriptor_index, FORCE_FIELD, attributes, "attributes mismatch");
4083     JSObject::MigrateToMap(object, new_map);
4084   }
4085
4086   object->WriteToField(descriptor_index, *value);
4087 }
4088
4089
4090 static void SetPropertyToFieldWithAttributes(LookupResult* lookup,
4091                                              Handle<Name> name,
4092                                              Handle<Object> value,
4093                                              PropertyAttributes attributes) {
4094   if (lookup->GetAttributes() == attributes) {
4095     if (value->IsUninitialized()) return;
4096     SetPropertyToField(lookup, value);
4097   } else {
4098     ConvertAndSetOwnProperty(lookup, name, value, attributes);
4099   }
4100 }
4101
4102
4103 MaybeHandle<Object> JSObject::SetPropertyForResult(
4104     Handle<JSObject> object,
4105     LookupResult* lookup,
4106     Handle<Name> name,
4107     Handle<Object> value,
4108     PropertyAttributes attributes,
4109     StrictMode strict_mode,
4110     StoreFromKeyed store_mode) {
4111   Isolate* isolate = object->GetIsolate();
4112
4113   // Make sure that the top context does not change when doing callbacks or
4114   // interceptor calls.
4115   AssertNoContextChange ncc(isolate);
4116
4117   // Optimization for 2-byte strings often used as keys in a decompression
4118   // dictionary.  We internalize these short keys to avoid constantly
4119   // reallocating them.
4120   if (name->IsString() && !name->IsInternalizedString() &&
4121       Handle<String>::cast(name)->length() <= 2) {
4122     name = isolate->factory()->InternalizeString(Handle<String>::cast(name));
4123   }
4124
4125   // Check access rights if needed.
4126   if (object->IsAccessCheckNeeded()) {
4127     if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4128       return SetPropertyWithFailedAccessCheck(object, lookup, name, value,
4129                                               true, strict_mode);
4130     }
4131   }
4132
4133   if (object->IsJSGlobalProxy()) {
4134     Handle<Object> proto(object->GetPrototype(), isolate);
4135     if (proto->IsNull()) return value;
4136     ASSERT(proto->IsJSGlobalObject());
4137     return SetPropertyForResult(Handle<JSObject>::cast(proto),
4138         lookup, name, value, attributes, strict_mode, store_mode);
4139   }
4140
4141   ASSERT(!lookup->IsFound() || lookup->holder() == *object ||
4142          lookup->holder()->map()->is_hidden_prototype());
4143
4144   if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) {
4145     bool done = false;
4146     Handle<Object> result_object;
4147     ASSIGN_RETURN_ON_EXCEPTION(
4148         isolate, result_object,
4149         SetPropertyViaPrototypes(
4150             object, name, value, attributes, strict_mode, &done),
4151         Object);
4152     if (done) return result_object;
4153   }
4154
4155   if (!lookup->IsFound()) {
4156     // Neither properties nor transitions found.
4157     return AddProperty(
4158         object, name, value, attributes, strict_mode, store_mode);
4159   }
4160
4161   if (lookup->IsProperty() && lookup->IsReadOnly()) {
4162     if (strict_mode == STRICT) {
4163       Handle<Object> args[] = { name, object };
4164       Handle<Object> error = isolate->factory()->NewTypeError(
4165           "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
4166       return isolate->Throw<Object>(error);
4167     } else {
4168       return value;
4169     }
4170   }
4171
4172   Handle<Object> old_value = isolate->factory()->the_hole_value();
4173   bool is_observed = object->map()->is_observed() &&
4174                      *name != isolate->heap()->hidden_string();
4175   if (is_observed && lookup->IsDataProperty()) {
4176     old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked();
4177   }
4178
4179   // This is a real property that is not read-only, or it is a
4180   // transition or null descriptor and there are no setters in the prototypes.
4181   MaybeHandle<Object> maybe_result = value;
4182   if (lookup->IsTransition()) {
4183     maybe_result = SetPropertyUsingTransition(handle(lookup->holder()), lookup,
4184                                               name, value, attributes);
4185   } else {
4186     switch (lookup->type()) {
4187       case NORMAL:
4188         SetNormalizedProperty(handle(lookup->holder()), lookup, value);
4189         break;
4190       case FIELD:
4191         SetPropertyToField(lookup, value);
4192         break;
4193       case CONSTANT:
4194         // Only replace the constant if necessary.
4195         if (*value == lookup->GetConstant()) return value;
4196         SetPropertyToField(lookup, value);
4197         break;
4198       case CALLBACKS: {
4199         Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
4200         return SetPropertyWithCallback(object, name, value,
4201                                        handle(lookup->holder()),
4202                                        callback_object, strict_mode);
4203       }
4204       case INTERCEPTOR:
4205         maybe_result = SetPropertyWithInterceptor(
4206             handle(lookup->holder()), name, value, attributes, strict_mode);
4207         break;
4208       case HANDLER:
4209       case NONEXISTENT:
4210         UNREACHABLE();
4211     }
4212   }
4213
4214   Handle<Object> result;
4215   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
4216
4217   if (is_observed) {
4218     if (lookup->IsTransition()) {
4219       EnqueueChangeRecord(object, "add", name, old_value);
4220     } else {
4221       LookupResult new_lookup(isolate);
4222       object->LookupOwn(name, &new_lookup, true);
4223       if (new_lookup.IsDataProperty()) {
4224         Handle<Object> new_value =
4225             Object::GetPropertyOrElement(object, name).ToHandleChecked();
4226         if (!new_value->SameValue(*old_value)) {
4227           EnqueueChangeRecord(object, "update", name, old_value);
4228         }
4229       }
4230     }
4231   }
4232
4233   return result;
4234 }
4235
4236
4237 // Set a real own property, even if it is READ_ONLY.  If the property is not
4238 // present, add it with attributes NONE.  This code is an exact clone of
4239 // SetProperty, with the check for IsReadOnly and the check for a
4240 // callback setter removed.  The two lines looking up the LookupResult
4241 // result are also added.  If one of the functions is changed, the other
4242 // should be.
4243 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4244     Handle<JSObject> object,
4245     Handle<Name> name,
4246     Handle<Object> value,
4247     PropertyAttributes attributes,
4248     ValueType value_type,
4249     StoreMode mode,
4250     ExtensibilityCheck extensibility_check,
4251     StoreFromKeyed store_from_keyed,
4252     ExecutableAccessorInfoHandling handling) {
4253   Isolate* isolate = object->GetIsolate();
4254
4255   // Make sure that the top context does not change when doing callbacks or
4256   // interceptor calls.
4257   AssertNoContextChange ncc(isolate);
4258
4259   LookupResult lookup(isolate);
4260   object->LookupOwn(name, &lookup, true);
4261   if (!lookup.IsFound()) {
4262     object->map()->LookupTransition(*object, *name, &lookup);
4263   }
4264
4265   // Check access rights if needed.
4266   if (object->IsAccessCheckNeeded()) {
4267     if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4268       return SetPropertyWithFailedAccessCheck(object, &lookup, name, value,
4269                                               false, SLOPPY);
4270     }
4271   }
4272
4273   if (object->IsJSGlobalProxy()) {
4274     Handle<Object> proto(object->GetPrototype(), isolate);
4275     if (proto->IsNull()) return value;
4276     ASSERT(proto->IsJSGlobalObject());
4277     return SetOwnPropertyIgnoreAttributes(Handle<JSObject>::cast(proto),
4278         name, value, attributes, value_type, mode, extensibility_check);
4279   }
4280
4281   if (lookup.IsInterceptor() ||
4282       (lookup.IsDescriptorOrDictionary() && lookup.type() == CALLBACKS)) {
4283     object->LookupOwnRealNamedProperty(name, &lookup);
4284   }
4285
4286   // Check for accessor in prototype chain removed here in clone.
4287   if (!lookup.IsFound()) {
4288     object->map()->LookupTransition(*object, *name, &lookup);
4289     TransitionFlag flag = lookup.IsFound()
4290         ? OMIT_TRANSITION : INSERT_TRANSITION;
4291     // Neither properties nor transitions found.
4292     return AddProperty(object, name, value, attributes, SLOPPY,
4293         store_from_keyed, extensibility_check, value_type, mode, flag);
4294   }
4295
4296   Handle<Object> old_value = isolate->factory()->the_hole_value();
4297   PropertyAttributes old_attributes = ABSENT;
4298   bool is_observed = object->map()->is_observed() &&
4299                      *name != isolate->heap()->hidden_string();
4300   if (is_observed && lookup.IsProperty()) {
4301     if (lookup.IsDataProperty()) {
4302       old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked();
4303     }
4304     old_attributes = lookup.GetAttributes();
4305   }
4306
4307   bool executed_set_prototype = false;
4308
4309   // Check of IsReadOnly removed from here in clone.
4310   if (lookup.IsTransition()) {
4311     Handle<Object> result;
4312     ASSIGN_RETURN_ON_EXCEPTION(
4313         isolate, result,
4314         SetPropertyUsingTransition(
4315             handle(lookup.holder()), &lookup, name, value, attributes),
4316         Object);
4317   } else {
4318     switch (lookup.type()) {
4319       case NORMAL:
4320         ReplaceSlowProperty(object, name, value, attributes);
4321         break;
4322       case FIELD:
4323         SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4324         break;
4325       case CONSTANT:
4326         // Only replace the constant if necessary.
4327         if (lookup.GetAttributes() != attributes ||
4328             *value != lookup.GetConstant()) {
4329           SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4330         }
4331         break;
4332       case CALLBACKS:
4333       {
4334         Handle<Object> callback(lookup.GetCallbackObject(), isolate);
4335         if (callback->IsExecutableAccessorInfo() &&
4336             handling == DONT_FORCE_FIELD) {
4337           Handle<Object> result;
4338           ASSIGN_RETURN_ON_EXCEPTION(
4339               isolate, result,
4340               JSObject::SetPropertyWithCallback(object,
4341                                                 name,
4342                                                 value,
4343                                                 handle(lookup.holder()),
4344                                                 callback,
4345                                                 STRICT),
4346               Object);
4347
4348           if (attributes != lookup.GetAttributes()) {
4349             Handle<ExecutableAccessorInfo> new_data =
4350                 Accessors::CloneAccessor(
4351                     isolate, Handle<ExecutableAccessorInfo>::cast(callback));
4352             new_data->set_property_attributes(attributes);
4353             if (attributes & READ_ONLY) {
4354               // This way we don't have to introduce a lookup to the setter,
4355               // simply make it unavailable to reflect the attributes.
4356               new_data->clear_setter();
4357             }
4358
4359             SetPropertyCallback(object, name, new_data, attributes);
4360           }
4361           if (is_observed) {
4362             // If we are setting the prototype of a function and are observed,
4363             // don't send change records because the prototype handles that
4364             // itself.
4365             executed_set_prototype = object->IsJSFunction() &&
4366                 String::Equals(isolate->factory()->prototype_string(),
4367                                Handle<String>::cast(name)) &&
4368                 Handle<JSFunction>::cast(object)->should_have_prototype();
4369           }
4370         } else {
4371           ConvertAndSetOwnProperty(&lookup, name, value, attributes);
4372         }
4373         break;
4374       }
4375       case NONEXISTENT:
4376       case HANDLER:
4377       case INTERCEPTOR:
4378         UNREACHABLE();
4379     }
4380   }
4381
4382   if (is_observed && !executed_set_prototype) {
4383     if (lookup.IsTransition()) {
4384       EnqueueChangeRecord(object, "add", name, old_value);
4385     } else if (old_value->IsTheHole()) {
4386       EnqueueChangeRecord(object, "reconfigure", name, old_value);
4387     } else {
4388       LookupResult new_lookup(isolate);
4389       object->LookupOwn(name, &new_lookup, true);
4390       bool value_changed = false;
4391       if (new_lookup.IsDataProperty()) {
4392         Handle<Object> new_value =
4393             Object::GetPropertyOrElement(object, name).ToHandleChecked();
4394         value_changed = !old_value->SameValue(*new_value);
4395       }
4396       if (new_lookup.GetAttributes() != old_attributes) {
4397         if (!value_changed) old_value = isolate->factory()->the_hole_value();
4398         EnqueueChangeRecord(object, "reconfigure", name, old_value);
4399       } else if (value_changed) {
4400         EnqueueChangeRecord(object, "update", name, old_value);
4401       }
4402     }
4403   }
4404
4405   return value;
4406 }
4407
4408
4409 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4410     Handle<JSObject> holder,
4411     Handle<Object> receiver,
4412     Handle<Name> name) {
4413   // TODO(rossberg): Support symbols in the API.
4414   if (name->IsSymbol()) return Maybe<PropertyAttributes>(ABSENT);
4415
4416   Isolate* isolate = holder->GetIsolate();
4417   HandleScope scope(isolate);
4418
4419   // Make sure that the top context does not change when doing
4420   // callbacks or interceptor calls.
4421   AssertNoContextChange ncc(isolate);
4422
4423   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
4424   PropertyCallbackArguments args(
4425       isolate, interceptor->data(), *receiver, *holder);
4426   if (!interceptor->query()->IsUndefined()) {
4427     v8::NamedPropertyQueryCallback query =
4428         v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query());
4429     LOG(isolate,
4430         ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
4431     v8::Handle<v8::Integer> result =
4432         args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name)));
4433     if (!result.IsEmpty()) {
4434       ASSERT(result->IsInt32());
4435       return Maybe<PropertyAttributes>(
4436           static_cast<PropertyAttributes>(result->Int32Value()));
4437     }
4438   } else if (!interceptor->getter()->IsUndefined()) {
4439     v8::NamedPropertyGetterCallback getter =
4440         v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
4441     LOG(isolate,
4442         ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
4443     v8::Handle<v8::Value> result =
4444         args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name)));
4445     if (!result.IsEmpty()) return Maybe<PropertyAttributes>(DONT_ENUM);
4446   }
4447   return Maybe<PropertyAttributes>();
4448 }
4449
4450
4451 PropertyAttributes JSReceiver::GetOwnPropertyAttributes(
4452     Handle<JSReceiver> object, Handle<Name> name) {
4453   // Check whether the name is an array index.
4454   uint32_t index = 0;
4455   if (object->IsJSObject() && name->AsArrayIndex(&index)) {
4456     return GetOwnElementAttribute(object, index);
4457   }
4458   LookupIterator it(object, name, LookupIterator::CHECK_OWN);
4459   return GetPropertyAttributes(&it);
4460 }
4461
4462
4463 PropertyAttributes JSReceiver::GetPropertyAttributes(LookupIterator* it) {
4464   for (; it->IsFound(); it->Next()) {
4465     switch (it->state()) {
4466       case LookupIterator::NOT_FOUND:
4467         UNREACHABLE();
4468       case LookupIterator::JSPROXY:
4469         return JSProxy::GetPropertyAttributesWithHandler(
4470             it->GetJSProxy(), it->GetReceiver(), it->name());
4471       case LookupIterator::INTERCEPTOR: {
4472         Maybe<PropertyAttributes> result =
4473             JSObject::GetPropertyAttributesWithInterceptor(
4474                 it->GetHolder(), it->GetReceiver(), it->name());
4475         if (result.has_value) return result.value;
4476         break;
4477       }
4478       case LookupIterator::ACCESS_CHECK:
4479         if (it->HasAccess(v8::ACCESS_HAS)) break;
4480         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
4481       case LookupIterator::PROPERTY:
4482         if (it->HasProperty()) return it->property_details().attributes();
4483         break;
4484     }
4485   }
4486   return ABSENT;
4487 }
4488
4489
4490 PropertyAttributes JSObject::GetElementAttributeWithReceiver(
4491     Handle<JSObject> object,
4492     Handle<JSReceiver> receiver,
4493     uint32_t index,
4494     bool check_prototype) {
4495   Isolate* isolate = object->GetIsolate();
4496
4497   // Check access rights if needed.
4498   if (object->IsAccessCheckNeeded()) {
4499     if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
4500       isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
4501       // TODO(yangguo): Issue 3269, check for scheduled exception missing?
4502       return ABSENT;
4503     }
4504   }
4505
4506   if (object->IsJSGlobalProxy()) {
4507     Handle<Object> proto(object->GetPrototype(), isolate);
4508     if (proto->IsNull()) return ABSENT;
4509     ASSERT(proto->IsJSGlobalObject());
4510     return JSObject::GetElementAttributeWithReceiver(
4511         Handle<JSObject>::cast(proto), receiver, index, check_prototype);
4512   }
4513
4514   // Check for lookup interceptor except when bootstrapping.
4515   if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
4516     return JSObject::GetElementAttributeWithInterceptor(
4517         object, receiver, index, check_prototype);
4518   }
4519
4520   return GetElementAttributeWithoutInterceptor(
4521       object, receiver, index, check_prototype);
4522 }
4523
4524
4525 PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
4526     Handle<JSObject> object,
4527     Handle<JSReceiver> receiver,
4528     uint32_t index,
4529     bool check_prototype) {
4530   Isolate* isolate = object->GetIsolate();
4531   HandleScope scope(isolate);
4532
4533   // Make sure that the top context does not change when doing
4534   // callbacks or interceptor calls.
4535   AssertNoContextChange ncc(isolate);
4536
4537   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
4538   PropertyCallbackArguments args(
4539       isolate, interceptor->data(), *receiver, *object);
4540   if (!interceptor->query()->IsUndefined()) {
4541     v8::IndexedPropertyQueryCallback query =
4542         v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4543     LOG(isolate,
4544         ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index));
4545     v8::Handle<v8::Integer> result = args.Call(query, index);
4546     if (!result.IsEmpty())
4547       return static_cast<PropertyAttributes>(result->Int32Value());
4548   } else if (!interceptor->getter()->IsUndefined()) {
4549     v8::IndexedPropertyGetterCallback getter =
4550         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4551     LOG(isolate,
4552         ApiIndexedPropertyAccess(
4553             "interceptor-indexed-get-has", *object, index));
4554     v8::Handle<v8::Value> result = args.Call(getter, index);
4555     if (!result.IsEmpty()) return NONE;
4556   }
4557
4558   return GetElementAttributeWithoutInterceptor(
4559        object, receiver, index, check_prototype);
4560 }
4561
4562
4563 PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
4564     Handle<JSObject> object,
4565     Handle<JSReceiver> receiver,
4566     uint32_t index,
4567     bool check_prototype) {
4568   PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes(
4569       receiver, object, index);
4570   if (attr != ABSENT) return attr;
4571
4572   // Handle [] on String objects.
4573   if (object->IsStringObjectWithCharacterAt(index)) {
4574     return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
4575   }
4576
4577   if (!check_prototype) return ABSENT;
4578
4579   Handle<Object> proto(object->GetPrototype(), object->GetIsolate());
4580   if (proto->IsJSProxy()) {
4581     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
4582     return JSProxy::GetElementAttributeWithHandler(
4583         Handle<JSProxy>::cast(proto), receiver, index);
4584   }
4585   if (proto->IsNull()) return ABSENT;
4586   return GetElementAttributeWithReceiver(
4587       Handle<JSObject>::cast(proto), receiver, index, true);
4588 }
4589
4590
4591 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
4592   Handle<FixedArray> array(
4593       isolate->factory()->NewFixedArray(kEntries, TENURED));
4594   return Handle<NormalizedMapCache>::cast(array);
4595 }
4596
4597
4598 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
4599                                          PropertyNormalizationMode mode) {
4600   DisallowHeapAllocation no_gc;
4601   Object* value = FixedArray::get(GetIndex(fast_map));
4602   if (!value->IsMap() ||
4603       !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4604     return MaybeHandle<Map>();
4605   }
4606   return handle(Map::cast(value));
4607 }
4608
4609
4610 void NormalizedMapCache::Set(Handle<Map> fast_map,
4611                              Handle<Map> normalized_map) {
4612   DisallowHeapAllocation no_gc;
4613   ASSERT(normalized_map->is_dictionary_map());
4614   FixedArray::set(GetIndex(fast_map), *normalized_map);
4615 }
4616
4617
4618 void NormalizedMapCache::Clear() {
4619   int entries = length();
4620   for (int i = 0; i != entries; i++) {
4621     set_undefined(i);
4622   }
4623 }
4624
4625
4626 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
4627                                     Handle<Name> name,
4628                                     Handle<Code> code) {
4629   Handle<Map> map(object->map());
4630   Map::UpdateCodeCache(map, name, code);
4631 }
4632
4633
4634 void JSObject::NormalizeProperties(Handle<JSObject> object,
4635                                    PropertyNormalizationMode mode,
4636                                    int expected_additional_properties) {
4637   if (!object->HasFastProperties()) return;
4638
4639   // The global object is always normalized.
4640   ASSERT(!object->IsGlobalObject());
4641   // JSGlobalProxy must never be normalized
4642   ASSERT(!object->IsJSGlobalProxy());
4643
4644   Isolate* isolate = object->GetIsolate();
4645   HandleScope scope(isolate);
4646   Handle<Map> map(object->map());
4647   Handle<Map> new_map = Map::Normalize(map, mode);
4648
4649   // Allocate new content.
4650   int real_size = map->NumberOfOwnDescriptors();
4651   int property_count = real_size;
4652   if (expected_additional_properties > 0) {
4653     property_count += expected_additional_properties;
4654   } else {
4655     property_count += 2;  // Make space for two more properties.
4656   }
4657   Handle<NameDictionary> dictionary =
4658       NameDictionary::New(isolate, property_count);
4659
4660   Handle<DescriptorArray> descs(map->instance_descriptors());
4661   for (int i = 0; i < real_size; i++) {
4662     PropertyDetails details = descs->GetDetails(i);
4663     switch (details.type()) {
4664       case CONSTANT: {
4665         Handle<Name> key(descs->GetKey(i));
4666         Handle<Object> value(descs->GetConstant(i), isolate);
4667         PropertyDetails d = PropertyDetails(
4668             details.attributes(), NORMAL, i + 1);
4669         dictionary = NameDictionary::Add(dictionary, key, value, d);
4670         break;
4671       }
4672       case FIELD: {
4673         Handle<Name> key(descs->GetKey(i));
4674         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4675         Handle<Object> value(
4676             object->RawFastPropertyAt(index), isolate);
4677         PropertyDetails d =
4678             PropertyDetails(details.attributes(), NORMAL, i + 1);
4679         dictionary = NameDictionary::Add(dictionary, key, value, d);
4680         break;
4681       }
4682       case CALLBACKS: {
4683         Handle<Name> key(descs->GetKey(i));
4684         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4685         PropertyDetails d = PropertyDetails(
4686             details.attributes(), CALLBACKS, i + 1);
4687         dictionary = NameDictionary::Add(dictionary, key, value, d);
4688         break;
4689       }
4690       case INTERCEPTOR:
4691         break;
4692       case HANDLER:
4693       case NORMAL:
4694       case NONEXISTENT:
4695         UNREACHABLE();
4696         break;
4697     }
4698   }
4699
4700   // Copy the next enumeration index from instance descriptor.
4701   dictionary->SetNextEnumerationIndex(real_size + 1);
4702
4703   // From here on we cannot fail and we shouldn't GC anymore.
4704   DisallowHeapAllocation no_allocation;
4705
4706   // Resize the object in the heap if necessary.
4707   int new_instance_size = new_map->instance_size();
4708   int instance_size_delta = map->instance_size() - new_instance_size;
4709   ASSERT(instance_size_delta >= 0);
4710   Heap* heap = isolate->heap();
4711   heap->CreateFillerObjectAt(object->address() + new_instance_size,
4712                              instance_size_delta);
4713   heap->AdjustLiveBytes(object->address(),
4714                         -instance_size_delta,
4715                         Heap::FROM_MUTATOR);
4716
4717   // We are storing the new map using release store after creating a filler for
4718   // the left-over space to avoid races with the sweeper thread.
4719   object->synchronized_set_map(*new_map);
4720
4721   object->set_properties(*dictionary);
4722
4723   isolate->counters()->props_to_dictionary()->Increment();
4724
4725 #ifdef DEBUG
4726   if (FLAG_trace_normalization) {
4727     PrintF("Object properties have been normalized:\n");
4728     object->Print();
4729   }
4730 #endif
4731 }
4732
4733
4734 void JSObject::TransformToFastProperties(Handle<JSObject> object,
4735                                          int unused_property_fields) {
4736   if (object->HasFastProperties()) return;
4737   ASSERT(!object->IsGlobalObject());
4738   Isolate* isolate = object->GetIsolate();
4739   Factory* factory = isolate->factory();
4740   Handle<NameDictionary> dictionary(object->property_dictionary());
4741
4742   // Make sure we preserve dictionary representation if there are too many
4743   // descriptors.
4744   int number_of_elements = dictionary->NumberOfElements();
4745   if (number_of_elements > kMaxNumberOfDescriptors) return;
4746
4747   if (number_of_elements != dictionary->NextEnumerationIndex()) {
4748     NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
4749   }
4750
4751   int instance_descriptor_length = 0;
4752   int number_of_fields = 0;
4753
4754   // Compute the length of the instance descriptor.
4755   int capacity = dictionary->Capacity();
4756   for (int i = 0; i < capacity; i++) {
4757     Object* k = dictionary->KeyAt(i);
4758     if (dictionary->IsKey(k)) {
4759       Object* value = dictionary->ValueAt(i);
4760       PropertyType type = dictionary->DetailsAt(i).type();
4761       ASSERT(type != FIELD);
4762       instance_descriptor_length++;
4763       if (type == NORMAL && !value->IsJSFunction()) {
4764         number_of_fields += 1;
4765       }
4766     }
4767   }
4768
4769   int inobject_props = object->map()->inobject_properties();
4770
4771   // Allocate new map.
4772   Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
4773   new_map->set_dictionary_map(false);
4774
4775   if (instance_descriptor_length == 0) {
4776     DisallowHeapAllocation no_gc;
4777     ASSERT_LE(unused_property_fields, inobject_props);
4778     // Transform the object.
4779     new_map->set_unused_property_fields(inobject_props);
4780     object->set_map(*new_map);
4781     object->set_properties(isolate->heap()->empty_fixed_array());
4782     // Check that it really works.
4783     ASSERT(object->HasFastProperties());
4784     return;
4785   }
4786
4787   // Allocate the instance descriptor.
4788   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
4789       isolate, instance_descriptor_length);
4790
4791   int number_of_allocated_fields =
4792       number_of_fields + unused_property_fields - inobject_props;
4793   if (number_of_allocated_fields < 0) {
4794     // There is enough inobject space for all fields (including unused).
4795     number_of_allocated_fields = 0;
4796     unused_property_fields = inobject_props - number_of_fields;
4797   }
4798
4799   // Allocate the fixed array for the fields.
4800   Handle<FixedArray> fields = factory->NewFixedArray(
4801       number_of_allocated_fields);
4802
4803   // Fill in the instance descriptor and the fields.
4804   int current_offset = 0;
4805   for (int i = 0; i < capacity; i++) {
4806     Object* k = dictionary->KeyAt(i);
4807     if (dictionary->IsKey(k)) {
4808       Object* value = dictionary->ValueAt(i);
4809       Handle<Name> key;
4810       if (k->IsSymbol()) {
4811         key = handle(Symbol::cast(k));
4812       } else {
4813         // Ensure the key is a unique name before writing into the
4814         // instance descriptor.
4815         key = factory->InternalizeString(handle(String::cast(k)));
4816       }
4817
4818       PropertyDetails details = dictionary->DetailsAt(i);
4819       int enumeration_index = details.dictionary_index();
4820       PropertyType type = details.type();
4821
4822       if (value->IsJSFunction()) {
4823         ConstantDescriptor d(key,
4824                              handle(value, isolate),
4825                              details.attributes());
4826         descriptors->Set(enumeration_index - 1, &d);
4827       } else if (type == NORMAL) {
4828         if (current_offset < inobject_props) {
4829           object->InObjectPropertyAtPut(current_offset,
4830                                         value,
4831                                         UPDATE_WRITE_BARRIER);
4832         } else {
4833           int offset = current_offset - inobject_props;
4834           fields->set(offset, value);
4835         }
4836         FieldDescriptor d(key,
4837                           current_offset++,
4838                           details.attributes(),
4839                           // TODO(verwaest): value->OptimalRepresentation();
4840                           Representation::Tagged());
4841         descriptors->Set(enumeration_index - 1, &d);
4842       } else if (type == CALLBACKS) {
4843         CallbacksDescriptor d(key,
4844                               handle(value, isolate),
4845                               details.attributes());
4846         descriptors->Set(enumeration_index - 1, &d);
4847       } else {
4848         UNREACHABLE();
4849       }
4850     }
4851   }
4852   ASSERT(current_offset == number_of_fields);
4853
4854   descriptors->Sort();
4855
4856   DisallowHeapAllocation no_gc;
4857   new_map->InitializeDescriptors(*descriptors);
4858   new_map->set_unused_property_fields(unused_property_fields);
4859
4860   // Transform the object.
4861   object->set_map(*new_map);
4862
4863   object->set_properties(*fields);
4864   ASSERT(object->IsJSObject());
4865
4866   // Check that it really works.
4867   ASSERT(object->HasFastProperties());
4868 }
4869
4870
4871 void JSObject::ResetElements(Handle<JSObject> object) {
4872   Heap* heap = object->GetIsolate()->heap();
4873   CHECK(object->map() != heap->sloppy_arguments_elements_map());
4874   object->set_elements(object->map()->GetInitialElements());
4875 }
4876
4877
4878 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4879     Handle<FixedArrayBase> array,
4880     int length,
4881     Handle<SeededNumberDictionary> dictionary) {
4882   Isolate* isolate = array->GetIsolate();
4883   Factory* factory = isolate->factory();
4884   bool has_double_elements = array->IsFixedDoubleArray();
4885   for (int i = 0; i < length; i++) {
4886     Handle<Object> value;
4887     if (has_double_elements) {
4888       Handle<FixedDoubleArray> double_array =
4889           Handle<FixedDoubleArray>::cast(array);
4890       if (double_array->is_the_hole(i)) {
4891         value = factory->the_hole_value();
4892       } else {
4893         value = factory->NewHeapNumber(double_array->get_scalar(i));
4894       }
4895     } else {
4896       value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4897     }
4898     if (!value->IsTheHole()) {
4899       PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
4900       dictionary =
4901           SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4902     }
4903   }
4904   return dictionary;
4905 }
4906
4907
4908 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4909     Handle<JSObject> object) {
4910   ASSERT(!object->HasExternalArrayElements() &&
4911          !object->HasFixedTypedArrayElements());
4912   Isolate* isolate = object->GetIsolate();
4913
4914   // Find the backing store.
4915   Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements()));
4916   bool is_arguments =
4917       (array->map() == isolate->heap()->sloppy_arguments_elements_map());
4918   if (is_arguments) {
4919     array = handle(FixedArrayBase::cast(
4920         Handle<FixedArray>::cast(array)->get(1)));
4921   }
4922   if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array);
4923
4924   ASSERT(object->HasFastSmiOrObjectElements() ||
4925          object->HasFastDoubleElements() ||
4926          object->HasFastArgumentsElements());
4927   // Compute the effective length and allocate a new backing store.
4928   int length = object->IsJSArray()
4929       ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4930       : array->length();
4931   int old_capacity = 0;
4932   int used_elements = 0;
4933   object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4934   Handle<SeededNumberDictionary> dictionary =
4935       SeededNumberDictionary::New(isolate, used_elements);
4936
4937   dictionary = CopyFastElementsToDictionary(array, length, dictionary);
4938
4939   // Switch to using the dictionary as the backing storage for elements.
4940   if (is_arguments) {
4941     FixedArray::cast(object->elements())->set(1, *dictionary);
4942   } else {
4943     // Set the new map first to satify the elements type assert in
4944     // set_elements().
4945     Handle<Map> new_map =
4946         JSObject::GetElementsTransitionMap(object, DICTIONARY_ELEMENTS);
4947
4948     JSObject::MigrateToMap(object, new_map);
4949     object->set_elements(*dictionary);
4950   }
4951
4952   isolate->counters()->elements_to_dictionary()->Increment();
4953
4954 #ifdef DEBUG
4955   if (FLAG_trace_normalization) {
4956     PrintF("Object elements have been normalized:\n");
4957     object->Print();
4958   }
4959 #endif
4960
4961   ASSERT(object->HasDictionaryElements() ||
4962          object->HasDictionaryArgumentsElements());
4963   return dictionary;
4964 }
4965
4966
4967 static Smi* GenerateIdentityHash(Isolate* isolate) {
4968   int hash_value;
4969   int attempts = 0;
4970   do {
4971     // Generate a random 32-bit hash value but limit range to fit
4972     // within a smi.
4973     hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4974     attempts++;
4975   } while (hash_value == 0 && attempts < 30);
4976   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
4977
4978   return Smi::FromInt(hash_value);
4979 }
4980
4981
4982 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4983   ASSERT(!object->IsJSGlobalProxy());
4984   Isolate* isolate = object->GetIsolate();
4985   SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4986 }
4987
4988
4989 template<typename ProxyType>
4990 static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
4991   Isolate* isolate = proxy->GetIsolate();
4992
4993   Handle<Object> maybe_hash(proxy->hash(), isolate);
4994   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4995
4996   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4997   proxy->set_hash(*hash);
4998   return hash;
4999 }
5000
5001
5002 Object* JSObject::GetIdentityHash() {
5003   DisallowHeapAllocation no_gc;
5004   Isolate* isolate = GetIsolate();
5005   if (IsJSGlobalProxy()) {
5006     return JSGlobalProxy::cast(this)->hash();
5007   }
5008   Object* stored_value =
5009       GetHiddenProperty(isolate->factory()->identity_hash_string());
5010   return stored_value->IsSmi()
5011       ? stored_value
5012       : isolate->heap()->undefined_value();
5013 }
5014
5015
5016 Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
5017   if (object->IsJSGlobalProxy()) {
5018     return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
5019   }
5020
5021   Isolate* isolate = object->GetIsolate();
5022
5023   Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
5024   if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
5025
5026   Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
5027   SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
5028   return hash;
5029 }
5030
5031
5032 Object* JSProxy::GetIdentityHash() {
5033   return this->hash();
5034 }
5035
5036
5037 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
5038   return GetOrCreateIdentityHashHelper(proxy);
5039 }
5040
5041
5042 Object* JSObject::GetHiddenProperty(Handle<Name> key) {
5043   DisallowHeapAllocation no_gc;
5044   ASSERT(key->IsUniqueName());
5045   if (IsJSGlobalProxy()) {
5046     // JSGlobalProxies store their hash internally.
5047     ASSERT(*key != GetHeap()->identity_hash_string());
5048     // For a proxy, use the prototype as target object.
5049     Object* proxy_parent = GetPrototype();
5050     // If the proxy is detached, return undefined.
5051     if (proxy_parent->IsNull()) return GetHeap()->the_hole_value();
5052     ASSERT(proxy_parent->IsJSGlobalObject());
5053     return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
5054   }
5055   ASSERT(!IsJSGlobalProxy());
5056   Object* inline_value = GetHiddenPropertiesHashTable();
5057
5058   if (inline_value->IsSmi()) {
5059     // Handle inline-stored identity hash.
5060     if (*key == GetHeap()->identity_hash_string()) {
5061       return inline_value;
5062     } else {
5063       return GetHeap()->the_hole_value();
5064     }
5065   }
5066
5067   if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
5068
5069   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
5070   Object* entry = hashtable->Lookup(key);
5071   return entry;
5072 }
5073
5074
5075 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
5076                                            Handle<Name> key,
5077                                            Handle<Object> value) {
5078   Isolate* isolate = object->GetIsolate();
5079
5080   ASSERT(key->IsUniqueName());
5081   if (object->IsJSGlobalProxy()) {
5082     // JSGlobalProxies store their hash internally.
5083     ASSERT(*key != *isolate->factory()->identity_hash_string());
5084     // For a proxy, use the prototype as target object.
5085     Handle<Object> proxy_parent(object->GetPrototype(), isolate);
5086     // If the proxy is detached, return undefined.
5087     if (proxy_parent->IsNull()) return isolate->factory()->undefined_value();
5088     ASSERT(proxy_parent->IsJSGlobalObject());
5089     return SetHiddenProperty(Handle<JSObject>::cast(proxy_parent), key, value);
5090   }
5091   ASSERT(!object->IsJSGlobalProxy());
5092
5093   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5094
5095   // If there is no backing store yet, store the identity hash inline.
5096   if (value->IsSmi() &&
5097       *key == *isolate->factory()->identity_hash_string() &&
5098       (inline_value->IsUndefined() || inline_value->IsSmi())) {
5099     return JSObject::SetHiddenPropertiesHashTable(object, value);
5100   }
5101
5102   Handle<ObjectHashTable> hashtable =
5103       GetOrCreateHiddenPropertiesHashtable(object);
5104
5105   // If it was found, check if the key is already in the dictionary.
5106   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
5107                                                            value);
5108   if (*new_table != *hashtable) {
5109     // If adding the key expanded the dictionary (i.e., Add returned a new
5110     // dictionary), store it back to the object.
5111     SetHiddenPropertiesHashTable(object, new_table);
5112   }
5113
5114   // Return this to mark success.
5115   return object;
5116 }
5117
5118
5119 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
5120   Isolate* isolate = object->GetIsolate();
5121   ASSERT(key->IsUniqueName());
5122
5123   if (object->IsJSGlobalProxy()) {
5124     Handle<Object> proto(object->GetPrototype(), isolate);
5125     if (proto->IsNull()) return;
5126     ASSERT(proto->IsJSGlobalObject());
5127     return DeleteHiddenProperty(Handle<JSObject>::cast(proto), key);
5128   }
5129
5130   Object* inline_value = object->GetHiddenPropertiesHashTable();
5131
5132   // We never delete (inline-stored) identity hashes.
5133   ASSERT(*key != *isolate->factory()->identity_hash_string());
5134   if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
5135
5136   Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
5137   bool was_present = false;
5138   ObjectHashTable::Remove(hashtable, key, &was_present);
5139 }
5140
5141
5142 bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
5143   Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
5144   LookupIterator it(object, hidden, LookupIterator::CHECK_OWN_REAL);
5145   return GetPropertyAttributes(&it) != ABSENT;
5146 }
5147
5148
5149 Object* JSObject::GetHiddenPropertiesHashTable() {
5150   ASSERT(!IsJSGlobalProxy());
5151   if (HasFastProperties()) {
5152     // If the object has fast properties, check whether the first slot
5153     // in the descriptor array matches the hidden string. Since the
5154     // hidden strings hash code is zero (and no other name has hash
5155     // code zero) it will always occupy the first entry if present.
5156     DescriptorArray* descriptors = this->map()->instance_descriptors();
5157     if (descriptors->number_of_descriptors() > 0) {
5158       int sorted_index = descriptors->GetSortedKeyIndex(0);
5159       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
5160           sorted_index < map()->NumberOfOwnDescriptors()) {
5161         ASSERT(descriptors->GetType(sorted_index) == FIELD);
5162         ASSERT(descriptors->GetDetails(sorted_index).representation().
5163                IsCompatibleForLoad(Representation::Tagged()));
5164         FieldIndex index = FieldIndex::ForDescriptor(this->map(),
5165                                                      sorted_index);
5166         return this->RawFastPropertyAt(index);
5167       } else {
5168         return GetHeap()->undefined_value();
5169       }
5170     } else {
5171       return GetHeap()->undefined_value();
5172     }
5173   } else {
5174     Isolate* isolate = GetIsolate();
5175     LookupResult result(isolate);
5176     LookupOwnRealNamedProperty(isolate->factory()->hidden_string(), &result);
5177     if (result.IsFound()) {
5178       ASSERT(result.IsNormal());
5179       ASSERT(result.holder() == this);
5180       Object* value = GetNormalizedProperty(&result);
5181       if (!value->IsTheHole()) return value;
5182     }
5183     return GetHeap()->undefined_value();
5184   }
5185 }
5186
5187 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
5188     Handle<JSObject> object) {
5189   Isolate* isolate = object->GetIsolate();
5190
5191   static const int kInitialCapacity = 4;
5192   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5193   if (inline_value->IsHashTable()) {
5194     return Handle<ObjectHashTable>::cast(inline_value);
5195   }
5196
5197   Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
5198       isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
5199
5200   if (inline_value->IsSmi()) {
5201     // We were storing the identity hash inline and now allocated an actual
5202     // dictionary.  Put the identity hash into the new dictionary.
5203     hashtable = ObjectHashTable::Put(hashtable,
5204                                      isolate->factory()->identity_hash_string(),
5205                                      inline_value);
5206   }
5207
5208   JSObject::SetOwnPropertyIgnoreAttributes(
5209       object,
5210       isolate->factory()->hidden_string(),
5211       hashtable,
5212       DONT_ENUM,
5213       OPTIMAL_REPRESENTATION,
5214       ALLOW_AS_CONSTANT,
5215       OMIT_EXTENSIBILITY_CHECK).Assert();
5216
5217   return hashtable;
5218 }
5219
5220
5221 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
5222                                                       Handle<Object> value) {
5223   ASSERT(!object->IsJSGlobalProxy());
5224
5225   Isolate* isolate = object->GetIsolate();
5226
5227   // We can store the identity hash inline iff there is no backing store
5228   // for hidden properties yet.
5229   ASSERT(JSObject::HasHiddenProperties(object) != value->IsSmi());
5230   if (object->HasFastProperties()) {
5231     // If the object has fast properties, check whether the first slot
5232     // in the descriptor array matches the hidden string. Since the
5233     // hidden strings hash code is zero (and no other name has hash
5234     // code zero) it will always occupy the first entry if present.
5235     DescriptorArray* descriptors = object->map()->instance_descriptors();
5236     if (descriptors->number_of_descriptors() > 0) {
5237       int sorted_index = descriptors->GetSortedKeyIndex(0);
5238       if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string()
5239           && sorted_index < object->map()->NumberOfOwnDescriptors()) {
5240         object->WriteToField(sorted_index, *value);
5241         return object;
5242       }
5243     }
5244   }
5245
5246   SetOwnPropertyIgnoreAttributes(object,
5247                                  isolate->factory()->hidden_string(),
5248                                  value,
5249                                  DONT_ENUM,
5250                                  OPTIMAL_REPRESENTATION,
5251                                  ALLOW_AS_CONSTANT,
5252                                  OMIT_EXTENSIBILITY_CHECK).Assert();
5253   return object;
5254 }
5255
5256
5257 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object,
5258                                                        Handle<Name> name,
5259                                                        DeleteMode mode) {
5260   // Check own property, ignore interceptor.
5261   Isolate* isolate = object->GetIsolate();
5262   LookupResult result(isolate);
5263   object->LookupOwnRealNamedProperty(name, &result);
5264   if (!result.IsFound()) return isolate->factory()->true_value();
5265
5266   // Normalize object if needed.
5267   NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5268
5269   return DeleteNormalizedProperty(object, name, mode);
5270 }
5271
5272
5273 MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
5274     Handle<JSObject> object, Handle<Name> name) {
5275   Isolate* isolate = object->GetIsolate();
5276
5277   // TODO(rossberg): Support symbols in the API.
5278   if (name->IsSymbol()) return isolate->factory()->false_value();
5279
5280   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
5281   if (!interceptor->deleter()->IsUndefined()) {
5282     v8::NamedPropertyDeleterCallback deleter =
5283         v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter());
5284     LOG(isolate,
5285         ApiNamedPropertyAccess("interceptor-named-delete", *object, *name));
5286     PropertyCallbackArguments args(
5287         isolate, interceptor->data(), *object, *object);
5288     v8::Handle<v8::Boolean> result =
5289         args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name)));
5290     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5291     if (!result.IsEmpty()) {
5292       ASSERT(result->IsBoolean());
5293       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5294       result_internal->VerifyApiCallResultType();
5295       // Rebox CustomArguments::kReturnValueOffset before returning.
5296       return handle(*result_internal, isolate);
5297     }
5298   }
5299   Handle<Object> result =
5300       DeletePropertyPostInterceptor(object, name, NORMAL_DELETION);
5301   return result;
5302 }
5303
5304
5305 MaybeHandle<Object> JSObject::DeleteElementWithInterceptor(
5306     Handle<JSObject> object,
5307     uint32_t index) {
5308   Isolate* isolate = object->GetIsolate();
5309   Factory* factory = isolate->factory();
5310
5311   // Make sure that the top context does not change when doing
5312   // callbacks or interceptor calls.
5313   AssertNoContextChange ncc(isolate);
5314
5315   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
5316   if (interceptor->deleter()->IsUndefined()) return factory->false_value();
5317   v8::IndexedPropertyDeleterCallback deleter =
5318       v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
5319   LOG(isolate,
5320       ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index));
5321   PropertyCallbackArguments args(
5322       isolate, interceptor->data(), *object, *object);
5323   v8::Handle<v8::Boolean> result = args.Call(deleter, index);
5324   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5325   if (!result.IsEmpty()) {
5326     ASSERT(result->IsBoolean());
5327     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5328     result_internal->VerifyApiCallResultType();
5329     // Rebox CustomArguments::kReturnValueOffset before returning.
5330     return handle(*result_internal, isolate);
5331   }
5332   MaybeHandle<Object> delete_result = object->GetElementsAccessor()->Delete(
5333       object, index, NORMAL_DELETION);
5334   return delete_result;
5335 }
5336
5337
5338 MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
5339                                             uint32_t index,
5340                                             DeleteMode mode) {
5341   Isolate* isolate = object->GetIsolate();
5342   Factory* factory = isolate->factory();
5343
5344   // Check access rights if needed.
5345   if (object->IsAccessCheckNeeded() &&
5346       !isolate->MayIndexedAccess(object, index, v8::ACCESS_DELETE)) {
5347     isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
5348     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5349     return factory->false_value();
5350   }
5351
5352   if (object->IsStringObjectWithCharacterAt(index)) {
5353     if (mode == STRICT_DELETION) {
5354       // Deleting a non-configurable property in strict mode.
5355       Handle<Object> name = factory->NewNumberFromUint(index);
5356       Handle<Object> args[2] = { name, object };
5357       Handle<Object> error =
5358           factory->NewTypeError("strict_delete_property",
5359                                 HandleVector(args, 2));
5360       isolate->Throw(*error);
5361       return Handle<Object>();
5362     }
5363     return factory->false_value();
5364   }
5365
5366   if (object->IsJSGlobalProxy()) {
5367     Handle<Object> proto(object->GetPrototype(), isolate);
5368     if (proto->IsNull()) return factory->false_value();
5369     ASSERT(proto->IsJSGlobalObject());
5370     return DeleteElement(Handle<JSObject>::cast(proto), index, mode);
5371   }
5372
5373   Handle<Object> old_value;
5374   bool should_enqueue_change_record = false;
5375   if (object->map()->is_observed()) {
5376     should_enqueue_change_record = HasOwnElement(object, index);
5377     if (should_enqueue_change_record) {
5378       if (!GetOwnElementAccessorPair(object, index).is_null()) {
5379         old_value = Handle<Object>::cast(factory->the_hole_value());
5380       } else {
5381         old_value = Object::GetElement(
5382             isolate, object, index).ToHandleChecked();
5383       }
5384     }
5385   }
5386
5387   // Skip interceptor if forcing deletion.
5388   MaybeHandle<Object> maybe_result;
5389   if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) {
5390     maybe_result = DeleteElementWithInterceptor(object, index);
5391   } else {
5392     maybe_result = object->GetElementsAccessor()->Delete(object, index, mode);
5393   }
5394   Handle<Object> result;
5395   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
5396
5397   if (should_enqueue_change_record && !HasOwnElement(object, index)) {
5398     Handle<String> name = factory->Uint32ToString(index);
5399     EnqueueChangeRecord(object, "delete", name, old_value);
5400   }
5401
5402   return result;
5403 }
5404
5405
5406 MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
5407                                              Handle<Name> name,
5408                                              DeleteMode mode) {
5409   Isolate* isolate = object->GetIsolate();
5410   // ECMA-262, 3rd, 8.6.2.5
5411   ASSERT(name->IsName());
5412
5413   // Check access rights if needed.
5414   if (object->IsAccessCheckNeeded() &&
5415       !isolate->MayNamedAccess(object, name, v8::ACCESS_DELETE)) {
5416     isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
5417     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5418     return isolate->factory()->false_value();
5419   }
5420
5421   if (object->IsJSGlobalProxy()) {
5422     Object* proto = object->GetPrototype();
5423     if (proto->IsNull()) return isolate->factory()->false_value();
5424     ASSERT(proto->IsJSGlobalObject());
5425     return JSGlobalObject::DeleteProperty(
5426         handle(JSGlobalObject::cast(proto)), name, mode);
5427   }
5428
5429   uint32_t index = 0;
5430   if (name->AsArrayIndex(&index)) {
5431     return DeleteElement(object, index, mode);
5432   }
5433
5434   LookupResult lookup(isolate);
5435   object->LookupOwn(name, &lookup, true);
5436   if (!lookup.IsFound()) return isolate->factory()->true_value();
5437   // Ignore attributes if forcing a deletion.
5438   if (lookup.IsDontDelete() && mode != FORCE_DELETION) {
5439     if (mode == STRICT_DELETION) {
5440       // Deleting a non-configurable property in strict mode.
5441       Handle<Object> args[2] = { name, object };
5442       Handle<Object> error = isolate->factory()->NewTypeError(
5443           "strict_delete_property", HandleVector(args, ARRAY_SIZE(args)));
5444       isolate->Throw(*error);
5445       return Handle<Object>();
5446     }
5447     return isolate->factory()->false_value();
5448   }
5449
5450   Handle<Object> old_value = isolate->factory()->the_hole_value();
5451   bool is_observed = object->map()->is_observed() &&
5452                      *name != isolate->heap()->hidden_string();
5453   if (is_observed && lookup.IsDataProperty()) {
5454     old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked();
5455   }
5456   Handle<Object> result;
5457
5458   // Check for interceptor.
5459   if (lookup.IsInterceptor()) {
5460     // Skip interceptor if forcing a deletion.
5461     if (mode == FORCE_DELETION) {
5462       result = DeletePropertyPostInterceptor(object, name, mode);
5463     } else {
5464       ASSIGN_RETURN_ON_EXCEPTION(
5465           isolate, result,
5466           DeletePropertyWithInterceptor(object, name),
5467           Object);
5468     }
5469   } else {
5470     // Normalize object if needed.
5471     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5472     // Make sure the properties are normalized before removing the entry.
5473     result = DeleteNormalizedProperty(object, name, mode);
5474   }
5475
5476   if (is_observed && !HasOwnProperty(object, name)) {
5477     EnqueueChangeRecord(object, "delete", name, old_value);
5478   }
5479
5480   return result;
5481 }
5482
5483
5484 MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
5485                                               uint32_t index,
5486                                               DeleteMode mode) {
5487   if (object->IsJSProxy()) {
5488     return JSProxy::DeleteElementWithHandler(
5489         Handle<JSProxy>::cast(object), index, mode);
5490   }
5491   return JSObject::DeleteElement(Handle<JSObject>::cast(object), index, mode);
5492 }
5493
5494
5495 MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
5496                                                Handle<Name> name,
5497                                                DeleteMode mode) {
5498   if (object->IsJSProxy()) {
5499     return JSProxy::DeletePropertyWithHandler(
5500         Handle<JSProxy>::cast(object), name, mode);
5501   }
5502   return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, mode);
5503 }
5504
5505
5506 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
5507                                             ElementsKind kind,
5508                                             Object* object) {
5509   ASSERT(IsFastObjectElementsKind(kind) ||
5510          kind == DICTIONARY_ELEMENTS);
5511   if (IsFastObjectElementsKind(kind)) {
5512     int length = IsJSArray()
5513         ? Smi::cast(JSArray::cast(this)->length())->value()
5514         : elements->length();
5515     for (int i = 0; i < length; ++i) {
5516       Object* element = elements->get(i);
5517       if (!element->IsTheHole() && element == object) return true;
5518     }
5519   } else {
5520     Object* key =
5521         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5522     if (!key->IsUndefined()) return true;
5523   }
5524   return false;
5525 }
5526
5527
5528 // Check whether this object references another object.
5529 bool JSObject::ReferencesObject(Object* obj) {
5530   Map* map_of_this = map();
5531   Heap* heap = GetHeap();
5532   DisallowHeapAllocation no_allocation;
5533
5534   // Is the object the constructor for this object?
5535   if (map_of_this->constructor() == obj) {
5536     return true;
5537   }
5538
5539   // Is the object the prototype for this object?
5540   if (map_of_this->prototype() == obj) {
5541     return true;
5542   }
5543
5544   // Check if the object is among the named properties.
5545   Object* key = SlowReverseLookup(obj);
5546   if (!key->IsUndefined()) {
5547     return true;
5548   }
5549
5550   // Check if the object is among the indexed properties.
5551   ElementsKind kind = GetElementsKind();
5552   switch (kind) {
5553     // Raw pixels and external arrays do not reference other
5554     // objects.
5555 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5556     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
5557     case TYPE##_ELEMENTS:                                                      \
5558       break;
5559
5560     TYPED_ARRAYS(TYPED_ARRAY_CASE)
5561 #undef TYPED_ARRAY_CASE
5562
5563     case FAST_DOUBLE_ELEMENTS:
5564     case FAST_HOLEY_DOUBLE_ELEMENTS:
5565       break;
5566     case FAST_SMI_ELEMENTS:
5567     case FAST_HOLEY_SMI_ELEMENTS:
5568       break;
5569     case FAST_ELEMENTS:
5570     case FAST_HOLEY_ELEMENTS:
5571     case DICTIONARY_ELEMENTS: {
5572       FixedArray* elements = FixedArray::cast(this->elements());
5573       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5574       break;
5575     }
5576     case SLOPPY_ARGUMENTS_ELEMENTS: {
5577       FixedArray* parameter_map = FixedArray::cast(elements());
5578       // Check the mapped parameters.
5579       int length = parameter_map->length();
5580       for (int i = 2; i < length; ++i) {
5581         Object* value = parameter_map->get(i);
5582         if (!value->IsTheHole() && value == obj) return true;
5583       }
5584       // Check the arguments.
5585       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5586       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5587           FAST_HOLEY_ELEMENTS;
5588       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5589       break;
5590     }
5591   }
5592
5593   // For functions check the context.
5594   if (IsJSFunction()) {
5595     // Get the constructor function for arguments array.
5596     JSObject* arguments_boilerplate =
5597         heap->isolate()->context()->native_context()->
5598             sloppy_arguments_boilerplate();
5599     JSFunction* arguments_function =
5600         JSFunction::cast(arguments_boilerplate->map()->constructor());
5601
5602     // Get the context and don't check if it is the native context.
5603     JSFunction* f = JSFunction::cast(this);
5604     Context* context = f->context();
5605     if (context->IsNativeContext()) {
5606       return false;
5607     }
5608
5609     // Check the non-special context slots.
5610     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5611       // Only check JS objects.
5612       if (context->get(i)->IsJSObject()) {
5613         JSObject* ctxobj = JSObject::cast(context->get(i));
5614         // If it is an arguments array check the content.
5615         if (ctxobj->map()->constructor() == arguments_function) {
5616           if (ctxobj->ReferencesObject(obj)) {
5617             return true;
5618           }
5619         } else if (ctxobj == obj) {
5620           return true;
5621         }
5622       }
5623     }
5624
5625     // Check the context extension (if any) if it can have references.
5626     if (context->has_extension() && !context->IsCatchContext()) {
5627       // With harmony scoping, a JSFunction may have a global context.
5628       // TODO(mvstanton): walk into the ScopeInfo.
5629       if (FLAG_harmony_scoping && context->IsGlobalContext()) {
5630         return false;
5631       }
5632
5633       return JSObject::cast(context->extension())->ReferencesObject(obj);
5634     }
5635   }
5636
5637   // No references to object.
5638   return false;
5639 }
5640
5641
5642 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5643   Isolate* isolate = object->GetIsolate();
5644
5645   if (!object->map()->is_extensible()) return object;
5646
5647   if (object->IsAccessCheckNeeded() &&
5648       !isolate->MayNamedAccess(
5649           object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5650     isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5651     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5652     return isolate->factory()->false_value();
5653   }
5654
5655   if (object->IsJSGlobalProxy()) {
5656     Handle<Object> proto(object->GetPrototype(), isolate);
5657     if (proto->IsNull()) return object;
5658     ASSERT(proto->IsJSGlobalObject());
5659     return PreventExtensions(Handle<JSObject>::cast(proto));
5660   }
5661
5662   // It's not possible to seal objects with external array elements
5663   if (object->HasExternalArrayElements() ||
5664       object->HasFixedTypedArrayElements()) {
5665     Handle<Object> error  =
5666         isolate->factory()->NewTypeError(
5667             "cant_prevent_ext_external_array_elements",
5668             HandleVector(&object, 1));
5669     return isolate->Throw<Object>(error);
5670   }
5671
5672   // If there are fast elements we normalize.
5673   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5674   ASSERT(object->HasDictionaryElements() ||
5675          object->HasDictionaryArgumentsElements());
5676
5677   // Make sure that we never go back to fast case.
5678   dictionary->set_requires_slow_elements();
5679
5680   // Do a map transition, other objects with this map may still
5681   // be extensible.
5682   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5683   Handle<Map> new_map = Map::Copy(handle(object->map()));
5684
5685   new_map->set_is_extensible(false);
5686   JSObject::MigrateToMap(object, new_map);
5687   ASSERT(!object->map()->is_extensible());
5688
5689   if (object->map()->is_observed()) {
5690     EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5691                         isolate->factory()->the_hole_value());
5692   }
5693   return object;
5694 }
5695
5696
5697 template<typename Dictionary>
5698 static void FreezeDictionary(Dictionary* dictionary) {
5699   int capacity = dictionary->Capacity();
5700   for (int i = 0; i < capacity; i++) {
5701     Object* k = dictionary->KeyAt(i);
5702     if (dictionary->IsKey(k)) {
5703       PropertyDetails details = dictionary->DetailsAt(i);
5704       int attrs = DONT_DELETE;
5705       // READ_ONLY is an invalid attribute for JS setters/getters.
5706       if (details.type() == CALLBACKS) {
5707         Object* v = dictionary->ValueAt(i);
5708         if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
5709         if (!v->IsAccessorPair()) attrs |= READ_ONLY;
5710       } else {
5711         attrs |= READ_ONLY;
5712       }
5713       details = details.CopyAddAttributes(
5714           static_cast<PropertyAttributes>(attrs));
5715       dictionary->DetailsAtPut(i, details);
5716     }
5717   }
5718 }
5719
5720
5721 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
5722   // Freezing sloppy arguments should be handled elsewhere.
5723   ASSERT(!object->HasSloppyArgumentsElements());
5724   ASSERT(!object->map()->is_observed());
5725
5726   if (object->map()->is_frozen()) return object;
5727
5728   Isolate* isolate = object->GetIsolate();
5729   if (object->IsAccessCheckNeeded() &&
5730       !isolate->MayNamedAccess(
5731           object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5732     isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5733     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5734     return isolate->factory()->false_value();
5735   }
5736
5737   if (object->IsJSGlobalProxy()) {
5738     Handle<Object> proto(object->GetPrototype(), isolate);
5739     if (proto->IsNull()) return object;
5740     ASSERT(proto->IsJSGlobalObject());
5741     return Freeze(Handle<JSObject>::cast(proto));
5742   }
5743
5744   // It's not possible to freeze objects with external array elements
5745   if (object->HasExternalArrayElements() ||
5746       object->HasFixedTypedArrayElements()) {
5747     Handle<Object> error  =
5748         isolate->factory()->NewTypeError(
5749             "cant_prevent_ext_external_array_elements",
5750             HandleVector(&object, 1));
5751     return isolate->Throw<Object>(error);
5752   }
5753
5754   Handle<SeededNumberDictionary> new_element_dictionary;
5755   if (!object->elements()->IsDictionary()) {
5756     int length = object->IsJSArray()
5757         ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5758         : object->elements()->length();
5759     if (length > 0) {
5760       int capacity = 0;
5761       int used = 0;
5762       object->GetElementsCapacityAndUsage(&capacity, &used);
5763       new_element_dictionary = SeededNumberDictionary::New(isolate, used);
5764
5765       // Move elements to a dictionary; avoid calling NormalizeElements to avoid
5766       // unnecessary transitions.
5767       new_element_dictionary = CopyFastElementsToDictionary(
5768           handle(object->elements()), length, new_element_dictionary);
5769     } else {
5770       // No existing elements, use a pre-allocated empty backing store
5771       new_element_dictionary =
5772           isolate->factory()->empty_slow_element_dictionary();
5773     }
5774   }
5775
5776   Handle<Map> old_map(object->map(), isolate);
5777   int transition_index = old_map->SearchTransition(
5778       isolate->heap()->frozen_symbol());
5779   if (transition_index != TransitionArray::kNotFound) {
5780     Handle<Map> transition_map(old_map->GetTransition(transition_index));
5781     ASSERT(transition_map->has_dictionary_elements());
5782     ASSERT(transition_map->is_frozen());
5783     ASSERT(!transition_map->is_extensible());
5784     JSObject::MigrateToMap(object, transition_map);
5785   } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5786     // Create a new descriptor array with fully-frozen properties
5787     Handle<Map> new_map = Map::CopyForFreeze(old_map);
5788     JSObject::MigrateToMap(object, new_map);
5789   } else {
5790     // Slow path: need to normalize properties for safety
5791     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5792
5793     // Create a new map, since other objects with this map may be extensible.
5794     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5795     Handle<Map> new_map = Map::Copy(handle(object->map()));
5796     new_map->freeze();
5797     new_map->set_is_extensible(false);
5798     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5799     JSObject::MigrateToMap(object, new_map);
5800
5801     // Freeze dictionary-mode properties
5802     FreezeDictionary(object->property_dictionary());
5803   }
5804
5805   ASSERT(object->map()->has_dictionary_elements());
5806   if (!new_element_dictionary.is_null()) {
5807     object->set_elements(*new_element_dictionary);
5808   }
5809
5810   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5811     SeededNumberDictionary* dictionary = object->element_dictionary();
5812     // Make sure we never go back to the fast case
5813     dictionary->set_requires_slow_elements();
5814     // Freeze all elements in the dictionary
5815     FreezeDictionary(dictionary);
5816   }
5817
5818   return object;
5819 }
5820
5821
5822 void JSObject::SetObserved(Handle<JSObject> object) {
5823   ASSERT(!object->IsJSGlobalProxy());
5824   ASSERT(!object->IsJSGlobalObject());
5825   Isolate* isolate = object->GetIsolate();
5826   Handle<Map> new_map;
5827   Handle<Map> old_map(object->map(), isolate);
5828   ASSERT(!old_map->is_observed());
5829   int transition_index = old_map->SearchTransition(
5830       isolate->heap()->observed_symbol());
5831   if (transition_index != TransitionArray::kNotFound) {
5832     new_map = handle(old_map->GetTransition(transition_index), isolate);
5833     ASSERT(new_map->is_observed());
5834   } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5835     new_map = Map::CopyForObserved(old_map);
5836   } else {
5837     new_map = Map::Copy(old_map);
5838     new_map->set_is_observed();
5839   }
5840   JSObject::MigrateToMap(object, new_map);
5841 }
5842
5843
5844 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
5845                                         Representation representation,
5846                                         FieldIndex index) {
5847   Isolate* isolate = object->GetIsolate();
5848   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
5849   return Object::NewStorageFor(isolate, raw_value, representation);
5850 }
5851
5852
5853 template<class ContextObject>
5854 class JSObjectWalkVisitor {
5855  public:
5856   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5857                       JSObject::DeepCopyHints hints)
5858     : site_context_(site_context),
5859       copying_(copying),
5860       hints_(hints) {}
5861
5862   MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
5863
5864  protected:
5865   MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
5866       Handle<JSObject> object,
5867       Handle<JSObject> value) {
5868     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5869     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
5870     site_context()->ExitScope(current_site, value);
5871     return copy_of_value;
5872   }
5873
5874   inline ContextObject* site_context() { return site_context_; }
5875   inline Isolate* isolate() { return site_context()->isolate(); }
5876
5877   inline bool copying() const { return copying_; }
5878
5879  private:
5880   ContextObject* site_context_;
5881   const bool copying_;
5882   const JSObject::DeepCopyHints hints_;
5883 };
5884
5885
5886 template <class ContextObject>
5887 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
5888     Handle<JSObject> object) {
5889   Isolate* isolate = this->isolate();
5890   bool copying = this->copying();
5891   bool shallow = hints_ == JSObject::kObjectIsShallowArray;
5892
5893   if (!shallow) {
5894     StackLimitCheck check(isolate);
5895
5896     if (check.HasOverflowed()) {
5897       isolate->StackOverflow();
5898       return MaybeHandle<JSObject>();
5899     }
5900   }
5901
5902   if (object->map()->is_deprecated()) {
5903     JSObject::MigrateInstance(object);
5904   }
5905
5906   Handle<JSObject> copy;
5907   if (copying) {
5908     Handle<AllocationSite> site_to_pass;
5909     if (site_context()->ShouldCreateMemento(object)) {
5910       site_to_pass = site_context()->current();
5911     }
5912     copy = isolate->factory()->CopyJSObjectWithAllocationSite(
5913         object, site_to_pass);
5914   } else {
5915     copy = object;
5916   }
5917
5918   ASSERT(copying || copy.is_identical_to(object));
5919
5920   ElementsKind kind = copy->GetElementsKind();
5921   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5922       FixedArray::cast(copy->elements())->map() ==
5923         isolate->heap()->fixed_cow_array_map()) {
5924     isolate->counters()->cow_arrays_created_runtime()->Increment();
5925   }
5926
5927   if (!shallow) {
5928     HandleScope scope(isolate);
5929
5930     // Deep copy own properties.
5931     if (copy->HasFastProperties()) {
5932       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5933       int limit = copy->map()->NumberOfOwnDescriptors();
5934       for (int i = 0; i < limit; i++) {
5935         PropertyDetails details = descriptors->GetDetails(i);
5936         if (details.type() != FIELD) continue;
5937         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
5938         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5939         if (value->IsJSObject()) {
5940           ASSIGN_RETURN_ON_EXCEPTION(
5941               isolate, value,
5942               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5943               JSObject);
5944         } else {
5945           Representation representation = details.representation();
5946           value = Object::NewStorageFor(isolate, value, representation);
5947         }
5948         if (copying) {
5949           copy->FastPropertyAtPut(index, *value);
5950         }
5951       }
5952     } else {
5953       Handle<FixedArray> names =
5954           isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
5955       copy->GetOwnPropertyNames(*names, 0);
5956       for (int i = 0; i < names->length(); i++) {
5957         ASSERT(names->get(i)->IsString());
5958         Handle<String> key_string(String::cast(names->get(i)));
5959         PropertyAttributes attributes =
5960             JSReceiver::GetOwnPropertyAttributes(copy, key_string);
5961         // Only deep copy fields from the object literal expression.
5962         // In particular, don't try to copy the length attribute of
5963         // an array.
5964         if (attributes != NONE) continue;
5965         Handle<Object> value =
5966             Object::GetProperty(copy, key_string).ToHandleChecked();
5967         if (value->IsJSObject()) {
5968           Handle<JSObject> result;
5969           ASSIGN_RETURN_ON_EXCEPTION(
5970               isolate, result,
5971               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5972               JSObject);
5973           if (copying) {
5974             // Creating object copy for literals. No strict mode needed.
5975             JSObject::SetProperty(
5976                 copy, key_string, result, NONE, SLOPPY).Assert();
5977           }
5978         }
5979       }
5980     }
5981
5982     // Deep copy own elements.
5983     // Pixel elements cannot be created using an object literal.
5984     ASSERT(!copy->HasExternalArrayElements());
5985     switch (kind) {
5986       case FAST_SMI_ELEMENTS:
5987       case FAST_ELEMENTS:
5988       case FAST_HOLEY_SMI_ELEMENTS:
5989       case FAST_HOLEY_ELEMENTS: {
5990         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5991         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5992 #ifdef DEBUG
5993           for (int i = 0; i < elements->length(); i++) {
5994             ASSERT(!elements->get(i)->IsJSObject());
5995           }
5996 #endif
5997         } else {
5998           for (int i = 0; i < elements->length(); i++) {
5999             Handle<Object> value(elements->get(i), isolate);
6000             ASSERT(value->IsSmi() ||
6001                    value->IsTheHole() ||
6002                    (IsFastObjectElementsKind(copy->GetElementsKind())));
6003             if (value->IsJSObject()) {
6004               Handle<JSObject> result;
6005               ASSIGN_RETURN_ON_EXCEPTION(
6006                   isolate, result,
6007                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
6008                   JSObject);
6009               if (copying) {
6010                 elements->set(i, *result);
6011               }
6012             }
6013           }
6014         }
6015         break;
6016       }
6017       case DICTIONARY_ELEMENTS: {
6018         Handle<SeededNumberDictionary> element_dictionary(
6019             copy->element_dictionary());
6020         int capacity = element_dictionary->Capacity();
6021         for (int i = 0; i < capacity; i++) {
6022           Object* k = element_dictionary->KeyAt(i);
6023           if (element_dictionary->IsKey(k)) {
6024             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
6025             if (value->IsJSObject()) {
6026               Handle<JSObject> result;
6027               ASSIGN_RETURN_ON_EXCEPTION(
6028                   isolate, result,
6029                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
6030                   JSObject);
6031               if (copying) {
6032                 element_dictionary->ValueAtPut(i, *result);
6033               }
6034             }
6035           }
6036         }
6037         break;
6038       }
6039       case SLOPPY_ARGUMENTS_ELEMENTS:
6040         UNIMPLEMENTED();
6041         break;
6042
6043
6044 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6045       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
6046       case TYPE##_ELEMENTS:                                                    \
6047
6048       TYPED_ARRAYS(TYPED_ARRAY_CASE)
6049 #undef TYPED_ARRAY_CASE
6050
6051       case FAST_DOUBLE_ELEMENTS:
6052       case FAST_HOLEY_DOUBLE_ELEMENTS:
6053         // No contained objects, nothing to do.
6054         break;
6055     }
6056   }
6057
6058   return copy;
6059 }
6060
6061
6062 MaybeHandle<JSObject> JSObject::DeepWalk(
6063     Handle<JSObject> object,
6064     AllocationSiteCreationContext* site_context) {
6065   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
6066                                                        kNoHints);
6067   MaybeHandle<JSObject> result = v.StructureWalk(object);
6068   Handle<JSObject> for_assert;
6069   ASSERT(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
6070   return result;
6071 }
6072
6073
6074 MaybeHandle<JSObject> JSObject::DeepCopy(
6075     Handle<JSObject> object,
6076     AllocationSiteUsageContext* site_context,
6077     DeepCopyHints hints) {
6078   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
6079   MaybeHandle<JSObject> copy = v.StructureWalk(object);
6080   Handle<JSObject> for_assert;
6081   ASSERT(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
6082   return copy;
6083 }
6084
6085
6086 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
6087                                          Handle<Name> key) {
6088   Isolate* isolate = object->GetIsolate();
6089   LookupResult lookup(isolate);
6090   {
6091     DisallowHeapAllocation no_allocation;
6092     object->LookupRealNamedProperty(key, &lookup);
6093   }
6094   Handle<Object> result = isolate->factory()->undefined_value();
6095   if (lookup.IsFound() && !lookup.IsTransition()) {
6096     switch (lookup.type()) {
6097       case NORMAL:
6098         result = GetNormalizedProperty(
6099             Handle<JSObject>(lookup.holder(), isolate), &lookup);
6100         break;
6101       case FIELD:
6102         result = FastPropertyAt(Handle<JSObject>(lookup.holder(), isolate),
6103                                 lookup.representation(),
6104                                 lookup.GetFieldIndex());
6105         break;
6106       case CONSTANT:
6107         result = Handle<Object>(lookup.GetConstant(), isolate);
6108         break;
6109       case CALLBACKS:
6110       case HANDLER:
6111       case INTERCEPTOR:
6112         break;
6113       case NONEXISTENT:
6114         UNREACHABLE();
6115     }
6116   }
6117   return result;
6118 }
6119
6120
6121 // Tests for the fast common case for property enumeration:
6122 // - This object and all prototypes has an enum cache (which means that
6123 //   it is no proxy, has no interceptors and needs no access checks).
6124 // - This object has no elements.
6125 // - No prototype has enumerable properties/elements.
6126 bool JSReceiver::IsSimpleEnum() {
6127   Heap* heap = GetHeap();
6128   for (Object* o = this;
6129        o != heap->null_value();
6130        o = JSObject::cast(o)->GetPrototype()) {
6131     if (!o->IsJSObject()) return false;
6132     JSObject* curr = JSObject::cast(o);
6133     int enum_length = curr->map()->EnumLength();
6134     if (enum_length == kInvalidEnumCacheSentinel) return false;
6135     if (curr->IsAccessCheckNeeded()) return false;
6136     ASSERT(!curr->HasNamedInterceptor());
6137     ASSERT(!curr->HasIndexedInterceptor());
6138     if (curr->NumberOfEnumElements() > 0) return false;
6139     if (curr != this && enum_length != 0) return false;
6140   }
6141   return true;
6142 }
6143
6144
6145 static bool FilterKey(Object* key, PropertyAttributes filter) {
6146   if ((filter & SYMBOLIC) && key->IsSymbol()) {
6147     return true;
6148   }
6149
6150   if ((filter & PRIVATE_SYMBOL) &&
6151       key->IsSymbol() && Symbol::cast(key)->is_private()) {
6152     return true;
6153   }
6154
6155   if ((filter & STRING) && !key->IsSymbol()) {
6156     return true;
6157   }
6158
6159   return false;
6160 }
6161
6162
6163 int Map::NumberOfDescribedProperties(DescriptorFlag which,
6164                                      PropertyAttributes filter) {
6165   int result = 0;
6166   DescriptorArray* descs = instance_descriptors();
6167   int limit = which == ALL_DESCRIPTORS
6168       ? descs->number_of_descriptors()
6169       : NumberOfOwnDescriptors();
6170   for (int i = 0; i < limit; i++) {
6171     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
6172         !FilterKey(descs->GetKey(i), filter)) {
6173       result++;
6174     }
6175   }
6176   return result;
6177 }
6178
6179
6180 int Map::NextFreePropertyIndex() {
6181   int max_index = -1;
6182   int number_of_own_descriptors = NumberOfOwnDescriptors();
6183   DescriptorArray* descs = instance_descriptors();
6184   for (int i = 0; i < number_of_own_descriptors; i++) {
6185     if (descs->GetType(i) == FIELD) {
6186       int current_index = descs->GetFieldIndex(i);
6187       if (current_index > max_index) max_index = current_index;
6188     }
6189   }
6190   return max_index + 1;
6191 }
6192
6193
6194 void JSReceiver::LookupOwn(
6195     Handle<Name> name, LookupResult* result, bool search_hidden_prototypes) {
6196   DisallowHeapAllocation no_gc;
6197   ASSERT(name->IsName());
6198
6199   if (IsJSGlobalProxy()) {
6200     Object* proto = GetPrototype();
6201     if (proto->IsNull()) return result->NotFound();
6202     ASSERT(proto->IsJSGlobalObject());
6203     return JSReceiver::cast(proto)->LookupOwn(
6204         name, result, search_hidden_prototypes);
6205   }
6206
6207   if (IsJSProxy()) {
6208     result->HandlerResult(JSProxy::cast(this));
6209     return;
6210   }
6211
6212   // Do not use inline caching if the object is a non-global object
6213   // that requires access checks.
6214   if (IsAccessCheckNeeded()) {
6215     result->DisallowCaching();
6216   }
6217
6218   JSObject* js_object = JSObject::cast(this);
6219
6220   // Check for lookup interceptor except when bootstrapping.
6221   if (js_object->HasNamedInterceptor() &&
6222       !GetIsolate()->bootstrapper()->IsActive()) {
6223     result->InterceptorResult(js_object);
6224     return;
6225   }
6226
6227   js_object->LookupOwnRealNamedProperty(name, result);
6228   if (result->IsFound() || !search_hidden_prototypes) return;
6229
6230   Object* proto = js_object->GetPrototype();
6231   if (!proto->IsJSReceiver()) return;
6232   JSReceiver* receiver = JSReceiver::cast(proto);
6233   if (receiver->map()->is_hidden_prototype()) {
6234     receiver->LookupOwn(name, result, search_hidden_prototypes);
6235   }
6236 }
6237
6238
6239 void JSReceiver::Lookup(Handle<Name> name, LookupResult* result) {
6240   DisallowHeapAllocation no_gc;
6241   // Ecma-262 3rd 8.6.2.4
6242   Handle<Object> null_value = GetIsolate()->factory()->null_value();
6243   for (Object* current = this;
6244        current != *null_value;
6245        current = JSObject::cast(current)->GetPrototype()) {
6246     JSReceiver::cast(current)->LookupOwn(name, result, false);
6247     if (result->IsFound()) return;
6248   }
6249   result->NotFound();
6250 }
6251
6252
6253 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
6254   int len = array->length();
6255   for (int i = 0; i < len; i++) {
6256     Object* e = array->get(i);
6257     if (!(e->IsString() || e->IsNumber())) return false;
6258   }
6259   return true;
6260 }
6261
6262
6263 static Handle<FixedArray> ReduceFixedArrayTo(
6264     Handle<FixedArray> array, int length) {
6265   ASSERT(array->length() >= length);
6266   if (array->length() == length) return array;
6267
6268   Handle<FixedArray> new_array =
6269       array->GetIsolate()->factory()->NewFixedArray(length);
6270   for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
6271   return new_array;
6272 }
6273
6274
6275 static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
6276                                               bool cache_result) {
6277   Isolate* isolate = object->GetIsolate();
6278   if (object->HasFastProperties()) {
6279     int own_property_count = object->map()->EnumLength();
6280     // If the enum length of the given map is set to kInvalidEnumCache, this
6281     // means that the map itself has never used the present enum cache. The
6282     // first step to using the cache is to set the enum length of the map by
6283     // counting the number of own descriptors that are not DONT_ENUM or
6284     // SYMBOLIC.
6285     if (own_property_count == kInvalidEnumCacheSentinel) {
6286       own_property_count = object->map()->NumberOfDescribedProperties(
6287           OWN_DESCRIPTORS, DONT_SHOW);
6288     } else {
6289       ASSERT(own_property_count == object->map()->NumberOfDescribedProperties(
6290           OWN_DESCRIPTORS, DONT_SHOW));
6291     }
6292
6293     if (object->map()->instance_descriptors()->HasEnumCache()) {
6294       DescriptorArray* desc = object->map()->instance_descriptors();
6295       Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
6296
6297       // In case the number of properties required in the enum are actually
6298       // present, we can reuse the enum cache. Otherwise, this means that the
6299       // enum cache was generated for a previous (smaller) version of the
6300       // Descriptor Array. In that case we regenerate the enum cache.
6301       if (own_property_count <= keys->length()) {
6302         if (cache_result) object->map()->SetEnumLength(own_property_count);
6303         isolate->counters()->enum_cache_hits()->Increment();
6304         return ReduceFixedArrayTo(keys, own_property_count);
6305       }
6306     }
6307
6308     Handle<Map> map(object->map());
6309
6310     if (map->instance_descriptors()->IsEmpty()) {
6311       isolate->counters()->enum_cache_hits()->Increment();
6312       if (cache_result) map->SetEnumLength(0);
6313       return isolate->factory()->empty_fixed_array();
6314     }
6315
6316     isolate->counters()->enum_cache_misses()->Increment();
6317
6318     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
6319         own_property_count);
6320     Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
6321         own_property_count);
6322
6323     Handle<DescriptorArray> descs =
6324         Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
6325
6326     int size = map->NumberOfOwnDescriptors();
6327     int index = 0;
6328
6329     for (int i = 0; i < size; i++) {
6330       PropertyDetails details = descs->GetDetails(i);
6331       Object* key = descs->GetKey(i);
6332       if (!(details.IsDontEnum() || key->IsSymbol())) {
6333         storage->set(index, key);
6334         if (!indices.is_null()) {
6335           if (details.type() != FIELD) {
6336             indices = Handle<FixedArray>();
6337           } else {
6338             FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
6339             int load_by_field_index = field_index.GetLoadByFieldIndex();
6340             indices->set(index, Smi::FromInt(load_by_field_index));
6341           }
6342         }
6343         index++;
6344       }
6345     }
6346     ASSERT(index == storage->length());
6347
6348     Handle<FixedArray> bridge_storage =
6349         isolate->factory()->NewFixedArray(
6350             DescriptorArray::kEnumCacheBridgeLength);
6351     DescriptorArray* desc = object->map()->instance_descriptors();
6352     desc->SetEnumCache(*bridge_storage,
6353                        *storage,
6354                        indices.is_null() ? Object::cast(Smi::FromInt(0))
6355                                          : Object::cast(*indices));
6356     if (cache_result) {
6357       object->map()->SetEnumLength(own_property_count);
6358     }
6359     return storage;
6360   } else {
6361     Handle<NameDictionary> dictionary(object->property_dictionary());
6362     int length = dictionary->NumberOfEnumElements();
6363     if (length == 0) {
6364       return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6365     }
6366     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6367     dictionary->CopyEnumKeysTo(*storage);
6368     return storage;
6369   }
6370 }
6371
6372
6373 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6374                                             KeyCollectionType type) {
6375   USE(ContainsOnlyValidKeys);
6376   Isolate* isolate = object->GetIsolate();
6377   Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
6378   Handle<JSObject> arguments_boilerplate = Handle<JSObject>(
6379       isolate->context()->native_context()->sloppy_arguments_boilerplate(),
6380       isolate);
6381   Handle<JSFunction> arguments_function = Handle<JSFunction>(
6382       JSFunction::cast(arguments_boilerplate->map()->constructor()),
6383       isolate);
6384
6385   // Only collect keys if access is permitted.
6386   for (Handle<Object> p = object;
6387        *p != isolate->heap()->null_value();
6388        p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
6389     if (p->IsJSProxy()) {
6390       Handle<JSProxy> proxy(JSProxy::cast(*p), isolate);
6391       Handle<Object> args[] = { proxy };
6392       Handle<Object> names;
6393       ASSIGN_RETURN_ON_EXCEPTION(
6394           isolate, names,
6395           Execution::Call(isolate,
6396                           isolate->proxy_enumerate(),
6397                           object,
6398                           ARRAY_SIZE(args),
6399                           args),
6400           FixedArray);
6401       ASSIGN_RETURN_ON_EXCEPTION(
6402           isolate, content,
6403           FixedArray::AddKeysFromArrayLike(
6404               content, Handle<JSObject>::cast(names)),
6405           FixedArray);
6406       break;
6407     }
6408
6409     Handle<JSObject> current(JSObject::cast(*p), isolate);
6410
6411     // Check access rights if required.
6412     if (current->IsAccessCheckNeeded() &&
6413         !isolate->MayNamedAccess(
6414             current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
6415       isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS);
6416       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6417       break;
6418     }
6419
6420     // Compute the element keys.
6421     Handle<FixedArray> element_keys =
6422         isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6423     current->GetEnumElementKeys(*element_keys);
6424     ASSIGN_RETURN_ON_EXCEPTION(
6425         isolate, content,
6426         FixedArray::UnionOfKeys(content, element_keys),
6427         FixedArray);
6428     ASSERT(ContainsOnlyValidKeys(content));
6429
6430     // Add the element keys from the interceptor.
6431     if (current->HasIndexedInterceptor()) {
6432       Handle<JSObject> result;
6433       if (JSObject::GetKeysForIndexedInterceptor(
6434               current, object).ToHandle(&result)) {
6435         ASSIGN_RETURN_ON_EXCEPTION(
6436             isolate, content,
6437             FixedArray::AddKeysFromArrayLike(content, result),
6438             FixedArray);
6439       }
6440       ASSERT(ContainsOnlyValidKeys(content));
6441     }
6442
6443     // We can cache the computed property keys if access checks are
6444     // not needed and no interceptors are involved.
6445     //
6446     // We do not use the cache if the object has elements and
6447     // therefore it does not make sense to cache the property names
6448     // for arguments objects.  Arguments objects will always have
6449     // elements.
6450     // Wrapped strings have elements, but don't have an elements
6451     // array or dictionary.  So the fast inline test for whether to
6452     // use the cache says yes, so we should not create a cache.
6453     bool cache_enum_keys =
6454         ((current->map()->constructor() != *arguments_function) &&
6455          !current->IsJSValue() &&
6456          !current->IsAccessCheckNeeded() &&
6457          !current->HasNamedInterceptor() &&
6458          !current->HasIndexedInterceptor());
6459     // Compute the property keys and cache them if possible.
6460     ASSIGN_RETURN_ON_EXCEPTION(
6461         isolate, content,
6462         FixedArray::UnionOfKeys(
6463             content, GetEnumPropertyKeys(current, cache_enum_keys)),
6464         FixedArray);
6465     ASSERT(ContainsOnlyValidKeys(content));
6466
6467     // Add the property keys from the interceptor.
6468     if (current->HasNamedInterceptor()) {
6469       Handle<JSObject> result;
6470       if (JSObject::GetKeysForNamedInterceptor(
6471               current, object).ToHandle(&result)) {
6472         ASSIGN_RETURN_ON_EXCEPTION(
6473             isolate, content,
6474             FixedArray::AddKeysFromArrayLike(content, result),
6475             FixedArray);
6476       }
6477       ASSERT(ContainsOnlyValidKeys(content));
6478     }
6479
6480     // If we only want own properties we bail out after the first
6481     // iteration.
6482     if (type == OWN_ONLY) break;
6483   }
6484   return content;
6485 }
6486
6487
6488 // Try to update an accessor in an elements dictionary. Return true if the
6489 // update succeeded, and false otherwise.
6490 static bool UpdateGetterSetterInDictionary(
6491     SeededNumberDictionary* dictionary,
6492     uint32_t index,
6493     Object* getter,
6494     Object* setter,
6495     PropertyAttributes attributes) {
6496   int entry = dictionary->FindEntry(index);
6497   if (entry != SeededNumberDictionary::kNotFound) {
6498     Object* result = dictionary->ValueAt(entry);
6499     PropertyDetails details = dictionary->DetailsAt(entry);
6500     if (details.type() == CALLBACKS && result->IsAccessorPair()) {
6501       ASSERT(!details.IsDontDelete());
6502       if (details.attributes() != attributes) {
6503         dictionary->DetailsAtPut(
6504             entry,
6505             PropertyDetails(attributes, CALLBACKS, index));
6506       }
6507       AccessorPair::cast(result)->SetComponents(getter, setter);
6508       return true;
6509     }
6510   }
6511   return false;
6512 }
6513
6514
6515 void JSObject::DefineElementAccessor(Handle<JSObject> object,
6516                                      uint32_t index,
6517                                      Handle<Object> getter,
6518                                      Handle<Object> setter,
6519                                      PropertyAttributes attributes,
6520                                      v8::AccessControl access_control) {
6521   switch (object->GetElementsKind()) {
6522     case FAST_SMI_ELEMENTS:
6523     case FAST_ELEMENTS:
6524     case FAST_DOUBLE_ELEMENTS:
6525     case FAST_HOLEY_SMI_ELEMENTS:
6526     case FAST_HOLEY_ELEMENTS:
6527     case FAST_HOLEY_DOUBLE_ELEMENTS:
6528       break;
6529
6530 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6531     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
6532     case TYPE##_ELEMENTS:                                                      \
6533
6534     TYPED_ARRAYS(TYPED_ARRAY_CASE)
6535 #undef TYPED_ARRAY_CASE
6536       // Ignore getters and setters on pixel and external array elements.
6537       return;
6538
6539     case DICTIONARY_ELEMENTS:
6540       if (UpdateGetterSetterInDictionary(object->element_dictionary(),
6541                                          index,
6542                                          *getter,
6543                                          *setter,
6544                                          attributes)) {
6545         return;
6546       }
6547       break;
6548     case SLOPPY_ARGUMENTS_ELEMENTS: {
6549       // Ascertain whether we have read-only properties or an existing
6550       // getter/setter pair in an arguments elements dictionary backing
6551       // store.
6552       FixedArray* parameter_map = FixedArray::cast(object->elements());
6553       uint32_t length = parameter_map->length();
6554       Object* probe =
6555           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
6556       if (probe == NULL || probe->IsTheHole()) {
6557         FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
6558         if (arguments->IsDictionary()) {
6559           SeededNumberDictionary* dictionary =
6560               SeededNumberDictionary::cast(arguments);
6561           if (UpdateGetterSetterInDictionary(dictionary,
6562                                              index,
6563                                              *getter,
6564                                              *setter,
6565                                              attributes)) {
6566             return;
6567           }
6568         }
6569       }
6570       break;
6571     }
6572   }
6573
6574   Isolate* isolate = object->GetIsolate();
6575   Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair();
6576   accessors->SetComponents(*getter, *setter);
6577   accessors->set_access_flags(access_control);
6578
6579   SetElementCallback(object, index, accessors, attributes);
6580 }
6581
6582
6583 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object,
6584                                                      Handle<Name> name) {
6585   Isolate* isolate = object->GetIsolate();
6586   LookupResult result(isolate);
6587   object->LookupOwnRealNamedProperty(name, &result);
6588   if (result.IsPropertyCallbacks()) {
6589     // Note that the result can actually have IsDontDelete() == true when we
6590     // e.g. have to fall back to the slow case while adding a setter after
6591     // successfully reusing a map transition for a getter. Nevertheless, this is
6592     // OK, because the assertion only holds for the whole addition of both
6593     // accessors, not for the addition of each part. See first comment in
6594     // DefinePropertyAccessor below.
6595     Object* obj = result.GetCallbackObject();
6596     if (obj->IsAccessorPair()) {
6597       return AccessorPair::Copy(handle(AccessorPair::cast(obj), isolate));
6598     }
6599   }
6600   return isolate->factory()->NewAccessorPair();
6601 }
6602
6603
6604 void JSObject::DefinePropertyAccessor(Handle<JSObject> object,
6605                                       Handle<Name> name,
6606                                       Handle<Object> getter,
6607                                       Handle<Object> setter,
6608                                       PropertyAttributes attributes,
6609                                       v8::AccessControl access_control) {
6610   // We could assert that the property is configurable here, but we would need
6611   // to do a lookup, which seems to be a bit of overkill.
6612   bool only_attribute_changes = getter->IsNull() && setter->IsNull();
6613   if (object->HasFastProperties() && !only_attribute_changes &&
6614       access_control == v8::DEFAULT &&
6615       (object->map()->NumberOfOwnDescriptors() <= kMaxNumberOfDescriptors)) {
6616     bool getterOk = getter->IsNull() ||
6617         DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes);
6618     bool setterOk = !getterOk || setter->IsNull() ||
6619         DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes);
6620     if (getterOk && setterOk) return;
6621   }
6622
6623   Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name);
6624   accessors->SetComponents(*getter, *setter);
6625   accessors->set_access_flags(access_control);
6626
6627   SetPropertyCallback(object, name, accessors, attributes);
6628 }
6629
6630
6631 bool Map::DictionaryElementsInPrototypeChainOnly() {
6632   Heap* heap = GetHeap();
6633
6634   if (IsDictionaryElementsKind(elements_kind())) {
6635     return false;
6636   }
6637
6638   for (Object* prototype = this->prototype();
6639        prototype != heap->null_value();
6640        prototype = prototype->GetPrototype(GetIsolate())) {
6641     if (prototype->IsJSProxy()) {
6642       // Be conservative, don't walk into proxies.
6643       return true;
6644     }
6645
6646     if (IsDictionaryElementsKind(
6647             JSObject::cast(prototype)->map()->elements_kind())) {
6648       return true;
6649     }
6650   }
6651
6652   return false;
6653 }
6654
6655
6656 void JSObject::SetElementCallback(Handle<JSObject> object,
6657                                   uint32_t index,
6658                                   Handle<Object> structure,
6659                                   PropertyAttributes attributes) {
6660   Heap* heap = object->GetHeap();
6661   PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6662
6663   // Normalize elements to make this operation simple.
6664   bool had_dictionary_elements = object->HasDictionaryElements();
6665   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
6666   ASSERT(object->HasDictionaryElements() ||
6667          object->HasDictionaryArgumentsElements());
6668   // Update the dictionary with the new CALLBACKS property.
6669   dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
6670                                            details);
6671   dictionary->set_requires_slow_elements();
6672
6673   // Update the dictionary backing store on the object.
6674   if (object->elements()->map() == heap->sloppy_arguments_elements_map()) {
6675     // Also delete any parameter alias.
6676     //
6677     // TODO(kmillikin): when deleting the last parameter alias we could
6678     // switch to a direct backing store without the parameter map.  This
6679     // would allow GC of the context.
6680     FixedArray* parameter_map = FixedArray::cast(object->elements());
6681     if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
6682       parameter_map->set(index + 2, heap->the_hole_value());
6683     }
6684     parameter_map->set(1, *dictionary);
6685   } else {
6686     object->set_elements(*dictionary);
6687
6688     if (!had_dictionary_elements) {
6689       // KeyedStoreICs (at least the non-generic ones) need a reset.
6690       heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
6691     }
6692   }
6693 }
6694
6695
6696 void JSObject::SetPropertyCallback(Handle<JSObject> object,
6697                                    Handle<Name> name,
6698                                    Handle<Object> structure,
6699                                    PropertyAttributes attributes) {
6700   // Normalize object to make this operation simple.
6701   NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
6702
6703   // For the global object allocate a new map to invalidate the global inline
6704   // caches which have a global property cell reference directly in the code.
6705   if (object->IsGlobalObject()) {
6706     Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
6707     ASSERT(new_map->is_dictionary_map());
6708     object->set_map(*new_map);
6709
6710     // When running crankshaft, changing the map is not enough. We
6711     // need to deoptimize all functions that rely on this global
6712     // object.
6713     Deoptimizer::DeoptimizeGlobalObject(*object);
6714   }
6715
6716   // Update the dictionary with the new CALLBACKS property.
6717   PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6718   SetNormalizedProperty(object, name, structure, details);
6719 }
6720
6721
6722 void JSObject::DefineAccessor(Handle<JSObject> object,
6723                               Handle<Name> name,
6724                               Handle<Object> getter,
6725                               Handle<Object> setter,
6726                               PropertyAttributes attributes,
6727                               v8::AccessControl access_control) {
6728   Isolate* isolate = object->GetIsolate();
6729   // Check access rights if needed.
6730   if (object->IsAccessCheckNeeded() &&
6731       !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6732     isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6733     // TODO(yangguo): Issue 3269, check for scheduled exception missing?
6734     return;
6735   }
6736
6737   if (object->IsJSGlobalProxy()) {
6738     Handle<Object> proto(object->GetPrototype(), isolate);
6739     if (proto->IsNull()) return;
6740     ASSERT(proto->IsJSGlobalObject());
6741     DefineAccessor(Handle<JSObject>::cast(proto),
6742                    name,
6743                    getter,
6744                    setter,
6745                    attributes,
6746                    access_control);
6747     return;
6748   }
6749
6750   // Make sure that the top context does not change when doing callbacks or
6751   // interceptor calls.
6752   AssertNoContextChange ncc(isolate);
6753
6754   // Try to flatten before operating on the string.
6755   if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6756
6757   uint32_t index = 0;
6758   bool is_element = name->AsArrayIndex(&index);
6759
6760   Handle<Object> old_value = isolate->factory()->the_hole_value();
6761   bool is_observed = object->map()->is_observed() &&
6762                      *name != isolate->heap()->hidden_string();
6763   bool preexists = false;
6764   if (is_observed) {
6765     if (is_element) {
6766       preexists = HasOwnElement(object, index);
6767       if (preexists && GetOwnElementAccessorPair(object, index).is_null()) {
6768         old_value =
6769             Object::GetElement(isolate, object, index).ToHandleChecked();
6770       }
6771     } else {
6772       LookupResult lookup(isolate);
6773       object->LookupOwn(name, &lookup, true);
6774       preexists = lookup.IsProperty();
6775       if (preexists && lookup.IsDataProperty()) {
6776         old_value =
6777             Object::GetPropertyOrElement(object, name).ToHandleChecked();
6778       }
6779     }
6780   }
6781
6782   if (is_element) {
6783     DefineElementAccessor(
6784         object, index, getter, setter, attributes, access_control);
6785   } else {
6786     DefinePropertyAccessor(
6787         object, name, getter, setter, attributes, access_control);
6788   }
6789
6790   if (is_observed) {
6791     const char* type = preexists ? "reconfigure" : "add";
6792     EnqueueChangeRecord(object, type, name, old_value);
6793   }
6794 }
6795
6796
6797 static bool TryAccessorTransition(Handle<JSObject> self,
6798                                   Handle<Map> transitioned_map,
6799                                   int target_descriptor,
6800                                   AccessorComponent component,
6801                                   Handle<Object> accessor,
6802                                   PropertyAttributes attributes) {
6803   DescriptorArray* descs = transitioned_map->instance_descriptors();
6804   PropertyDetails details = descs->GetDetails(target_descriptor);
6805
6806   // If the transition target was not callbacks, fall back to the slow case.
6807   if (details.type() != CALLBACKS) return false;
6808   Object* descriptor = descs->GetCallbacksObject(target_descriptor);
6809   if (!descriptor->IsAccessorPair()) return false;
6810
6811   Object* target_accessor = AccessorPair::cast(descriptor)->get(component);
6812   PropertyAttributes target_attributes = details.attributes();
6813
6814   // Reuse transition if adding same accessor with same attributes.
6815   if (target_accessor == *accessor && target_attributes == attributes) {
6816     JSObject::MigrateToMap(self, transitioned_map);
6817     return true;
6818   }
6819
6820   // If either not the same accessor, or not the same attributes, fall back to
6821   // the slow case.
6822   return false;
6823 }
6824
6825
6826 bool JSObject::DefineFastAccessor(Handle<JSObject> object,
6827                                   Handle<Name> name,
6828                                   AccessorComponent component,
6829                                   Handle<Object> accessor,
6830                                   PropertyAttributes attributes) {
6831   ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
6832   Isolate* isolate = object->GetIsolate();
6833   LookupResult result(isolate);
6834   object->LookupOwn(name, &result);
6835
6836   if (result.IsFound() && !result.IsPropertyCallbacks()) {
6837     return false;
6838   }
6839
6840   // Return success if the same accessor with the same attributes already exist.
6841   AccessorPair* source_accessors = NULL;
6842   if (result.IsPropertyCallbacks()) {
6843     Object* callback_value = result.GetCallbackObject();
6844     if (callback_value->IsAccessorPair()) {
6845       source_accessors = AccessorPair::cast(callback_value);
6846       Object* entry = source_accessors->get(component);
6847       if (entry == *accessor && result.GetAttributes() == attributes) {
6848         return true;
6849       }
6850     } else {
6851       return false;
6852     }
6853
6854     int descriptor_number = result.GetDescriptorIndex();
6855
6856     object->map()->LookupTransition(*object, *name, &result);
6857
6858     if (result.IsFound()) {
6859       Handle<Map> target(result.GetTransitionTarget());
6860       ASSERT(target->NumberOfOwnDescriptors() ==
6861              object->map()->NumberOfOwnDescriptors());
6862       // This works since descriptors are sorted in order of addition.
6863       ASSERT(object->map()->instance_descriptors()->
6864              GetKey(descriptor_number) == *name);
6865       return TryAccessorTransition(object, target, descriptor_number,
6866                                    component, accessor, attributes);
6867     }
6868   } else {
6869     // If not, lookup a transition.
6870     object->map()->LookupTransition(*object, *name, &result);
6871
6872     // If there is a transition, try to follow it.
6873     if (result.IsFound()) {
6874       Handle<Map> target(result.GetTransitionTarget());
6875       int descriptor_number = target->LastAdded();
6876       ASSERT(Name::Equals(name,
6877           handle(target->instance_descriptors()->GetKey(descriptor_number))));
6878       return TryAccessorTransition(object, target, descriptor_number,
6879                                    component, accessor, attributes);
6880     }
6881   }
6882
6883   // If there is no transition yet, add a transition to the a new accessor pair
6884   // containing the accessor.  Allocate a new pair if there were no source
6885   // accessors.  Otherwise, copy the pair and modify the accessor.
6886   Handle<AccessorPair> accessors = source_accessors != NULL
6887       ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
6888       : isolate->factory()->NewAccessorPair();
6889   accessors->set(component, *accessor);
6890
6891   CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
6892   Handle<Map> new_map = Map::CopyInsertDescriptor(
6893       handle(object->map()), &new_accessors_desc, INSERT_TRANSITION);
6894
6895   JSObject::MigrateToMap(object, new_map);
6896   return true;
6897 }
6898
6899
6900 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6901                                           Handle<AccessorInfo> info) {
6902   Isolate* isolate = object->GetIsolate();
6903   Factory* factory = isolate->factory();
6904   Handle<Name> name(Name::cast(info->name()));
6905
6906   // Check access rights if needed.
6907   if (object->IsAccessCheckNeeded() &&
6908       !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6909     isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6910     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6911     return factory->undefined_value();
6912   }
6913
6914   if (object->IsJSGlobalProxy()) {
6915     Handle<Object> proto(object->GetPrototype(), isolate);
6916     if (proto->IsNull()) return object;
6917     ASSERT(proto->IsJSGlobalObject());
6918     return SetAccessor(Handle<JSObject>::cast(proto), info);
6919   }
6920
6921   // Make sure that the top context does not change when doing callbacks or
6922   // interceptor calls.
6923   AssertNoContextChange ncc(isolate);
6924
6925   // Try to flatten before operating on the string.
6926   if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6927
6928   uint32_t index = 0;
6929   bool is_element = name->AsArrayIndex(&index);
6930
6931   if (is_element) {
6932     if (object->IsJSArray()) return factory->undefined_value();
6933
6934     // Accessors overwrite previous callbacks (cf. with getters/setters).
6935     switch (object->GetElementsKind()) {
6936       case FAST_SMI_ELEMENTS:
6937       case FAST_ELEMENTS:
6938       case FAST_DOUBLE_ELEMENTS:
6939       case FAST_HOLEY_SMI_ELEMENTS:
6940       case FAST_HOLEY_ELEMENTS:
6941       case FAST_HOLEY_DOUBLE_ELEMENTS:
6942         break;
6943
6944 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6945       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
6946       case TYPE##_ELEMENTS:                                                    \
6947
6948       TYPED_ARRAYS(TYPED_ARRAY_CASE)
6949 #undef TYPED_ARRAY_CASE
6950         // Ignore getters and setters on pixel and external array
6951         // elements.
6952         return factory->undefined_value();
6953
6954       case DICTIONARY_ELEMENTS:
6955         break;
6956       case SLOPPY_ARGUMENTS_ELEMENTS:
6957         UNIMPLEMENTED();
6958         break;
6959     }
6960
6961     SetElementCallback(object, index, info, info->property_attributes());
6962   } else {
6963     // Lookup the name.
6964     LookupResult result(isolate);
6965     object->LookupOwn(name, &result, true);
6966     // ES5 forbids turning a property into an accessor if it's not
6967     // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
6968     if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) {
6969       return factory->undefined_value();
6970     }
6971
6972     SetPropertyCallback(object, name, info, info->property_attributes());
6973   }
6974
6975   return object;
6976 }
6977
6978
6979 MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
6980                                           Handle<Name> name,
6981                                           AccessorComponent component) {
6982   Isolate* isolate = object->GetIsolate();
6983
6984   // Make sure that the top context does not change when doing callbacks or
6985   // interceptor calls.
6986   AssertNoContextChange ncc(isolate);
6987
6988   // Check access rights if needed.
6989   if (object->IsAccessCheckNeeded() &&
6990       !isolate->MayNamedAccess(object, name, v8::ACCESS_HAS)) {
6991     isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
6992     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6993     return isolate->factory()->undefined_value();
6994   }
6995
6996   // Make the lookup and include prototypes.
6997   uint32_t index = 0;
6998   if (name->AsArrayIndex(&index)) {
6999     for (Handle<Object> obj = object;
7000          !obj->IsNull();
7001          obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) {
7002       if (obj->IsJSObject() && JSObject::cast(*obj)->HasDictionaryElements()) {
7003         JSObject* js_object = JSObject::cast(*obj);
7004         SeededNumberDictionary* dictionary = js_object->element_dictionary();
7005         int entry = dictionary->FindEntry(index);
7006         if (entry != SeededNumberDictionary::kNotFound) {
7007           Object* element = dictionary->ValueAt(entry);
7008           if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
7009               element->IsAccessorPair()) {
7010             return handle(AccessorPair::cast(element)->GetComponent(component),
7011                           isolate);
7012           }
7013         }
7014       }
7015     }
7016   } else {
7017     for (Handle<Object> obj = object;
7018          !obj->IsNull();
7019          obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) {
7020       LookupResult result(isolate);
7021       JSReceiver::cast(*obj)->LookupOwn(name, &result);
7022       if (result.IsFound()) {
7023         if (result.IsReadOnly()) return isolate->factory()->undefined_value();
7024         if (result.IsPropertyCallbacks()) {
7025           Object* obj = result.GetCallbackObject();
7026           if (obj->IsAccessorPair()) {
7027             return handle(AccessorPair::cast(obj)->GetComponent(component),
7028                           isolate);
7029           }
7030         }
7031       }
7032     }
7033   }
7034   return isolate->factory()->undefined_value();
7035 }
7036
7037
7038 Object* JSObject::SlowReverseLookup(Object* value) {
7039   if (HasFastProperties()) {
7040     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
7041     DescriptorArray* descs = map()->instance_descriptors();
7042     for (int i = 0; i < number_of_own_descriptors; i++) {
7043       if (descs->GetType(i) == FIELD) {
7044         Object* property =
7045             RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i));
7046         if (descs->GetDetails(i).representation().IsDouble()) {
7047           ASSERT(property->IsHeapNumber());
7048           if (value->IsNumber() && property->Number() == value->Number()) {
7049             return descs->GetKey(i);
7050           }
7051         } else if (property == value) {
7052           return descs->GetKey(i);
7053         }
7054       } else if (descs->GetType(i) == CONSTANT) {
7055         if (descs->GetConstant(i) == value) {
7056           return descs->GetKey(i);
7057         }
7058       }
7059     }
7060     return GetHeap()->undefined_value();
7061   } else {
7062     return property_dictionary()->SlowReverseLookup(value);
7063   }
7064 }
7065
7066
7067 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
7068   Handle<Map> result = map->GetIsolate()->factory()->NewMap(
7069       map->instance_type(), instance_size);
7070   result->set_prototype(map->prototype());
7071   result->set_constructor(map->constructor());
7072   result->set_bit_field(map->bit_field());
7073   result->set_bit_field2(map->bit_field2());
7074   int new_bit_field3 = map->bit_field3();
7075   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
7076   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
7077   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
7078                                           kInvalidEnumCacheSentinel);
7079   new_bit_field3 = Deprecated::update(new_bit_field3, false);
7080   if (!map->is_dictionary_map()) {
7081     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
7082   }
7083   new_bit_field3 = ConstructionCount::update(new_bit_field3,
7084                                              JSFunction::kNoSlackTracking);
7085   result->set_bit_field3(new_bit_field3);
7086   return result;
7087 }
7088
7089
7090 Handle<Map> Map::Normalize(Handle<Map> fast_map,
7091                            PropertyNormalizationMode mode) {
7092   ASSERT(!fast_map->is_dictionary_map());
7093
7094   Isolate* isolate = fast_map->GetIsolate();
7095   Handle<NormalizedMapCache> cache(
7096       isolate->context()->native_context()->normalized_map_cache());
7097
7098   Handle<Map> new_map;
7099   if (cache->Get(fast_map, mode).ToHandle(&new_map)) {
7100 #ifdef VERIFY_HEAP
7101     if (FLAG_verify_heap) {
7102       new_map->SharedMapVerify();
7103     }
7104 #endif
7105 #ifdef ENABLE_SLOW_ASSERTS
7106     if (FLAG_enable_slow_asserts) {
7107       // The cached map should match newly created normalized map bit-by-bit,
7108       // except for the code cache, which can contain some ics which can be
7109       // applied to the shared map.
7110       Handle<Map> fresh = Map::CopyNormalized(
7111           fast_map, mode, SHARED_NORMALIZED_MAP);
7112
7113       ASSERT(memcmp(fresh->address(),
7114                     new_map->address(),
7115                     Map::kCodeCacheOffset) == 0);
7116       STATIC_ASSERT(Map::kDependentCodeOffset ==
7117                     Map::kCodeCacheOffset + kPointerSize);
7118       int offset = Map::kDependentCodeOffset + kPointerSize;
7119       ASSERT(memcmp(fresh->address() + offset,
7120                     new_map->address() + offset,
7121                     Map::kSize - offset) == 0);
7122     }
7123 #endif
7124   } else {
7125     new_map = Map::CopyNormalized(fast_map, mode, SHARED_NORMALIZED_MAP);
7126     cache->Set(fast_map, new_map);
7127     isolate->counters()->normalized_maps()->Increment();
7128   }
7129   fast_map->NotifyLeafMapLayoutChange();
7130   return new_map;
7131 }
7132
7133
7134 Handle<Map> Map::CopyNormalized(Handle<Map> map,
7135                                 PropertyNormalizationMode mode,
7136                                 NormalizedMapSharingMode sharing) {
7137   int new_instance_size = map->instance_size();
7138   if (mode == CLEAR_INOBJECT_PROPERTIES) {
7139     new_instance_size -= map->inobject_properties() * kPointerSize;
7140   }
7141
7142   Handle<Map> result = RawCopy(map, new_instance_size);
7143
7144   if (mode != CLEAR_INOBJECT_PROPERTIES) {
7145     result->set_inobject_properties(map->inobject_properties());
7146   }
7147
7148   result->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
7149   result->set_dictionary_map(true);
7150   result->set_migration_target(false);
7151
7152 #ifdef VERIFY_HEAP
7153   if (FLAG_verify_heap && result->is_shared()) {
7154     result->SharedMapVerify();
7155   }
7156 #endif
7157
7158   return result;
7159 }
7160
7161
7162 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
7163   Handle<Map> result = RawCopy(map, map->instance_size());
7164
7165   // Please note instance_type and instance_size are set when allocated.
7166   result->set_inobject_properties(map->inobject_properties());
7167   result->set_unused_property_fields(map->unused_property_fields());
7168
7169   result->set_pre_allocated_property_fields(
7170       map->pre_allocated_property_fields());
7171   result->set_is_shared(false);
7172   result->ClearCodeCache(map->GetHeap());
7173   map->NotifyLeafMapLayoutChange();
7174   return result;
7175 }
7176
7177
7178 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
7179                                  Handle<DescriptorArray> descriptors,
7180                                  Descriptor* descriptor) {
7181   // Sanity check. This path is only to be taken if the map owns its descriptor
7182   // array, implying that its NumberOfOwnDescriptors equals the number of
7183   // descriptors in the descriptor array.
7184   ASSERT(map->NumberOfOwnDescriptors() ==
7185          map->instance_descriptors()->number_of_descriptors());
7186
7187   Handle<Map> result = CopyDropDescriptors(map);
7188   Handle<Name> name = descriptor->GetKey();
7189   Handle<TransitionArray> transitions =
7190       TransitionArray::CopyInsert(map, name, result, SIMPLE_TRANSITION);
7191
7192   // Ensure there's space for the new descriptor in the shared descriptor array.
7193   if (descriptors->NumberOfSlackDescriptors() == 0) {
7194     int old_size = descriptors->number_of_descriptors();
7195     if (old_size == 0) {
7196       descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
7197     } else {
7198       EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2);
7199       descriptors = handle(map->instance_descriptors());
7200     }
7201   }
7202
7203   // Commit the state atomically.
7204   DisallowHeapAllocation no_gc;
7205
7206   descriptors->Append(descriptor);
7207   result->SetBackPointer(*map);
7208   result->InitializeDescriptors(*descriptors);
7209
7210   ASSERT(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
7211
7212   map->set_transitions(*transitions);
7213   map->set_owns_descriptors(false);
7214
7215   return result;
7216 }
7217
7218
7219 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
7220                                         Handle<DescriptorArray> descriptors,
7221                                         TransitionFlag flag,
7222                                         MaybeHandle<Name> maybe_name,
7223                                         SimpleTransitionFlag simple_flag) {
7224   ASSERT(descriptors->IsSortedNoDuplicates());
7225
7226   Handle<Map> result = CopyDropDescriptors(map);
7227   result->InitializeDescriptors(*descriptors);
7228
7229   if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) {
7230     Handle<Name> name;
7231     CHECK(maybe_name.ToHandle(&name));
7232     Handle<TransitionArray> transitions = TransitionArray::CopyInsert(
7233         map, name, result, simple_flag);
7234     map->set_transitions(*transitions);
7235     result->SetBackPointer(*map);
7236   } else {
7237     int length = descriptors->number_of_descriptors();
7238     for (int i = 0; i < length; i++) {
7239       descriptors->SetRepresentation(i, Representation::Tagged());
7240       if (descriptors->GetDetails(i).type() == FIELD) {
7241         descriptors->SetValue(i, HeapType::Any());
7242       }
7243     }
7244   }
7245
7246   return result;
7247 }
7248
7249
7250 // Since this method is used to rewrite an existing transition tree, it can
7251 // always insert transitions without checking.
7252 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map,
7253                                         int new_descriptor,
7254                                         Handle<DescriptorArray> descriptors) {
7255   ASSERT(descriptors->IsSortedNoDuplicates());
7256
7257   Handle<Map> result = CopyDropDescriptors(map);
7258
7259   result->InitializeDescriptors(*descriptors);
7260   result->SetNumberOfOwnDescriptors(new_descriptor + 1);
7261
7262   int unused_property_fields = map->unused_property_fields();
7263   if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
7264     unused_property_fields = map->unused_property_fields() - 1;
7265     if (unused_property_fields < 0) {
7266       unused_property_fields += JSObject::kFieldsAdded;
7267     }
7268   }
7269
7270   result->set_unused_property_fields(unused_property_fields);
7271   result->set_owns_descriptors(false);
7272
7273   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
7274   Handle<TransitionArray> transitions = TransitionArray::CopyInsert(
7275       map, name, result, SIMPLE_TRANSITION);
7276
7277   map->set_transitions(*transitions);
7278   result->SetBackPointer(*map);
7279
7280   return result;
7281 }
7282
7283
7284 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
7285                                     TransitionFlag flag) {
7286   if (flag == INSERT_TRANSITION) {
7287     ASSERT(!map->HasElementsTransition() ||
7288         ((map->elements_transition_map()->elements_kind() ==
7289           DICTIONARY_ELEMENTS ||
7290           IsExternalArrayElementsKind(
7291               map->elements_transition_map()->elements_kind())) &&
7292          (kind == DICTIONARY_ELEMENTS ||
7293           IsExternalArrayElementsKind(kind))));
7294     ASSERT(!IsFastElementsKind(kind) ||
7295            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
7296     ASSERT(kind != map->elements_kind());
7297   }
7298
7299   bool insert_transition =
7300       flag == INSERT_TRANSITION && !map->HasElementsTransition();
7301
7302   if (insert_transition && map->owns_descriptors()) {
7303     // In case the map owned its own descriptors, share the descriptors and
7304     // transfer ownership to the new map.
7305     Handle<Map> new_map = CopyDropDescriptors(map);
7306
7307     SetElementsTransitionMap(map, new_map);
7308
7309     new_map->set_elements_kind(kind);
7310     new_map->InitializeDescriptors(map->instance_descriptors());
7311     new_map->SetBackPointer(*map);
7312     map->set_owns_descriptors(false);
7313     return new_map;
7314   }
7315
7316   // In case the map did not own its own descriptors, a split is forced by
7317   // copying the map; creating a new descriptor array cell.
7318   // Create a new free-floating map only if we are not allowed to store it.
7319   Handle<Map> new_map = Copy(map);
7320
7321   new_map->set_elements_kind(kind);
7322
7323   if (insert_transition) {
7324     SetElementsTransitionMap(map, new_map);
7325     new_map->SetBackPointer(*map);
7326   }
7327
7328   return new_map;
7329 }
7330
7331
7332 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
7333   ASSERT(!map->is_observed());
7334
7335   Isolate* isolate = map->GetIsolate();
7336
7337   // In case the map owned its own descriptors, share the descriptors and
7338   // transfer ownership to the new map.
7339   Handle<Map> new_map;
7340   if (map->owns_descriptors()) {
7341     new_map = CopyDropDescriptors(map);
7342   } else {
7343     new_map = Copy(map);
7344   }
7345
7346   Handle<TransitionArray> transitions = TransitionArray::CopyInsert(
7347       map, isolate->factory()->observed_symbol(), new_map, FULL_TRANSITION);
7348
7349   map->set_transitions(*transitions);
7350
7351   new_map->set_is_observed();
7352
7353   if (map->owns_descriptors()) {
7354     new_map->InitializeDescriptors(map->instance_descriptors());
7355     map->set_owns_descriptors(false);
7356   }
7357
7358   new_map->SetBackPointer(*map);
7359   return new_map;
7360 }
7361
7362
7363 Handle<Map> Map::Copy(Handle<Map> map) {
7364   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7365   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
7366   Handle<DescriptorArray> new_descriptors =
7367       DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
7368   return CopyReplaceDescriptors(
7369       map, new_descriptors, OMIT_TRANSITION, MaybeHandle<Name>());
7370 }
7371
7372
7373 Handle<Map> Map::Create(Handle<JSFunction> constructor,
7374                         int extra_inobject_properties) {
7375   Handle<Map> copy = Copy(handle(constructor->initial_map()));
7376
7377   // Check that we do not overflow the instance size when adding the
7378   // extra inobject properties.
7379   int instance_size_delta = extra_inobject_properties * kPointerSize;
7380   int max_instance_size_delta =
7381       JSObject::kMaxInstanceSize - copy->instance_size();
7382   int max_extra_properties = max_instance_size_delta >> kPointerSizeLog2;
7383
7384   // If the instance size overflows, we allocate as many properties as we can as
7385   // inobject properties.
7386   if (extra_inobject_properties > max_extra_properties) {
7387     instance_size_delta = max_instance_size_delta;
7388     extra_inobject_properties = max_extra_properties;
7389   }
7390
7391   // Adjust the map with the extra inobject properties.
7392   int inobject_properties =
7393       copy->inobject_properties() + extra_inobject_properties;
7394   copy->set_inobject_properties(inobject_properties);
7395   copy->set_unused_property_fields(inobject_properties);
7396   copy->set_instance_size(copy->instance_size() + instance_size_delta);
7397   copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
7398   return copy;
7399 }
7400
7401
7402 Handle<Map> Map::CopyForFreeze(Handle<Map> map) {
7403   int num_descriptors = map->NumberOfOwnDescriptors();
7404   Isolate* isolate = map->GetIsolate();
7405   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
7406       handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN);
7407   Handle<Map> new_map = CopyReplaceDescriptors(
7408       map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol());
7409   new_map->freeze();
7410   new_map->set_is_extensible(false);
7411   new_map->set_elements_kind(DICTIONARY_ELEMENTS);
7412   return new_map;
7413 }
7414
7415
7416 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7417                                    Descriptor* descriptor,
7418                                    TransitionFlag flag) {
7419   Handle<DescriptorArray> descriptors(map->instance_descriptors());
7420
7421   // Ensure the key is unique.
7422   descriptor->KeyToUniqueName();
7423
7424   if (flag == INSERT_TRANSITION &&
7425       map->owns_descriptors() &&
7426       map->CanHaveMoreTransitions()) {
7427     return ShareDescriptor(map, descriptors, descriptor);
7428   }
7429
7430   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7431       descriptors, map->NumberOfOwnDescriptors(), 1);
7432   new_descriptors->Append(descriptor);
7433
7434   return CopyReplaceDescriptors(
7435       map, new_descriptors, flag, descriptor->GetKey(), SIMPLE_TRANSITION);
7436 }
7437
7438
7439 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
7440                                       Descriptor* descriptor,
7441                                       TransitionFlag flag) {
7442   Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
7443
7444   // Ensure the key is unique.
7445   descriptor->KeyToUniqueName();
7446
7447   // We replace the key if it is already present.
7448   int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
7449   if (index != DescriptorArray::kNotFound) {
7450     return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
7451   }
7452   return CopyAddDescriptor(map, descriptor, flag);
7453 }
7454
7455
7456 Handle<DescriptorArray> DescriptorArray::CopyUpTo(
7457     Handle<DescriptorArray> desc,
7458     int enumeration_index,
7459     int slack) {
7460   return DescriptorArray::CopyUpToAddAttributes(
7461       desc, enumeration_index, NONE, slack);
7462 }
7463
7464
7465 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
7466     Handle<DescriptorArray> desc,
7467     int enumeration_index,
7468     PropertyAttributes attributes,
7469     int slack) {
7470   if (enumeration_index + slack == 0) {
7471     return desc->GetIsolate()->factory()->empty_descriptor_array();
7472   }
7473
7474   int size = enumeration_index;
7475
7476   Handle<DescriptorArray> descriptors =
7477       DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
7478   DescriptorArray::WhitenessWitness witness(*descriptors);
7479
7480   if (attributes != NONE) {
7481     for (int i = 0; i < size; ++i) {
7482       Object* value = desc->GetValue(i);
7483       PropertyDetails details = desc->GetDetails(i);
7484       int mask = DONT_DELETE | DONT_ENUM;
7485       // READ_ONLY is an invalid attribute for JS setters/getters.
7486       if (details.type() != CALLBACKS || !value->IsAccessorPair()) {
7487         mask |= READ_ONLY;
7488       }
7489       details = details.CopyAddAttributes(
7490           static_cast<PropertyAttributes>(attributes & mask));
7491       Descriptor inner_desc(handle(desc->GetKey(i)),
7492                             handle(value, desc->GetIsolate()),
7493                             details);
7494       descriptors->Set(i, &inner_desc, witness);
7495     }
7496   } else {
7497     for (int i = 0; i < size; ++i) {
7498       descriptors->CopyFrom(i, *desc, witness);
7499     }
7500   }
7501
7502   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
7503
7504   return descriptors;
7505 }
7506
7507
7508 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
7509                                        Handle<DescriptorArray> descriptors,
7510                                        Descriptor* descriptor,
7511                                        int insertion_index,
7512                                        TransitionFlag flag) {
7513   // Ensure the key is unique.
7514   descriptor->KeyToUniqueName();
7515
7516   Handle<Name> key = descriptor->GetKey();
7517   ASSERT(*key == descriptors->GetKey(insertion_index));
7518
7519   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7520       descriptors, map->NumberOfOwnDescriptors());
7521
7522   new_descriptors->Replace(insertion_index, descriptor);
7523
7524   SimpleTransitionFlag simple_flag =
7525       (insertion_index == descriptors->number_of_descriptors() - 1)
7526       ? SIMPLE_TRANSITION
7527       : FULL_TRANSITION;
7528   return CopyReplaceDescriptors(map, new_descriptors, flag, key, simple_flag);
7529 }
7530
7531
7532 void Map::UpdateCodeCache(Handle<Map> map,
7533                           Handle<Name> name,
7534                           Handle<Code> code) {
7535   Isolate* isolate = map->GetIsolate();
7536   HandleScope scope(isolate);
7537   // Allocate the code cache if not present.
7538   if (map->code_cache()->IsFixedArray()) {
7539     Handle<Object> result = isolate->factory()->NewCodeCache();
7540     map->set_code_cache(*result);
7541   }
7542
7543   // Update the code cache.
7544   Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
7545   CodeCache::Update(code_cache, name, code);
7546 }
7547
7548
7549 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
7550   // Do a lookup if a code cache exists.
7551   if (!code_cache()->IsFixedArray()) {
7552     return CodeCache::cast(code_cache())->Lookup(name, flags);
7553   } else {
7554     return GetHeap()->undefined_value();
7555   }
7556 }
7557
7558
7559 int Map::IndexInCodeCache(Object* name, Code* code) {
7560   // Get the internal index if a code cache exists.
7561   if (!code_cache()->IsFixedArray()) {
7562     return CodeCache::cast(code_cache())->GetIndex(name, code);
7563   }
7564   return -1;
7565 }
7566
7567
7568 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7569   // No GC is supposed to happen between a call to IndexInCodeCache and
7570   // RemoveFromCodeCache so the code cache must be there.
7571   ASSERT(!code_cache()->IsFixedArray());
7572   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7573 }
7574
7575
7576 // An iterator over all map transitions in an descriptor array, reusing the
7577 // constructor field of the map while it is running. Negative values in
7578 // the constructor field indicate an active map transition iteration. The
7579 // original constructor is restored after iterating over all entries.
7580 class IntrusiveMapTransitionIterator {
7581  public:
7582   IntrusiveMapTransitionIterator(
7583       Map* map, TransitionArray* transition_array, Object* constructor)
7584       : map_(map),
7585         transition_array_(transition_array),
7586         constructor_(constructor) { }
7587
7588   void StartIfNotStarted() {
7589     ASSERT(!(*IteratorField())->IsSmi() || IsIterating());
7590     if (!(*IteratorField())->IsSmi()) {
7591       ASSERT(*IteratorField() == constructor_);
7592       *IteratorField() = Smi::FromInt(-1);
7593     }
7594   }
7595
7596   bool IsIterating() {
7597     return (*IteratorField())->IsSmi() &&
7598            Smi::cast(*IteratorField())->value() < 0;
7599   }
7600
7601   Map* Next() {
7602     ASSERT(IsIterating());
7603     int value = Smi::cast(*IteratorField())->value();
7604     int index = -value - 1;
7605     int number_of_transitions = transition_array_->number_of_transitions();
7606     while (index < number_of_transitions) {
7607       *IteratorField() = Smi::FromInt(value - 1);
7608       return transition_array_->GetTarget(index);
7609     }
7610
7611     *IteratorField() = constructor_;
7612     return NULL;
7613   }
7614
7615  private:
7616   Object** IteratorField() {
7617     return HeapObject::RawField(map_, Map::kConstructorOffset);
7618   }
7619
7620   Map* map_;
7621   TransitionArray* transition_array_;
7622   Object* constructor_;
7623 };
7624
7625
7626 // An iterator over all prototype transitions, reusing the constructor field
7627 // of the map while it is running.  Positive values in the constructor field
7628 // indicate an active prototype transition iteration. The original constructor
7629 // is restored after iterating over all entries.
7630 class IntrusivePrototypeTransitionIterator {
7631  public:
7632   IntrusivePrototypeTransitionIterator(
7633       Map* map, HeapObject* proto_trans, Object* constructor)
7634       : map_(map), proto_trans_(proto_trans), constructor_(constructor) { }
7635
7636   void StartIfNotStarted() {
7637     if (!(*IteratorField())->IsSmi()) {
7638       ASSERT(*IteratorField() == constructor_);
7639       *IteratorField() = Smi::FromInt(0);
7640     }
7641   }
7642
7643   bool IsIterating() {
7644     return (*IteratorField())->IsSmi() &&
7645            Smi::cast(*IteratorField())->value() >= 0;
7646   }
7647
7648   Map* Next() {
7649     ASSERT(IsIterating());
7650     int transitionNumber = Smi::cast(*IteratorField())->value();
7651     if (transitionNumber < NumberOfTransitions()) {
7652       *IteratorField() = Smi::FromInt(transitionNumber + 1);
7653       return GetTransition(transitionNumber);
7654     }
7655     *IteratorField() = constructor_;
7656     return NULL;
7657   }
7658
7659  private:
7660   Object** IteratorField() {
7661     return HeapObject::RawField(map_, Map::kConstructorOffset);
7662   }
7663
7664   int NumberOfTransitions() {
7665     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7666     Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
7667     return Smi::cast(num)->value();
7668   }
7669
7670   Map* GetTransition(int transitionNumber) {
7671     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7672     return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
7673   }
7674
7675   int IndexFor(int transitionNumber) {
7676     return Map::kProtoTransitionHeaderSize +
7677         Map::kProtoTransitionMapOffset +
7678         transitionNumber * Map::kProtoTransitionElementsPerEntry;
7679   }
7680
7681   Map* map_;
7682   HeapObject* proto_trans_;
7683   Object* constructor_;
7684 };
7685
7686
7687 // To traverse the transition tree iteratively, we have to store two kinds of
7688 // information in a map: The parent map in the traversal and which children of a
7689 // node have already been visited. To do this without additional memory, we
7690 // temporarily reuse two fields with known values:
7691 //
7692 //  (1) The map of the map temporarily holds the parent, and is restored to the
7693 //      meta map afterwards.
7694 //
7695 //  (2) The info which children have already been visited depends on which part
7696 //      of the map we currently iterate. We use the constructor field of the
7697 //      map to store the current index. We can do that because the constructor
7698 //      is the same for all involved maps.
7699 //
7700 //    (a) If we currently follow normal map transitions, we temporarily store
7701 //        the current index in the constructor field, and restore it to the
7702 //        original constructor afterwards. Note that a single descriptor can
7703 //        have 0, 1, or 2 transitions.
7704 //
7705 //    (b) If we currently follow prototype transitions, we temporarily store
7706 //        the current index in the constructor field, and restore it to the
7707 //        original constructor afterwards.
7708 //
7709 // Note that the child iterator is just a concatenation of two iterators: One
7710 // iterating over map transitions and one iterating over prototype transisitons.
7711 class TraversableMap : public Map {
7712  public:
7713   // Record the parent in the traversal within this map. Note that this destroys
7714   // this map's map!
7715   void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
7716
7717   // Reset the current map's map, returning the parent previously stored in it.
7718   TraversableMap* GetAndResetParent() {
7719     TraversableMap* old_parent = static_cast<TraversableMap*>(map());
7720     set_map_no_write_barrier(GetHeap()->meta_map());
7721     return old_parent;
7722   }
7723
7724   // If we have an unvisited child map, return that one and advance. If we have
7725   // none, return NULL and restore the overwritten constructor field.
7726   TraversableMap* ChildIteratorNext(Object* constructor) {
7727     if (!HasTransitionArray()) return NULL;
7728
7729     TransitionArray* transition_array = transitions();
7730     if (transition_array->HasPrototypeTransitions()) {
7731       HeapObject* proto_transitions =
7732           transition_array->GetPrototypeTransitions();
7733       IntrusivePrototypeTransitionIterator proto_iterator(this,
7734                                                           proto_transitions,
7735                                                           constructor);
7736       proto_iterator.StartIfNotStarted();
7737       if (proto_iterator.IsIterating()) {
7738         Map* next = proto_iterator.Next();
7739         if (next != NULL) return static_cast<TraversableMap*>(next);
7740       }
7741     }
7742
7743     IntrusiveMapTransitionIterator transition_iterator(this,
7744                                                        transition_array,
7745                                                        constructor);
7746     transition_iterator.StartIfNotStarted();
7747     if (transition_iterator.IsIterating()) {
7748       Map* next = transition_iterator.Next();
7749       if (next != NULL) return static_cast<TraversableMap*>(next);
7750     }
7751
7752     return NULL;
7753   }
7754 };
7755
7756
7757 // Traverse the transition tree in postorder without using the C++ stack by
7758 // doing pointer reversal.
7759 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
7760   // Make sure that we do not allocate in the callback.
7761   DisallowHeapAllocation no_allocation;
7762
7763   TraversableMap* current = static_cast<TraversableMap*>(this);
7764   // Get the root constructor here to restore it later when finished iterating
7765   // over maps.
7766   Object* root_constructor = constructor();
7767   while (true) {
7768     TraversableMap* child = current->ChildIteratorNext(root_constructor);
7769     if (child != NULL) {
7770       child->SetParent(current);
7771       current = child;
7772     } else {
7773       TraversableMap* parent = current->GetAndResetParent();
7774       callback(current, data);
7775       if (current == this) break;
7776       current = parent;
7777     }
7778   }
7779 }
7780
7781
7782 void CodeCache::Update(
7783     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7784   // The number of monomorphic stubs for normal load/store/call IC's can grow to
7785   // a large number and therefore they need to go into a hash table. They are
7786   // used to load global properties from cells.
7787   if (code->type() == Code::NORMAL) {
7788     // Make sure that a hash table is allocated for the normal load code cache.
7789     if (code_cache->normal_type_cache()->IsUndefined()) {
7790       Handle<Object> result =
7791           CodeCacheHashTable::New(code_cache->GetIsolate(),
7792                                   CodeCacheHashTable::kInitialSize);
7793       code_cache->set_normal_type_cache(*result);
7794     }
7795     UpdateNormalTypeCache(code_cache, name, code);
7796   } else {
7797     ASSERT(code_cache->default_cache()->IsFixedArray());
7798     UpdateDefaultCache(code_cache, name, code);
7799   }
7800 }
7801
7802
7803 void CodeCache::UpdateDefaultCache(
7804     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7805   // When updating the default code cache we disregard the type encoded in the
7806   // flags. This allows call constant stubs to overwrite call field
7807   // stubs, etc.
7808   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7809
7810   // First check whether we can update existing code cache without
7811   // extending it.
7812   Handle<FixedArray> cache = handle(code_cache->default_cache());
7813   int length = cache->length();
7814   {
7815     DisallowHeapAllocation no_alloc;
7816     int deleted_index = -1;
7817     for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7818       Object* key = cache->get(i);
7819       if (key->IsNull()) {
7820         if (deleted_index < 0) deleted_index = i;
7821         continue;
7822       }
7823       if (key->IsUndefined()) {
7824         if (deleted_index >= 0) i = deleted_index;
7825         cache->set(i + kCodeCacheEntryNameOffset, *name);
7826         cache->set(i + kCodeCacheEntryCodeOffset, *code);
7827         return;
7828       }
7829       if (name->Equals(Name::cast(key))) {
7830         Code::Flags found =
7831             Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7832         if (Code::RemoveTypeFromFlags(found) == flags) {
7833           cache->set(i + kCodeCacheEntryCodeOffset, *code);
7834           return;
7835         }
7836       }
7837     }
7838
7839     // Reached the end of the code cache.  If there were deleted
7840     // elements, reuse the space for the first of them.
7841     if (deleted_index >= 0) {
7842       cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
7843       cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
7844       return;
7845     }
7846   }
7847
7848   // Extend the code cache with some new entries (at least one). Must be a
7849   // multiple of the entry size.
7850   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7851   new_length = new_length - new_length % kCodeCacheEntrySize;
7852   ASSERT((new_length % kCodeCacheEntrySize) == 0);
7853   cache = FixedArray::CopySize(cache, new_length);
7854
7855   // Add the (name, code) pair to the new cache.
7856   cache->set(length + kCodeCacheEntryNameOffset, *name);
7857   cache->set(length + kCodeCacheEntryCodeOffset, *code);
7858   code_cache->set_default_cache(*cache);
7859 }
7860
7861
7862 void CodeCache::UpdateNormalTypeCache(
7863     Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7864   // Adding a new entry can cause a new cache to be allocated.
7865   Handle<CodeCacheHashTable> cache(
7866       CodeCacheHashTable::cast(code_cache->normal_type_cache()));
7867   Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
7868   code_cache->set_normal_type_cache(*new_cache);
7869 }
7870
7871
7872 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
7873   Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7874   if (result->IsCode()) {
7875     if (Code::cast(result)->flags() == flags) return result;
7876     return GetHeap()->undefined_value();
7877   }
7878   return LookupNormalTypeCache(name, flags);
7879 }
7880
7881
7882 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
7883   FixedArray* cache = default_cache();
7884   int length = cache->length();
7885   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7886     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7887     // Skip deleted elements.
7888     if (key->IsNull()) continue;
7889     if (key->IsUndefined()) return key;
7890     if (name->Equals(Name::cast(key))) {
7891       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
7892       if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
7893         return code;
7894       }
7895     }
7896   }
7897   return GetHeap()->undefined_value();
7898 }
7899
7900
7901 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
7902   if (!normal_type_cache()->IsUndefined()) {
7903     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7904     return cache->Lookup(name, flags);
7905   } else {
7906     return GetHeap()->undefined_value();
7907   }
7908 }
7909
7910
7911 int CodeCache::GetIndex(Object* name, Code* code) {
7912   if (code->type() == Code::NORMAL) {
7913     if (normal_type_cache()->IsUndefined()) return -1;
7914     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7915     return cache->GetIndex(Name::cast(name), code->flags());
7916   }
7917
7918   FixedArray* array = default_cache();
7919   int len = array->length();
7920   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
7921     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
7922   }
7923   return -1;
7924 }
7925
7926
7927 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
7928   if (code->type() == Code::NORMAL) {
7929     ASSERT(!normal_type_cache()->IsUndefined());
7930     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7931     ASSERT(cache->GetIndex(Name::cast(name), code->flags()) == index);
7932     cache->RemoveByIndex(index);
7933   } else {
7934     FixedArray* array = default_cache();
7935     ASSERT(array->length() >= index && array->get(index)->IsCode());
7936     // Use null instead of undefined for deleted elements to distinguish
7937     // deleted elements from unused elements.  This distinction is used
7938     // when looking up in the cache and when updating the cache.
7939     ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
7940     array->set_null(index - 1);  // Name.
7941     array->set_null(index);  // Code.
7942   }
7943 }
7944
7945
7946 // The key in the code cache hash table consists of the property name and the
7947 // code object. The actual match is on the name and the code flags. If a key
7948 // is created using the flags and not a code object it can only be used for
7949 // lookup not to create a new entry.
7950 class CodeCacheHashTableKey : public HashTableKey {
7951  public:
7952   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
7953       : name_(name), flags_(flags), code_() { }
7954
7955   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
7956       : name_(name), flags_(code->flags()), code_(code) { }
7957
7958   bool IsMatch(Object* other) V8_OVERRIDE {
7959     if (!other->IsFixedArray()) return false;
7960     FixedArray* pair = FixedArray::cast(other);
7961     Name* name = Name::cast(pair->get(0));
7962     Code::Flags flags = Code::cast(pair->get(1))->flags();
7963     if (flags != flags_) {
7964       return false;
7965     }
7966     return name_->Equals(name);
7967   }
7968
7969   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
7970     return name->Hash() ^ flags;
7971   }
7972
7973   uint32_t Hash() V8_OVERRIDE { return NameFlagsHashHelper(*name_, flags_); }
7974
7975   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
7976     FixedArray* pair = FixedArray::cast(obj);
7977     Name* name = Name::cast(pair->get(0));
7978     Code* code = Code::cast(pair->get(1));
7979     return NameFlagsHashHelper(name, code->flags());
7980   }
7981
7982   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
7983     Handle<Code> code = code_.ToHandleChecked();
7984     Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
7985     pair->set(0, *name_);
7986     pair->set(1, *code);
7987     return pair;
7988   }
7989
7990  private:
7991   Handle<Name> name_;
7992   Code::Flags flags_;
7993   // TODO(jkummerow): We should be able to get by without this.
7994   MaybeHandle<Code> code_;
7995 };
7996
7997
7998 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
7999   DisallowHeapAllocation no_alloc;
8000   CodeCacheHashTableKey key(handle(name), flags);
8001   int entry = FindEntry(&key);
8002   if (entry == kNotFound) return GetHeap()->undefined_value();
8003   return get(EntryToIndex(entry) + 1);
8004 }
8005
8006
8007 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
8008     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
8009   CodeCacheHashTableKey key(name, code);
8010
8011   Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
8012
8013   int entry = new_cache->FindInsertionEntry(key.Hash());
8014   Handle<Object> k = key.AsHandle(cache->GetIsolate());
8015
8016   new_cache->set(EntryToIndex(entry), *k);
8017   new_cache->set(EntryToIndex(entry) + 1, *code);
8018   new_cache->ElementAdded();
8019   return new_cache;
8020 }
8021
8022
8023 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
8024   DisallowHeapAllocation no_alloc;
8025   CodeCacheHashTableKey key(handle(name), flags);
8026   int entry = FindEntry(&key);
8027   return (entry == kNotFound) ? -1 : entry;
8028 }
8029
8030
8031 void CodeCacheHashTable::RemoveByIndex(int index) {
8032   ASSERT(index >= 0);
8033   Heap* heap = GetHeap();
8034   set(EntryToIndex(index), heap->the_hole_value());
8035   set(EntryToIndex(index) + 1, heap->the_hole_value());
8036   ElementRemoved();
8037 }
8038
8039
8040 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
8041                                   MapHandleList* maps,
8042                                   Code::Flags flags,
8043                                   Handle<Code> code) {
8044   Isolate* isolate = code_cache->GetIsolate();
8045   if (code_cache->cache()->IsUndefined()) {
8046     Handle<PolymorphicCodeCacheHashTable> result =
8047         PolymorphicCodeCacheHashTable::New(
8048             isolate,
8049             PolymorphicCodeCacheHashTable::kInitialSize);
8050     code_cache->set_cache(*result);
8051   } else {
8052     // This entry shouldn't be contained in the cache yet.
8053     ASSERT(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
8054                ->Lookup(maps, flags)->IsUndefined());
8055   }
8056   Handle<PolymorphicCodeCacheHashTable> hash_table =
8057       handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
8058   Handle<PolymorphicCodeCacheHashTable> new_cache =
8059       PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
8060   code_cache->set_cache(*new_cache);
8061 }
8062
8063
8064 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
8065                                             Code::Flags flags) {
8066   if (!cache()->IsUndefined()) {
8067     PolymorphicCodeCacheHashTable* hash_table =
8068         PolymorphicCodeCacheHashTable::cast(cache());
8069     return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
8070   } else {
8071     return GetIsolate()->factory()->undefined_value();
8072   }
8073 }
8074
8075
8076 // Despite their name, object of this class are not stored in the actual
8077 // hash table; instead they're temporarily used for lookups. It is therefore
8078 // safe to have a weak (non-owning) pointer to a MapList as a member field.
8079 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
8080  public:
8081   // Callers must ensure that |maps| outlives the newly constructed object.
8082   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
8083       : maps_(maps),
8084         code_flags_(code_flags) {}
8085
8086   bool IsMatch(Object* other) V8_OVERRIDE {
8087     MapHandleList other_maps(kDefaultListAllocationSize);
8088     int other_flags;
8089     FromObject(other, &other_flags, &other_maps);
8090     if (code_flags_ != other_flags) return false;
8091     if (maps_->length() != other_maps.length()) return false;
8092     // Compare just the hashes first because it's faster.
8093     int this_hash = MapsHashHelper(maps_, code_flags_);
8094     int other_hash = MapsHashHelper(&other_maps, other_flags);
8095     if (this_hash != other_hash) return false;
8096
8097     // Full comparison: for each map in maps_, look for an equivalent map in
8098     // other_maps. This implementation is slow, but probably good enough for
8099     // now because the lists are short (<= 4 elements currently).
8100     for (int i = 0; i < maps_->length(); ++i) {
8101       bool match_found = false;
8102       for (int j = 0; j < other_maps.length(); ++j) {
8103         if (*(maps_->at(i)) == *(other_maps.at(j))) {
8104           match_found = true;
8105           break;
8106         }
8107       }
8108       if (!match_found) return false;
8109     }
8110     return true;
8111   }
8112
8113   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
8114     uint32_t hash = code_flags;
8115     for (int i = 0; i < maps->length(); ++i) {
8116       hash ^= maps->at(i)->Hash();
8117     }
8118     return hash;
8119   }
8120
8121   uint32_t Hash() V8_OVERRIDE {
8122     return MapsHashHelper(maps_, code_flags_);
8123   }
8124
8125   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
8126     MapHandleList other_maps(kDefaultListAllocationSize);
8127     int other_flags;
8128     FromObject(obj, &other_flags, &other_maps);
8129     return MapsHashHelper(&other_maps, other_flags);
8130   }
8131
8132   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
8133     // The maps in |maps_| must be copied to a newly allocated FixedArray,
8134     // both because the referenced MapList is short-lived, and because C++
8135     // objects can't be stored in the heap anyway.
8136     Handle<FixedArray> list =
8137         isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
8138     list->set(0, Smi::FromInt(code_flags_));
8139     for (int i = 0; i < maps_->length(); ++i) {
8140       list->set(i + 1, *maps_->at(i));
8141     }
8142     return list;
8143   }
8144
8145  private:
8146   static MapHandleList* FromObject(Object* obj,
8147                                    int* code_flags,
8148                                    MapHandleList* maps) {
8149     FixedArray* list = FixedArray::cast(obj);
8150     maps->Rewind(0);
8151     *code_flags = Smi::cast(list->get(0))->value();
8152     for (int i = 1; i < list->length(); ++i) {
8153       maps->Add(Handle<Map>(Map::cast(list->get(i))));
8154     }
8155     return maps;
8156   }
8157
8158   MapHandleList* maps_;  // weak.
8159   int code_flags_;
8160   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
8161 };
8162
8163
8164 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
8165                                               int code_kind) {
8166   DisallowHeapAllocation no_alloc;
8167   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
8168   int entry = FindEntry(&key);
8169   if (entry == kNotFound) return GetHeap()->undefined_value();
8170   return get(EntryToIndex(entry) + 1);
8171 }
8172
8173
8174 Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
8175       Handle<PolymorphicCodeCacheHashTable> hash_table,
8176       MapHandleList* maps,
8177       int code_kind,
8178       Handle<Code> code) {
8179   PolymorphicCodeCacheHashTableKey key(maps, code_kind);
8180   Handle<PolymorphicCodeCacheHashTable> cache =
8181       EnsureCapacity(hash_table, 1, &key);
8182   int entry = cache->FindInsertionEntry(key.Hash());
8183
8184   Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
8185   cache->set(EntryToIndex(entry), *obj);
8186   cache->set(EntryToIndex(entry) + 1, *code);
8187   cache->ElementAdded();
8188   return cache;
8189 }
8190
8191
8192 void FixedArray::Shrink(int new_length) {
8193   ASSERT(0 <= new_length && new_length <= length());
8194   if (new_length < length()) {
8195     RightTrimFixedArray<Heap::FROM_MUTATOR>(
8196         GetHeap(), this, length() - new_length);
8197   }
8198 }
8199
8200
8201 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
8202     Handle<FixedArray> content,
8203     Handle<JSObject> array) {
8204   ASSERT(array->IsJSArray() || array->HasSloppyArgumentsElements());
8205   ElementsAccessor* accessor = array->GetElementsAccessor();
8206   Handle<FixedArray> result;
8207   ASSIGN_RETURN_ON_EXCEPTION(
8208       array->GetIsolate(), result,
8209       accessor->AddElementsToFixedArray(array, array, content),
8210       FixedArray);
8211
8212 #ifdef ENABLE_SLOW_ASSERTS
8213   if (FLAG_enable_slow_asserts) {
8214     DisallowHeapAllocation no_allocation;
8215     for (int i = 0; i < result->length(); i++) {
8216       Object* current = result->get(i);
8217       ASSERT(current->IsNumber() || current->IsName());
8218     }
8219   }
8220 #endif
8221   return result;
8222 }
8223
8224
8225 MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
8226                                                 Handle<FixedArray> second) {
8227   ElementsAccessor* accessor = ElementsAccessor::ForArray(second);
8228   Handle<FixedArray> result;
8229   ASSIGN_RETURN_ON_EXCEPTION(
8230       first->GetIsolate(), result,
8231       accessor->AddElementsToFixedArray(
8232           Handle<Object>::null(),     // receiver
8233           Handle<JSObject>::null(),   // holder
8234           first,
8235           Handle<FixedArrayBase>::cast(second)),
8236       FixedArray);
8237
8238 #ifdef ENABLE_SLOW_ASSERTS
8239   if (FLAG_enable_slow_asserts) {
8240     DisallowHeapAllocation no_allocation;
8241     for (int i = 0; i < result->length(); i++) {
8242       Object* current = result->get(i);
8243       ASSERT(current->IsNumber() || current->IsName());
8244     }
8245   }
8246 #endif
8247   return result;
8248 }
8249
8250
8251 Handle<FixedArray> FixedArray::CopySize(
8252     Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
8253   Isolate* isolate = array->GetIsolate();
8254   if (new_length == 0) return isolate->factory()->empty_fixed_array();
8255   Handle<FixedArray> result =
8256       isolate->factory()->NewFixedArray(new_length, pretenure);
8257   // Copy the content
8258   DisallowHeapAllocation no_gc;
8259   int len = array->length();
8260   if (new_length < len) len = new_length;
8261   // We are taking the map from the old fixed array so the map is sure to
8262   // be an immortal immutable object.
8263   result->set_map_no_write_barrier(array->map());
8264   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
8265   for (int i = 0; i < len; i++) {
8266     result->set(i, array->get(i), mode);
8267   }
8268   return result;
8269 }
8270
8271
8272 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
8273   DisallowHeapAllocation no_gc;
8274   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
8275   for (int index = 0; index < len; index++) {
8276     dest->set(dest_pos+index, get(pos+index), mode);
8277   }
8278 }
8279
8280
8281 #ifdef DEBUG
8282 bool FixedArray::IsEqualTo(FixedArray* other) {
8283   if (length() != other->length()) return false;
8284   for (int i = 0 ; i < length(); ++i) {
8285     if (get(i) != other->get(i)) return false;
8286   }
8287   return true;
8288 }
8289 #endif
8290
8291
8292 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
8293                                                   int number_of_descriptors,
8294                                                   int slack) {
8295   ASSERT(0 <= number_of_descriptors);
8296   Factory* factory = isolate->factory();
8297   // Do not use DescriptorArray::cast on incomplete object.
8298   int size = number_of_descriptors + slack;
8299   if (size == 0) return factory->empty_descriptor_array();
8300   // Allocate the array of keys.
8301   Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
8302
8303   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
8304   result->set(kEnumCacheIndex, Smi::FromInt(0));
8305   return Handle<DescriptorArray>::cast(result);
8306 }
8307
8308
8309 void DescriptorArray::ClearEnumCache() {
8310   set(kEnumCacheIndex, Smi::FromInt(0));
8311 }
8312
8313
8314 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
8315   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
8316   Set(index, descriptor);
8317 }
8318
8319
8320 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
8321                                    FixedArray* new_cache,
8322                                    Object* new_index_cache) {
8323   ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
8324   ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
8325   ASSERT(!IsEmpty());
8326   ASSERT(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
8327   FixedArray::cast(bridge_storage)->
8328     set(kEnumCacheBridgeCacheIndex, new_cache);
8329   FixedArray::cast(bridge_storage)->
8330     set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
8331   set(kEnumCacheIndex, bridge_storage);
8332 }
8333
8334
8335 void DescriptorArray::CopyFrom(int index,
8336                                DescriptorArray* src,
8337                                const WhitenessWitness& witness) {
8338   Object* value = src->GetValue(index);
8339   PropertyDetails details = src->GetDetails(index);
8340   Descriptor desc(handle(src->GetKey(index)),
8341                   handle(value, src->GetIsolate()),
8342                   details);
8343   Set(index, &desc, witness);
8344 }
8345
8346
8347 // We need the whiteness witness since sort will reshuffle the entries in the
8348 // descriptor array. If the descriptor array were to be black, the shuffling
8349 // would move a slot that was already recorded as pointing into an evacuation
8350 // candidate. This would result in missing updates upon evacuation.
8351 void DescriptorArray::Sort() {
8352   // In-place heap sort.
8353   int len = number_of_descriptors();
8354   // Reset sorting since the descriptor array might contain invalid pointers.
8355   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
8356   // Bottom-up max-heap construction.
8357   // Index of the last node with children
8358   const int max_parent_index = (len / 2) - 1;
8359   for (int i = max_parent_index; i >= 0; --i) {
8360     int parent_index = i;
8361     const uint32_t parent_hash = GetSortedKey(i)->Hash();
8362     while (parent_index <= max_parent_index) {
8363       int child_index = 2 * parent_index + 1;
8364       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8365       if (child_index + 1 < len) {
8366         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8367         if (right_child_hash > child_hash) {
8368           child_index++;
8369           child_hash = right_child_hash;
8370         }
8371       }
8372       if (child_hash <= parent_hash) break;
8373       SwapSortedKeys(parent_index, child_index);
8374       // Now element at child_index could be < its children.
8375       parent_index = child_index;  // parent_hash remains correct.
8376     }
8377   }
8378
8379   // Extract elements and create sorted array.
8380   for (int i = len - 1; i > 0; --i) {
8381     // Put max element at the back of the array.
8382     SwapSortedKeys(0, i);
8383     // Shift down the new top element.
8384     int parent_index = 0;
8385     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
8386     const int max_parent_index = (i / 2) - 1;
8387     while (parent_index <= max_parent_index) {
8388       int child_index = parent_index * 2 + 1;
8389       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8390       if (child_index + 1 < i) {
8391         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8392         if (right_child_hash > child_hash) {
8393           child_index++;
8394           child_hash = right_child_hash;
8395         }
8396       }
8397       if (child_hash <= parent_hash) break;
8398       SwapSortedKeys(parent_index, child_index);
8399       parent_index = child_index;
8400     }
8401   }
8402   ASSERT(IsSortedNoDuplicates());
8403 }
8404
8405
8406 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
8407   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
8408   copy->set_getter(pair->getter());
8409   copy->set_setter(pair->setter());
8410   return copy;
8411 }
8412
8413
8414 Object* AccessorPair::GetComponent(AccessorComponent component) {
8415   Object* accessor = get(component);
8416   return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
8417 }
8418
8419
8420 Handle<DeoptimizationInputData> DeoptimizationInputData::New(
8421     Isolate* isolate,
8422     int deopt_entry_count,
8423     PretenureFlag pretenure) {
8424   ASSERT(deopt_entry_count > 0);
8425   return Handle<DeoptimizationInputData>::cast(
8426       isolate->factory()->NewFixedArray(
8427           LengthFor(deopt_entry_count), pretenure));
8428 }
8429
8430
8431 Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
8432     Isolate* isolate,
8433     int number_of_deopt_points,
8434     PretenureFlag pretenure) {
8435   Handle<FixedArray> result;
8436   if (number_of_deopt_points == 0) {
8437     result = isolate->factory()->empty_fixed_array();
8438   } else {
8439     result = isolate->factory()->NewFixedArray(
8440         LengthOfFixedArray(number_of_deopt_points), pretenure);
8441   }
8442   return Handle<DeoptimizationOutputData>::cast(result);
8443 }
8444
8445
8446 #ifdef DEBUG
8447 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
8448   if (IsEmpty()) return other->IsEmpty();
8449   if (other->IsEmpty()) return false;
8450   if (length() != other->length()) return false;
8451   for (int i = 0; i < length(); ++i) {
8452     if (get(i) != other->get(i)) return false;
8453   }
8454   return true;
8455 }
8456 #endif
8457
8458
8459 bool String::LooksValid() {
8460   if (!GetIsolate()->heap()->Contains(this)) return false;
8461   return true;
8462 }
8463
8464
8465 String::FlatContent String::GetFlatContent() {
8466   ASSERT(!AllowHeapAllocation::IsAllowed());
8467   int length = this->length();
8468   StringShape shape(this);
8469   String* string = this;
8470   int offset = 0;
8471   if (shape.representation_tag() == kConsStringTag) {
8472     ConsString* cons = ConsString::cast(string);
8473     if (cons->second()->length() != 0) {
8474       return FlatContent();
8475     }
8476     string = cons->first();
8477     shape = StringShape(string);
8478   }
8479   if (shape.representation_tag() == kSlicedStringTag) {
8480     SlicedString* slice = SlicedString::cast(string);
8481     offset = slice->offset();
8482     string = slice->parent();
8483     shape = StringShape(string);
8484     ASSERT(shape.representation_tag() != kConsStringTag &&
8485            shape.representation_tag() != kSlicedStringTag);
8486   }
8487   if (shape.encoding_tag() == kOneByteStringTag) {
8488     const uint8_t* start;
8489     if (shape.representation_tag() == kSeqStringTag) {
8490       start = SeqOneByteString::cast(string)->GetChars();
8491     } else {
8492       start = ExternalAsciiString::cast(string)->GetChars();
8493     }
8494     return FlatContent(start + offset, length);
8495   } else {
8496     ASSERT(shape.encoding_tag() == kTwoByteStringTag);
8497     const uc16* start;
8498     if (shape.representation_tag() == kSeqStringTag) {
8499       start = SeqTwoByteString::cast(string)->GetChars();
8500     } else {
8501       start = ExternalTwoByteString::cast(string)->GetChars();
8502     }
8503     return FlatContent(start + offset, length);
8504   }
8505 }
8506
8507
8508 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8509                                           RobustnessFlag robust_flag,
8510                                           int offset,
8511                                           int length,
8512                                           int* length_return) {
8513   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8514     return SmartArrayPointer<char>(NULL);
8515   }
8516   Heap* heap = GetHeap();
8517
8518   // Negative length means the to the end of the string.
8519   if (length < 0) length = kMaxInt - offset;
8520
8521   // Compute the size of the UTF-8 string. Start at the specified offset.
8522   Access<ConsStringIteratorOp> op(
8523       heap->isolate()->objects_string_iterator());
8524   StringCharacterStream stream(this, op.value(), offset);
8525   int character_position = offset;
8526   int utf8_bytes = 0;
8527   int last = unibrow::Utf16::kNoPreviousCharacter;
8528   while (stream.HasMore() && character_position++ < offset + length) {
8529     uint16_t character = stream.GetNext();
8530     utf8_bytes += unibrow::Utf8::Length(character, last);
8531     last = character;
8532   }
8533
8534   if (length_return) {
8535     *length_return = utf8_bytes;
8536   }
8537
8538   char* result = NewArray<char>(utf8_bytes + 1);
8539
8540   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8541   stream.Reset(this, offset);
8542   character_position = offset;
8543   int utf8_byte_position = 0;
8544   last = unibrow::Utf16::kNoPreviousCharacter;
8545   while (stream.HasMore() && character_position++ < offset + length) {
8546     uint16_t character = stream.GetNext();
8547     if (allow_nulls == DISALLOW_NULLS && character == 0) {
8548       character = ' ';
8549     }
8550     utf8_byte_position +=
8551         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8552     last = character;
8553   }
8554   result[utf8_byte_position] = 0;
8555   return SmartArrayPointer<char>(result);
8556 }
8557
8558
8559 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8560                                           RobustnessFlag robust_flag,
8561                                           int* length_return) {
8562   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8563 }
8564
8565
8566 const uc16* String::GetTwoByteData(unsigned start) {
8567   ASSERT(!IsOneByteRepresentationUnderneath());
8568   switch (StringShape(this).representation_tag()) {
8569     case kSeqStringTag:
8570       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8571     case kExternalStringTag:
8572       return ExternalTwoByteString::cast(this)->
8573         ExternalTwoByteStringGetData(start);
8574     case kSlicedStringTag: {
8575       SlicedString* slice = SlicedString::cast(this);
8576       return slice->parent()->GetTwoByteData(start + slice->offset());
8577     }
8578     case kConsStringTag:
8579       UNREACHABLE();
8580       return NULL;
8581   }
8582   UNREACHABLE();
8583   return NULL;
8584 }
8585
8586
8587 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
8588   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8589     return SmartArrayPointer<uc16>();
8590   }
8591   Heap* heap = GetHeap();
8592
8593   Access<ConsStringIteratorOp> op(
8594       heap->isolate()->objects_string_iterator());
8595   StringCharacterStream stream(this, op.value());
8596
8597   uc16* result = NewArray<uc16>(length() + 1);
8598
8599   int i = 0;
8600   while (stream.HasMore()) {
8601     uint16_t character = stream.GetNext();
8602     result[i++] = character;
8603   }
8604   result[i] = 0;
8605   return SmartArrayPointer<uc16>(result);
8606 }
8607
8608
8609 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
8610   return reinterpret_cast<uc16*>(
8611       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8612 }
8613
8614
8615 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8616   Relocatable* current = isolate->relocatable_top();
8617   while (current != NULL) {
8618     current->PostGarbageCollection();
8619     current = current->prev_;
8620   }
8621 }
8622
8623
8624 // Reserve space for statics needing saving and restoring.
8625 int Relocatable::ArchiveSpacePerThread() {
8626   return sizeof(Relocatable*);  // NOLINT
8627 }
8628
8629
8630 // Archive statics that are thread-local.
8631 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8632   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8633   isolate->set_relocatable_top(NULL);
8634   return to + ArchiveSpacePerThread();
8635 }
8636
8637
8638 // Restore statics that are thread-local.
8639 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8640   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8641   return from + ArchiveSpacePerThread();
8642 }
8643
8644
8645 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8646   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8647   Iterate(v, top);
8648   return thread_storage + ArchiveSpacePerThread();
8649 }
8650
8651
8652 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8653   Iterate(v, isolate->relocatable_top());
8654 }
8655
8656
8657 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8658   Relocatable* current = top;
8659   while (current != NULL) {
8660     current->IterateInstance(v);
8661     current = current->prev_;
8662   }
8663 }
8664
8665
8666 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
8667     : Relocatable(isolate),
8668       str_(str.location()),
8669       length_(str->length()) {
8670   PostGarbageCollection();
8671 }
8672
8673
8674 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
8675     : Relocatable(isolate),
8676       str_(0),
8677       is_ascii_(true),
8678       length_(input.length()),
8679       start_(input.start()) { }
8680
8681
8682 void FlatStringReader::PostGarbageCollection() {
8683   if (str_ == NULL) return;
8684   Handle<String> str(str_);
8685   ASSERT(str->IsFlat());
8686   DisallowHeapAllocation no_gc;
8687   // This does not actually prevent the vector from being relocated later.
8688   String::FlatContent content = str->GetFlatContent();
8689   ASSERT(content.IsFlat());
8690   is_ascii_ = content.IsAscii();
8691   if (is_ascii_) {
8692     start_ = content.ToOneByteVector().start();
8693   } else {
8694     start_ = content.ToUC16Vector().start();
8695   }
8696 }
8697
8698
8699 void ConsStringIteratorOp::Initialize(ConsString* cons_string, int offset) {
8700   ASSERT(cons_string != NULL);
8701   root_ = cons_string;
8702   consumed_ = offset;
8703   // Force stack blown condition to trigger restart.
8704   depth_ = 1;
8705   maximum_depth_ = kStackSize + depth_;
8706   ASSERT(StackBlown());
8707 }
8708
8709
8710 String* ConsStringIteratorOp::Continue(int* offset_out) {
8711   ASSERT(depth_ != 0);
8712   ASSERT_EQ(0, *offset_out);
8713   bool blew_stack = StackBlown();
8714   String* string = NULL;
8715   // Get the next leaf if there is one.
8716   if (!blew_stack) string = NextLeaf(&blew_stack);
8717   // Restart search from root.
8718   if (blew_stack) {
8719     ASSERT(string == NULL);
8720     string = Search(offset_out);
8721   }
8722   // Ensure future calls return null immediately.
8723   if (string == NULL) Reset(NULL);
8724   return string;
8725 }
8726
8727
8728 String* ConsStringIteratorOp::Search(int* offset_out) {
8729   ConsString* cons_string = root_;
8730   // Reset the stack, pushing the root string.
8731   depth_ = 1;
8732   maximum_depth_ = 1;
8733   frames_[0] = cons_string;
8734   const int consumed = consumed_;
8735   int offset = 0;
8736   while (true) {
8737     // Loop until the string is found which contains the target offset.
8738     String* string = cons_string->first();
8739     int length = string->length();
8740     int32_t type;
8741     if (consumed < offset + length) {
8742       // Target offset is in the left branch.
8743       // Keep going if we're still in a ConString.
8744       type = string->map()->instance_type();
8745       if ((type & kStringRepresentationMask) == kConsStringTag) {
8746         cons_string = ConsString::cast(string);
8747         PushLeft(cons_string);
8748         continue;
8749       }
8750       // Tell the stack we're done descending.
8751       AdjustMaximumDepth();
8752     } else {
8753       // Descend right.
8754       // Update progress through the string.
8755       offset += length;
8756       // Keep going if we're still in a ConString.
8757       string = cons_string->second();
8758       type = string->map()->instance_type();
8759       if ((type & kStringRepresentationMask) == kConsStringTag) {
8760         cons_string = ConsString::cast(string);
8761         PushRight(cons_string);
8762         continue;
8763       }
8764       // Need this to be updated for the current string.
8765       length = string->length();
8766       // Account for the possibility of an empty right leaf.
8767       // This happens only if we have asked for an offset outside the string.
8768       if (length == 0) {
8769         // Reset so future operations will return null immediately.
8770         Reset(NULL);
8771         return NULL;
8772       }
8773       // Tell the stack we're done descending.
8774       AdjustMaximumDepth();
8775       // Pop stack so next iteration is in correct place.
8776       Pop();
8777     }
8778     ASSERT(length != 0);
8779     // Adjust return values and exit.
8780     consumed_ = offset + length;
8781     *offset_out = consumed - offset;
8782     return string;
8783   }
8784   UNREACHABLE();
8785   return NULL;
8786 }
8787
8788
8789 String* ConsStringIteratorOp::NextLeaf(bool* blew_stack) {
8790   while (true) {
8791     // Tree traversal complete.
8792     if (depth_ == 0) {
8793       *blew_stack = false;
8794       return NULL;
8795     }
8796     // We've lost track of higher nodes.
8797     if (StackBlown()) {
8798       *blew_stack = true;
8799       return NULL;
8800     }
8801     // Go right.
8802     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
8803     String* string = cons_string->second();
8804     int32_t type = string->map()->instance_type();
8805     if ((type & kStringRepresentationMask) != kConsStringTag) {
8806       // Pop stack so next iteration is in correct place.
8807       Pop();
8808       int length = string->length();
8809       // Could be a flattened ConsString.
8810       if (length == 0) continue;
8811       consumed_ += length;
8812       return string;
8813     }
8814     cons_string = ConsString::cast(string);
8815     PushRight(cons_string);
8816     // Need to traverse all the way left.
8817     while (true) {
8818       // Continue left.
8819       string = cons_string->first();
8820       type = string->map()->instance_type();
8821       if ((type & kStringRepresentationMask) != kConsStringTag) {
8822         AdjustMaximumDepth();
8823         int length = string->length();
8824         ASSERT(length != 0);
8825         consumed_ += length;
8826         return string;
8827       }
8828       cons_string = ConsString::cast(string);
8829       PushLeft(cons_string);
8830     }
8831   }
8832   UNREACHABLE();
8833   return NULL;
8834 }
8835
8836
8837 uint16_t ConsString::ConsStringGet(int index) {
8838   ASSERT(index >= 0 && index < this->length());
8839
8840   // Check for a flattened cons string
8841   if (second()->length() == 0) {
8842     String* left = first();
8843     return left->Get(index);
8844   }
8845
8846   String* string = String::cast(this);
8847
8848   while (true) {
8849     if (StringShape(string).IsCons()) {
8850       ConsString* cons_string = ConsString::cast(string);
8851       String* left = cons_string->first();
8852       if (left->length() > index) {
8853         string = left;
8854       } else {
8855         index -= left->length();
8856         string = cons_string->second();
8857       }
8858     } else {
8859       return string->Get(index);
8860     }
8861   }
8862
8863   UNREACHABLE();
8864   return 0;
8865 }
8866
8867
8868 uint16_t SlicedString::SlicedStringGet(int index) {
8869   return parent()->Get(offset() + index);
8870 }
8871
8872
8873 template <typename sinkchar>
8874 void String::WriteToFlat(String* src,
8875                          sinkchar* sink,
8876                          int f,
8877                          int t) {
8878   String* source = src;
8879   int from = f;
8880   int to = t;
8881   while (true) {
8882     ASSERT(0 <= from && from <= to && to <= source->length());
8883     switch (StringShape(source).full_representation_tag()) {
8884       case kOneByteStringTag | kExternalStringTag: {
8885         CopyChars(sink,
8886                   ExternalAsciiString::cast(source)->GetChars() + from,
8887                   to - from);
8888         return;
8889       }
8890       case kTwoByteStringTag | kExternalStringTag: {
8891         const uc16* data =
8892             ExternalTwoByteString::cast(source)->GetChars();
8893         CopyChars(sink,
8894                   data + from,
8895                   to - from);
8896         return;
8897       }
8898       case kOneByteStringTag | kSeqStringTag: {
8899         CopyChars(sink,
8900                   SeqOneByteString::cast(source)->GetChars() + from,
8901                   to - from);
8902         return;
8903       }
8904       case kTwoByteStringTag | kSeqStringTag: {
8905         CopyChars(sink,
8906                   SeqTwoByteString::cast(source)->GetChars() + from,
8907                   to - from);
8908         return;
8909       }
8910       case kOneByteStringTag | kConsStringTag:
8911       case kTwoByteStringTag | kConsStringTag: {
8912         ConsString* cons_string = ConsString::cast(source);
8913         String* first = cons_string->first();
8914         int boundary = first->length();
8915         if (to - boundary >= boundary - from) {
8916           // Right hand side is longer.  Recurse over left.
8917           if (from < boundary) {
8918             WriteToFlat(first, sink, from, boundary);
8919             sink += boundary - from;
8920             from = 0;
8921           } else {
8922             from -= boundary;
8923           }
8924           to -= boundary;
8925           source = cons_string->second();
8926         } else {
8927           // Left hand side is longer.  Recurse over right.
8928           if (to > boundary) {
8929             String* second = cons_string->second();
8930             // When repeatedly appending to a string, we get a cons string that
8931             // is unbalanced to the left, a list, essentially.  We inline the
8932             // common case of sequential ascii right child.
8933             if (to - boundary == 1) {
8934               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
8935             } else if (second->IsSeqOneByteString()) {
8936               CopyChars(sink + boundary - from,
8937                         SeqOneByteString::cast(second)->GetChars(),
8938                         to - boundary);
8939             } else {
8940               WriteToFlat(second,
8941                           sink + boundary - from,
8942                           0,
8943                           to - boundary);
8944             }
8945             to = boundary;
8946           }
8947           source = first;
8948         }
8949         break;
8950       }
8951       case kOneByteStringTag | kSlicedStringTag:
8952       case kTwoByteStringTag | kSlicedStringTag: {
8953         SlicedString* slice = SlicedString::cast(source);
8954         unsigned offset = slice->offset();
8955         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
8956         return;
8957       }
8958     }
8959   }
8960 }
8961
8962
8963
8964 template <typename SourceChar>
8965 static void CalculateLineEndsImpl(Isolate* isolate,
8966                                   List<int>* line_ends,
8967                                   Vector<const SourceChar> src,
8968                                   bool include_ending_line) {
8969   const int src_len = src.length();
8970   StringSearch<uint8_t, SourceChar> search(isolate, STATIC_ASCII_VECTOR("\n"));
8971
8972   // Find and record line ends.
8973   int position = 0;
8974   while (position != -1 && position < src_len) {
8975     position = search.Search(src, position);
8976     if (position != -1) {
8977       line_ends->Add(position);
8978       position++;
8979     } else if (include_ending_line) {
8980       // Even if the last line misses a line end, it is counted.
8981       line_ends->Add(src_len);
8982       return;
8983     }
8984   }
8985 }
8986
8987
8988 Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
8989                                              bool include_ending_line) {
8990   src = Flatten(src);
8991   // Rough estimate of line count based on a roughly estimated average
8992   // length of (unpacked) code.
8993   int line_count_estimate = src->length() >> 4;
8994   List<int> line_ends(line_count_estimate);
8995   Isolate* isolate = src->GetIsolate();
8996   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
8997     // Dispatch on type of strings.
8998     String::FlatContent content = src->GetFlatContent();
8999     ASSERT(content.IsFlat());
9000     if (content.IsAscii()) {
9001       CalculateLineEndsImpl(isolate,
9002                             &line_ends,
9003                             content.ToOneByteVector(),
9004                             include_ending_line);
9005     } else {
9006       CalculateLineEndsImpl(isolate,
9007                             &line_ends,
9008                             content.ToUC16Vector(),
9009                             include_ending_line);
9010     }
9011   }
9012   int line_count = line_ends.length();
9013   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
9014   for (int i = 0; i < line_count; i++) {
9015     array->set(i, Smi::FromInt(line_ends[i]));
9016   }
9017   return array;
9018 }
9019
9020
9021 // Compares the contents of two strings by reading and comparing
9022 // int-sized blocks of characters.
9023 template <typename Char>
9024 static inline bool CompareRawStringContents(const Char* const a,
9025                                             const Char* const b,
9026                                             int length) {
9027   int i = 0;
9028 #ifndef V8_HOST_CAN_READ_UNALIGNED
9029   // If this architecture isn't comfortable reading unaligned ints
9030   // then we have to check that the strings are aligned before
9031   // comparing them blockwise.
9032   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
9033   uint32_t pa_addr = reinterpret_cast<uint32_t>(a);
9034   uint32_t pb_addr = reinterpret_cast<uint32_t>(b);
9035   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
9036 #endif
9037     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
9038     int endpoint = length - kStepSize;
9039     // Compare blocks until we reach near the end of the string.
9040     for (; i <= endpoint; i += kStepSize) {
9041       uint32_t wa = *reinterpret_cast<const uint32_t*>(a + i);
9042       uint32_t wb = *reinterpret_cast<const uint32_t*>(b + i);
9043       if (wa != wb) {
9044         return false;
9045       }
9046     }
9047 #ifndef V8_HOST_CAN_READ_UNALIGNED
9048   }
9049 #endif
9050   // Compare the remaining characters that didn't fit into a block.
9051   for (; i < length; i++) {
9052     if (a[i] != b[i]) {
9053       return false;
9054     }
9055   }
9056   return true;
9057 }
9058
9059
9060 template<typename Chars1, typename Chars2>
9061 class RawStringComparator : public AllStatic {
9062  public:
9063   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
9064     ASSERT(sizeof(Chars1) != sizeof(Chars2));
9065     for (int i = 0; i < len; i++) {
9066       if (a[i] != b[i]) {
9067         return false;
9068       }
9069     }
9070     return true;
9071   }
9072 };
9073
9074
9075 template<>
9076 class RawStringComparator<uint16_t, uint16_t> {
9077  public:
9078   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
9079     return CompareRawStringContents(a, b, len);
9080   }
9081 };
9082
9083
9084 template<>
9085 class RawStringComparator<uint8_t, uint8_t> {
9086  public:
9087   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
9088     return CompareRawStringContents(a, b, len);
9089   }
9090 };
9091
9092
9093 class StringComparator {
9094   class State {
9095    public:
9096     explicit inline State(ConsStringIteratorOp* op)
9097       : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {}
9098
9099     inline void Init(String* string) {
9100       ConsString* cons_string = String::VisitFlat(this, string);
9101       op_->Reset(cons_string);
9102       if (cons_string != NULL) {
9103         int offset;
9104         string = op_->Next(&offset);
9105         String::VisitFlat(this, string, offset);
9106       }
9107     }
9108
9109     inline void VisitOneByteString(const uint8_t* chars, int length) {
9110       is_one_byte_ = true;
9111       buffer8_ = chars;
9112       length_ = length;
9113     }
9114
9115     inline void VisitTwoByteString(const uint16_t* chars, int length) {
9116       is_one_byte_ = false;
9117       buffer16_ = chars;
9118       length_ = length;
9119     }
9120
9121     void Advance(int consumed) {
9122       ASSERT(consumed <= length_);
9123       // Still in buffer.
9124       if (length_ != consumed) {
9125         if (is_one_byte_) {
9126           buffer8_ += consumed;
9127         } else {
9128           buffer16_ += consumed;
9129         }
9130         length_ -= consumed;
9131         return;
9132       }
9133       // Advance state.
9134       int offset;
9135       String* next = op_->Next(&offset);
9136       ASSERT_EQ(0, offset);
9137       ASSERT(next != NULL);
9138       String::VisitFlat(this, next);
9139     }
9140
9141     ConsStringIteratorOp* const op_;
9142     bool is_one_byte_;
9143     int length_;
9144     union {
9145       const uint8_t* buffer8_;
9146       const uint16_t* buffer16_;
9147     };
9148
9149    private:
9150     DISALLOW_IMPLICIT_CONSTRUCTORS(State);
9151   };
9152
9153  public:
9154   inline StringComparator(ConsStringIteratorOp* op_1,
9155                           ConsStringIteratorOp* op_2)
9156     : state_1_(op_1),
9157       state_2_(op_2) {
9158   }
9159
9160   template<typename Chars1, typename Chars2>
9161   static inline bool Equals(State* state_1, State* state_2, int to_check) {
9162     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
9163     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
9164     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
9165   }
9166
9167   bool Equals(String* string_1, String* string_2) {
9168     int length = string_1->length();
9169     state_1_.Init(string_1);
9170     state_2_.Init(string_2);
9171     while (true) {
9172       int to_check = Min(state_1_.length_, state_2_.length_);
9173       ASSERT(to_check > 0 && to_check <= length);
9174       bool is_equal;
9175       if (state_1_.is_one_byte_) {
9176         if (state_2_.is_one_byte_) {
9177           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
9178         } else {
9179           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
9180         }
9181       } else {
9182         if (state_2_.is_one_byte_) {
9183           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
9184         } else {
9185           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
9186         }
9187       }
9188       // Looping done.
9189       if (!is_equal) return false;
9190       length -= to_check;
9191       // Exit condition. Strings are equal.
9192       if (length == 0) return true;
9193       state_1_.Advance(to_check);
9194       state_2_.Advance(to_check);
9195     }
9196   }
9197
9198  private:
9199   State state_1_;
9200   State state_2_;
9201   DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator);
9202 };
9203
9204
9205 bool String::SlowEquals(String* other) {
9206   DisallowHeapAllocation no_gc;
9207   // Fast check: negative check with lengths.
9208   int len = length();
9209   if (len != other->length()) return false;
9210   if (len == 0) return true;
9211
9212   // Fast check: if hash code is computed for both strings
9213   // a fast negative check can be performed.
9214   if (HasHashCode() && other->HasHashCode()) {
9215 #ifdef ENABLE_SLOW_ASSERTS
9216     if (FLAG_enable_slow_asserts) {
9217       if (Hash() != other->Hash()) {
9218         bool found_difference = false;
9219         for (int i = 0; i < len; i++) {
9220           if (Get(i) != other->Get(i)) {
9221             found_difference = true;
9222             break;
9223           }
9224         }
9225         ASSERT(found_difference);
9226       }
9227     }
9228 #endif
9229     if (Hash() != other->Hash()) return false;
9230   }
9231
9232   // We know the strings are both non-empty. Compare the first chars
9233   // before we try to flatten the strings.
9234   if (this->Get(0) != other->Get(0)) return false;
9235
9236   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
9237     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
9238     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
9239     return CompareRawStringContents(str1, str2, len);
9240   }
9241
9242   Isolate* isolate = GetIsolate();
9243   StringComparator comparator(isolate->objects_string_compare_iterator_a(),
9244                               isolate->objects_string_compare_iterator_b());
9245
9246   return comparator.Equals(this, other);
9247 }
9248
9249
9250 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
9251   // Fast check: negative check with lengths.
9252   int one_length = one->length();
9253   if (one_length != two->length()) return false;
9254   if (one_length == 0) return true;
9255
9256   // Fast check: if hash code is computed for both strings
9257   // a fast negative check can be performed.
9258   if (one->HasHashCode() && two->HasHashCode()) {
9259 #ifdef ENABLE_SLOW_ASSERTS
9260     if (FLAG_enable_slow_asserts) {
9261       if (one->Hash() != two->Hash()) {
9262         bool found_difference = false;
9263         for (int i = 0; i < one_length; i++) {
9264           if (one->Get(i) != two->Get(i)) {
9265             found_difference = true;
9266             break;
9267           }
9268         }
9269         ASSERT(found_difference);
9270       }
9271     }
9272 #endif
9273     if (one->Hash() != two->Hash()) return false;
9274   }
9275
9276   // We know the strings are both non-empty. Compare the first chars
9277   // before we try to flatten the strings.
9278   if (one->Get(0) != two->Get(0)) return false;
9279
9280   one = String::Flatten(one);
9281   two = String::Flatten(two);
9282
9283   DisallowHeapAllocation no_gc;
9284   String::FlatContent flat1 = one->GetFlatContent();
9285   String::FlatContent flat2 = two->GetFlatContent();
9286
9287   if (flat1.IsAscii() && flat2.IsAscii()) {
9288       return CompareRawStringContents(flat1.ToOneByteVector().start(),
9289                                       flat2.ToOneByteVector().start(),
9290                                       one_length);
9291   } else {
9292     for (int i = 0; i < one_length; i++) {
9293       if (flat1.Get(i) != flat2.Get(i)) return false;
9294     }
9295     return true;
9296   }
9297 }
9298
9299
9300 bool String::MarkAsUndetectable() {
9301   if (StringShape(this).IsInternalized()) return false;
9302
9303   Map* map = this->map();
9304   Heap* heap = GetHeap();
9305   if (map == heap->string_map()) {
9306     this->set_map(heap->undetectable_string_map());
9307     return true;
9308   } else if (map == heap->ascii_string_map()) {
9309     this->set_map(heap->undetectable_ascii_string_map());
9310     return true;
9311   }
9312   // Rest cannot be marked as undetectable
9313   return false;
9314 }
9315
9316
9317 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
9318   int slen = length();
9319   // Can't check exact length equality, but we can check bounds.
9320   int str_len = str.length();
9321   if (!allow_prefix_match &&
9322       (str_len < slen ||
9323           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
9324     return false;
9325   }
9326   int i;
9327   unsigned remaining_in_str = static_cast<unsigned>(str_len);
9328   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
9329   for (i = 0; i < slen && remaining_in_str > 0; i++) {
9330     unsigned cursor = 0;
9331     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
9332     ASSERT(cursor > 0 && cursor <= remaining_in_str);
9333     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
9334       if (i > slen - 1) return false;
9335       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
9336       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
9337     } else {
9338       if (Get(i) != r) return false;
9339     }
9340     utf8_data += cursor;
9341     remaining_in_str -= cursor;
9342   }
9343   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
9344 }
9345
9346
9347 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
9348   int slen = length();
9349   if (str.length() != slen) return false;
9350   DisallowHeapAllocation no_gc;
9351   FlatContent content = GetFlatContent();
9352   if (content.IsAscii()) {
9353     return CompareChars(content.ToOneByteVector().start(),
9354                         str.start(), slen) == 0;
9355   }
9356   for (int i = 0; i < slen; i++) {
9357     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
9358   }
9359   return true;
9360 }
9361
9362
9363 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
9364   int slen = length();
9365   if (str.length() != slen) return false;
9366   DisallowHeapAllocation no_gc;
9367   FlatContent content = GetFlatContent();
9368   if (content.IsTwoByte()) {
9369     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
9370   }
9371   for (int i = 0; i < slen; i++) {
9372     if (Get(i) != str[i]) return false;
9373   }
9374   return true;
9375 }
9376
9377
9378 class IteratingStringHasher: public StringHasher {
9379  public:
9380   static inline uint32_t Hash(String* string, uint32_t seed) {
9381     IteratingStringHasher hasher(string->length(), seed);
9382     // Nothing to do.
9383     if (hasher.has_trivial_hash()) return hasher.GetHashField();
9384     ConsString* cons_string = String::VisitFlat(&hasher, string);
9385     // The string was flat.
9386     if (cons_string == NULL) return hasher.GetHashField();
9387     // This is a ConsString, iterate across it.
9388     ConsStringIteratorOp op(cons_string);
9389     int offset;
9390     while (NULL != (string = op.Next(&offset))) {
9391       String::VisitFlat(&hasher, string, offset);
9392     }
9393     return hasher.GetHashField();
9394   }
9395   inline void VisitOneByteString(const uint8_t* chars, int length) {
9396     AddCharacters(chars, length);
9397   }
9398   inline void VisitTwoByteString(const uint16_t* chars, int length) {
9399     AddCharacters(chars, length);
9400   }
9401
9402  private:
9403   inline IteratingStringHasher(int len, uint32_t seed)
9404       : StringHasher(len, seed) {
9405   }
9406   DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher);
9407 };
9408
9409
9410 uint32_t String::ComputeAndSetHash() {
9411   // Should only be called if hash code has not yet been computed.
9412   ASSERT(!HasHashCode());
9413
9414   // Store the hash code in the object.
9415   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
9416   set_hash_field(field);
9417
9418   // Check the hash code is there.
9419   ASSERT(HasHashCode());
9420   uint32_t result = field >> kHashShift;
9421   ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
9422   return result;
9423 }
9424
9425
9426 bool String::ComputeArrayIndex(uint32_t* index) {
9427   int length = this->length();
9428   if (length == 0 || length > kMaxArrayIndexSize) return false;
9429   ConsStringIteratorOp op;
9430   StringCharacterStream stream(this, &op);
9431   uint16_t ch = stream.GetNext();
9432
9433   // If the string begins with a '0' character, it must only consist
9434   // of it to be a legal array index.
9435   if (ch == '0') {
9436     *index = 0;
9437     return length == 1;
9438   }
9439
9440   // Convert string to uint32 array index; character by character.
9441   int d = ch - '0';
9442   if (d < 0 || d > 9) return false;
9443   uint32_t result = d;
9444   while (stream.HasMore()) {
9445     d = stream.GetNext() - '0';
9446     if (d < 0 || d > 9) return false;
9447     // Check that the new result is below the 32 bit limit.
9448     if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
9449     result = (result * 10) + d;
9450   }
9451
9452   *index = result;
9453   return true;
9454 }
9455
9456
9457 bool String::SlowAsArrayIndex(uint32_t* index) {
9458   if (length() <= kMaxCachedArrayIndexLength) {
9459     Hash();  // force computation of hash code
9460     uint32_t field = hash_field();
9461     if ((field & kIsNotArrayIndexMask) != 0) return false;
9462     // Isolate the array index form the full hash field.
9463     *index = ArrayIndexValueBits::decode(field);
9464     return true;
9465   } else {
9466     return ComputeArrayIndex(index);
9467   }
9468 }
9469
9470
9471 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
9472   int new_size, old_size;
9473   int old_length = string->length();
9474   if (old_length <= new_length) return string;
9475
9476   if (string->IsSeqOneByteString()) {
9477     old_size = SeqOneByteString::SizeFor(old_length);
9478     new_size = SeqOneByteString::SizeFor(new_length);
9479   } else {
9480     ASSERT(string->IsSeqTwoByteString());
9481     old_size = SeqTwoByteString::SizeFor(old_length);
9482     new_size = SeqTwoByteString::SizeFor(new_length);
9483   }
9484
9485   int delta = old_size - new_size;
9486
9487   Address start_of_string = string->address();
9488   ASSERT_OBJECT_ALIGNED(start_of_string);
9489   ASSERT_OBJECT_ALIGNED(start_of_string + new_size);
9490
9491   Heap* heap = string->GetHeap();
9492   NewSpace* newspace = heap->new_space();
9493   if (newspace->Contains(start_of_string) &&
9494       newspace->top() == start_of_string + old_size) {
9495     // Last allocated object in new space.  Simply lower allocation top.
9496     newspace->set_top(start_of_string + new_size);
9497   } else {
9498     // Sizes are pointer size aligned, so that we can use filler objects
9499     // that are a multiple of pointer size.
9500     heap->CreateFillerObjectAt(start_of_string + new_size, delta);
9501   }
9502   heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR);
9503
9504   // We are storing the new length using release store after creating a filler
9505   // for the left-over space to avoid races with the sweeper thread.
9506   string->synchronized_set_length(new_length);
9507
9508   if (new_length == 0) return heap->isolate()->factory()->empty_string();
9509   return string;
9510 }
9511
9512
9513 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
9514   // For array indexes mix the length into the hash as an array index could
9515   // be zero.
9516   ASSERT(length > 0);
9517   ASSERT(length <= String::kMaxArrayIndexSize);
9518   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
9519          (1 << String::kArrayIndexValueBits));
9520
9521   value <<= String::ArrayIndexValueBits::kShift;
9522   value |= length << String::ArrayIndexLengthBits::kShift;
9523
9524   ASSERT((value & String::kIsNotArrayIndexMask) == 0);
9525   ASSERT((length > String::kMaxCachedArrayIndexLength) ||
9526          (value & String::kContainsCachedArrayIndexMask) == 0);
9527   return value;
9528 }
9529
9530
9531 uint32_t StringHasher::GetHashField() {
9532   if (length_ <= String::kMaxHashCalcLength) {
9533     if (is_array_index_) {
9534       return MakeArrayIndexHash(array_index_, length_);
9535     }
9536     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
9537            String::kIsNotArrayIndexMask;
9538   } else {
9539     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
9540   }
9541 }
9542
9543
9544 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
9545                                        uint32_t seed,
9546                                        int* utf16_length_out) {
9547   int vector_length = chars.length();
9548   // Handle some edge cases
9549   if (vector_length <= 1) {
9550     ASSERT(vector_length == 0 ||
9551            static_cast<uint8_t>(chars.start()[0]) <=
9552                unibrow::Utf8::kMaxOneByteChar);
9553     *utf16_length_out = vector_length;
9554     return HashSequentialString(chars.start(), vector_length, seed);
9555   }
9556   // Start with a fake length which won't affect computation.
9557   // It will be updated later.
9558   StringHasher hasher(String::kMaxArrayIndexSize, seed);
9559   unsigned remaining = static_cast<unsigned>(vector_length);
9560   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
9561   int utf16_length = 0;
9562   bool is_index = true;
9563   ASSERT(hasher.is_array_index_);
9564   while (remaining > 0) {
9565     unsigned consumed = 0;
9566     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
9567     ASSERT(consumed > 0 && consumed <= remaining);
9568     stream += consumed;
9569     remaining -= consumed;
9570     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
9571     utf16_length += is_two_characters ? 2 : 1;
9572     // No need to keep hashing. But we do need to calculate utf16_length.
9573     if (utf16_length > String::kMaxHashCalcLength) continue;
9574     if (is_two_characters) {
9575       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
9576       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
9577       hasher.AddCharacter(c1);
9578       hasher.AddCharacter(c2);
9579       if (is_index) is_index = hasher.UpdateIndex(c1);
9580       if (is_index) is_index = hasher.UpdateIndex(c2);
9581     } else {
9582       hasher.AddCharacter(c);
9583       if (is_index) is_index = hasher.UpdateIndex(c);
9584     }
9585   }
9586   *utf16_length_out = static_cast<int>(utf16_length);
9587   // Must set length here so that hash computation is correct.
9588   hasher.length_ = utf16_length;
9589   return hasher.GetHashField();
9590 }
9591
9592
9593 void String::PrintOn(FILE* file) {
9594   int length = this->length();
9595   for (int i = 0; i < length; i++) {
9596     PrintF(file, "%c", Get(i));
9597   }
9598 }
9599
9600
9601 static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) {
9602   int live_enum = map->EnumLength();
9603   if (live_enum == kInvalidEnumCacheSentinel) {
9604     live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
9605   }
9606   if (live_enum == 0) return descriptors->ClearEnumCache();
9607
9608   FixedArray* enum_cache = descriptors->GetEnumCache();
9609
9610   int to_trim = enum_cache->length() - live_enum;
9611   if (to_trim <= 0) return;
9612   RightTrimFixedArray<Heap::FROM_GC>(
9613       heap, descriptors->GetEnumCache(), to_trim);
9614
9615   if (!descriptors->HasEnumIndicesCache()) return;
9616   FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache();
9617   RightTrimFixedArray<Heap::FROM_GC>(heap, enum_indices_cache, to_trim);
9618 }
9619
9620
9621 static void TrimDescriptorArray(Heap* heap,
9622                                 Map* map,
9623                                 DescriptorArray* descriptors,
9624                                 int number_of_own_descriptors) {
9625   int number_of_descriptors = descriptors->number_of_descriptors_storage();
9626   int to_trim = number_of_descriptors - number_of_own_descriptors;
9627   if (to_trim == 0) return;
9628
9629   RightTrimFixedArray<Heap::FROM_GC>(
9630       heap, descriptors, to_trim * DescriptorArray::kDescriptorSize);
9631   descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
9632
9633   if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors);
9634   descriptors->Sort();
9635 }
9636
9637
9638 // Clear a possible back pointer in case the transition leads to a dead map.
9639 // Return true in case a back pointer has been cleared and false otherwise.
9640 static bool ClearBackPointer(Heap* heap, Map* target) {
9641   if (Marking::MarkBitFrom(target).Get()) return false;
9642   target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
9643   return true;
9644 }
9645
9646
9647 // TODO(mstarzinger): This method should be moved into MarkCompactCollector,
9648 // because it cannot be called from outside the GC and we already have methods
9649 // depending on the transitions layout in the GC anyways.
9650 void Map::ClearNonLiveTransitions(Heap* heap) {
9651   // If there are no transitions to be cleared, return.
9652   // TODO(verwaest) Should be an assert, otherwise back pointers are not
9653   // properly cleared.
9654   if (!HasTransitionArray()) return;
9655
9656   TransitionArray* t = transitions();
9657   MarkCompactCollector* collector = heap->mark_compact_collector();
9658
9659   int transition_index = 0;
9660
9661   DescriptorArray* descriptors = instance_descriptors();
9662   bool descriptors_owner_died = false;
9663
9664   // Compact all live descriptors to the left.
9665   for (int i = 0; i < t->number_of_transitions(); ++i) {
9666     Map* target = t->GetTarget(i);
9667     if (ClearBackPointer(heap, target)) {
9668       if (target->instance_descriptors() == descriptors) {
9669         descriptors_owner_died = true;
9670       }
9671     } else {
9672       if (i != transition_index) {
9673         Name* key = t->GetKey(i);
9674         t->SetKey(transition_index, key);
9675         Object** key_slot = t->GetKeySlot(transition_index);
9676         collector->RecordSlot(key_slot, key_slot, key);
9677         // Target slots do not need to be recorded since maps are not compacted.
9678         t->SetTarget(transition_index, t->GetTarget(i));
9679       }
9680       transition_index++;
9681     }
9682   }
9683
9684   // If there are no transitions to be cleared, return.
9685   // TODO(verwaest) Should be an assert, otherwise back pointers are not
9686   // properly cleared.
9687   if (transition_index == t->number_of_transitions()) return;
9688
9689   int number_of_own_descriptors = NumberOfOwnDescriptors();
9690
9691   if (descriptors_owner_died) {
9692     if (number_of_own_descriptors > 0) {
9693       TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors);
9694       ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
9695       set_owns_descriptors(true);
9696     } else {
9697       ASSERT(descriptors == GetHeap()->empty_descriptor_array());
9698     }
9699   }
9700
9701   // Note that we never eliminate a transition array, though we might right-trim
9702   // such that number_of_transitions() == 0. If this assumption changes,
9703   // TransitionArray::CopyInsert() will need to deal with the case that a
9704   // transition array disappeared during GC.
9705   int trim = t->number_of_transitions() - transition_index;
9706   if (trim > 0) {
9707     RightTrimFixedArray<Heap::FROM_GC>(heap, t, t->IsSimpleTransition()
9708         ? trim : trim * TransitionArray::kTransitionSize);
9709   }
9710   ASSERT(HasTransitionArray());
9711 }
9712
9713
9714 int Map::Hash() {
9715   // For performance reasons we only hash the 3 most variable fields of a map:
9716   // constructor, prototype and bit_field2.
9717
9718   // Shift away the tag.
9719   int hash = (static_cast<uint32_t>(
9720         reinterpret_cast<uintptr_t>(constructor())) >> 2);
9721
9722   // XOR-ing the prototype and constructor directly yields too many zero bits
9723   // when the two pointers are close (which is fairly common).
9724   // To avoid this we shift the prototype 4 bits relatively to the constructor.
9725   hash ^= (static_cast<uint32_t>(
9726         reinterpret_cast<uintptr_t>(prototype())) << 2);
9727
9728   return hash ^ (hash >> 16) ^ bit_field2();
9729 }
9730
9731
9732 static bool CheckEquivalent(Map* first, Map* second) {
9733   return
9734     first->constructor() == second->constructor() &&
9735     first->prototype() == second->prototype() &&
9736     first->instance_type() == second->instance_type() &&
9737     first->bit_field() == second->bit_field() &&
9738     first->bit_field2() == second->bit_field2() &&
9739     first->is_frozen() == second->is_frozen() &&
9740     first->has_instance_call_handler() == second->has_instance_call_handler();
9741 }
9742
9743
9744 bool Map::EquivalentToForTransition(Map* other) {
9745   return CheckEquivalent(this, other);
9746 }
9747
9748
9749 bool Map::EquivalentToForNormalization(Map* other,
9750                                        PropertyNormalizationMode mode) {
9751   int properties = mode == CLEAR_INOBJECT_PROPERTIES
9752       ? 0 : other->inobject_properties();
9753   return CheckEquivalent(this, other) && inobject_properties() == properties;
9754 }
9755
9756
9757 void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) {
9758   ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR);
9759   while (!code_iter.is_finished()) {
9760     v->VisitCodeEntry(reinterpret_cast<Address>(
9761         RawFieldOfElementAt(code_iter.next_index())));
9762   }
9763
9764   ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR);
9765   while (!heap_iter.is_finished()) {
9766     v->VisitPointer(RawFieldOfElementAt(heap_iter.next_index()));
9767   }
9768 }
9769
9770
9771 void ConstantPoolArray::ClearPtrEntries(Isolate* isolate) {
9772   Type type[] = { CODE_PTR, HEAP_PTR };
9773   Address default_value[] = {
9774         isolate->builtins()->builtin(Builtins::kIllegal)->entry(),
9775         reinterpret_cast<Address>(isolate->heap()->undefined_value()) };
9776
9777   for (int i = 0; i < 2; ++i) {
9778     for (int s = 0; s <= final_section(); ++s) {
9779       LayoutSection section = static_cast<LayoutSection>(s);
9780       if (number_of_entries(type[i], section) > 0) {
9781         int offset = OffsetOfElementAt(first_index(type[i], section));
9782         MemsetPointer(
9783           reinterpret_cast<Address*>(HeapObject::RawField(this, offset)),
9784           default_value[i],
9785           number_of_entries(type[i], section));
9786       }
9787     }
9788   }
9789 }
9790
9791
9792 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
9793   // Iterate over all fields in the body but take care in dealing with
9794   // the code entry.
9795   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
9796   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9797   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9798 }
9799
9800
9801 void JSFunction::MarkForOptimization() {
9802   ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
9803   ASSERT(!IsOptimized());
9804   ASSERT(shared()->allows_lazy_compilation() ||
9805          code()->optimizable());
9806   ASSERT(!shared()->is_generator());
9807   set_code_no_write_barrier(
9808       GetIsolate()->builtins()->builtin(Builtins::kCompileOptimized));
9809   // No write barrier required, since the builtin is part of the root set.
9810 }
9811
9812
9813 void JSFunction::MarkForConcurrentOptimization() {
9814   ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
9815   ASSERT(!IsOptimized());
9816   ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
9817   ASSERT(!shared()->is_generator());
9818   ASSERT(GetIsolate()->concurrent_recompilation_enabled());
9819   if (FLAG_trace_concurrent_recompilation) {
9820     PrintF("  ** Marking ");
9821     PrintName();
9822     PrintF(" for concurrent recompilation.\n");
9823   }
9824   set_code_no_write_barrier(
9825       GetIsolate()->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9826   // No write barrier required, since the builtin is part of the root set.
9827 }
9828
9829
9830 void JSFunction::MarkInOptimizationQueue() {
9831   // We can only arrive here via the concurrent-recompilation builtin.  If
9832   // break points were set, the code would point to the lazy-compile builtin.
9833   ASSERT(!GetIsolate()->DebuggerHasBreakPoints());
9834   ASSERT(IsMarkedForConcurrentOptimization() && !IsOptimized());
9835   ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
9836   ASSERT(GetIsolate()->concurrent_recompilation_enabled());
9837   if (FLAG_trace_concurrent_recompilation) {
9838     PrintF("  ** Queueing ");
9839     PrintName();
9840     PrintF(" for concurrent recompilation.\n");
9841   }
9842   set_code_no_write_barrier(
9843       GetIsolate()->builtins()->builtin(Builtins::kInOptimizationQueue));
9844   // No write barrier required, since the builtin is part of the root set.
9845 }
9846
9847
9848 void SharedFunctionInfo::AddToOptimizedCodeMap(
9849     Handle<SharedFunctionInfo> shared,
9850     Handle<Context> native_context,
9851     Handle<Code> code,
9852     Handle<FixedArray> literals,
9853     BailoutId osr_ast_id) {
9854   Isolate* isolate = shared->GetIsolate();
9855   ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
9856   ASSERT(native_context->IsNativeContext());
9857   STATIC_ASSERT(kEntryLength == 4);
9858   Handle<FixedArray> new_code_map;
9859   Handle<Object> value(shared->optimized_code_map(), isolate);
9860   int old_length;
9861   if (value->IsSmi()) {
9862     // No optimized code map.
9863     ASSERT_EQ(0, Smi::cast(*value)->value());
9864     // Create 3 entries per context {context, code, literals}.
9865     new_code_map = isolate->factory()->NewFixedArray(kInitialLength);
9866     old_length = kEntriesStart;
9867   } else {
9868     // Copy old map and append one new entry.
9869     Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value);
9870     ASSERT_EQ(-1, shared->SearchOptimizedCodeMap(*native_context, osr_ast_id));
9871     old_length = old_code_map->length();
9872     new_code_map = FixedArray::CopySize(
9873         old_code_map, old_length + kEntryLength);
9874     // Zap the old map for the sake of the heap verifier.
9875     if (Heap::ShouldZapGarbage()) {
9876       Object** data = old_code_map->data_start();
9877       MemsetPointer(data, isolate->heap()->the_hole_value(), old_length);
9878     }
9879   }
9880   new_code_map->set(old_length + kContextOffset, *native_context);
9881   new_code_map->set(old_length + kCachedCodeOffset, *code);
9882   new_code_map->set(old_length + kLiteralsOffset, *literals);
9883   new_code_map->set(old_length + kOsrAstIdOffset,
9884                     Smi::FromInt(osr_ast_id.ToInt()));
9885
9886 #ifdef DEBUG
9887   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9888     ASSERT(new_code_map->get(i + kContextOffset)->IsNativeContext());
9889     ASSERT(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9890     ASSERT(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9891            Code::OPTIMIZED_FUNCTION);
9892     ASSERT(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9893     ASSERT(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9894   }
9895 #endif
9896   shared->set_optimized_code_map(*new_code_map);
9897 }
9898
9899
9900 FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) {
9901   ASSERT(index > kEntriesStart);
9902   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9903   if (!bound()) {
9904     FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
9905     ASSERT_NE(NULL, cached_literals);
9906     return cached_literals;
9907   }
9908   return NULL;
9909 }
9910
9911
9912 Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) {
9913   ASSERT(index > kEntriesStart);
9914   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9915   Code* code = Code::cast(code_map->get(index));
9916   ASSERT_NE(NULL, code);
9917   return code;
9918 }
9919
9920
9921 void SharedFunctionInfo::ClearOptimizedCodeMap() {
9922   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9923
9924   // If the next map link slot is already used then the function was
9925   // enqueued with code flushing and we remove it now.
9926   if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9927     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
9928     flusher->EvictOptimizedCodeMap(this);
9929   }
9930
9931   ASSERT(code_map->get(kNextMapIndex)->IsUndefined());
9932   set_optimized_code_map(Smi::FromInt(0));
9933 }
9934
9935
9936 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
9937                                                    const char* reason) {
9938   DisallowHeapAllocation no_gc;
9939   if (optimized_code_map()->IsSmi()) return;
9940
9941   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9942   int dst = kEntriesStart;
9943   int length = code_map->length();
9944   for (int src = kEntriesStart; src < length; src += kEntryLength) {
9945     ASSERT(code_map->get(src)->IsNativeContext());
9946     if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9947       // Evict the src entry by not copying it to the dst entry.
9948       if (FLAG_trace_opt) {
9949         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9950         ShortPrint();
9951         BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9952         if (osr.IsNone()) {
9953           PrintF("]\n");
9954         } else {
9955           PrintF(" (osr ast id %d)]\n", osr.ToInt());
9956         }
9957       }
9958     } else {
9959       // Keep the src entry by copying it to the dst entry.
9960       if (dst != src) {
9961         code_map->set(dst + kContextOffset,
9962                       code_map->get(src + kContextOffset));
9963         code_map->set(dst + kCachedCodeOffset,
9964                       code_map->get(src + kCachedCodeOffset));
9965         code_map->set(dst + kLiteralsOffset,
9966                       code_map->get(src + kLiteralsOffset));
9967         code_map->set(dst + kOsrAstIdOffset,
9968                       code_map->get(src + kOsrAstIdOffset));
9969       }
9970       dst += kEntryLength;
9971     }
9972   }
9973   if (dst != length) {
9974     // Always trim even when array is cleared because of heap verifier.
9975     RightTrimFixedArray<Heap::FROM_MUTATOR>(GetHeap(), code_map, length - dst);
9976     if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap();
9977   }
9978 }
9979
9980
9981 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
9982   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9983   ASSERT(shrink_by % kEntryLength == 0);
9984   ASSERT(shrink_by <= code_map->length() - kEntriesStart);
9985   // Always trim even when array is cleared because of heap verifier.
9986   RightTrimFixedArray<Heap::FROM_GC>(GetHeap(), code_map, shrink_by);
9987   if (code_map->length() == kEntriesStart) {
9988     ClearOptimizedCodeMap();
9989   }
9990 }
9991
9992
9993 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) {
9994   if (object->IsGlobalObject()) return;
9995
9996   // Make sure prototypes are fast objects and their maps have the bit set
9997   // so they remain fast.
9998   if (!object->HasFastProperties()) {
9999     TransformToFastProperties(object, 0);
10000   }
10001 }
10002
10003
10004 Handle<Object> CacheInitialJSArrayMaps(
10005     Handle<Context> native_context, Handle<Map> initial_map) {
10006   // Replace all of the cached initial array maps in the native context with
10007   // the appropriate transitioned elements kind maps.
10008   Factory* factory = native_context->GetIsolate()->factory();
10009   Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
10010       kElementsKindCount, TENURED);
10011
10012   Handle<Map> current_map = initial_map;
10013   ElementsKind kind = current_map->elements_kind();
10014   ASSERT(kind == GetInitialFastElementsKind());
10015   maps->set(kind, *current_map);
10016   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
10017        i < kFastElementsKindCount; ++i) {
10018     Handle<Map> new_map;
10019     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
10020     if (current_map->HasElementsTransition()) {
10021       new_map = handle(current_map->elements_transition_map());
10022       ASSERT(new_map->elements_kind() == next_kind);
10023     } else {
10024       new_map = Map::CopyAsElementsKind(
10025           current_map, next_kind, INSERT_TRANSITION);
10026     }
10027     maps->set(next_kind, *new_map);
10028     current_map = new_map;
10029   }
10030   native_context->set_js_array_maps(*maps);
10031   return initial_map;
10032 }
10033
10034
10035 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
10036                                       Handle<Object> value) {
10037   Isolate* isolate = function->GetIsolate();
10038
10039   ASSERT(value->IsJSReceiver());
10040
10041   // First some logic for the map of the prototype to make sure it is in fast
10042   // mode.
10043   if (value->IsJSObject()) {
10044     JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
10045   }
10046
10047   // Now some logic for the maps of the objects that are created by using this
10048   // function as a constructor.
10049   if (function->has_initial_map()) {
10050     // If the function has allocated the initial map replace it with a
10051     // copy containing the new prototype.  Also complete any in-object
10052     // slack tracking that is in progress at this point because it is
10053     // still tracking the old copy.
10054     if (function->IsInobjectSlackTrackingInProgress()) {
10055       function->CompleteInobjectSlackTracking();
10056     }
10057     Handle<Map> initial_map(function->initial_map(), isolate);
10058     Handle<Map> new_map = Map::Copy(initial_map);
10059     new_map->set_prototype(*value);
10060
10061     // If the function is used as the global Array function, cache the
10062     // initial map (and transitioned versions) in the native context.
10063     Context* native_context = function->context()->native_context();
10064     Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX);
10065     if (array_function->IsJSFunction() &&
10066         *function == JSFunction::cast(array_function)) {
10067       CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
10068     }
10069
10070     function->set_initial_map(*new_map);
10071
10072     // Deoptimize all code that embeds the previous initial map.
10073     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
10074         isolate, DependentCode::kInitialMapChangedGroup);
10075   } else {
10076     // Put the value in the initial map field until an initial map is
10077     // needed.  At that point, a new initial map is created and the
10078     // prototype is put into the initial map where it belongs.
10079     function->set_prototype_or_initial_map(*value);
10080   }
10081   isolate->heap()->ClearInstanceofCache();
10082 }
10083
10084
10085 void JSFunction::SetPrototype(Handle<JSFunction> function,
10086                               Handle<Object> value) {
10087   ASSERT(function->should_have_prototype());
10088   Handle<Object> construct_prototype = value;
10089
10090   // If the value is not a JSReceiver, store the value in the map's
10091   // constructor field so it can be accessed.  Also, set the prototype
10092   // used for constructing objects to the original object prototype.
10093   // See ECMA-262 13.2.2.
10094   if (!value->IsJSReceiver()) {
10095     // Copy the map so this does not affect unrelated functions.
10096     // Remove map transitions because they point to maps with a
10097     // different prototype.
10098     Handle<Map> new_map = Map::Copy(handle(function->map()));
10099
10100     JSObject::MigrateToMap(function, new_map);
10101     new_map->set_constructor(*value);
10102     new_map->set_non_instance_prototype(true);
10103     Isolate* isolate = new_map->GetIsolate();
10104     construct_prototype = handle(
10105         isolate->context()->native_context()->initial_object_prototype(),
10106         isolate);
10107   } else {
10108     function->map()->set_non_instance_prototype(false);
10109   }
10110
10111   return SetInstancePrototype(function, construct_prototype);
10112 }
10113
10114
10115 bool JSFunction::RemovePrototype() {
10116   Context* native_context = context()->native_context();
10117   Map* no_prototype_map = shared()->strict_mode() == SLOPPY
10118       ? native_context->sloppy_function_without_prototype_map()
10119       : native_context->strict_function_without_prototype_map();
10120
10121   if (map() == no_prototype_map) return true;
10122
10123 #ifdef DEBUG
10124   if (map() != (shared()->strict_mode() == SLOPPY
10125                    ? native_context->sloppy_function_map()
10126                    : native_context->strict_function_map())) {
10127     return false;
10128   }
10129 #endif
10130
10131   set_map(no_prototype_map);
10132   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
10133   return true;
10134 }
10135
10136
10137 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
10138   if (function->has_initial_map()) return;
10139   Isolate* isolate = function->GetIsolate();
10140
10141   // First create a new map with the size and number of in-object properties
10142   // suggested by the function.
10143   InstanceType instance_type;
10144   int instance_size;
10145   int in_object_properties;
10146   if (function->shared()->is_generator()) {
10147     instance_type = JS_GENERATOR_OBJECT_TYPE;
10148     instance_size = JSGeneratorObject::kSize;
10149     in_object_properties = 0;
10150   } else {
10151     instance_type = JS_OBJECT_TYPE;
10152     instance_size = function->shared()->CalculateInstanceSize();
10153     in_object_properties = function->shared()->CalculateInObjectProperties();
10154   }
10155   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
10156
10157   // Fetch or allocate prototype.
10158   Handle<Object> prototype;
10159   if (function->has_instance_prototype()) {
10160     prototype = handle(function->instance_prototype(), isolate);
10161     for (Handle<Object> p = prototype; !p->IsNull() && !p->IsJSProxy();
10162          p = Object::GetPrototype(isolate, p)) {
10163       JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(p));
10164     }
10165   } else {
10166     prototype = isolate->factory()->NewFunctionPrototype(function);
10167   }
10168   map->set_inobject_properties(in_object_properties);
10169   map->set_unused_property_fields(in_object_properties);
10170   map->set_prototype(*prototype);
10171   ASSERT(map->has_fast_object_elements());
10172
10173   // Finally link initial map and constructor function.
10174   function->set_initial_map(*map);
10175   map->set_constructor(*function);
10176
10177   if (!function->shared()->is_generator()) {
10178     function->StartInobjectSlackTracking();
10179   }
10180 }
10181
10182
10183 void JSFunction::SetInstanceClassName(String* name) {
10184   shared()->set_instance_class_name(name);
10185 }
10186
10187
10188 void JSFunction::PrintName(FILE* out) {
10189   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
10190   PrintF(out, "%s", name.get());
10191 }
10192
10193
10194 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) {
10195   return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex));
10196 }
10197
10198
10199 // The filter is a pattern that matches function names in this way:
10200 //   "*"      all; the default
10201 //   "-"      all but the top-level function
10202 //   "-name"  all but the function "name"
10203 //   ""       only the top-level function
10204 //   "name"   only the function "name"
10205 //   "name*"  only functions starting with "name"
10206 bool JSFunction::PassesFilter(const char* raw_filter) {
10207   if (*raw_filter == '*') return true;
10208   String* name = shared()->DebugName();
10209   Vector<const char> filter = CStrVector(raw_filter);
10210   if (filter.length() == 0) return name->length() == 0;
10211   if (filter[0] == '-') {
10212     // Negative filter.
10213     if (filter.length() == 1) {
10214       return (name->length() != 0);
10215     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
10216       return false;
10217     }
10218     if (filter[filter.length() - 1] == '*' &&
10219         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
10220       return false;
10221     }
10222     return true;
10223
10224   } else if (name->IsUtf8EqualTo(filter)) {
10225     return true;
10226   }
10227   if (filter[filter.length() - 1] == '*' &&
10228       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
10229     return true;
10230   }
10231   return false;
10232 }
10233
10234
10235 void Oddball::Initialize(Isolate* isolate,
10236                          Handle<Oddball> oddball,
10237                          const char* to_string,
10238                          Handle<Object> to_number,
10239                          byte kind) {
10240   Handle<String> internalized_to_string =
10241       isolate->factory()->InternalizeUtf8String(to_string);
10242   oddball->set_to_string(*internalized_to_string);
10243   oddball->set_to_number(*to_number);
10244   oddball->set_kind(kind);
10245 }
10246
10247
10248 void Script::InitLineEnds(Handle<Script> script) {
10249   if (!script->line_ends()->IsUndefined()) return;
10250
10251   Isolate* isolate = script->GetIsolate();
10252
10253   if (!script->source()->IsString()) {
10254     ASSERT(script->source()->IsUndefined());
10255     Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
10256     script->set_line_ends(*empty);
10257     ASSERT(script->line_ends()->IsFixedArray());
10258     return;
10259   }
10260
10261   Handle<String> src(String::cast(script->source()), isolate);
10262
10263   Handle<FixedArray> array = String::CalculateLineEnds(src, true);
10264
10265   if (*array != isolate->heap()->empty_fixed_array()) {
10266     array->set_map(isolate->heap()->fixed_cow_array_map());
10267   }
10268
10269   script->set_line_ends(*array);
10270   ASSERT(script->line_ends()->IsFixedArray());
10271 }
10272
10273
10274 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
10275   int line_number = GetLineNumber(script, code_pos);
10276   if (line_number == -1) return -1;
10277
10278   DisallowHeapAllocation no_allocation;
10279   FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
10280   line_number = line_number - script->line_offset()->value();
10281   if (line_number == 0) return code_pos + script->column_offset()->value();
10282   int prev_line_end_pos =
10283       Smi::cast(line_ends_array->get(line_number - 1))->value();
10284   return code_pos - (prev_line_end_pos + 1);
10285 }
10286
10287
10288 int Script::GetLineNumberWithArray(int code_pos) {
10289   DisallowHeapAllocation no_allocation;
10290   ASSERT(line_ends()->IsFixedArray());
10291   FixedArray* line_ends_array = FixedArray::cast(line_ends());
10292   int line_ends_len = line_ends_array->length();
10293   if (line_ends_len == 0) return -1;
10294
10295   if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
10296     return line_offset()->value();
10297   }
10298
10299   int left = 0;
10300   int right = line_ends_len;
10301   while (int half = (right - left) / 2) {
10302     if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
10303       right -= half;
10304     } else {
10305       left += half;
10306     }
10307   }
10308   return right + line_offset()->value();
10309 }
10310
10311
10312 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
10313   InitLineEnds(script);
10314   return script->GetLineNumberWithArray(code_pos);
10315 }
10316
10317
10318 int Script::GetLineNumber(int code_pos) {
10319   DisallowHeapAllocation no_allocation;
10320   if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
10321
10322   // Slow mode: we do not have line_ends. We have to iterate through source.
10323   if (!source()->IsString()) return -1;
10324
10325   String* source_string = String::cast(source());
10326   int line = 0;
10327   int len = source_string->length();
10328   for (int pos = 0; pos < len; pos++) {
10329     if (pos == code_pos) break;
10330     if (source_string->Get(pos) == '\n') line++;
10331   }
10332   return line;
10333 }
10334
10335
10336 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
10337   Isolate* isolate = script->GetIsolate();
10338   Handle<String> name_or_source_url_key =
10339       isolate->factory()->InternalizeOneByteString(
10340           STATIC_ASCII_VECTOR("nameOrSourceURL"));
10341   Handle<JSObject> script_wrapper = Script::GetWrapper(script);
10342   Handle<Object> property = Object::GetProperty(
10343       script_wrapper, name_or_source_url_key).ToHandleChecked();
10344   ASSERT(property->IsJSFunction());
10345   Handle<JSFunction> method = Handle<JSFunction>::cast(property);
10346   Handle<Object> result;
10347   // Do not check against pending exception, since this function may be called
10348   // when an exception has already been pending.
10349   if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
10350     return isolate->factory()->undefined_value();
10351   }
10352   return result;
10353 }
10354
10355
10356 // Wrappers for scripts are kept alive and cached in weak global
10357 // handles referred from foreign objects held by the scripts as long as
10358 // they are used. When they are not used anymore, the garbage
10359 // collector will call the weak callback on the global handle
10360 // associated with the wrapper and get rid of both the wrapper and the
10361 // handle.
10362 static void ClearWrapperCache(
10363     const v8::WeakCallbackData<v8::Value, void>& data) {
10364   Object** location = reinterpret_cast<Object**>(data.GetParameter());
10365   JSValue* wrapper = JSValue::cast(*location);
10366   Foreign* foreign = Script::cast(wrapper->value())->wrapper();
10367   ASSERT_EQ(foreign->foreign_address(), reinterpret_cast<Address>(location));
10368   foreign->set_foreign_address(0);
10369   GlobalHandles::Destroy(location);
10370   Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate());
10371   isolate->counters()->script_wrappers()->Decrement();
10372 }
10373
10374
10375 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
10376   if (script->wrapper()->foreign_address() != NULL) {
10377     // Return a handle for the existing script wrapper from the cache.
10378     return Handle<JSValue>(
10379         *reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
10380   }
10381   Isolate* isolate = script->GetIsolate();
10382   // Construct a new script wrapper.
10383   isolate->counters()->script_wrappers()->Increment();
10384   Handle<JSFunction> constructor = isolate->script_function();
10385   Handle<JSValue> result =
10386       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
10387
10388   result->set_value(*script);
10389
10390   // Create a new weak global handle and use it to cache the wrapper
10391   // for future use. The cache will automatically be cleared by the
10392   // garbage collector when it is not used anymore.
10393   Handle<Object> handle = isolate->global_handles()->Create(*result);
10394   GlobalHandles::MakeWeak(handle.location(),
10395                           reinterpret_cast<void*>(handle.location()),
10396                           &ClearWrapperCache);
10397   script->wrapper()->set_foreign_address(
10398       reinterpret_cast<Address>(handle.location()));
10399   return result;
10400 }
10401
10402
10403 String* SharedFunctionInfo::DebugName() {
10404   Object* n = name();
10405   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
10406   return String::cast(n);
10407 }
10408
10409
10410 bool SharedFunctionInfo::HasSourceCode() {
10411   return !script()->IsUndefined() &&
10412          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
10413 }
10414
10415
10416 Handle<Object> SharedFunctionInfo::GetSourceCode() {
10417   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
10418   Handle<String> source(String::cast(Script::cast(script())->source()));
10419   return GetIsolate()->factory()->NewSubString(
10420       source, start_position(), end_position());
10421 }
10422
10423
10424 bool SharedFunctionInfo::IsInlineable() {
10425   // Check that the function has a script associated with it.
10426   if (!script()->IsScript()) return false;
10427   if (optimization_disabled()) return false;
10428   // If we never ran this (unlikely) then lets try to optimize it.
10429   if (code()->kind() != Code::FUNCTION) return true;
10430   return code()->optimizable();
10431 }
10432
10433
10434 int SharedFunctionInfo::SourceSize() {
10435   return end_position() - start_position();
10436 }
10437
10438
10439 int SharedFunctionInfo::CalculateInstanceSize() {
10440   int instance_size =
10441       JSObject::kHeaderSize +
10442       expected_nof_properties() * kPointerSize;
10443   if (instance_size > JSObject::kMaxInstanceSize) {
10444     instance_size = JSObject::kMaxInstanceSize;
10445   }
10446   return instance_size;
10447 }
10448
10449
10450 int SharedFunctionInfo::CalculateInObjectProperties() {
10451   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
10452 }
10453
10454
10455 // Support function for printing the source code to a StringStream
10456 // without any allocation in the heap.
10457 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
10458                                          int max_length) {
10459   // For some native functions there is no source.
10460   if (!HasSourceCode()) {
10461     accumulator->Add("<No Source>");
10462     return;
10463   }
10464
10465   // Get the source for the script which this function came from.
10466   // Don't use String::cast because we don't want more assertion errors while
10467   // we are already creating a stack dump.
10468   String* script_source =
10469       reinterpret_cast<String*>(Script::cast(script())->source());
10470
10471   if (!script_source->LooksValid()) {
10472     accumulator->Add("<Invalid Source>");
10473     return;
10474   }
10475
10476   if (!is_toplevel()) {
10477     accumulator->Add("function ");
10478     Object* name = this->name();
10479     if (name->IsString() && String::cast(name)->length() > 0) {
10480       accumulator->PrintName(name);
10481     }
10482   }
10483
10484   int len = end_position() - start_position();
10485   if (len <= max_length || max_length < 0) {
10486     accumulator->Put(script_source, start_position(), end_position());
10487   } else {
10488     accumulator->Put(script_source,
10489                      start_position(),
10490                      start_position() + max_length);
10491     accumulator->Add("...\n");
10492   }
10493 }
10494
10495
10496 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
10497   if (code->instruction_size() != recompiled->instruction_size()) return false;
10498   ByteArray* code_relocation = code->relocation_info();
10499   ByteArray* recompiled_relocation = recompiled->relocation_info();
10500   int length = code_relocation->length();
10501   if (length != recompiled_relocation->length()) return false;
10502   int compare = memcmp(code_relocation->GetDataStartAddress(),
10503                        recompiled_relocation->GetDataStartAddress(),
10504                        length);
10505   return compare == 0;
10506 }
10507
10508
10509 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
10510   ASSERT(!has_deoptimization_support());
10511   DisallowHeapAllocation no_allocation;
10512   Code* code = this->code();
10513   if (IsCodeEquivalent(code, recompiled)) {
10514     // Copy the deoptimization data from the recompiled code.
10515     code->set_deoptimization_data(recompiled->deoptimization_data());
10516     code->set_has_deoptimization_support(true);
10517   } else {
10518     // TODO(3025757): In case the recompiled isn't equivalent to the
10519     // old code, we have to replace it. We should try to avoid this
10520     // altogether because it flushes valuable type feedback by
10521     // effectively resetting all IC state.
10522     ReplaceCode(recompiled);
10523   }
10524   ASSERT(has_deoptimization_support());
10525 }
10526
10527
10528 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
10529   // Disable optimization for the shared function info and mark the
10530   // code as non-optimizable. The marker on the shared function info
10531   // is there because we flush non-optimized code thereby loosing the
10532   // non-optimizable information for the code. When the code is
10533   // regenerated and set on the shared function info it is marked as
10534   // non-optimizable if optimization is disabled for the shared
10535   // function info.
10536   set_optimization_disabled(true);
10537   set_bailout_reason(reason);
10538   // Code should be the lazy compilation stub or else unoptimized.  If the
10539   // latter, disable optimization for the code too.
10540   ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
10541   if (code()->kind() == Code::FUNCTION) {
10542     code()->set_optimizable(false);
10543   }
10544   PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
10545   if (FLAG_trace_opt) {
10546     PrintF("[disabled optimization for ");
10547     ShortPrint();
10548     PrintF(", reason: %s]\n", GetBailoutReason(reason));
10549   }
10550 }
10551
10552
10553 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
10554   ASSERT(!id.IsNone());
10555   Code* unoptimized = code();
10556   DeoptimizationOutputData* data =
10557       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
10558   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
10559   USE(ignore);
10560   return true;  // Return true if there was no ASSERT.
10561 }
10562
10563
10564 void JSFunction::StartInobjectSlackTracking() {
10565   ASSERT(has_initial_map() && !IsInobjectSlackTrackingInProgress());
10566
10567   if (!FLAG_clever_optimizations) return;
10568   Map* map = initial_map();
10569
10570   // Only initiate the tracking the first time.
10571   if (map->done_inobject_slack_tracking()) return;
10572   map->set_done_inobject_slack_tracking(true);
10573
10574   // No tracking during the snapshot construction phase.
10575   Isolate* isolate = GetIsolate();
10576   if (isolate->serializer_enabled()) return;
10577
10578   if (map->unused_property_fields() == 0) return;
10579
10580   map->set_construction_count(kGenerousAllocationCount);
10581 }
10582
10583
10584 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
10585   code()->ClearInlineCaches();
10586   // If we clear ICs, we need to clear the type feedback vector too, since
10587   // CallICs are synced with a feedback vector slot.
10588   ClearTypeFeedbackInfo();
10589   set_ic_age(new_ic_age);
10590   if (code()->kind() == Code::FUNCTION) {
10591     code()->set_profiler_ticks(0);
10592     if (optimization_disabled() &&
10593         opt_count() >= FLAG_max_opt_count) {
10594       // Re-enable optimizations if they were disabled due to opt_count limit.
10595       set_optimization_disabled(false);
10596       code()->set_optimizable(true);
10597     }
10598     set_opt_count(0);
10599     set_deopt_count(0);
10600   }
10601 }
10602
10603
10604 static void GetMinInobjectSlack(Map* map, void* data) {
10605   int slack = map->unused_property_fields();
10606   if (*reinterpret_cast<int*>(data) > slack) {
10607     *reinterpret_cast<int*>(data) = slack;
10608   }
10609 }
10610
10611
10612 static void ShrinkInstanceSize(Map* map, void* data) {
10613   int slack = *reinterpret_cast<int*>(data);
10614   map->set_inobject_properties(map->inobject_properties() - slack);
10615   map->set_unused_property_fields(map->unused_property_fields() - slack);
10616   map->set_instance_size(map->instance_size() - slack * kPointerSize);
10617
10618   // Visitor id might depend on the instance size, recalculate it.
10619   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
10620 }
10621
10622
10623 void JSFunction::CompleteInobjectSlackTracking() {
10624   ASSERT(has_initial_map());
10625   Map* map = initial_map();
10626
10627   ASSERT(map->done_inobject_slack_tracking());
10628   map->set_construction_count(kNoSlackTracking);
10629
10630   int slack = map->unused_property_fields();
10631   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
10632   if (slack != 0) {
10633     // Resize the initial map and all maps in its transition tree.
10634     map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
10635   }
10636 }
10637
10638
10639 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
10640                                                BailoutId osr_ast_id) {
10641   DisallowHeapAllocation no_gc;
10642   ASSERT(native_context->IsNativeContext());
10643   if (!FLAG_cache_optimized_code) return -1;
10644   Object* value = optimized_code_map();
10645   if (!value->IsSmi()) {
10646     FixedArray* optimized_code_map = FixedArray::cast(value);
10647     int length = optimized_code_map->length();
10648     Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
10649     for (int i = kEntriesStart; i < length; i += kEntryLength) {
10650       if (optimized_code_map->get(i + kContextOffset) == native_context &&
10651           optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
10652         return i + kCachedCodeOffset;
10653       }
10654     }
10655     if (FLAG_trace_opt) {
10656       PrintF("[didn't find optimized code in optimized code map for ");
10657       ShortPrint();
10658       PrintF("]\n");
10659     }
10660   }
10661   return -1;
10662 }
10663
10664
10665 #define DECLARE_TAG(ignore1, name, ignore2) name,
10666 const char* const VisitorSynchronization::kTags[
10667     VisitorSynchronization::kNumberOfSyncTags] = {
10668   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10669 };
10670 #undef DECLARE_TAG
10671
10672
10673 #define DECLARE_TAG(ignore1, ignore2, name) name,
10674 const char* const VisitorSynchronization::kTagNames[
10675     VisitorSynchronization::kNumberOfSyncTags] = {
10676   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10677 };
10678 #undef DECLARE_TAG
10679
10680
10681 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10682   ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
10683   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10684   Object* old_target = target;
10685   VisitPointer(&target);
10686   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10687 }
10688
10689
10690 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10691   ASSERT(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10692   Object* stub = rinfo->code_age_stub();
10693   if (stub) {
10694     VisitPointer(&stub);
10695   }
10696 }
10697
10698
10699 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10700   Object* code = Code::GetObjectFromEntryAddress(entry_address);
10701   Object* old_code = code;
10702   VisitPointer(&code);
10703   if (code != old_code) {
10704     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10705   }
10706 }
10707
10708
10709 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10710   ASSERT(rinfo->rmode() == RelocInfo::CELL);
10711   Object* cell = rinfo->target_cell();
10712   Object* old_cell = cell;
10713   VisitPointer(&cell);
10714   if (cell != old_cell) {
10715     rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10716   }
10717 }
10718
10719
10720 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10721   ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
10722           rinfo->IsPatchedReturnSequence()) ||
10723          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10724           rinfo->IsPatchedDebugBreakSlotSequence()));
10725   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
10726   Object* old_target = target;
10727   VisitPointer(&target);
10728   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10729 }
10730
10731
10732 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10733   ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10734   Object* p = rinfo->target_object();
10735   VisitPointer(&p);
10736 }
10737
10738
10739 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10740   Address p = rinfo->target_reference();
10741   VisitExternalReference(&p);
10742 }
10743
10744
10745 void Code::InvalidateRelocation() {
10746   set_relocation_info(GetHeap()->empty_byte_array());
10747 }
10748
10749
10750 void Code::InvalidateEmbeddedObjects() {
10751   Object* undefined = GetHeap()->undefined_value();
10752   Cell* undefined_cell = GetHeap()->undefined_cell();
10753   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10754                   RelocInfo::ModeMask(RelocInfo::CELL);
10755   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10756     RelocInfo::Mode mode = it.rinfo()->rmode();
10757     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10758       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10759     } else if (mode == RelocInfo::CELL) {
10760       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10761     }
10762   }
10763 }
10764
10765
10766 void Code::Relocate(intptr_t delta) {
10767   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10768     it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10769   }
10770   CPU::FlushICache(instruction_start(), instruction_size());
10771 }
10772
10773
10774 void Code::CopyFrom(const CodeDesc& desc) {
10775   ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
10776
10777   // copy code
10778   CopyBytes(instruction_start(), desc.buffer,
10779             static_cast<size_t>(desc.instr_size));
10780
10781   // copy reloc info
10782   CopyBytes(relocation_start(),
10783             desc.buffer + desc.buffer_size - desc.reloc_size,
10784             static_cast<size_t>(desc.reloc_size));
10785
10786   // unbox handles and relocate
10787   intptr_t delta = instruction_start() - desc.buffer;
10788   int mode_mask = RelocInfo::kCodeTargetMask |
10789                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10790                   RelocInfo::ModeMask(RelocInfo::CELL) |
10791                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
10792                   RelocInfo::kApplyMask;
10793   // Needed to find target_object and runtime_entry on X64
10794   Assembler* origin = desc.origin;
10795   AllowDeferredHandleDereference embedding_raw_address;
10796   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10797     RelocInfo::Mode mode = it.rinfo()->rmode();
10798     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10799       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10800       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10801     } else if (mode == RelocInfo::CELL) {
10802       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
10803       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10804     } else if (RelocInfo::IsCodeTarget(mode)) {
10805       // rewrite code handles in inline cache targets to direct
10806       // pointers to the first instruction in the code object
10807       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10808       Code* code = Code::cast(*p);
10809       it.rinfo()->set_target_address(code->instruction_start(),
10810                                      SKIP_WRITE_BARRIER,
10811                                      SKIP_ICACHE_FLUSH);
10812     } else if (RelocInfo::IsRuntimeEntry(mode)) {
10813       Address p = it.rinfo()->target_runtime_entry(origin);
10814       it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
10815                                            SKIP_ICACHE_FLUSH);
10816     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10817       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10818       Code* code = Code::cast(*p);
10819       it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
10820     } else {
10821       it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10822     }
10823   }
10824   CPU::FlushICache(instruction_start(), instruction_size());
10825 }
10826
10827
10828 // Locate the source position which is closest to the address in the code. This
10829 // is using the source position information embedded in the relocation info.
10830 // The position returned is relative to the beginning of the script where the
10831 // source for this function is found.
10832 int Code::SourcePosition(Address pc) {
10833   int distance = kMaxInt;
10834   int position = RelocInfo::kNoPosition;  // Initially no position found.
10835   // Run through all the relocation info to find the best matching source
10836   // position. All the code needs to be considered as the sequence of the
10837   // instructions in the code does not necessarily follow the same order as the
10838   // source.
10839   RelocIterator it(this, RelocInfo::kPositionMask);
10840   while (!it.done()) {
10841     // Only look at positions after the current pc.
10842     if (it.rinfo()->pc() < pc) {
10843       // Get position and distance.
10844
10845       int dist = static_cast<int>(pc - it.rinfo()->pc());
10846       int pos = static_cast<int>(it.rinfo()->data());
10847       // If this position is closer than the current candidate or if it has the
10848       // same distance as the current candidate and the position is higher then
10849       // this position is the new candidate.
10850       if ((dist < distance) ||
10851           (dist == distance && pos > position)) {
10852         position = pos;
10853         distance = dist;
10854       }
10855     }
10856     it.next();
10857   }
10858   return position;
10859 }
10860
10861
10862 // Same as Code::SourcePosition above except it only looks for statement
10863 // positions.
10864 int Code::SourceStatementPosition(Address pc) {
10865   // First find the position as close as possible using all position
10866   // information.
10867   int position = SourcePosition(pc);
10868   // Now find the closest statement position before the position.
10869   int statement_position = 0;
10870   RelocIterator it(this, RelocInfo::kPositionMask);
10871   while (!it.done()) {
10872     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
10873       int p = static_cast<int>(it.rinfo()->data());
10874       if (statement_position < p && p <= position) {
10875         statement_position = p;
10876       }
10877     }
10878     it.next();
10879   }
10880   return statement_position;
10881 }
10882
10883
10884 SafepointEntry Code::GetSafepointEntry(Address pc) {
10885   SafepointTable table(this);
10886   return table.FindEntry(pc);
10887 }
10888
10889
10890 Object* Code::FindNthObject(int n, Map* match_map) {
10891   ASSERT(is_inline_cache_stub());
10892   DisallowHeapAllocation no_allocation;
10893   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10894   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10895     RelocInfo* info = it.rinfo();
10896     Object* object = info->target_object();
10897     if (object->IsHeapObject()) {
10898       if (HeapObject::cast(object)->map() == match_map) {
10899         if (--n == 0) return object;
10900       }
10901     }
10902   }
10903   return NULL;
10904 }
10905
10906
10907 AllocationSite* Code::FindFirstAllocationSite() {
10908   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
10909   return (result != NULL) ? AllocationSite::cast(result) : NULL;
10910 }
10911
10912
10913 Map* Code::FindFirstMap() {
10914   Object* result = FindNthObject(1, GetHeap()->meta_map());
10915   return (result != NULL) ? Map::cast(result) : NULL;
10916 }
10917
10918
10919 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
10920   ASSERT(is_inline_cache_stub() || is_handler());
10921   DisallowHeapAllocation no_allocation;
10922   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10923   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
10924   int current_pattern = 0;
10925   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10926     RelocInfo* info = it.rinfo();
10927     Object* object = info->target_object();
10928     if (object->IsHeapObject()) {
10929       Map* map = HeapObject::cast(object)->map();
10930       if (map == *pattern.find_[current_pattern]) {
10931         info->set_target_object(*pattern.replace_[current_pattern]);
10932         if (++current_pattern == pattern.count_) return;
10933       }
10934     }
10935   }
10936   UNREACHABLE();
10937 }
10938
10939
10940 void Code::FindAllMaps(MapHandleList* maps) {
10941   ASSERT(is_inline_cache_stub());
10942   DisallowHeapAllocation no_allocation;
10943   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10944   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10945     RelocInfo* info = it.rinfo();
10946     Object* object = info->target_object();
10947     if (object->IsMap()) maps->Add(handle(Map::cast(object)));
10948   }
10949 }
10950
10951
10952 Code* Code::FindFirstHandler() {
10953   ASSERT(is_inline_cache_stub());
10954   DisallowHeapAllocation no_allocation;
10955   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
10956   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10957     RelocInfo* info = it.rinfo();
10958     Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10959     if (code->kind() == Code::HANDLER) return code;
10960   }
10961   return NULL;
10962 }
10963
10964
10965 bool Code::FindHandlers(CodeHandleList* code_list, int length) {
10966   ASSERT(is_inline_cache_stub());
10967   DisallowHeapAllocation no_allocation;
10968   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
10969   int i = 0;
10970   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10971     if (i == length) return true;
10972     RelocInfo* info = it.rinfo();
10973     Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10974     // IC stubs with handlers never contain non-handler code objects before
10975     // handler targets.
10976     if (code->kind() != Code::HANDLER) break;
10977     code_list->Add(Handle<Code>(code));
10978     i++;
10979   }
10980   return i == length;
10981 }
10982
10983
10984 Name* Code::FindFirstName() {
10985   ASSERT(is_inline_cache_stub());
10986   DisallowHeapAllocation no_allocation;
10987   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10988   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10989     RelocInfo* info = it.rinfo();
10990     Object* object = info->target_object();
10991     if (object->IsName()) return Name::cast(object);
10992   }
10993   return NULL;
10994 }
10995
10996
10997 void Code::ClearInlineCaches() {
10998   ClearInlineCaches(NULL);
10999 }
11000
11001
11002 void Code::ClearInlineCaches(Code::Kind kind) {
11003   ClearInlineCaches(&kind);
11004 }
11005
11006
11007 void Code::ClearInlineCaches(Code::Kind* kind) {
11008   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
11009              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
11010              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
11011   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11012     RelocInfo* info = it.rinfo();
11013     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
11014     if (target->is_inline_cache_stub()) {
11015       if (kind == NULL || *kind == target->kind()) {
11016         IC::Clear(this->GetIsolate(), info->pc(),
11017                   info->host()->constant_pool());
11018       }
11019     }
11020   }
11021 }
11022
11023
11024 void SharedFunctionInfo::ClearTypeFeedbackInfo() {
11025   FixedArray* vector = feedback_vector();
11026   Heap* heap = GetHeap();
11027   int length = vector->length();
11028
11029   for (int i = 0; i < length; i++) {
11030     Object* obj = vector->get(i);
11031     if (obj->IsHeapObject()) {
11032       InstanceType instance_type =
11033           HeapObject::cast(obj)->map()->instance_type();
11034       switch (instance_type) {
11035         case ALLOCATION_SITE_TYPE:
11036           // AllocationSites are not cleared because they do not store
11037           // information that leaks.
11038           break;
11039           // Fall through...
11040         default:
11041           vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap),
11042                       SKIP_WRITE_BARRIER);
11043       }
11044     }
11045   }
11046 }
11047
11048
11049 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
11050   DisallowHeapAllocation no_gc;
11051   ASSERT(kind() == FUNCTION);
11052   BackEdgeTable back_edges(this, &no_gc);
11053   for (uint32_t i = 0; i < back_edges.length(); i++) {
11054     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
11055   }
11056   return BailoutId::None();
11057 }
11058
11059
11060 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
11061   DisallowHeapAllocation no_gc;
11062   ASSERT(kind() == FUNCTION);
11063   BackEdgeTable back_edges(this, &no_gc);
11064   for (uint32_t i = 0; i < back_edges.length(); i++) {
11065     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
11066   }
11067   UNREACHABLE();  // We expect to find the back edge.
11068   return 0;
11069 }
11070
11071
11072 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
11073   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
11074 }
11075
11076
11077 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
11078   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
11079       NO_MARKING_PARITY);
11080 }
11081
11082
11083 static Code::Age EffectiveAge(Code::Age age) {
11084   if (age == Code::kNotExecutedCodeAge) {
11085     // Treat that's never been executed as old immediately.
11086     age = Code::kIsOldCodeAge;
11087   } else if (age == Code::kExecutedOnceCodeAge) {
11088     // Pre-age code that has only been executed once.
11089     age = Code::kPreAgedCodeAge;
11090   }
11091   return age;
11092 }
11093
11094
11095 void Code::MakeOlder(MarkingParity current_parity) {
11096   byte* sequence = FindCodeAgeSequence();
11097   if (sequence != NULL) {
11098     Age age;
11099     MarkingParity code_parity;
11100     Isolate* isolate = GetIsolate();
11101     GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
11102     age = EffectiveAge(age);
11103     if (age != kLastCodeAge && code_parity != current_parity) {
11104       PatchPlatformCodeAge(isolate,
11105                            sequence,
11106                            static_cast<Age>(age + 1),
11107                            current_parity);
11108     }
11109   }
11110 }
11111
11112
11113 bool Code::IsOld() {
11114   return GetAge() >= kIsOldCodeAge;
11115 }
11116
11117
11118 byte* Code::FindCodeAgeSequence() {
11119   return FLAG_age_code &&
11120       prologue_offset() != Code::kPrologueOffsetNotSet &&
11121       (kind() == OPTIMIZED_FUNCTION ||
11122        (kind() == FUNCTION && !has_debug_break_slots()))
11123       ? instruction_start() + prologue_offset()
11124       : NULL;
11125 }
11126
11127
11128 Code::Age Code::GetAge() {
11129   return EffectiveAge(GetRawAge());
11130 }
11131
11132
11133 Code::Age Code::GetRawAge() {
11134   byte* sequence = FindCodeAgeSequence();
11135   if (sequence == NULL) {
11136     return kNoAgeCodeAge;
11137   }
11138   Age age;
11139   MarkingParity parity;
11140   GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
11141   return age;
11142 }
11143
11144
11145 void Code::GetCodeAgeAndParity(Code* code, Age* age,
11146                                MarkingParity* parity) {
11147   Isolate* isolate = code->GetIsolate();
11148   Builtins* builtins = isolate->builtins();
11149   Code* stub = NULL;
11150 #define HANDLE_CODE_AGE(AGE)                                            \
11151   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
11152   if (code == stub) {                                                   \
11153     *age = k##AGE##CodeAge;                                             \
11154     *parity = EVEN_MARKING_PARITY;                                      \
11155     return;                                                             \
11156   }                                                                     \
11157   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
11158   if (code == stub) {                                                   \
11159     *age = k##AGE##CodeAge;                                             \
11160     *parity = ODD_MARKING_PARITY;                                       \
11161     return;                                                             \
11162   }
11163   CODE_AGE_LIST(HANDLE_CODE_AGE)
11164 #undef HANDLE_CODE_AGE
11165   stub = *builtins->MarkCodeAsExecutedOnce();
11166   if (code == stub) {
11167     *age = kNotExecutedCodeAge;
11168     *parity = NO_MARKING_PARITY;
11169     return;
11170   }
11171   stub = *builtins->MarkCodeAsExecutedTwice();
11172   if (code == stub) {
11173     *age = kExecutedOnceCodeAge;
11174     *parity = NO_MARKING_PARITY;
11175     return;
11176   }
11177   UNREACHABLE();
11178 }
11179
11180
11181 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
11182   Builtins* builtins = isolate->builtins();
11183   switch (age) {
11184 #define HANDLE_CODE_AGE(AGE)                                            \
11185     case k##AGE##CodeAge: {                                             \
11186       Code* stub = parity == EVEN_MARKING_PARITY                        \
11187           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
11188           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
11189       return stub;                                                      \
11190     }
11191     CODE_AGE_LIST(HANDLE_CODE_AGE)
11192 #undef HANDLE_CODE_AGE
11193     case kNotExecutedCodeAge: {
11194       ASSERT(parity == NO_MARKING_PARITY);
11195       return *builtins->MarkCodeAsExecutedOnce();
11196     }
11197     case kExecutedOnceCodeAge: {
11198       ASSERT(parity == NO_MARKING_PARITY);
11199       return *builtins->MarkCodeAsExecutedTwice();
11200     }
11201     default:
11202       UNREACHABLE();
11203       break;
11204   }
11205   return NULL;
11206 }
11207
11208
11209 void Code::PrintDeoptLocation(FILE* out, int bailout_id) {
11210   const char* last_comment = NULL;
11211   int mask = RelocInfo::ModeMask(RelocInfo::COMMENT)
11212       | RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
11213   for (RelocIterator it(this, mask); !it.done(); it.next()) {
11214     RelocInfo* info = it.rinfo();
11215     if (info->rmode() == RelocInfo::COMMENT) {
11216       last_comment = reinterpret_cast<const char*>(info->data());
11217     } else if (last_comment != NULL) {
11218       if ((bailout_id == Deoptimizer::GetDeoptimizationId(
11219               GetIsolate(), info->target_address(), Deoptimizer::EAGER)) ||
11220           (bailout_id == Deoptimizer::GetDeoptimizationId(
11221               GetIsolate(), info->target_address(), Deoptimizer::SOFT))) {
11222         CHECK(RelocInfo::IsRuntimeEntry(info->rmode()));
11223         PrintF(out, "            %s\n", last_comment);
11224         return;
11225       }
11226     }
11227   }
11228 }
11229
11230
11231 bool Code::CanDeoptAt(Address pc) {
11232   DeoptimizationInputData* deopt_data =
11233       DeoptimizationInputData::cast(deoptimization_data());
11234   Address code_start_address = instruction_start();
11235   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
11236     if (deopt_data->Pc(i)->value() == -1) continue;
11237     Address address = code_start_address + deopt_data->Pc(i)->value();
11238     if (address == pc) return true;
11239   }
11240   return false;
11241 }
11242
11243
11244 // Identify kind of code.
11245 const char* Code::Kind2String(Kind kind) {
11246   switch (kind) {
11247 #define CASE(name) case name: return #name;
11248     CODE_KIND_LIST(CASE)
11249 #undef CASE
11250     case NUMBER_OF_KINDS: break;
11251   }
11252   UNREACHABLE();
11253   return NULL;
11254 }
11255
11256
11257 #ifdef ENABLE_DISASSEMBLER
11258
11259 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
11260   disasm::NameConverter converter;
11261   int deopt_count = DeoptCount();
11262   PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
11263   if (0 == deopt_count) return;
11264
11265   PrintF(out, "%6s  %6s  %6s %6s %12s\n", "index", "ast id", "argc", "pc",
11266          FLAG_print_code_verbose ? "commands" : "");
11267   for (int i = 0; i < deopt_count; i++) {
11268     PrintF(out, "%6d  %6d  %6d %6d",
11269            i,
11270            AstId(i).ToInt(),
11271            ArgumentsStackHeight(i)->value(),
11272            Pc(i)->value());
11273
11274     if (!FLAG_print_code_verbose) {
11275       PrintF(out, "\n");
11276       continue;
11277     }
11278     // Print details of the frame translation.
11279     int translation_index = TranslationIndex(i)->value();
11280     TranslationIterator iterator(TranslationByteArray(), translation_index);
11281     Translation::Opcode opcode =
11282         static_cast<Translation::Opcode>(iterator.Next());
11283     ASSERT(Translation::BEGIN == opcode);
11284     int frame_count = iterator.Next();
11285     int jsframe_count = iterator.Next();
11286     PrintF(out, "  %s {frame count=%d, js frame count=%d}\n",
11287            Translation::StringFor(opcode),
11288            frame_count,
11289            jsframe_count);
11290
11291     while (iterator.HasNext() &&
11292            Translation::BEGIN !=
11293            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
11294       PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
11295
11296       switch (opcode) {
11297         case Translation::BEGIN:
11298           UNREACHABLE();
11299           break;
11300
11301         case Translation::JS_FRAME: {
11302           int ast_id = iterator.Next();
11303           int function_id = iterator.Next();
11304           unsigned height = iterator.Next();
11305           PrintF(out, "{ast_id=%d, function=", ast_id);
11306           if (function_id != Translation::kSelfLiteralId) {
11307             Object* function = LiteralArray()->get(function_id);
11308             JSFunction::cast(function)->PrintName(out);
11309           } else {
11310             PrintF(out, "<self>");
11311           }
11312           PrintF(out, ", height=%u}", height);
11313           break;
11314         }
11315
11316         case Translation::COMPILED_STUB_FRAME: {
11317           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
11318           PrintF(out, "{kind=%d}", stub_kind);
11319           break;
11320         }
11321
11322         case Translation::ARGUMENTS_ADAPTOR_FRAME:
11323         case Translation::CONSTRUCT_STUB_FRAME: {
11324           int function_id = iterator.Next();
11325           JSFunction* function =
11326               JSFunction::cast(LiteralArray()->get(function_id));
11327           unsigned height = iterator.Next();
11328           PrintF(out, "{function=");
11329           function->PrintName(out);
11330           PrintF(out, ", height=%u}", height);
11331           break;
11332         }
11333
11334         case Translation::GETTER_STUB_FRAME:
11335         case Translation::SETTER_STUB_FRAME: {
11336           int function_id = iterator.Next();
11337           JSFunction* function =
11338               JSFunction::cast(LiteralArray()->get(function_id));
11339           PrintF(out, "{function=");
11340           function->PrintName(out);
11341           PrintF(out, "}");
11342           break;
11343         }
11344
11345         case Translation::REGISTER: {
11346           int reg_code = iterator.Next();
11347             PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
11348           break;
11349         }
11350
11351         case Translation::INT32_REGISTER: {
11352           int reg_code = iterator.Next();
11353           PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
11354           break;
11355         }
11356
11357         case Translation::UINT32_REGISTER: {
11358           int reg_code = iterator.Next();
11359           PrintF(out, "{input=%s (unsigned)}",
11360                  converter.NameOfCPURegister(reg_code));
11361           break;
11362         }
11363
11364         case Translation::DOUBLE_REGISTER: {
11365           int reg_code = iterator.Next();
11366           PrintF(out, "{input=%s}",
11367                  DoubleRegister::AllocationIndexToString(reg_code));
11368           break;
11369         }
11370
11371         case Translation::FLOAT32x4_REGISTER: {
11372           int reg_code = iterator.Next();
11373           PrintF(out, "{input=%s}",
11374                  SIMD128Register::AllocationIndexToString(reg_code));
11375           break;
11376         }
11377
11378         case Translation::FLOAT64x2_REGISTER: {
11379           int reg_code = iterator.Next();
11380           PrintF(out, "{input=%s}",
11381                  SIMD128Register::AllocationIndexToString(reg_code));
11382           break;
11383         }
11384
11385         case Translation::INT32x4_REGISTER: {
11386           int reg_code = iterator.Next();
11387           PrintF(out, "{input=%s}",
11388                  SIMD128Register::AllocationIndexToString(reg_code));
11389           break;
11390         }
11391
11392         case Translation::STACK_SLOT: {
11393           int input_slot_index = iterator.Next();
11394           PrintF(out, "{input=%d}", input_slot_index);
11395           break;
11396         }
11397
11398         case Translation::INT32_STACK_SLOT: {
11399           int input_slot_index = iterator.Next();
11400           PrintF(out, "{input=%d}", input_slot_index);
11401           break;
11402         }
11403
11404         case Translation::UINT32_STACK_SLOT: {
11405           int input_slot_index = iterator.Next();
11406           PrintF(out, "{input=%d (unsigned)}", input_slot_index);
11407           break;
11408         }
11409
11410         case Translation::DOUBLE_STACK_SLOT: {
11411           int input_slot_index = iterator.Next();
11412           PrintF(out, "{input=%d}", input_slot_index);
11413           break;
11414         }
11415
11416         case Translation::FLOAT32x4_STACK_SLOT: {
11417           int input_slot_index = iterator.Next();
11418           PrintF(out, "{input=%d}", input_slot_index);
11419           break;
11420         }
11421
11422         case Translation::FLOAT64x2_STACK_SLOT: {
11423           int input_slot_index = iterator.Next();
11424           PrintF(out, "{input=%d}", input_slot_index);
11425           break;
11426         }
11427
11428         case Translation::INT32x4_STACK_SLOT: {
11429           int input_slot_index = iterator.Next();
11430           PrintF(out, "{input=%d}", input_slot_index);
11431           break;
11432         }
11433
11434         case Translation::LITERAL: {
11435           unsigned literal_index = iterator.Next();
11436           PrintF(out, "{literal_id=%u}", literal_index);
11437           break;
11438         }
11439
11440         case Translation::DUPLICATED_OBJECT: {
11441           int object_index = iterator.Next();
11442           PrintF(out, "{object_index=%d}", object_index);
11443           break;
11444         }
11445
11446         case Translation::ARGUMENTS_OBJECT:
11447         case Translation::CAPTURED_OBJECT: {
11448           int args_length = iterator.Next();
11449           PrintF(out, "{length=%d}", args_length);
11450           break;
11451         }
11452       }
11453       PrintF(out, "\n");
11454     }
11455   }
11456 }
11457
11458
11459 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
11460   PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
11461          this->DeoptPoints());
11462   if (this->DeoptPoints() == 0) return;
11463
11464   PrintF(out, "%6s  %8s  %s\n", "ast id", "pc", "state");
11465   for (int i = 0; i < this->DeoptPoints(); i++) {
11466     int pc_and_state = this->PcAndState(i)->value();
11467     PrintF(out, "%6d  %8d  %s\n",
11468            this->AstId(i).ToInt(),
11469            FullCodeGenerator::PcField::decode(pc_and_state),
11470            FullCodeGenerator::State2String(
11471                FullCodeGenerator::StateField::decode(pc_and_state)));
11472   }
11473 }
11474
11475
11476 const char* Code::ICState2String(InlineCacheState state) {
11477   switch (state) {
11478     case UNINITIALIZED: return "UNINITIALIZED";
11479     case PREMONOMORPHIC: return "PREMONOMORPHIC";
11480     case MONOMORPHIC: return "MONOMORPHIC";
11481     case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
11482     case POLYMORPHIC: return "POLYMORPHIC";
11483     case MEGAMORPHIC: return "MEGAMORPHIC";
11484     case GENERIC: return "GENERIC";
11485     case DEBUG_STUB: return "DEBUG_STUB";
11486   }
11487   UNREACHABLE();
11488   return NULL;
11489 }
11490
11491
11492 const char* Code::StubType2String(StubType type) {
11493   switch (type) {
11494     case NORMAL: return "NORMAL";
11495     case FAST: return "FAST";
11496   }
11497   UNREACHABLE();  // keep the compiler happy
11498   return NULL;
11499 }
11500
11501
11502 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
11503   PrintF(out, "extra_ic_state = ");
11504   const char* name = NULL;
11505   switch (kind) {
11506     case STORE_IC:
11507     case KEYED_STORE_IC:
11508       if (extra == STRICT) name = "STRICT";
11509       break;
11510     default:
11511       break;
11512   }
11513   if (name != NULL) {
11514     PrintF(out, "%s\n", name);
11515   } else {
11516     PrintF(out, "%d\n", extra);
11517   }
11518 }
11519
11520
11521 void Code::Disassemble(const char* name, FILE* out) {
11522   PrintF(out, "kind = %s\n", Kind2String(kind()));
11523   if (has_major_key()) {
11524     PrintF(out, "major_key = %s\n",
11525            CodeStub::MajorName(CodeStub::GetMajorKey(this), true));
11526   }
11527   if (is_inline_cache_stub()) {
11528     PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
11529     PrintExtraICState(out, kind(), extra_ic_state());
11530     if (ic_state() == MONOMORPHIC) {
11531       PrintF(out, "type = %s\n", StubType2String(type()));
11532     }
11533     if (is_compare_ic_stub()) {
11534       ASSERT(major_key() == CodeStub::CompareIC);
11535       CompareIC::State left_state, right_state, handler_state;
11536       Token::Value op;
11537       ICCompareStub::DecodeMinorKey(stub_info(), &left_state, &right_state,
11538                                     &handler_state, &op);
11539       PrintF(out, "compare_state = %s*%s -> %s\n",
11540              CompareIC::GetStateName(left_state),
11541              CompareIC::GetStateName(right_state),
11542              CompareIC::GetStateName(handler_state));
11543       PrintF(out, "compare_operation = %s\n", Token::Name(op));
11544     }
11545   }
11546   if ((name != NULL) && (name[0] != '\0')) {
11547     PrintF(out, "name = %s\n", name);
11548   }
11549   if (kind() == OPTIMIZED_FUNCTION) {
11550     PrintF(out, "stack_slots = %d\n", stack_slots());
11551   }
11552
11553   PrintF(out, "Instructions (size = %d)\n", instruction_size());
11554   Disassembler::Decode(out, this);
11555   PrintF(out, "\n");
11556
11557   if (kind() == FUNCTION) {
11558     DeoptimizationOutputData* data =
11559         DeoptimizationOutputData::cast(this->deoptimization_data());
11560     data->DeoptimizationOutputDataPrint(out);
11561   } else if (kind() == OPTIMIZED_FUNCTION) {
11562     DeoptimizationInputData* data =
11563         DeoptimizationInputData::cast(this->deoptimization_data());
11564     data->DeoptimizationInputDataPrint(out);
11565   }
11566   PrintF(out, "\n");
11567
11568   if (is_crankshafted()) {
11569     SafepointTable table(this);
11570     PrintF(out, "Safepoints (size = %u)\n", table.size());
11571     for (unsigned i = 0; i < table.length(); i++) {
11572       unsigned pc_offset = table.GetPcOffset(i);
11573       PrintF(out, "%p  %4d  ", (instruction_start() + pc_offset), pc_offset);
11574       table.PrintEntry(i, out);
11575       PrintF(out, " (sp -> fp)");
11576       SafepointEntry entry = table.GetEntry(i);
11577       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
11578         PrintF(out, "  %6d", entry.deoptimization_index());
11579       } else {
11580         PrintF(out, "  <none>");
11581       }
11582       if (entry.argument_count() > 0) {
11583         PrintF(out, " argc: %d", entry.argument_count());
11584       }
11585       PrintF(out, "\n");
11586     }
11587     PrintF(out, "\n");
11588   } else if (kind() == FUNCTION) {
11589     unsigned offset = back_edge_table_offset();
11590     // If there is no back edge table, the "table start" will be at or after
11591     // (due to alignment) the end of the instruction stream.
11592     if (static_cast<int>(offset) < instruction_size()) {
11593       DisallowHeapAllocation no_gc;
11594       BackEdgeTable back_edges(this, &no_gc);
11595
11596       PrintF(out, "Back edges (size = %u)\n", back_edges.length());
11597       PrintF(out, "ast_id  pc_offset  loop_depth\n");
11598
11599       for (uint32_t i = 0; i < back_edges.length(); i++) {
11600         PrintF(out, "%6d  %9u  %10u\n", back_edges.ast_id(i).ToInt(),
11601                                         back_edges.pc_offset(i),
11602                                         back_edges.loop_depth(i));
11603       }
11604
11605       PrintF(out, "\n");
11606     }
11607 #ifdef OBJECT_PRINT
11608     if (!type_feedback_info()->IsUndefined()) {
11609       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out);
11610       PrintF(out, "\n");
11611     }
11612 #endif
11613   }
11614
11615   PrintF(out, "RelocInfo (size = %d)\n", relocation_size());
11616   for (RelocIterator it(this); !it.done(); it.next()) {
11617     it.rinfo()->Print(GetIsolate(), out);
11618   }
11619   PrintF(out, "\n");
11620 }
11621 #endif  // ENABLE_DISASSEMBLER
11622
11623
11624 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
11625     Handle<JSObject> object,
11626     int capacity,
11627     int length,
11628     SetFastElementsCapacitySmiMode smi_mode) {
11629   // We should never end in here with a pixel or external array.
11630   ASSERT(!object->HasExternalArrayElements());
11631
11632   // Allocate a new fast elements backing store.
11633   Handle<FixedArray> new_elements =
11634       object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
11635
11636   ElementsKind elements_kind = object->GetElementsKind();
11637   ElementsKind new_elements_kind;
11638   // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
11639   // or if it's allowed and the old elements array contained only SMIs.
11640   bool has_fast_smi_elements =
11641       (smi_mode == kForceSmiElements) ||
11642       ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements());
11643   if (has_fast_smi_elements) {
11644     if (IsHoleyElementsKind(elements_kind)) {
11645       new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
11646     } else {
11647       new_elements_kind = FAST_SMI_ELEMENTS;
11648     }
11649   } else {
11650     if (IsHoleyElementsKind(elements_kind)) {
11651       new_elements_kind = FAST_HOLEY_ELEMENTS;
11652     } else {
11653       new_elements_kind = FAST_ELEMENTS;
11654     }
11655   }
11656   Handle<FixedArrayBase> old_elements(object->elements());
11657   ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
11658   accessor->CopyElements(object, new_elements, elements_kind);
11659
11660   if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
11661     Handle<Map> new_map = (new_elements_kind != elements_kind)
11662         ? GetElementsTransitionMap(object, new_elements_kind)
11663         : handle(object->map());
11664     JSObject::ValidateElements(object);
11665     JSObject::SetMapAndElements(object, new_map, new_elements);
11666
11667     // Transition through the allocation site as well if present.
11668     JSObject::UpdateAllocationSite(object, new_elements_kind);
11669   } else {
11670     Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11671     parameter_map->set(1, *new_elements);
11672   }
11673
11674   if (FLAG_trace_elements_transitions) {
11675     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11676                             object->GetElementsKind(), new_elements);
11677   }
11678
11679   if (object->IsJSArray()) {
11680     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11681   }
11682   return new_elements;
11683 }
11684
11685
11686 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object,
11687                                                       int capacity,
11688                                                       int length) {
11689   // We should never end in here with a pixel or external array.
11690   ASSERT(!object->HasExternalArrayElements());
11691
11692   Handle<FixedArrayBase> elems =
11693       object->GetIsolate()->factory()->NewFixedDoubleArray(capacity);
11694
11695   ElementsKind elements_kind = object->GetElementsKind();
11696   CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS);
11697   ElementsKind new_elements_kind = elements_kind;
11698   if (IsHoleyElementsKind(elements_kind)) {
11699     new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
11700   } else {
11701     new_elements_kind = FAST_DOUBLE_ELEMENTS;
11702   }
11703
11704   Handle<Map> new_map = GetElementsTransitionMap(object, new_elements_kind);
11705
11706   Handle<FixedArrayBase> old_elements(object->elements());
11707   ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
11708   accessor->CopyElements(object, elems, elements_kind);
11709
11710   JSObject::ValidateElements(object);
11711   JSObject::SetMapAndElements(object, new_map, elems);
11712
11713   if (FLAG_trace_elements_transitions) {
11714     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11715                             object->GetElementsKind(), elems);
11716   }
11717
11718   if (object->IsJSArray()) {
11719     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11720   }
11721 }
11722
11723
11724 // static
11725 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11726   ASSERT(capacity >= 0);
11727   array->GetIsolate()->factory()->NewJSArrayStorage(
11728       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11729 }
11730
11731
11732 void JSArray::Expand(Handle<JSArray> array, int required_size) {
11733   ElementsAccessor* accessor = array->GetElementsAccessor();
11734   accessor->SetCapacityAndLength(array, required_size, required_size);
11735 }
11736
11737
11738 // Returns false if the passed-in index is marked non-configurable,
11739 // which will cause the ES5 truncation operation to halt, and thus
11740 // no further old values need be collected.
11741 static bool GetOldValue(Isolate* isolate,
11742                         Handle<JSObject> object,
11743                         uint32_t index,
11744                         List<Handle<Object> >* old_values,
11745                         List<uint32_t>* indices) {
11746   PropertyAttributes attributes =
11747       JSReceiver::GetOwnElementAttribute(object, index);
11748   ASSERT(attributes != ABSENT);
11749   if (attributes == DONT_DELETE) return false;
11750   Handle<Object> value;
11751   if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
11752     value = Handle<Object>::cast(isolate->factory()->the_hole_value());
11753   } else {
11754     value = Object::GetElement(isolate, object, index).ToHandleChecked();
11755   }
11756   old_values->Add(value);
11757   indices->Add(index);
11758   return true;
11759 }
11760
11761 static void EnqueueSpliceRecord(Handle<JSArray> object,
11762                                 uint32_t index,
11763                                 Handle<JSArray> deleted,
11764                                 uint32_t add_count) {
11765   Isolate* isolate = object->GetIsolate();
11766   HandleScope scope(isolate);
11767   Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
11768   Handle<Object> add_count_object =
11769       isolate->factory()->NewNumberFromUint(add_count);
11770
11771   Handle<Object> args[] =
11772       { object, index_object, deleted, add_count_object };
11773
11774   Execution::Call(isolate,
11775                   Handle<JSFunction>(isolate->observers_enqueue_splice()),
11776                   isolate->factory()->undefined_value(),
11777                   ARRAY_SIZE(args),
11778                   args).Assert();
11779 }
11780
11781
11782 static void BeginPerformSplice(Handle<JSArray> object) {
11783   Isolate* isolate = object->GetIsolate();
11784   HandleScope scope(isolate);
11785   Handle<Object> args[] = { object };
11786
11787   Execution::Call(isolate,
11788                   Handle<JSFunction>(isolate->observers_begin_perform_splice()),
11789                   isolate->factory()->undefined_value(),
11790                   ARRAY_SIZE(args),
11791                   args).Assert();
11792 }
11793
11794
11795 static void EndPerformSplice(Handle<JSArray> object) {
11796   Isolate* isolate = object->GetIsolate();
11797   HandleScope scope(isolate);
11798   Handle<Object> args[] = { object };
11799
11800   Execution::Call(isolate,
11801                   Handle<JSFunction>(isolate->observers_end_perform_splice()),
11802                   isolate->factory()->undefined_value(),
11803                   ARRAY_SIZE(args),
11804                   args).Assert();
11805 }
11806
11807
11808 MaybeHandle<Object> JSArray::SetElementsLength(
11809     Handle<JSArray> array,
11810     Handle<Object> new_length_handle) {
11811   // We should never end in here with a pixel or external array.
11812   ASSERT(array->AllowsSetElementsLength());
11813   if (!array->map()->is_observed()) {
11814     return array->GetElementsAccessor()->SetLength(array, new_length_handle);
11815   }
11816
11817   Isolate* isolate = array->GetIsolate();
11818   List<uint32_t> indices;
11819   List<Handle<Object> > old_values;
11820   Handle<Object> old_length_handle(array->length(), isolate);
11821   uint32_t old_length = 0;
11822   CHECK(old_length_handle->ToArrayIndex(&old_length));
11823   uint32_t new_length = 0;
11824   CHECK(new_length_handle->ToArrayIndex(&new_length));
11825
11826   static const PropertyAttributes kNoAttrFilter = NONE;
11827   int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
11828   if (num_elements > 0) {
11829     if (old_length == static_cast<uint32_t>(num_elements)) {
11830       // Simple case for arrays without holes.
11831       for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
11832         if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
11833       }
11834     } else {
11835       // For sparse arrays, only iterate over existing elements.
11836       // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
11837       // the to-be-removed indices twice.
11838       Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
11839       array->GetOwnElementKeys(*keys, kNoAttrFilter);
11840       while (num_elements-- > 0) {
11841         uint32_t index = NumberToUint32(keys->get(num_elements));
11842         if (index < new_length) break;
11843         if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
11844       }
11845     }
11846   }
11847
11848   Handle<Object> hresult;
11849   ASSIGN_RETURN_ON_EXCEPTION(
11850       isolate, hresult,
11851       array->GetElementsAccessor()->SetLength(array, new_length_handle),
11852       Object);
11853
11854   CHECK(array->length()->ToArrayIndex(&new_length));
11855   if (old_length == new_length) return hresult;
11856
11857   BeginPerformSplice(array);
11858
11859   for (int i = 0; i < indices.length(); ++i) {
11860     // For deletions where the property was an accessor, old_values[i]
11861     // will be the hole, which instructs EnqueueChangeRecord to elide
11862     // the "oldValue" property.
11863     JSObject::EnqueueChangeRecord(
11864         array, "delete", isolate->factory()->Uint32ToString(indices[i]),
11865         old_values[i]);
11866   }
11867   JSObject::EnqueueChangeRecord(
11868       array, "update", isolate->factory()->length_string(),
11869       old_length_handle);
11870
11871   EndPerformSplice(array);
11872
11873   uint32_t index = Min(old_length, new_length);
11874   uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11875   uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11876   Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11877   if (delete_count > 0) {
11878     for (int i = indices.length() - 1; i >= 0; i--) {
11879       // Skip deletions where the property was an accessor, leaving holes
11880       // in the array of old values.
11881       if (old_values[i]->IsTheHole()) continue;
11882       JSObject::SetElement(
11883           deleted, indices[i] - index, old_values[i], NONE, SLOPPY).Assert();
11884     }
11885
11886     SetProperty(deleted, isolate->factory()->length_string(),
11887                 isolate->factory()->NewNumberFromUint(delete_count),
11888                 NONE, SLOPPY).Assert();
11889   }
11890
11891   EnqueueSpliceRecord(array, index, deleted, add_count);
11892
11893   return hresult;
11894 }
11895
11896
11897 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map,
11898                                         Handle<Object> prototype) {
11899   FixedArray* cache = map->GetPrototypeTransitions();
11900   int number_of_transitions = map->NumberOfProtoTransitions();
11901   const int proto_offset =
11902       kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
11903   const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
11904   const int step = kProtoTransitionElementsPerEntry;
11905   for (int i = 0; i < number_of_transitions; i++) {
11906     if (cache->get(proto_offset + i * step) == *prototype) {
11907       Object* result = cache->get(map_offset + i * step);
11908       return Handle<Map>(Map::cast(result));
11909     }
11910   }
11911   return Handle<Map>();
11912 }
11913
11914
11915 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
11916                                         Handle<Object> prototype,
11917                                         Handle<Map> target_map) {
11918   ASSERT(target_map->IsMap());
11919   ASSERT(HeapObject::cast(*prototype)->map()->IsMap());
11920   // Don't cache prototype transition if this map is shared.
11921   if (map->is_shared() || !FLAG_cache_prototype_transitions) return map;
11922
11923   const int step = kProtoTransitionElementsPerEntry;
11924   const int header = kProtoTransitionHeaderSize;
11925
11926   Handle<FixedArray> cache(map->GetPrototypeTransitions());
11927   int capacity = (cache->length() - header) / step;
11928   int transitions = map->NumberOfProtoTransitions() + 1;
11929
11930   if (transitions > capacity) {
11931     if (capacity > kMaxCachedPrototypeTransitions) return map;
11932
11933     // Grow array by factor 2 over and above what we need.
11934     cache = FixedArray::CopySize(cache, transitions * 2 * step + header);
11935
11936     SetPrototypeTransitions(map, cache);
11937   }
11938
11939   // Reload number of transitions as GC might shrink them.
11940   int last = map->NumberOfProtoTransitions();
11941   int entry = header + last * step;
11942
11943   cache->set(entry + kProtoTransitionPrototypeOffset, *prototype);
11944   cache->set(entry + kProtoTransitionMapOffset, *target_map);
11945   map->SetNumberOfProtoTransitions(last + 1);
11946
11947   return map;
11948 }
11949
11950
11951 void Map::ZapTransitions() {
11952   TransitionArray* transition_array = transitions();
11953   // TODO(mstarzinger): Temporarily use a slower version instead of the faster
11954   // MemsetPointer to investigate a crasher. Switch back to MemsetPointer.
11955   Object** data = transition_array->data_start();
11956   Object* the_hole = GetHeap()->the_hole_value();
11957   int length = transition_array->length();
11958   for (int i = 0; i < length; i++) {
11959     data[i] = the_hole;
11960   }
11961 }
11962
11963
11964 void Map::ZapPrototypeTransitions() {
11965   FixedArray* proto_transitions = GetPrototypeTransitions();
11966   MemsetPointer(proto_transitions->data_start(),
11967                 GetHeap()->the_hole_value(),
11968                 proto_transitions->length());
11969 }
11970
11971
11972 // static
11973 void Map::AddDependentCompilationInfo(Handle<Map> map,
11974                                       DependentCode::DependencyGroup group,
11975                                       CompilationInfo* info) {
11976   Handle<DependentCode> codes =
11977       DependentCode::Insert(handle(map->dependent_code(), info->isolate()),
11978                             group, info->object_wrapper());
11979   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11980   info->dependencies(group)->Add(map, info->zone());
11981 }
11982
11983
11984 // static
11985 void Map::AddDependentCode(Handle<Map> map,
11986                            DependentCode::DependencyGroup group,
11987                            Handle<Code> code) {
11988   Handle<DependentCode> codes = DependentCode::Insert(
11989       Handle<DependentCode>(map->dependent_code()), group, code);
11990   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11991 }
11992
11993
11994 // static
11995 void Map::AddDependentIC(Handle<Map> map,
11996                          Handle<Code> stub) {
11997   ASSERT(stub->next_code_link()->IsUndefined());
11998   int n = map->dependent_code()->number_of_entries(DependentCode::kWeakICGroup);
11999   if (n == 0) {
12000     // Slow path: insert the head of the list with possible heap allocation.
12001     Map::AddDependentCode(map, DependentCode::kWeakICGroup, stub);
12002   } else {
12003     // Fast path: link the stub to the existing head of the list without any
12004     // heap allocation.
12005     ASSERT(n == 1);
12006     map->dependent_code()->AddToDependentICList(stub);
12007   }
12008 }
12009
12010
12011 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
12012   Recompute(entries);
12013 }
12014
12015
12016 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
12017   start_indexes_[0] = 0;
12018   for (int g = 1; g <= kGroupCount; g++) {
12019     int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
12020     start_indexes_[g] = start_indexes_[g - 1] + count;
12021   }
12022 }
12023
12024
12025 DependentCode* DependentCode::ForObject(Handle<HeapObject> object,
12026                                         DependencyGroup group) {
12027   AllowDeferredHandleDereference dependencies_are_safe;
12028   if (group == DependentCode::kPropertyCellChangedGroup) {
12029     return Handle<PropertyCell>::cast(object)->dependent_code();
12030   } else if (group == DependentCode::kAllocationSiteTenuringChangedGroup ||
12031       group == DependentCode::kAllocationSiteTransitionChangedGroup) {
12032     return Handle<AllocationSite>::cast(object)->dependent_code();
12033   }
12034   return Handle<Map>::cast(object)->dependent_code();
12035 }
12036
12037
12038 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
12039                                             DependencyGroup group,
12040                                             Handle<Object> object) {
12041   GroupStartIndexes starts(*entries);
12042   int start = starts.at(group);
12043   int end = starts.at(group + 1);
12044   int number_of_entries = starts.number_of_entries();
12045   // Check for existing entry to avoid duplicates.
12046   for (int i = start; i < end; i++) {
12047     if (entries->object_at(i) == *object) return entries;
12048   }
12049   if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
12050     int capacity = kCodesStartIndex + number_of_entries + 1;
12051     if (capacity > 5) capacity = capacity * 5 / 4;
12052     Handle<DependentCode> new_entries = Handle<DependentCode>::cast(
12053         FixedArray::CopySize(entries, capacity, TENURED));
12054     // The number of codes can change after GC.
12055     starts.Recompute(*entries);
12056     start = starts.at(group);
12057     end = starts.at(group + 1);
12058     number_of_entries = starts.number_of_entries();
12059     for (int i = 0; i < number_of_entries; i++) {
12060       entries->clear_at(i);
12061     }
12062     // If the old fixed array was empty, we need to reset counters of the
12063     // new array.
12064     if (number_of_entries == 0) {
12065       for (int g = 0; g < kGroupCount; g++) {
12066         new_entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
12067       }
12068     }
12069     entries = new_entries;
12070   }
12071   entries->ExtendGroup(group);
12072   entries->set_object_at(end, *object);
12073   entries->set_number_of_entries(group, end + 1 - start);
12074   return entries;
12075 }
12076
12077
12078 void DependentCode::UpdateToFinishedCode(DependencyGroup group,
12079                                          CompilationInfo* info,
12080                                          Code* code) {
12081   DisallowHeapAllocation no_gc;
12082   AllowDeferredHandleDereference get_object_wrapper;
12083   Foreign* info_wrapper = *info->object_wrapper();
12084   GroupStartIndexes starts(this);
12085   int start = starts.at(group);
12086   int end = starts.at(group + 1);
12087   for (int i = start; i < end; i++) {
12088     if (object_at(i) == info_wrapper) {
12089       set_object_at(i, code);
12090       break;
12091     }
12092   }
12093
12094 #ifdef DEBUG
12095   for (int i = start; i < end; i++) {
12096     ASSERT(is_code_at(i) || compilation_info_at(i) != info);
12097   }
12098 #endif
12099 }
12100
12101
12102 void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
12103                                           CompilationInfo* info) {
12104   DisallowHeapAllocation no_allocation;
12105   AllowDeferredHandleDereference get_object_wrapper;
12106   Foreign* info_wrapper = *info->object_wrapper();
12107   GroupStartIndexes starts(this);
12108   int start = starts.at(group);
12109   int end = starts.at(group + 1);
12110   // Find compilation info wrapper.
12111   int info_pos = -1;
12112   for (int i = start; i < end; i++) {
12113     if (object_at(i) == info_wrapper) {
12114       info_pos = i;
12115       break;
12116     }
12117   }
12118   if (info_pos == -1) return;  // Not found.
12119   int gap = info_pos;
12120   // Use the last of each group to fill the gap in the previous group.
12121   for (int i = group; i < kGroupCount; i++) {
12122     int last_of_group = starts.at(i + 1) - 1;
12123     ASSERT(last_of_group >= gap);
12124     if (last_of_group == gap) continue;
12125     copy(last_of_group, gap);
12126     gap = last_of_group;
12127   }
12128   ASSERT(gap == starts.number_of_entries() - 1);
12129   clear_at(gap);  // Clear last gap.
12130   set_number_of_entries(group, end - start - 1);
12131
12132 #ifdef DEBUG
12133   for (int i = start; i < end - 1; i++) {
12134     ASSERT(is_code_at(i) || compilation_info_at(i) != info);
12135   }
12136 #endif
12137 }
12138
12139
12140 static bool CodeListContains(Object* head, Code* code) {
12141   while (!head->IsUndefined()) {
12142     if (head == code) return true;
12143     head = Code::cast(head)->next_code_link();
12144   }
12145   return false;
12146 }
12147
12148
12149 bool DependentCode::Contains(DependencyGroup group, Code* code) {
12150   GroupStartIndexes starts(this);
12151   int start = starts.at(group);
12152   int end = starts.at(group + 1);
12153   if (group == kWeakICGroup) {
12154     return CodeListContains(object_at(start), code);
12155   }
12156   for (int i = start; i < end; i++) {
12157     if (object_at(i) == code) return true;
12158   }
12159   return false;
12160 }
12161
12162
12163 bool DependentCode::MarkCodeForDeoptimization(
12164     Isolate* isolate,
12165     DependentCode::DependencyGroup group) {
12166   DisallowHeapAllocation no_allocation_scope;
12167   DependentCode::GroupStartIndexes starts(this);
12168   int start = starts.at(group);
12169   int end = starts.at(group + 1);
12170   int code_entries = starts.number_of_entries();
12171   if (start == end) return false;
12172
12173   // Mark all the code that needs to be deoptimized.
12174   bool marked = false;
12175   for (int i = start; i < end; i++) {
12176     if (is_code_at(i)) {
12177       Code* code = code_at(i);
12178       if (!code->marked_for_deoptimization()) {
12179         code->set_marked_for_deoptimization(true);
12180         marked = true;
12181       }
12182     } else {
12183       CompilationInfo* info = compilation_info_at(i);
12184       info->AbortDueToDependencyChange();
12185     }
12186   }
12187   // Compact the array by moving all subsequent groups to fill in the new holes.
12188   for (int src = end, dst = start; src < code_entries; src++, dst++) {
12189     copy(src, dst);
12190   }
12191   // Now the holes are at the end of the array, zap them for heap-verifier.
12192   int removed = end - start;
12193   for (int i = code_entries - removed; i < code_entries; i++) {
12194     clear_at(i);
12195   }
12196   set_number_of_entries(group, 0);
12197   return marked;
12198 }
12199
12200
12201 void DependentCode::DeoptimizeDependentCodeGroup(
12202     Isolate* isolate,
12203     DependentCode::DependencyGroup group) {
12204   ASSERT(AllowCodeDependencyChange::IsAllowed());
12205   DisallowHeapAllocation no_allocation_scope;
12206   bool marked = MarkCodeForDeoptimization(isolate, group);
12207
12208   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
12209 }
12210
12211
12212 void DependentCode::AddToDependentICList(Handle<Code> stub) {
12213   DisallowHeapAllocation no_heap_allocation;
12214   GroupStartIndexes starts(this);
12215   int i = starts.at(kWeakICGroup);
12216   Object* head = object_at(i);
12217   // Try to insert the stub after the head of the list to minimize number of
12218   // writes to the DependentCode array, since a write to the array can make it
12219   // strong if it was alread marked by incremental marker.
12220   if (head->IsCode()) {
12221     stub->set_next_code_link(Code::cast(head)->next_code_link());
12222     Code::cast(head)->set_next_code_link(*stub);
12223   } else {
12224     stub->set_next_code_link(head);
12225     set_object_at(i, *stub);
12226   }
12227 }
12228
12229
12230 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
12231                                        Handle<Object> prototype) {
12232   Handle<Map> new_map = GetPrototypeTransition(map, prototype);
12233   if (new_map.is_null()) {
12234     new_map = Copy(map);
12235     PutPrototypeTransition(map, prototype, new_map);
12236     new_map->set_prototype(*prototype);
12237   }
12238   return new_map;
12239 }
12240
12241
12242 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12243                                            Handle<Object> value,
12244                                            bool skip_hidden_prototypes) {
12245 #ifdef DEBUG
12246   int size = object->Size();
12247 #endif
12248
12249   Isolate* isolate = object->GetIsolate();
12250   Heap* heap = isolate->heap();
12251   // Silently ignore the change if value is not a JSObject or null.
12252   // SpiderMonkey behaves this way.
12253   if (!value->IsJSReceiver() && !value->IsNull()) return value;
12254
12255   // From 8.6.2 Object Internal Methods
12256   // ...
12257   // In addition, if [[Extensible]] is false the value of the [[Class]] and
12258   // [[Prototype]] internal properties of the object may not be modified.
12259   // ...
12260   // Implementation specific extensions that modify [[Class]], [[Prototype]]
12261   // or [[Extensible]] must not violate the invariants defined in the preceding
12262   // paragraph.
12263   if (!object->map()->is_extensible()) {
12264     Handle<Object> args[] = { object };
12265     Handle<Object> error = isolate->factory()->NewTypeError(
12266         "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args)));
12267     return isolate->Throw<Object>(error);
12268   }
12269
12270   // Before we can set the prototype we need to be sure
12271   // prototype cycles are prevented.
12272   // It is sufficient to validate that the receiver is not in the new prototype
12273   // chain.
12274   for (Object* pt = *value;
12275        pt != heap->null_value();
12276        pt = pt->GetPrototype(isolate)) {
12277     if (JSReceiver::cast(pt) == *object) {
12278       // Cycle detected.
12279       Handle<Object> error = isolate->factory()->NewError(
12280           "cyclic_proto", HandleVector<Object>(NULL, 0));
12281       return isolate->Throw<Object>(error);
12282     }
12283   }
12284
12285   bool dictionary_elements_in_chain =
12286       object->map()->DictionaryElementsInPrototypeChainOnly();
12287   Handle<JSObject> real_receiver = object;
12288
12289   if (skip_hidden_prototypes) {
12290     // Find the first object in the chain whose prototype object is not
12291     // hidden and set the new prototype on that object.
12292     Object* current_proto = real_receiver->GetPrototype();
12293     while (current_proto->IsJSObject() &&
12294           JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
12295       real_receiver = handle(JSObject::cast(current_proto), isolate);
12296       current_proto = current_proto->GetPrototype(isolate);
12297     }
12298   }
12299
12300   // Set the new prototype of the object.
12301   Handle<Map> map(real_receiver->map());
12302
12303   // Nothing to do if prototype is already set.
12304   if (map->prototype() == *value) return value;
12305
12306   if (value->IsJSObject()) {
12307     JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
12308   }
12309
12310   Handle<Map> new_map = Map::TransitionToPrototype(map, value);
12311   ASSERT(new_map->prototype() == *value);
12312   JSObject::MigrateToMap(real_receiver, new_map);
12313
12314   if (!dictionary_elements_in_chain &&
12315       new_map->DictionaryElementsInPrototypeChainOnly()) {
12316     // If the prototype chain didn't previously have element callbacks, then
12317     // KeyedStoreICs need to be cleared to ensure any that involve this
12318     // map go generic.
12319     object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
12320   }
12321
12322   heap->ClearInstanceofCache();
12323   ASSERT(size == object->Size());
12324   return value;
12325 }
12326
12327
12328 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
12329                                         Arguments* args,
12330                                         uint32_t first_arg,
12331                                         uint32_t arg_count,
12332                                         EnsureElementsMode mode) {
12333   // Elements in |Arguments| are ordered backwards (because they're on the
12334   // stack), but the method that's called here iterates over them in forward
12335   // direction.
12336   return EnsureCanContainElements(
12337       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
12338 }
12339
12340
12341 MaybeHandle<AccessorPair> JSObject::GetOwnPropertyAccessorPair(
12342     Handle<JSObject> object,
12343     Handle<Name> name) {
12344   uint32_t index = 0;
12345   if (name->AsArrayIndex(&index)) {
12346     return GetOwnElementAccessorPair(object, index);
12347   }
12348
12349   Isolate* isolate = object->GetIsolate();
12350   LookupResult lookup(isolate);
12351   object->LookupOwnRealNamedProperty(name, &lookup);
12352
12353   if (lookup.IsPropertyCallbacks() &&
12354       lookup.GetCallbackObject()->IsAccessorPair()) {
12355     return handle(AccessorPair::cast(lookup.GetCallbackObject()), isolate);
12356   }
12357   return MaybeHandle<AccessorPair>();
12358 }
12359
12360
12361 MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair(
12362     Handle<JSObject> object,
12363     uint32_t index) {
12364   if (object->IsJSGlobalProxy()) {
12365     Handle<Object> proto(object->GetPrototype(), object->GetIsolate());
12366     if (proto->IsNull()) return MaybeHandle<AccessorPair>();
12367     ASSERT(proto->IsJSGlobalObject());
12368     return GetOwnElementAccessorPair(Handle<JSObject>::cast(proto), index);
12369   }
12370
12371   // Check for lookup interceptor.
12372   if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>();
12373
12374   return object->GetElementsAccessor()->GetAccessorPair(object, object, index);
12375 }
12376
12377
12378 MaybeHandle<Object> JSObject::SetElementWithInterceptor(
12379     Handle<JSObject> object,
12380     uint32_t index,
12381     Handle<Object> value,
12382     PropertyAttributes attributes,
12383     StrictMode strict_mode,
12384     bool check_prototype,
12385     SetPropertyMode set_mode) {
12386   Isolate* isolate = object->GetIsolate();
12387
12388   // Make sure that the top context does not change when doing
12389   // callbacks or interceptor calls.
12390   AssertNoContextChange ncc(isolate);
12391
12392   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
12393   if (!interceptor->setter()->IsUndefined()) {
12394     v8::IndexedPropertySetterCallback setter =
12395         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
12396     LOG(isolate,
12397         ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
12398     PropertyCallbackArguments args(isolate, interceptor->data(), *object,
12399                                    *object);
12400     v8::Handle<v8::Value> result =
12401         args.Call(setter, index, v8::Utils::ToLocal(value));
12402     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12403     if (!result.IsEmpty()) return value;
12404   }
12405
12406   return SetElementWithoutInterceptor(object, index, value, attributes,
12407                                       strict_mode,
12408                                       check_prototype,
12409                                       set_mode);
12410 }
12411
12412
12413 MaybeHandle<Object> JSObject::GetElementWithCallback(
12414     Handle<JSObject> object,
12415     Handle<Object> receiver,
12416     Handle<Object> structure,
12417     uint32_t index,
12418     Handle<Object> holder) {
12419   Isolate* isolate = object->GetIsolate();
12420   ASSERT(!structure->IsForeign());
12421   // api style callbacks.
12422   if (structure->IsExecutableAccessorInfo()) {
12423     Handle<ExecutableAccessorInfo> data =
12424         Handle<ExecutableAccessorInfo>::cast(structure);
12425     Object* fun_obj = data->getter();
12426     v8::AccessorGetterCallback call_fun =
12427         v8::ToCData<v8::AccessorGetterCallback>(fun_obj);
12428     if (call_fun == NULL) return isolate->factory()->undefined_value();
12429     Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder);
12430     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12431     Handle<String> key = isolate->factory()->NumberToString(number);
12432     LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key));
12433     PropertyCallbackArguments
12434         args(isolate, data->data(), *receiver, *holder_handle);
12435     v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
12436     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12437     if (result.IsEmpty()) return isolate->factory()->undefined_value();
12438     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12439     result_internal->VerifyApiCallResultType();
12440     // Rebox handle before return.
12441     return handle(*result_internal, isolate);
12442   }
12443
12444   // __defineGetter__ callback
12445   if (structure->IsAccessorPair()) {
12446     Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
12447                           isolate);
12448     if (getter->IsSpecFunction()) {
12449       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12450       return GetPropertyWithDefinedGetter(
12451           receiver, Handle<JSReceiver>::cast(getter));
12452     }
12453     // Getter is not a function.
12454     return isolate->factory()->undefined_value();
12455   }
12456
12457   if (structure->IsDeclaredAccessorInfo()) {
12458     return GetDeclaredAccessorProperty(
12459         receiver, Handle<DeclaredAccessorInfo>::cast(structure), isolate);
12460   }
12461
12462   UNREACHABLE();
12463   return MaybeHandle<Object>();
12464 }
12465
12466
12467 MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
12468                                                      Handle<Object> structure,
12469                                                      uint32_t index,
12470                                                      Handle<Object> value,
12471                                                      Handle<JSObject> holder,
12472                                                      StrictMode strict_mode) {
12473   Isolate* isolate = object->GetIsolate();
12474
12475   // We should never get here to initialize a const with the hole
12476   // value since a const declaration would conflict with the setter.
12477   ASSERT(!value->IsTheHole());
12478   ASSERT(!structure->IsForeign());
12479   if (structure->IsExecutableAccessorInfo()) {
12480     // api style callbacks
12481     Handle<ExecutableAccessorInfo> data =
12482         Handle<ExecutableAccessorInfo>::cast(structure);
12483     Object* call_obj = data->setter();
12484     v8::AccessorSetterCallback call_fun =
12485         v8::ToCData<v8::AccessorSetterCallback>(call_obj);
12486     if (call_fun == NULL) return value;
12487     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12488     Handle<String> key(isolate->factory()->NumberToString(number));
12489     LOG(isolate, ApiNamedPropertyAccess("store", *object, *key));
12490     PropertyCallbackArguments
12491         args(isolate, data->data(), *object, *holder);
12492     args.Call(call_fun,
12493               v8::Utils::ToLocal(key),
12494               v8::Utils::ToLocal(value));
12495     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12496     return value;
12497   }
12498
12499   if (structure->IsAccessorPair()) {
12500     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
12501     if (setter->IsSpecFunction()) {
12502       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12503       return SetPropertyWithDefinedSetter(
12504           object, Handle<JSReceiver>::cast(setter), value);
12505     } else {
12506       if (strict_mode == SLOPPY) return value;
12507       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
12508       Handle<Object> args[2] = { key, holder };
12509       Handle<Object> error = isolate->factory()->NewTypeError(
12510           "no_setter_in_callback", HandleVector(args, 2));
12511       return isolate->Throw<Object>(error);
12512     }
12513   }
12514
12515   // TODO(dcarney): Handle correctly.
12516   if (structure->IsDeclaredAccessorInfo()) return value;
12517
12518   UNREACHABLE();
12519   return MaybeHandle<Object>();
12520 }
12521
12522
12523 bool JSObject::HasFastArgumentsElements() {
12524   Heap* heap = GetHeap();
12525   if (!elements()->IsFixedArray()) return false;
12526   FixedArray* elements = FixedArray::cast(this->elements());
12527   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12528     return false;
12529   }
12530   FixedArray* arguments = FixedArray::cast(elements->get(1));
12531   return !arguments->IsDictionary();
12532 }
12533
12534
12535 bool JSObject::HasDictionaryArgumentsElements() {
12536   Heap* heap = GetHeap();
12537   if (!elements()->IsFixedArray()) return false;
12538   FixedArray* elements = FixedArray::cast(this->elements());
12539   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12540     return false;
12541   }
12542   FixedArray* arguments = FixedArray::cast(elements->get(1));
12543   return arguments->IsDictionary();
12544 }
12545
12546
12547 // Adding n elements in fast case is O(n*n).
12548 // Note: revisit design to have dual undefined values to capture absent
12549 // elements.
12550 MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
12551                                              uint32_t index,
12552                                              Handle<Object> value,
12553                                              StrictMode strict_mode,
12554                                              bool check_prototype) {
12555   ASSERT(object->HasFastSmiOrObjectElements() ||
12556          object->HasFastArgumentsElements());
12557
12558   Isolate* isolate = object->GetIsolate();
12559
12560   // Array optimizations rely on the prototype lookups of Array objects always
12561   // returning undefined. If there is a store to the initial prototype object,
12562   // make sure all of these optimizations are invalidated.
12563   if (isolate->is_initial_object_prototype(*object) ||
12564       isolate->is_initial_array_prototype(*object)) {
12565     object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate,
12566         DependentCode::kElementsCantBeAddedGroup);
12567   }
12568
12569   Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12570   if (backing_store->map() ==
12571       isolate->heap()->sloppy_arguments_elements_map()) {
12572     backing_store = handle(FixedArray::cast(backing_store->get(1)));
12573   } else {
12574     backing_store = EnsureWritableFastElements(object);
12575   }
12576   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12577
12578   if (check_prototype &&
12579       (index >= capacity || backing_store->get(index)->IsTheHole())) {
12580     bool found;
12581     MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12582         object, index, value, &found, strict_mode);
12583     if (found) return result;
12584   }
12585
12586   uint32_t new_capacity = capacity;
12587   // Check if the length property of this object needs to be updated.
12588   uint32_t array_length = 0;
12589   bool must_update_array_length = false;
12590   bool introduces_holes = true;
12591   if (object->IsJSArray()) {
12592     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12593     introduces_holes = index > array_length;
12594     if (index >= array_length) {
12595       must_update_array_length = true;
12596       array_length = index + 1;
12597     }
12598   } else {
12599     introduces_holes = index >= capacity;
12600   }
12601
12602   // If the array is growing, and it's not growth by a single element at the
12603   // end, make sure that the ElementsKind is HOLEY.
12604   ElementsKind elements_kind = object->GetElementsKind();
12605   if (introduces_holes &&
12606       IsFastElementsKind(elements_kind) &&
12607       !IsFastHoleyElementsKind(elements_kind)) {
12608     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12609     TransitionElementsKind(object, transitioned_kind);
12610   }
12611
12612   // Check if the capacity of the backing store needs to be increased, or if
12613   // a transition to slow elements is necessary.
12614   if (index >= capacity) {
12615     bool convert_to_slow = true;
12616     if ((index - capacity) < kMaxGap) {
12617       new_capacity = NewElementsCapacity(index + 1);
12618       ASSERT(new_capacity > index);
12619       if (!object->ShouldConvertToSlowElements(new_capacity)) {
12620         convert_to_slow = false;
12621       }
12622     }
12623     if (convert_to_slow) {
12624       NormalizeElements(object);
12625       return SetDictionaryElement(object, index, value, NONE, strict_mode,
12626                                   check_prototype);
12627     }
12628   }
12629   // Convert to fast double elements if appropriate.
12630   if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12631     // Consider fixing the boilerplate as well if we have one.
12632     ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
12633         ? FAST_HOLEY_DOUBLE_ELEMENTS
12634         : FAST_DOUBLE_ELEMENTS;
12635
12636     UpdateAllocationSite(object, to_kind);
12637
12638     SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12639     FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12640     JSObject::ValidateElements(object);
12641     return value;
12642   }
12643   // Change elements kind from Smi-only to generic FAST if necessary.
12644   if (object->HasFastSmiElements() && !value->IsSmi()) {
12645     ElementsKind kind = object->HasFastHoleyElements()
12646         ? FAST_HOLEY_ELEMENTS
12647         : FAST_ELEMENTS;
12648
12649     UpdateAllocationSite(object, kind);
12650     Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12651     JSObject::MigrateToMap(object, new_map);
12652     ASSERT(IsFastObjectElementsKind(object->GetElementsKind()));
12653   }
12654   // Increase backing store capacity if that's been decided previously.
12655   if (new_capacity != capacity) {
12656     SetFastElementsCapacitySmiMode smi_mode =
12657         value->IsSmi() && object->HasFastSmiElements()
12658             ? kAllowSmiElements
12659             : kDontAllowSmiElements;
12660     Handle<FixedArray> new_elements =
12661         SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12662                                          smi_mode);
12663     new_elements->set(index, *value);
12664     JSObject::ValidateElements(object);
12665     return value;
12666   }
12667
12668   // Finally, set the new element and length.
12669   ASSERT(object->elements()->IsFixedArray());
12670   backing_store->set(index, *value);
12671   if (must_update_array_length) {
12672     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12673   }
12674   return value;
12675 }
12676
12677
12678 MaybeHandle<Object> JSObject::SetDictionaryElement(
12679     Handle<JSObject> object,
12680     uint32_t index,
12681     Handle<Object> value,
12682     PropertyAttributes attributes,
12683     StrictMode strict_mode,
12684     bool check_prototype,
12685     SetPropertyMode set_mode) {
12686   ASSERT(object->HasDictionaryElements() ||
12687          object->HasDictionaryArgumentsElements());
12688   Isolate* isolate = object->GetIsolate();
12689
12690   // Insert element in the dictionary.
12691   Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12692   bool is_arguments =
12693       (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12694   Handle<SeededNumberDictionary> dictionary(is_arguments
12695     ? SeededNumberDictionary::cast(elements->get(1))
12696     : SeededNumberDictionary::cast(*elements));
12697
12698   int entry = dictionary->FindEntry(index);
12699   if (entry != SeededNumberDictionary::kNotFound) {
12700     Handle<Object> element(dictionary->ValueAt(entry), isolate);
12701     PropertyDetails details = dictionary->DetailsAt(entry);
12702     if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
12703       return SetElementWithCallback(object, element, index, value, object,
12704                                     strict_mode);
12705     } else {
12706       dictionary->UpdateMaxNumberKey(index);
12707       // If a value has not been initialized we allow writing to it even if it
12708       // is read-only (a declared const that has not been initialized).  If a
12709       // value is being defined we skip attribute checks completely.
12710       if (set_mode == DEFINE_PROPERTY) {
12711         details = PropertyDetails(
12712             attributes, NORMAL, details.dictionary_index());
12713         dictionary->DetailsAtPut(entry, details);
12714       } else if (details.IsReadOnly() && !element->IsTheHole()) {
12715         if (strict_mode == SLOPPY) {
12716           return isolate->factory()->undefined_value();
12717         } else {
12718           Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12719           Handle<Object> args[2] = { number, object };
12720           Handle<Object> error =
12721               isolate->factory()->NewTypeError("strict_read_only_property",
12722                                                HandleVector(args, 2));
12723           return isolate->Throw<Object>(error);
12724         }
12725       }
12726       // Elements of the arguments object in slow mode might be slow aliases.
12727       if (is_arguments && element->IsAliasedArgumentsEntry()) {
12728         Handle<AliasedArgumentsEntry> entry =
12729             Handle<AliasedArgumentsEntry>::cast(element);
12730         Handle<Context> context(Context::cast(elements->get(0)));
12731         int context_index = entry->aliased_context_slot();
12732         ASSERT(!context->get(context_index)->IsTheHole());
12733         context->set(context_index, *value);
12734         // For elements that are still writable we keep slow aliasing.
12735         if (!details.IsReadOnly()) value = element;
12736       }
12737       dictionary->ValueAtPut(entry, *value);
12738     }
12739   } else {
12740     // Index not already used. Look for an accessor in the prototype chain.
12741     // Can cause GC!
12742     if (check_prototype) {
12743       bool found;
12744       MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12745           object, index, value, &found, strict_mode);
12746       if (found) return result;
12747     }
12748
12749     // When we set the is_extensible flag to false we always force the
12750     // element into dictionary mode (and force them to stay there).
12751     if (!object->map()->is_extensible()) {
12752       if (strict_mode == SLOPPY) {
12753         return isolate->factory()->undefined_value();
12754       } else {
12755         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12756         Handle<String> name = isolate->factory()->NumberToString(number);
12757         Handle<Object> args[1] = { name };
12758         Handle<Object> error =
12759             isolate->factory()->NewTypeError("object_not_extensible",
12760                                              HandleVector(args, 1));
12761         return isolate->Throw<Object>(error);
12762       }
12763     }
12764
12765     PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
12766     Handle<SeededNumberDictionary> new_dictionary =
12767         SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
12768                                                details);
12769     if (*dictionary != *new_dictionary) {
12770       if (is_arguments) {
12771         elements->set(1, *new_dictionary);
12772       } else {
12773         object->set_elements(*new_dictionary);
12774       }
12775       dictionary = new_dictionary;
12776     }
12777   }
12778
12779   // Update the array length if this JSObject is an array.
12780   if (object->IsJSArray()) {
12781     JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index,
12782                                           value);
12783   }
12784
12785   // Attempt to put this object back in fast case.
12786   if (object->ShouldConvertToFastElements()) {
12787     uint32_t new_length = 0;
12788     if (object->IsJSArray()) {
12789       CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length));
12790     } else {
12791       new_length = dictionary->max_number_key() + 1;
12792     }
12793     SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays
12794         ? kAllowSmiElements
12795         : kDontAllowSmiElements;
12796     bool has_smi_only_elements = false;
12797     bool should_convert_to_fast_double_elements =
12798         object->ShouldConvertToFastDoubleElements(&has_smi_only_elements);
12799     if (has_smi_only_elements) {
12800       smi_mode = kForceSmiElements;
12801     }
12802
12803     if (should_convert_to_fast_double_elements) {
12804       SetFastDoubleElementsCapacityAndLength(object, new_length, new_length);
12805     } else {
12806       SetFastElementsCapacityAndLength(object, new_length, new_length,
12807                                        smi_mode);
12808     }
12809     JSObject::ValidateElements(object);
12810 #ifdef DEBUG
12811     if (FLAG_trace_normalization) {
12812       PrintF("Object elements are fast case again:\n");
12813       object->Print();
12814     }
12815 #endif
12816   }
12817   return value;
12818 }
12819
12820 MaybeHandle<Object> JSObject::SetFastDoubleElement(
12821     Handle<JSObject> object,
12822     uint32_t index,
12823     Handle<Object> value,
12824     StrictMode strict_mode,
12825     bool check_prototype) {
12826   ASSERT(object->HasFastDoubleElements());
12827
12828   Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12829   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
12830
12831   // If storing to an element that isn't in the array, pass the store request
12832   // up the prototype chain before storing in the receiver's elements.
12833   if (check_prototype &&
12834       (index >= elms_length ||
12835        Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
12836     bool found;
12837     MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12838         object, index, value, &found, strict_mode);
12839     if (found) return result;
12840   }
12841
12842   // If the value object is not a heap number, switch to fast elements and try
12843   // again.
12844   bool value_is_smi = value->IsSmi();
12845   bool introduces_holes = true;
12846   uint32_t length = elms_length;
12847   if (object->IsJSArray()) {
12848     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length));
12849     introduces_holes = index > length;
12850   } else {
12851     introduces_holes = index >= elms_length;
12852   }
12853
12854   if (!value->IsNumber()) {
12855     SetFastElementsCapacityAndLength(object, elms_length, length,
12856                                      kDontAllowSmiElements);
12857     Handle<Object> result;
12858     ASSIGN_RETURN_ON_EXCEPTION(
12859         object->GetIsolate(), result,
12860         SetFastElement(object, index, value, strict_mode, check_prototype),
12861         Object);
12862     JSObject::ValidateElements(object);
12863     return result;
12864   }
12865
12866   double double_value = value_is_smi
12867       ? static_cast<double>(Handle<Smi>::cast(value)->value())
12868       : Handle<HeapNumber>::cast(value)->value();
12869
12870   // If the array is growing, and it's not growth by a single element at the
12871   // end, make sure that the ElementsKind is HOLEY.
12872   ElementsKind elements_kind = object->GetElementsKind();
12873   if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
12874     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12875     TransitionElementsKind(object, transitioned_kind);
12876   }
12877
12878   // Check whether there is extra space in the fixed array.
12879   if (index < elms_length) {
12880     Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
12881     elms->set(index, double_value);
12882     if (object->IsJSArray()) {
12883       // Update the length of the array if needed.
12884       uint32_t array_length = 0;
12885       CHECK(
12886           Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12887       if (index >= array_length) {
12888         Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12889       }
12890     }
12891     return value;
12892   }
12893
12894   // Allow gap in fast case.
12895   if ((index - elms_length) < kMaxGap) {
12896     // Try allocating extra space.
12897     int new_capacity = NewElementsCapacity(index+1);
12898     if (!object->ShouldConvertToSlowElements(new_capacity)) {
12899       ASSERT(static_cast<uint32_t>(new_capacity) > index);
12900       SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
12901       FixedDoubleArray::cast(object->elements())->set(index, double_value);
12902       JSObject::ValidateElements(object);
12903       return value;
12904     }
12905   }
12906
12907   // Otherwise default to slow case.
12908   ASSERT(object->HasFastDoubleElements());
12909   ASSERT(object->map()->has_fast_double_elements());
12910   ASSERT(object->elements()->IsFixedDoubleArray() ||
12911          object->elements()->length() == 0);
12912
12913   NormalizeElements(object);
12914   ASSERT(object->HasDictionaryElements());
12915   return SetElement(object, index, value, NONE, strict_mode, check_prototype);
12916 }
12917
12918
12919 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12920                                            uint32_t index,
12921                                            Handle<Object> value,
12922                                            PropertyAttributes attributes,
12923                                            StrictMode strict_mode) {
12924   if (object->IsJSProxy()) {
12925     return JSProxy::SetElementWithHandler(
12926         Handle<JSProxy>::cast(object), object, index, value, strict_mode);
12927   }
12928   return JSObject::SetElement(
12929       Handle<JSObject>::cast(object), index, value, attributes, strict_mode);
12930 }
12931
12932
12933 MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
12934                                             uint32_t index,
12935                                             Handle<Object> value,
12936                                             StrictMode strict_mode) {
12937   ASSERT(!object->HasExternalArrayElements());
12938   return JSObject::SetElement(object, index, value, NONE, strict_mode, false);
12939 }
12940
12941
12942 MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object,
12943                                          uint32_t index,
12944                                          Handle<Object> value,
12945                                          PropertyAttributes attributes,
12946                                          StrictMode strict_mode,
12947                                          bool check_prototype,
12948                                          SetPropertyMode set_mode) {
12949   Isolate* isolate = object->GetIsolate();
12950
12951   if (object->HasExternalArrayElements() ||
12952       object->HasFixedTypedArrayElements()) {
12953     if (!value->IsNumber() && !value->IsFloat32x4() && !value->IsFloat64x2() &&
12954         !value->IsInt32x4() && !value->IsUndefined()) {
12955       ASSIGN_RETURN_ON_EXCEPTION(
12956           isolate, value,
12957           Execution::ToNumber(isolate, value), Object);
12958     }
12959   }
12960
12961   // Check access rights if needed.
12962   if (object->IsAccessCheckNeeded()) {
12963     if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_SET)) {
12964       isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
12965       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12966       return value;
12967     }
12968   }
12969
12970   if (object->IsJSGlobalProxy()) {
12971     Handle<Object> proto(object->GetPrototype(), isolate);
12972     if (proto->IsNull()) return value;
12973     ASSERT(proto->IsJSGlobalObject());
12974     return SetElement(Handle<JSObject>::cast(proto), index, value, attributes,
12975                       strict_mode,
12976                       check_prototype,
12977                       set_mode);
12978   }
12979
12980   // Don't allow element properties to be redefined for external arrays.
12981   if ((object->HasExternalArrayElements() ||
12982           object->HasFixedTypedArrayElements()) &&
12983       set_mode == DEFINE_PROPERTY) {
12984     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12985     Handle<Object> args[] = { object, number };
12986     Handle<Object> error = isolate->factory()->NewTypeError(
12987         "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
12988     return isolate->Throw<Object>(error);
12989   }
12990
12991   // Normalize the elements to enable attributes on the property.
12992   if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
12993     Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
12994     // Make sure that we never go back to fast case.
12995     dictionary->set_requires_slow_elements();
12996   }
12997
12998   if (!object->map()->is_observed()) {
12999     return object->HasIndexedInterceptor()
13000       ? SetElementWithInterceptor(object, index, value, attributes,
13001                                   strict_mode, check_prototype, set_mode)
13002       : SetElementWithoutInterceptor(object, index, value, attributes,
13003                                      strict_mode, check_prototype, set_mode);
13004   }
13005
13006   PropertyAttributes old_attributes =
13007       JSReceiver::GetOwnElementAttribute(object, index);
13008   Handle<Object> old_value = isolate->factory()->the_hole_value();
13009   Handle<Object> old_length_handle;
13010   Handle<Object> new_length_handle;
13011
13012   if (old_attributes != ABSENT) {
13013     if (GetOwnElementAccessorPair(object, index).is_null()) {
13014       old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
13015     }
13016   } else if (object->IsJSArray()) {
13017     // Store old array length in case adding an element grows the array.
13018     old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13019                                isolate);
13020   }
13021
13022   // Check for lookup interceptor
13023   Handle<Object> result;
13024   ASSIGN_RETURN_ON_EXCEPTION(
13025       isolate, result,
13026       object->HasIndexedInterceptor()
13027           ? SetElementWithInterceptor(
13028               object, index, value, attributes,
13029               strict_mode, check_prototype, set_mode)
13030           : SetElementWithoutInterceptor(
13031               object, index, value, attributes,
13032               strict_mode, check_prototype, set_mode),
13033       Object);
13034
13035   Handle<String> name = isolate->factory()->Uint32ToString(index);
13036   PropertyAttributes new_attributes = GetOwnElementAttribute(object, index);
13037   if (old_attributes == ABSENT) {
13038     if (object->IsJSArray() &&
13039         !old_length_handle->SameValue(
13040             Handle<JSArray>::cast(object)->length())) {
13041       new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
13042                                  isolate);
13043       uint32_t old_length = 0;
13044       uint32_t new_length = 0;
13045       CHECK(old_length_handle->ToArrayIndex(&old_length));
13046       CHECK(new_length_handle->ToArrayIndex(&new_length));
13047
13048       BeginPerformSplice(Handle<JSArray>::cast(object));
13049       EnqueueChangeRecord(object, "add", name, old_value);
13050       EnqueueChangeRecord(object, "update", isolate->factory()->length_string(),
13051                           old_length_handle);
13052       EndPerformSplice(Handle<JSArray>::cast(object));
13053       Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
13054       EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length, deleted,
13055                           new_length - old_length);
13056     } else {
13057       EnqueueChangeRecord(object, "add", name, old_value);
13058     }
13059   } else if (old_value->IsTheHole()) {
13060     EnqueueChangeRecord(object, "reconfigure", name, old_value);
13061   } else {
13062     Handle<Object> new_value =
13063         Object::GetElement(isolate, object, index).ToHandleChecked();
13064     bool value_changed = !old_value->SameValue(*new_value);
13065     if (old_attributes != new_attributes) {
13066       if (!value_changed) old_value = isolate->factory()->the_hole_value();
13067       EnqueueChangeRecord(object, "reconfigure", name, old_value);
13068     } else if (value_changed) {
13069       EnqueueChangeRecord(object, "update", name, old_value);
13070     }
13071   }
13072
13073   return result;
13074 }
13075
13076
13077 MaybeHandle<Object> JSObject::SetElementWithoutInterceptor(
13078     Handle<JSObject> object,
13079     uint32_t index,
13080     Handle<Object> value,
13081     PropertyAttributes attributes,
13082     StrictMode strict_mode,
13083     bool check_prototype,
13084     SetPropertyMode set_mode) {
13085   ASSERT(object->HasDictionaryElements() ||
13086          object->HasDictionaryArgumentsElements() ||
13087          (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
13088   Isolate* isolate = object->GetIsolate();
13089   if (FLAG_trace_external_array_abuse &&
13090       IsExternalArrayElementsKind(object->GetElementsKind())) {
13091     CheckArrayAbuse(object, "external elements write", index);
13092   }
13093   if (FLAG_trace_js_array_abuse &&
13094       !IsExternalArrayElementsKind(object->GetElementsKind())) {
13095     if (object->IsJSArray()) {
13096       CheckArrayAbuse(object, "elements write", index, true);
13097     }
13098   }
13099   if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
13100       Handle<JSArray>::cast(object), index)) {
13101     if (strict_mode == SLOPPY) {
13102       return value;
13103     } else {
13104       return JSArray::ReadOnlyLengthError(Handle<JSArray>::cast(object));
13105     }
13106   }
13107   switch (object->GetElementsKind()) {
13108     case FAST_SMI_ELEMENTS:
13109     case FAST_ELEMENTS:
13110     case FAST_HOLEY_SMI_ELEMENTS:
13111     case FAST_HOLEY_ELEMENTS:
13112       return SetFastElement(object, index, value, strict_mode, check_prototype);
13113     case FAST_DOUBLE_ELEMENTS:
13114     case FAST_HOLEY_DOUBLE_ELEMENTS:
13115       return SetFastDoubleElement(object, index, value, strict_mode,
13116                                   check_prototype);
13117
13118 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
13119     case EXTERNAL_##TYPE##_ELEMENTS: {                                        \
13120       Handle<External##Type##Array> array(                                    \
13121           External##Type##Array::cast(object->elements()));                   \
13122       return External##Type##Array::SetValue(array, index, value);            \
13123     }                                                                         \
13124     case TYPE##_ELEMENTS: {                                                   \
13125       Handle<Fixed##Type##Array> array(                                       \
13126           Fixed##Type##Array::cast(object->elements()));                      \
13127       return Fixed##Type##Array::SetValue(array, index, value);               \
13128     }
13129
13130     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13131
13132 #undef TYPED_ARRAY_CASE
13133
13134     case DICTIONARY_ELEMENTS:
13135       return SetDictionaryElement(object, index, value, attributes, strict_mode,
13136                                   check_prototype,
13137                                   set_mode);
13138     case SLOPPY_ARGUMENTS_ELEMENTS: {
13139       Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
13140       uint32_t length = parameter_map->length();
13141       Handle<Object> probe = index < length - 2 ?
13142           Handle<Object>(parameter_map->get(index + 2), isolate) :
13143           Handle<Object>();
13144       if (!probe.is_null() && !probe->IsTheHole()) {
13145         Handle<Context> context(Context::cast(parameter_map->get(0)));
13146         int context_index = Handle<Smi>::cast(probe)->value();
13147         ASSERT(!context->get(context_index)->IsTheHole());
13148         context->set(context_index, *value);
13149         // Redefining attributes of an aliased element destroys fast aliasing.
13150         if (set_mode == SET_PROPERTY || attributes == NONE) return value;
13151         parameter_map->set_the_hole(index + 2);
13152         // For elements that are still writable we re-establish slow aliasing.
13153         if ((attributes & READ_ONLY) == 0) {
13154           value = Handle<Object>::cast(
13155               isolate->factory()->NewAliasedArgumentsEntry(context_index));
13156         }
13157       }
13158       Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
13159       if (arguments->IsDictionary()) {
13160         return SetDictionaryElement(object, index, value, attributes,
13161                                     strict_mode,
13162                                     check_prototype,
13163                                     set_mode);
13164       } else {
13165         return SetFastElement(object, index, value, strict_mode,
13166                               check_prototype);
13167       }
13168     }
13169   }
13170   // All possible cases have been handled above. Add a return to avoid the
13171   // complaints from the compiler.
13172   UNREACHABLE();
13173   return isolate->factory()->null_value();
13174 }
13175
13176
13177 const double AllocationSite::kPretenureRatio = 0.85;
13178
13179
13180 void AllocationSite::ResetPretenureDecision() {
13181   set_pretenure_decision(kUndecided);
13182   set_memento_found_count(0);
13183   set_memento_create_count(0);
13184 }
13185
13186
13187 PretenureFlag AllocationSite::GetPretenureMode() {
13188   PretenureDecision mode = pretenure_decision();
13189   // Zombie objects "decide" to be untenured.
13190   return mode == kTenure ? TENURED : NOT_TENURED;
13191 }
13192
13193
13194 bool AllocationSite::IsNestedSite() {
13195   ASSERT(FLAG_trace_track_allocation_sites);
13196   Object* current = GetHeap()->allocation_sites_list();
13197   while (current->IsAllocationSite()) {
13198     AllocationSite* current_site = AllocationSite::cast(current);
13199     if (current_site->nested_site() == this) {
13200       return true;
13201     }
13202     current = current_site->weak_next();
13203   }
13204   return false;
13205 }
13206
13207
13208 void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
13209                                               ElementsKind to_kind) {
13210   Isolate* isolate = site->GetIsolate();
13211
13212   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
13213     Handle<JSArray> transition_info =
13214         handle(JSArray::cast(site->transition_info()));
13215     ElementsKind kind = transition_info->GetElementsKind();
13216     // if kind is holey ensure that to_kind is as well.
13217     if (IsHoleyElementsKind(kind)) {
13218       to_kind = GetHoleyElementsKind(to_kind);
13219     }
13220     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
13221       // If the array is huge, it's not likely to be defined in a local
13222       // function, so we shouldn't make new instances of it very often.
13223       uint32_t length = 0;
13224       CHECK(transition_info->length()->ToArrayIndex(&length));
13225       if (length <= kMaximumArrayBytesToPretransition) {
13226         if (FLAG_trace_track_allocation_sites) {
13227           bool is_nested = site->IsNestedSite();
13228           PrintF(
13229               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
13230               reinterpret_cast<void*>(*site),
13231               is_nested ? "(nested)" : "",
13232               ElementsKindToString(kind),
13233               ElementsKindToString(to_kind));
13234         }
13235         JSObject::TransitionElementsKind(transition_info, to_kind);
13236         site->dependent_code()->DeoptimizeDependentCodeGroup(
13237             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
13238       }
13239     }
13240   } else {
13241     ElementsKind kind = site->GetElementsKind();
13242     // if kind is holey ensure that to_kind is as well.
13243     if (IsHoleyElementsKind(kind)) {
13244       to_kind = GetHoleyElementsKind(to_kind);
13245     }
13246     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
13247       if (FLAG_trace_track_allocation_sites) {
13248         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
13249                reinterpret_cast<void*>(*site),
13250                ElementsKindToString(kind),
13251                ElementsKindToString(to_kind));
13252       }
13253       site->SetElementsKind(to_kind);
13254       site->dependent_code()->DeoptimizeDependentCodeGroup(
13255           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
13256     }
13257   }
13258 }
13259
13260
13261 // static
13262 void AllocationSite::AddDependentCompilationInfo(Handle<AllocationSite> site,
13263                                                  Reason reason,
13264                                                  CompilationInfo* info) {
13265   DependentCode::DependencyGroup group = site->ToDependencyGroup(reason);
13266   Handle<DependentCode> dep(site->dependent_code());
13267   Handle<DependentCode> codes =
13268       DependentCode::Insert(dep, group, info->object_wrapper());
13269   if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
13270   info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
13271 }
13272
13273
13274 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
13275   switch (decision) {
13276     case kUndecided: return "undecided";
13277     case kDontTenure: return "don't tenure";
13278     case kMaybeTenure: return "maybe tenure";
13279     case kTenure: return "tenure";
13280     case kZombie: return "zombie";
13281     default: UNREACHABLE();
13282   }
13283   return NULL;
13284 }
13285
13286
13287 void JSObject::UpdateAllocationSite(Handle<JSObject> object,
13288                                     ElementsKind to_kind) {
13289   if (!object->IsJSArray()) return;
13290
13291   Heap* heap = object->GetHeap();
13292   if (!heap->InNewSpace(*object)) return;
13293
13294   Handle<AllocationSite> site;
13295   {
13296     DisallowHeapAllocation no_allocation;
13297
13298     AllocationMemento* memento = heap->FindAllocationMemento(*object);
13299     if (memento == NULL) return;
13300
13301     // Walk through to the Allocation Site
13302     site = handle(memento->GetAllocationSite());
13303   }
13304   AllocationSite::DigestTransitionFeedback(site, to_kind);
13305 }
13306
13307
13308 void JSObject::TransitionElementsKind(Handle<JSObject> object,
13309                                       ElementsKind to_kind) {
13310   ElementsKind from_kind = object->map()->elements_kind();
13311
13312   if (IsFastHoleyElementsKind(from_kind)) {
13313     to_kind = GetHoleyElementsKind(to_kind);
13314   }
13315
13316   if (from_kind == to_kind) return;
13317   // Don't update the site if to_kind isn't fast
13318   if (IsFastElementsKind(to_kind)) {
13319     UpdateAllocationSite(object, to_kind);
13320   }
13321
13322   Isolate* isolate = object->GetIsolate();
13323   if (object->elements() == isolate->heap()->empty_fixed_array() ||
13324       (IsFastSmiOrObjectElementsKind(from_kind) &&
13325        IsFastSmiOrObjectElementsKind(to_kind)) ||
13326       (from_kind == FAST_DOUBLE_ELEMENTS &&
13327        to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
13328     ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
13329     // No change is needed to the elements() buffer, the transition
13330     // only requires a map change.
13331     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
13332     MigrateToMap(object, new_map);
13333     if (FLAG_trace_elements_transitions) {
13334       Handle<FixedArrayBase> elms(object->elements());
13335       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
13336     }
13337     return;
13338   }
13339
13340   Handle<FixedArrayBase> elms(object->elements());
13341   uint32_t capacity = static_cast<uint32_t>(elms->length());
13342   uint32_t length = capacity;
13343
13344   if (object->IsJSArray()) {
13345     Object* raw_length = Handle<JSArray>::cast(object)->length();
13346     if (raw_length->IsUndefined()) {
13347       // If length is undefined, then JSArray is being initialized and has no
13348       // elements, assume a length of zero.
13349       length = 0;
13350     } else {
13351       CHECK(raw_length->ToArrayIndex(&length));
13352     }
13353   }
13354
13355   if (IsFastSmiElementsKind(from_kind) &&
13356       IsFastDoubleElementsKind(to_kind)) {
13357     SetFastDoubleElementsCapacityAndLength(object, capacity, length);
13358     JSObject::ValidateElements(object);
13359     return;
13360   }
13361
13362   if (IsFastDoubleElementsKind(from_kind) &&
13363       IsFastObjectElementsKind(to_kind)) {
13364     SetFastElementsCapacityAndLength(object, capacity, length,
13365                                      kDontAllowSmiElements);
13366     JSObject::ValidateElements(object);
13367     return;
13368   }
13369
13370   // This method should never be called for any other case than the ones
13371   // handled above.
13372   UNREACHABLE();
13373 }
13374
13375
13376 // static
13377 bool Map::IsValidElementsTransition(ElementsKind from_kind,
13378                                     ElementsKind to_kind) {
13379   // Transitions can't go backwards.
13380   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
13381     return false;
13382   }
13383
13384   // Transitions from HOLEY -> PACKED are not allowed.
13385   return !IsFastHoleyElementsKind(from_kind) ||
13386       IsFastHoleyElementsKind(to_kind);
13387 }
13388
13389
13390 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array,
13391                                            uint32_t index,
13392                                            Handle<Object> value) {
13393   uint32_t old_len = 0;
13394   CHECK(array->length()->ToArrayIndex(&old_len));
13395   // Check to see if we need to update the length. For now, we make
13396   // sure that the length stays within 32-bits (unsigned).
13397   if (index >= old_len && index != 0xffffffff) {
13398     Handle<Object> len = array->GetIsolate()->factory()->NewNumber(
13399         static_cast<double>(index) + 1);
13400     array->set_length(*len);
13401   }
13402 }
13403
13404
13405 bool JSArray::IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map) {
13406     Isolate* isolate = jsarray_map->GetIsolate();
13407     ASSERT(!jsarray_map->is_dictionary_map());
13408     LookupResult lookup(isolate);
13409     Handle<Name> length_string = isolate->factory()->length_string();
13410     jsarray_map->LookupDescriptor(NULL, *length_string, &lookup);
13411     return lookup.IsReadOnly();
13412 }
13413
13414
13415 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
13416                                         uint32_t index) {
13417   uint32_t length = 0;
13418   CHECK(array->length()->ToArrayIndex(&length));
13419   if (length <= index) {
13420     Isolate* isolate = array->GetIsolate();
13421     LookupResult lookup(isolate);
13422     Handle<Name> length_string = isolate->factory()->length_string();
13423     array->LookupOwnRealNamedProperty(length_string, &lookup);
13424     return lookup.IsReadOnly();
13425   }
13426   return false;
13427 }
13428
13429
13430 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
13431   Isolate* isolate = array->GetIsolate();
13432   Handle<Name> length = isolate->factory()->length_string();
13433   Handle<Object> args[2] = { length, array };
13434   Handle<Object> error = isolate->factory()->NewTypeError(
13435       "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
13436   return isolate->Throw<Object>(error);
13437 }
13438
13439
13440 MaybeHandle<Object> JSObject::GetElementWithInterceptor(
13441     Handle<JSObject> object,
13442     Handle<Object> receiver,
13443     uint32_t index) {
13444   Isolate* isolate = object->GetIsolate();
13445
13446   // Make sure that the top context does not change when doing
13447   // callbacks or interceptor calls.
13448   AssertNoContextChange ncc(isolate);
13449
13450   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate);
13451   if (!interceptor->getter()->IsUndefined()) {
13452     v8::IndexedPropertyGetterCallback getter =
13453         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
13454     LOG(isolate,
13455         ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
13456     PropertyCallbackArguments
13457         args(isolate, interceptor->data(), *receiver, *object);
13458     v8::Handle<v8::Value> result = args.Call(getter, index);
13459     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13460     if (!result.IsEmpty()) {
13461       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13462       result_internal->VerifyApiCallResultType();
13463       // Rebox handle before return.
13464       return handle(*result_internal, isolate);
13465     }
13466   }
13467
13468   ElementsAccessor* handler = object->GetElementsAccessor();
13469   Handle<Object> result;
13470   ASSIGN_RETURN_ON_EXCEPTION(
13471       isolate, result, handler->Get(receiver,  object, index),
13472       Object);
13473   if (!result->IsTheHole()) return result;
13474
13475   Handle<Object> proto(object->GetPrototype(), isolate);
13476   if (proto->IsNull()) return isolate->factory()->undefined_value();
13477   return Object::GetElementWithReceiver(isolate, proto, receiver, index);
13478 }
13479
13480
13481 bool JSObject::HasDenseElements() {
13482   int capacity = 0;
13483   int used = 0;
13484   GetElementsCapacityAndUsage(&capacity, &used);
13485   return (capacity == 0) || (used > (capacity / 2));
13486 }
13487
13488
13489 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
13490   *capacity = 0;
13491   *used = 0;
13492
13493   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
13494   FixedArray* backing_store = NULL;
13495   switch (GetElementsKind()) {
13496     case SLOPPY_ARGUMENTS_ELEMENTS:
13497       backing_store_base =
13498           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
13499       backing_store = FixedArray::cast(backing_store_base);
13500       if (backing_store->IsDictionary()) {
13501         SeededNumberDictionary* dictionary =
13502             SeededNumberDictionary::cast(backing_store);
13503         *capacity = dictionary->Capacity();
13504         *used = dictionary->NumberOfElements();
13505         break;
13506       }
13507       // Fall through.
13508     case FAST_SMI_ELEMENTS:
13509     case FAST_ELEMENTS:
13510       if (IsJSArray()) {
13511         *capacity = backing_store_base->length();
13512         *used = Smi::cast(JSArray::cast(this)->length())->value();
13513         break;
13514       }
13515       // Fall through if packing is not guaranteed.
13516     case FAST_HOLEY_SMI_ELEMENTS:
13517     case FAST_HOLEY_ELEMENTS:
13518       backing_store = FixedArray::cast(backing_store_base);
13519       *capacity = backing_store->length();
13520       for (int i = 0; i < *capacity; ++i) {
13521         if (!backing_store->get(i)->IsTheHole()) ++(*used);
13522       }
13523       break;
13524     case DICTIONARY_ELEMENTS: {
13525       SeededNumberDictionary* dictionary = element_dictionary();
13526       *capacity = dictionary->Capacity();
13527       *used = dictionary->NumberOfElements();
13528       break;
13529     }
13530     case FAST_DOUBLE_ELEMENTS:
13531       if (IsJSArray()) {
13532         *capacity = backing_store_base->length();
13533         *used = Smi::cast(JSArray::cast(this)->length())->value();
13534         break;
13535       }
13536       // Fall through if packing is not guaranteed.
13537     case FAST_HOLEY_DOUBLE_ELEMENTS: {
13538       *capacity = elements()->length();
13539       if (*capacity == 0) break;
13540       FixedDoubleArray * elms = FixedDoubleArray::cast(elements());
13541       for (int i = 0; i < *capacity; i++) {
13542         if (!elms->is_the_hole(i)) ++(*used);
13543       }
13544       break;
13545     }
13546
13547 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
13548     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
13549     case TYPE##_ELEMENTS:                                                    \
13550
13551     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13552 #undef TYPED_ARRAY_CASE
13553     {
13554       // External arrays are considered 100% used.
13555       FixedArrayBase* external_array = FixedArrayBase::cast(elements());
13556       *capacity = external_array->length();
13557       *used = external_array->length();
13558       break;
13559     }
13560   }
13561 }
13562
13563
13564 bool JSObject::WouldConvertToSlowElements(Handle<Object> key) {
13565   uint32_t index;
13566   if (HasFastElements() && key->ToArrayIndex(&index)) {
13567     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
13568     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
13569     if (index >= capacity) {
13570       if ((index - capacity) >= kMaxGap) return true;
13571       uint32_t new_capacity = NewElementsCapacity(index + 1);
13572       return ShouldConvertToSlowElements(new_capacity);
13573     }
13574   }
13575   return false;
13576 }
13577
13578
13579 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
13580   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
13581                 kMaxUncheckedFastElementsLength);
13582   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
13583       (new_capacity <= kMaxUncheckedFastElementsLength &&
13584        GetHeap()->InNewSpace(this))) {
13585     return false;
13586   }
13587   // If the fast-case backing storage takes up roughly three times as
13588   // much space (in machine words) as a dictionary backing storage
13589   // would, the object should have slow elements.
13590   int old_capacity = 0;
13591   int used_elements = 0;
13592   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
13593   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
13594       SeededNumberDictionary::kEntrySize;
13595   return 3 * dictionary_size <= new_capacity;
13596 }
13597
13598
13599 bool JSObject::ShouldConvertToFastElements() {
13600   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
13601   // If the elements are sparse, we should not go back to fast case.
13602   if (!HasDenseElements()) return false;
13603   // An object requiring access checks is never allowed to have fast
13604   // elements.  If it had fast elements we would skip security checks.
13605   if (IsAccessCheckNeeded()) return false;
13606   // Observed objects may not go to fast mode because they rely on map checks,
13607   // and for fast element accesses we sometimes check element kinds only.
13608   if (map()->is_observed()) return false;
13609
13610   FixedArray* elements = FixedArray::cast(this->elements());
13611   SeededNumberDictionary* dictionary = NULL;
13612   if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) {
13613     dictionary = SeededNumberDictionary::cast(elements->get(1));
13614   } else {
13615     dictionary = SeededNumberDictionary::cast(elements);
13616   }
13617   // If an element has been added at a very high index in the elements
13618   // dictionary, we cannot go back to fast case.
13619   if (dictionary->requires_slow_elements()) return false;
13620   // If the dictionary backing storage takes up roughly half as much
13621   // space (in machine words) as a fast-case backing storage would,
13622   // the object should have fast elements.
13623   uint32_t array_size = 0;
13624   if (IsJSArray()) {
13625     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
13626   } else {
13627     array_size = dictionary->max_number_key();
13628   }
13629   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
13630       SeededNumberDictionary::kEntrySize;
13631   return 2 * dictionary_size >= array_size;
13632 }
13633
13634
13635 bool JSObject::ShouldConvertToFastDoubleElements(
13636     bool* has_smi_only_elements) {
13637   *has_smi_only_elements = false;
13638   if (HasSloppyArgumentsElements()) return false;
13639   if (FLAG_unbox_double_arrays) {
13640     ASSERT(HasDictionaryElements());
13641     SeededNumberDictionary* dictionary = element_dictionary();
13642     bool found_double = false;
13643     for (int i = 0; i < dictionary->Capacity(); i++) {
13644       Object* key = dictionary->KeyAt(i);
13645       if (key->IsNumber()) {
13646         Object* value = dictionary->ValueAt(i);
13647         if (!value->IsNumber()) return false;
13648         if (!value->IsSmi()) {
13649           found_double = true;
13650         }
13651       }
13652     }
13653     *has_smi_only_elements = !found_double;
13654     return found_double;
13655   } else {
13656     return false;
13657   }
13658 }
13659
13660
13661 // Certain compilers request function template instantiation when they
13662 // see the definition of the other template functions in the
13663 // class. This requires us to have the template functions put
13664 // together, so even though this function belongs in objects-debug.cc,
13665 // we keep it here instead to satisfy certain compilers.
13666 #ifdef OBJECT_PRINT
13667 template<typename Derived, typename Shape, typename Key>
13668 void Dictionary<Derived, Shape, Key>::Print(FILE* out) {
13669   int capacity = DerivedHashTable::Capacity();
13670   for (int i = 0; i < capacity; i++) {
13671     Object* k = DerivedHashTable::KeyAt(i);
13672     if (DerivedHashTable::IsKey(k)) {
13673       PrintF(out, " ");
13674       if (k->IsString()) {
13675         String::cast(k)->StringPrint(out);
13676       } else {
13677         k->ShortPrint(out);
13678       }
13679       PrintF(out, ": ");
13680       ValueAt(i)->ShortPrint(out);
13681       PrintF(out, "\n");
13682     }
13683   }
13684 }
13685 #endif
13686
13687
13688 template<typename Derived, typename Shape, typename Key>
13689 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
13690   int pos = 0;
13691   int capacity = DerivedHashTable::Capacity();
13692   DisallowHeapAllocation no_gc;
13693   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
13694   for (int i = 0; i < capacity; i++) {
13695     Object* k =  Dictionary::KeyAt(i);
13696     if (Dictionary::IsKey(k)) {
13697       elements->set(pos++, ValueAt(i), mode);
13698     }
13699   }
13700   ASSERT(pos == elements->length());
13701 }
13702
13703
13704 InterceptorInfo* JSObject::GetNamedInterceptor() {
13705   ASSERT(map()->has_named_interceptor());
13706   JSFunction* constructor = JSFunction::cast(map()->constructor());
13707   ASSERT(constructor->shared()->IsApiFunction());
13708   Object* result =
13709       constructor->shared()->get_api_func_data()->named_property_handler();
13710   return InterceptorInfo::cast(result);
13711 }
13712
13713
13714 InterceptorInfo* JSObject::GetIndexedInterceptor() {
13715   ASSERT(map()->has_indexed_interceptor());
13716   JSFunction* constructor = JSFunction::cast(map()->constructor());
13717   ASSERT(constructor->shared()->IsApiFunction());
13718   Object* result =
13719       constructor->shared()->get_api_func_data()->indexed_property_handler();
13720   return InterceptorInfo::cast(result);
13721 }
13722
13723
13724 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(
13725     Handle<JSObject> holder,
13726     Handle<Object> receiver,
13727     Handle<Name> name) {
13728   Isolate* isolate = holder->GetIsolate();
13729
13730   // TODO(rossberg): Support symbols in the API.
13731   if (name->IsSymbol()) return isolate->factory()->undefined_value();
13732
13733   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor(), isolate);
13734   Handle<String> name_string = Handle<String>::cast(name);
13735
13736   if (interceptor->getter()->IsUndefined()) return MaybeHandle<Object>();
13737
13738   v8::NamedPropertyGetterCallback getter =
13739       v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
13740   LOG(isolate,
13741       ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
13742   PropertyCallbackArguments
13743       args(isolate, interceptor->data(), *receiver, *holder);
13744   v8::Handle<v8::Value> result =
13745       args.Call(getter, v8::Utils::ToLocal(name_string));
13746   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13747   if (result.IsEmpty()) return MaybeHandle<Object>();
13748
13749   Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13750   result_internal->VerifyApiCallResultType();
13751   // Rebox handle before return
13752   return handle(*result_internal, isolate);
13753 }
13754
13755
13756 // Compute the property keys from the interceptor.
13757 // TODO(rossberg): support symbols in API, and filter here if needed.
13758 MaybeHandle<JSObject> JSObject::GetKeysForNamedInterceptor(
13759     Handle<JSObject> object, Handle<JSReceiver> receiver) {
13760   Isolate* isolate = receiver->GetIsolate();
13761   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
13762   PropertyCallbackArguments
13763       args(isolate, interceptor->data(), *receiver, *object);
13764   v8::Handle<v8::Object> result;
13765   if (!interceptor->enumerator()->IsUndefined()) {
13766     v8::NamedPropertyEnumeratorCallback enum_fun =
13767         v8::ToCData<v8::NamedPropertyEnumeratorCallback>(
13768             interceptor->enumerator());
13769     LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
13770     result = args.Call(enum_fun);
13771   }
13772   if (result.IsEmpty()) return MaybeHandle<JSObject>();
13773 #if ENABLE_EXTRA_CHECKS
13774   CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13775         v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13776 #endif
13777   // Rebox before returning.
13778   return handle(*v8::Utils::OpenHandle(*result), isolate);
13779 }
13780
13781
13782 // Compute the element keys from the interceptor.
13783 MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor(
13784     Handle<JSObject> object, Handle<JSReceiver> receiver) {
13785   Isolate* isolate = receiver->GetIsolate();
13786   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
13787   PropertyCallbackArguments
13788       args(isolate, interceptor->data(), *receiver, *object);
13789   v8::Handle<v8::Object> result;
13790   if (!interceptor->enumerator()->IsUndefined()) {
13791     v8::IndexedPropertyEnumeratorCallback enum_fun =
13792         v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
13793             interceptor->enumerator());
13794     LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
13795     result = args.Call(enum_fun);
13796   }
13797   if (result.IsEmpty()) return MaybeHandle<JSObject>();
13798 #if ENABLE_EXTRA_CHECKS
13799   CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13800         v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13801 #endif
13802   // Rebox before returning.
13803   return handle(*v8::Utils::OpenHandle(*result), isolate);
13804 }
13805
13806
13807 bool JSObject::HasRealNamedProperty(Handle<JSObject> object,
13808                                     Handle<Name> key) {
13809   Isolate* isolate = object->GetIsolate();
13810   SealHandleScope shs(isolate);
13811   // Check access rights if needed.
13812   if (object->IsAccessCheckNeeded()) {
13813     if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) {
13814       isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
13815       // TODO(yangguo): Issue 3269, check for scheduled exception missing?
13816       return false;
13817     }
13818   }
13819
13820   LookupResult result(isolate);
13821   object->LookupOwnRealNamedProperty(key, &result);
13822   return result.IsFound() && !result.IsInterceptor();
13823 }
13824
13825
13826 bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) {
13827   Isolate* isolate = object->GetIsolate();
13828   HandleScope scope(isolate);
13829   // Check access rights if needed.
13830   if (object->IsAccessCheckNeeded()) {
13831     if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
13832       isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
13833       // TODO(yangguo): Issue 3269, check for scheduled exception missing?
13834       return false;
13835     }
13836   }
13837
13838   if (object->IsJSGlobalProxy()) {
13839     HandleScope scope(isolate);
13840     Handle<Object> proto(object->GetPrototype(), isolate);
13841     if (proto->IsNull()) return false;
13842     ASSERT(proto->IsJSGlobalObject());
13843     return HasRealElementProperty(Handle<JSObject>::cast(proto), index);
13844   }
13845
13846   return GetElementAttributeWithoutInterceptor(
13847              object, object, index, false) != ABSENT;
13848 }
13849
13850
13851 bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
13852                                             Handle<Name> key) {
13853   Isolate* isolate = object->GetIsolate();
13854   SealHandleScope shs(isolate);
13855   // Check access rights if needed.
13856   if (object->IsAccessCheckNeeded()) {
13857     if (!isolate->MayNamedAccess(object, key, v8::ACCESS_HAS)) {
13858       isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
13859       // TODO(yangguo): Issue 3269, check for scheduled exception missing?
13860       return false;
13861     }
13862   }
13863
13864   LookupResult result(isolate);
13865   object->LookupOwnRealNamedProperty(key, &result);
13866   return result.IsPropertyCallbacks();
13867 }
13868
13869
13870 int JSObject::NumberOfOwnProperties(PropertyAttributes filter) {
13871   if (HasFastProperties()) {
13872     Map* map = this->map();
13873     if (filter == NONE) return map->NumberOfOwnDescriptors();
13874     if (filter & DONT_ENUM) {
13875       int result = map->EnumLength();
13876       if (result != kInvalidEnumCacheSentinel) return result;
13877     }
13878     return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
13879   }
13880   return property_dictionary()->NumberOfElementsFilterAttributes(filter);
13881 }
13882
13883
13884 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
13885   Object* temp = get(i);
13886   set(i, get(j));
13887   set(j, temp);
13888   if (this != numbers) {
13889     temp = numbers->get(i);
13890     numbers->set(i, Smi::cast(numbers->get(j)));
13891     numbers->set(j, Smi::cast(temp));
13892   }
13893 }
13894
13895
13896 static void InsertionSortPairs(FixedArray* content,
13897                                FixedArray* numbers,
13898                                int len) {
13899   for (int i = 1; i < len; i++) {
13900     int j = i;
13901     while (j > 0 &&
13902            (NumberToUint32(numbers->get(j - 1)) >
13903             NumberToUint32(numbers->get(j)))) {
13904       content->SwapPairs(numbers, j - 1, j);
13905       j--;
13906     }
13907   }
13908 }
13909
13910
13911 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
13912   // In-place heap sort.
13913   ASSERT(content->length() == numbers->length());
13914
13915   // Bottom-up max-heap construction.
13916   for (int i = 1; i < len; ++i) {
13917     int child_index = i;
13918     while (child_index > 0) {
13919       int parent_index = ((child_index + 1) >> 1) - 1;
13920       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13921       uint32_t child_value = NumberToUint32(numbers->get(child_index));
13922       if (parent_value < child_value) {
13923         content->SwapPairs(numbers, parent_index, child_index);
13924       } else {
13925         break;
13926       }
13927       child_index = parent_index;
13928     }
13929   }
13930
13931   // Extract elements and create sorted array.
13932   for (int i = len - 1; i > 0; --i) {
13933     // Put max element at the back of the array.
13934     content->SwapPairs(numbers, 0, i);
13935     // Sift down the new top element.
13936     int parent_index = 0;
13937     while (true) {
13938       int child_index = ((parent_index + 1) << 1) - 1;
13939       if (child_index >= i) break;
13940       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
13941       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
13942       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13943       if (child_index + 1 >= i || child1_value > child2_value) {
13944         if (parent_value > child1_value) break;
13945         content->SwapPairs(numbers, parent_index, child_index);
13946         parent_index = child_index;
13947       } else {
13948         if (parent_value > child2_value) break;
13949         content->SwapPairs(numbers, parent_index, child_index + 1);
13950         parent_index = child_index + 1;
13951       }
13952     }
13953   }
13954 }
13955
13956
13957 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
13958 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
13959   ASSERT(this->length() == numbers->length());
13960   // For small arrays, simply use insertion sort.
13961   if (len <= 10) {
13962     InsertionSortPairs(this, numbers, len);
13963     return;
13964   }
13965   // Check the range of indices.
13966   uint32_t min_index = NumberToUint32(numbers->get(0));
13967   uint32_t max_index = min_index;
13968   uint32_t i;
13969   for (i = 1; i < len; i++) {
13970     if (NumberToUint32(numbers->get(i)) < min_index) {
13971       min_index = NumberToUint32(numbers->get(i));
13972     } else if (NumberToUint32(numbers->get(i)) > max_index) {
13973       max_index = NumberToUint32(numbers->get(i));
13974     }
13975   }
13976   if (max_index - min_index + 1 == len) {
13977     // Indices form a contiguous range, unless there are duplicates.
13978     // Do an in-place linear time sort assuming distinct numbers, but
13979     // avoid hanging in case they are not.
13980     for (i = 0; i < len; i++) {
13981       uint32_t p;
13982       uint32_t j = 0;
13983       // While the current element at i is not at its correct position p,
13984       // swap the elements at these two positions.
13985       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
13986              j++ < len) {
13987         SwapPairs(numbers, i, p);
13988       }
13989     }
13990   } else {
13991     HeapSortPairs(this, numbers, len);
13992     return;
13993   }
13994 }
13995
13996
13997 // Fill in the names of own properties into the supplied storage. The main
13998 // purpose of this function is to provide reflection information for the object
13999 // mirrors.
14000 void JSObject::GetOwnPropertyNames(
14001     FixedArray* storage, int index, PropertyAttributes filter) {
14002   ASSERT(storage->length() >= (NumberOfOwnProperties(filter) - index));
14003   if (HasFastProperties()) {
14004     int real_size = map()->NumberOfOwnDescriptors();
14005     DescriptorArray* descs = map()->instance_descriptors();
14006     for (int i = 0; i < real_size; i++) {
14007       if ((descs->GetDetails(i).attributes() & filter) == 0 &&
14008           !FilterKey(descs->GetKey(i), filter)) {
14009         storage->set(index++, descs->GetKey(i));
14010       }
14011     }
14012   } else {
14013     property_dictionary()->CopyKeysTo(storage,
14014                                       index,
14015                                       filter,
14016                                       NameDictionary::UNSORTED);
14017   }
14018 }
14019
14020
14021 int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
14022   return GetOwnElementKeys(NULL, filter);
14023 }
14024
14025
14026 int JSObject::NumberOfEnumElements() {
14027   // Fast case for objects with no elements.
14028   if (!IsJSValue() && HasFastObjectElements()) {
14029     uint32_t length = IsJSArray() ?
14030         static_cast<uint32_t>(
14031             Smi::cast(JSArray::cast(this)->length())->value()) :
14032         static_cast<uint32_t>(FixedArray::cast(elements())->length());
14033     if (length == 0) return 0;
14034   }
14035   // Compute the number of enumerable elements.
14036   return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
14037 }
14038
14039
14040 int JSObject::GetOwnElementKeys(FixedArray* storage,
14041                                 PropertyAttributes filter) {
14042   int counter = 0;
14043   switch (GetElementsKind()) {
14044     case FAST_SMI_ELEMENTS:
14045     case FAST_ELEMENTS:
14046     case FAST_HOLEY_SMI_ELEMENTS:
14047     case FAST_HOLEY_ELEMENTS: {
14048       int length = IsJSArray() ?
14049           Smi::cast(JSArray::cast(this)->length())->value() :
14050           FixedArray::cast(elements())->length();
14051       for (int i = 0; i < length; i++) {
14052         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
14053           if (storage != NULL) {
14054             storage->set(counter, Smi::FromInt(i));
14055           }
14056           counter++;
14057         }
14058       }
14059       ASSERT(!storage || storage->length() >= counter);
14060       break;
14061     }
14062     case FAST_DOUBLE_ELEMENTS:
14063     case FAST_HOLEY_DOUBLE_ELEMENTS: {
14064       int length = IsJSArray() ?
14065           Smi::cast(JSArray::cast(this)->length())->value() :
14066           FixedArrayBase::cast(elements())->length();
14067       for (int i = 0; i < length; i++) {
14068         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
14069           if (storage != NULL) {
14070             storage->set(counter, Smi::FromInt(i));
14071           }
14072           counter++;
14073         }
14074       }
14075       ASSERT(!storage || storage->length() >= counter);
14076       break;
14077     }
14078
14079 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
14080     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
14081     case TYPE##_ELEMENTS:                                                    \
14082
14083     TYPED_ARRAYS(TYPED_ARRAY_CASE)
14084 #undef TYPED_ARRAY_CASE
14085     {
14086       int length = FixedArrayBase::cast(elements())->length();
14087       while (counter < length) {
14088         if (storage != NULL) {
14089           storage->set(counter, Smi::FromInt(counter));
14090         }
14091         counter++;
14092       }
14093       ASSERT(!storage || storage->length() >= counter);
14094       break;
14095     }
14096
14097     case DICTIONARY_ELEMENTS: {
14098       if (storage != NULL) {
14099         element_dictionary()->CopyKeysTo(storage,
14100                                          filter,
14101                                          SeededNumberDictionary::SORTED);
14102       }
14103       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
14104       break;
14105     }
14106     case SLOPPY_ARGUMENTS_ELEMENTS: {
14107       FixedArray* parameter_map = FixedArray::cast(elements());
14108       int mapped_length = parameter_map->length() - 2;
14109       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
14110       if (arguments->IsDictionary()) {
14111         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
14112         // will insert in storage starting at index 0.
14113         SeededNumberDictionary* dictionary =
14114             SeededNumberDictionary::cast(arguments);
14115         if (storage != NULL) {
14116           dictionary->CopyKeysTo(
14117               storage, filter, SeededNumberDictionary::UNSORTED);
14118         }
14119         counter += dictionary->NumberOfElementsFilterAttributes(filter);
14120         for (int i = 0; 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           }
14125         }
14126         if (storage != NULL) storage->SortPairs(storage, counter);
14127
14128       } else {
14129         int backing_length = arguments->length();
14130         int i = 0;
14131         for (; i < mapped_length; ++i) {
14132           if (!parameter_map->get(i + 2)->IsTheHole()) {
14133             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14134             ++counter;
14135           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
14136             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14137             ++counter;
14138           }
14139         }
14140         for (; i < backing_length; ++i) {
14141           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
14142           ++counter;
14143         }
14144       }
14145       break;
14146     }
14147   }
14148
14149   if (this->IsJSValue()) {
14150     Object* val = JSValue::cast(this)->value();
14151     if (val->IsString()) {
14152       String* str = String::cast(val);
14153       if (storage) {
14154         for (int i = 0; i < str->length(); i++) {
14155           storage->set(counter + i, Smi::FromInt(i));
14156         }
14157       }
14158       counter += str->length();
14159     }
14160   }
14161   ASSERT(!storage || storage->length() == counter);
14162   return counter;
14163 }
14164
14165
14166 int JSObject::GetEnumElementKeys(FixedArray* storage) {
14167   return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
14168 }
14169
14170
14171 // StringKey simply carries a string object as key.
14172 class StringKey : public HashTableKey {
14173  public:
14174   explicit StringKey(String* string) :
14175       string_(string),
14176       hash_(HashForObject(string)) { }
14177
14178   bool IsMatch(Object* string) {
14179     // We know that all entries in a hash table had their hash keys created.
14180     // Use that knowledge to have fast failure.
14181     if (hash_ != HashForObject(string)) {
14182       return false;
14183     }
14184     return string_->Equals(String::cast(string));
14185   }
14186
14187   uint32_t Hash() { return hash_; }
14188
14189   uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
14190
14191   Object* AsObject(Heap* heap) { return string_; }
14192
14193   String* string_;
14194   uint32_t hash_;
14195 };
14196
14197
14198 // StringSharedKeys are used as keys in the eval cache.
14199 class StringSharedKey : public HashTableKey {
14200  public:
14201   StringSharedKey(Handle<String> source,
14202                   Handle<SharedFunctionInfo> shared,
14203                   StrictMode strict_mode,
14204                   int scope_position)
14205       : source_(source),
14206         shared_(shared),
14207         strict_mode_(strict_mode),
14208         scope_position_(scope_position) { }
14209
14210   bool IsMatch(Object* other) V8_OVERRIDE {
14211     DisallowHeapAllocation no_allocation;
14212     if (!other->IsFixedArray()) return false;
14213     FixedArray* other_array = FixedArray::cast(other);
14214     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
14215     if (shared != *shared_) return false;
14216     int strict_unchecked = Smi::cast(other_array->get(2))->value();
14217     ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
14218     StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
14219     if (strict_mode != strict_mode_) return false;
14220     int scope_position = Smi::cast(other_array->get(3))->value();
14221     if (scope_position != scope_position_) return false;
14222     String* source = String::cast(other_array->get(1));
14223     return source->Equals(*source_);
14224   }
14225
14226   static uint32_t StringSharedHashHelper(String* source,
14227                                          SharedFunctionInfo* shared,
14228                                          StrictMode strict_mode,
14229                                          int scope_position) {
14230     uint32_t hash = source->Hash();
14231     if (shared->HasSourceCode()) {
14232       // Instead of using the SharedFunctionInfo pointer in the hash
14233       // code computation, we use a combination of the hash of the
14234       // script source code and the start position of the calling scope.
14235       // We do this to ensure that the cache entries can survive garbage
14236       // collection.
14237       Script* script(Script::cast(shared->script()));
14238       hash ^= String::cast(script->source())->Hash();
14239       if (strict_mode == STRICT) hash ^= 0x8000;
14240       hash += scope_position;
14241     }
14242     return hash;
14243   }
14244
14245   uint32_t Hash() V8_OVERRIDE {
14246     return StringSharedHashHelper(*source_, *shared_, strict_mode_,
14247                                   scope_position_);
14248   }
14249
14250   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
14251     DisallowHeapAllocation no_allocation;
14252     FixedArray* other_array = FixedArray::cast(obj);
14253     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
14254     String* source = String::cast(other_array->get(1));
14255     int strict_unchecked = Smi::cast(other_array->get(2))->value();
14256     ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
14257     StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
14258     int scope_position = Smi::cast(other_array->get(3))->value();
14259     return StringSharedHashHelper(
14260         source, shared, strict_mode, scope_position);
14261   }
14262
14263
14264   Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
14265     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
14266     array->set(0, *shared_);
14267     array->set(1, *source_);
14268     array->set(2, Smi::FromInt(strict_mode_));
14269     array->set(3, Smi::FromInt(scope_position_));
14270     return array;
14271   }
14272
14273  private:
14274   Handle<String> source_;
14275   Handle<SharedFunctionInfo> shared_;
14276   StrictMode strict_mode_;
14277   int scope_position_;
14278 };
14279
14280
14281 // RegExpKey carries the source and flags of a regular expression as key.
14282 class RegExpKey : public HashTableKey {
14283  public:
14284   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
14285       : string_(string),
14286         flags_(Smi::FromInt(flags.value())) { }
14287
14288   // Rather than storing the key in the hash table, a pointer to the
14289   // stored value is stored where the key should be.  IsMatch then
14290   // compares the search key to the found object, rather than comparing
14291   // a key to a key.
14292   bool IsMatch(Object* obj) V8_OVERRIDE {
14293     FixedArray* val = FixedArray::cast(obj);
14294     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
14295         && (flags_ == val->get(JSRegExp::kFlagsIndex));
14296   }
14297
14298   uint32_t Hash() V8_OVERRIDE { return RegExpHash(*string_, flags_); }
14299
14300   Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
14301     // Plain hash maps, which is where regexp keys are used, don't
14302     // use this function.
14303     UNREACHABLE();
14304     return MaybeHandle<Object>().ToHandleChecked();
14305   }
14306
14307   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
14308     FixedArray* val = FixedArray::cast(obj);
14309     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
14310                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
14311   }
14312
14313   static uint32_t RegExpHash(String* string, Smi* flags) {
14314     return string->Hash() + flags->value();
14315   }
14316
14317   Handle<String> string_;
14318   Smi* flags_;
14319 };
14320
14321
14322 Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
14323   if (hash_field_ == 0) Hash();
14324   return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
14325 }
14326
14327
14328 Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
14329   if (hash_field_ == 0) Hash();
14330   return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
14331 }
14332
14333
14334 template<>
14335 const uint8_t* SubStringKey<uint8_t>::GetChars() {
14336   return string_->IsSeqOneByteString()
14337       ? SeqOneByteString::cast(*string_)->GetChars()
14338       : ExternalAsciiString::cast(*string_)->GetChars();
14339 }
14340
14341
14342 template<>
14343 const uint16_t* SubStringKey<uint16_t>::GetChars() {
14344   return string_->IsSeqTwoByteString()
14345       ? SeqTwoByteString::cast(*string_)->GetChars()
14346       : ExternalTwoByteString::cast(*string_)->GetChars();
14347 }
14348
14349
14350 template<>
14351 Handle<Object> SubStringKey<uint8_t>::AsHandle(Isolate* isolate) {
14352   if (hash_field_ == 0) Hash();
14353   Vector<const uint8_t> chars(GetChars() + from_, length_);
14354   return isolate->factory()->NewOneByteInternalizedString(chars, hash_field_);
14355 }
14356
14357
14358 template<>
14359 Handle<Object> SubStringKey<uint16_t>::AsHandle(Isolate* isolate) {
14360   if (hash_field_ == 0) Hash();
14361   Vector<const uint16_t> chars(GetChars() + from_, length_);
14362   return isolate->factory()->NewTwoByteInternalizedString(chars, hash_field_);
14363 }
14364
14365
14366 template<>
14367 bool SubStringKey<uint8_t>::IsMatch(Object* string) {
14368   Vector<const uint8_t> chars(GetChars() + from_, length_);
14369   return String::cast(string)->IsOneByteEqualTo(chars);
14370 }
14371
14372
14373 template<>
14374 bool SubStringKey<uint16_t>::IsMatch(Object* string) {
14375   Vector<const uint16_t> chars(GetChars() + from_, length_);
14376   return String::cast(string)->IsTwoByteEqualTo(chars);
14377 }
14378
14379
14380 template class SubStringKey<uint8_t>;
14381 template class SubStringKey<uint16_t>;
14382
14383
14384 // InternalizedStringKey carries a string/internalized-string object as key.
14385 class InternalizedStringKey : public HashTableKey {
14386  public:
14387   explicit InternalizedStringKey(Handle<String> string)
14388       : string_(string) { }
14389
14390   virtual bool IsMatch(Object* string) V8_OVERRIDE {
14391     return String::cast(string)->Equals(*string_);
14392   }
14393
14394   virtual uint32_t Hash() V8_OVERRIDE { return string_->Hash(); }
14395
14396   virtual uint32_t HashForObject(Object* other) V8_OVERRIDE {
14397     return String::cast(other)->Hash();
14398   }
14399
14400   virtual Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
14401     // Internalize the string if possible.
14402     MaybeHandle<Map> maybe_map =
14403         isolate->factory()->InternalizedStringMapForString(string_);
14404     Handle<Map> map;
14405     if (maybe_map.ToHandle(&map)) {
14406       string_->set_map_no_write_barrier(*map);
14407       ASSERT(string_->IsInternalizedString());
14408       return string_;
14409     }
14410     // Otherwise allocate a new internalized string.
14411     return isolate->factory()->NewInternalizedStringImpl(
14412         string_, string_->length(), string_->hash_field());
14413   }
14414
14415   static uint32_t StringHash(Object* obj) {
14416     return String::cast(obj)->Hash();
14417   }
14418
14419   Handle<String> string_;
14420 };
14421
14422
14423 template<typename Derived, typename Shape, typename Key>
14424 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
14425   IteratePointers(v, 0, kElementsStartOffset);
14426 }
14427
14428
14429 template<typename Derived, typename Shape, typename Key>
14430 void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
14431   IteratePointers(v,
14432                   kElementsStartOffset,
14433                   kHeaderSize + length() * kPointerSize);
14434 }
14435
14436
14437 template<typename Derived, typename Shape, typename Key>
14438 Handle<Derived> HashTable<Derived, Shape, Key>::New(
14439     Isolate* isolate,
14440     int at_least_space_for,
14441     MinimumCapacity capacity_option,
14442     PretenureFlag pretenure) {
14443   ASSERT(0 <= at_least_space_for);
14444   ASSERT(!capacity_option || IsPowerOf2(at_least_space_for));
14445   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
14446                      ? at_least_space_for
14447                      : ComputeCapacity(at_least_space_for);
14448   if (capacity > HashTable::kMaxCapacity) {
14449     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
14450   }
14451
14452   Factory* factory = isolate->factory();
14453   int length = EntryToIndex(capacity);
14454   Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
14455   array->set_map_no_write_barrier(*factory->hash_table_map());
14456   Handle<Derived> table = Handle<Derived>::cast(array);
14457
14458   table->SetNumberOfElements(0);
14459   table->SetNumberOfDeletedElements(0);
14460   table->SetCapacity(capacity);
14461   return table;
14462 }
14463
14464
14465 // Find entry for key otherwise return kNotFound.
14466 int NameDictionary::FindEntry(Handle<Name> key) {
14467   if (!key->IsUniqueName()) {
14468     return DerivedHashTable::FindEntry(key);
14469   }
14470
14471   // Optimized for unique names. Knowledge of the key type allows:
14472   // 1. Move the check if the key is unique out of the loop.
14473   // 2. Avoid comparing hash codes in unique-to-unique comparison.
14474   // 3. Detect a case when a dictionary key is not unique but the key is.
14475   //    In case of positive result the dictionary key may be replaced by the
14476   //    internalized string with minimal performance penalty. It gives a chance
14477   //    to perform further lookups in code stubs (and significant performance
14478   //    boost a certain style of code).
14479
14480   // EnsureCapacity will guarantee the hash table is never full.
14481   uint32_t capacity = Capacity();
14482   uint32_t entry = FirstProbe(key->Hash(), capacity);
14483   uint32_t count = 1;
14484
14485   while (true) {
14486     int index = EntryToIndex(entry);
14487     Object* element = get(index);
14488     if (element->IsUndefined()) break;  // Empty entry.
14489     if (*key == element) return entry;
14490     if (!element->IsUniqueName() &&
14491         !element->IsTheHole() &&
14492         Name::cast(element)->Equals(*key)) {
14493       // Replace a key that is a non-internalized string by the equivalent
14494       // internalized string for faster further lookups.
14495       set(index, *key);
14496       return entry;
14497     }
14498     ASSERT(element->IsTheHole() || !Name::cast(element)->Equals(*key));
14499     entry = NextProbe(entry, count++, capacity);
14500   }
14501   return kNotFound;
14502 }
14503
14504
14505 template<typename Derived, typename Shape, typename Key>
14506 void HashTable<Derived, Shape, Key>::Rehash(
14507     Handle<Derived> new_table,
14508     Key key) {
14509   ASSERT(NumberOfElements() < new_table->Capacity());
14510
14511   DisallowHeapAllocation no_gc;
14512   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
14513
14514   // Copy prefix to new array.
14515   for (int i = kPrefixStartIndex;
14516        i < kPrefixStartIndex + Shape::kPrefixSize;
14517        i++) {
14518     new_table->set(i, get(i), mode);
14519   }
14520
14521   // Rehash the elements.
14522   int capacity = Capacity();
14523   for (int i = 0; i < capacity; i++) {
14524     uint32_t from_index = EntryToIndex(i);
14525     Object* k = get(from_index);
14526     if (IsKey(k)) {
14527       uint32_t hash = HashTable::HashForObject(key, k);
14528       uint32_t insertion_index =
14529           EntryToIndex(new_table->FindInsertionEntry(hash));
14530       for (int j = 0; j < Shape::kEntrySize; j++) {
14531         new_table->set(insertion_index + j, get(from_index + j), mode);
14532       }
14533     }
14534   }
14535   new_table->SetNumberOfElements(NumberOfElements());
14536   new_table->SetNumberOfDeletedElements(0);
14537 }
14538
14539
14540 template<typename Derived, typename Shape, typename Key>
14541 uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
14542     Key key,
14543     Object* k,
14544     int probe,
14545     uint32_t expected) {
14546   uint32_t hash = HashTable::HashForObject(key, k);
14547   uint32_t capacity = Capacity();
14548   uint32_t entry = FirstProbe(hash, capacity);
14549   for (int i = 1; i < probe; i++) {
14550     if (entry == expected) return expected;
14551     entry = NextProbe(entry, i, capacity);
14552   }
14553   return entry;
14554 }
14555
14556
14557 template<typename Derived, typename Shape, typename Key>
14558 void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
14559                                           uint32_t entry2,
14560                                           WriteBarrierMode mode) {
14561   int index1 = EntryToIndex(entry1);
14562   int index2 = EntryToIndex(entry2);
14563   Object* temp[Shape::kEntrySize];
14564   for (int j = 0; j < Shape::kEntrySize; j++) {
14565     temp[j] = get(index1 + j);
14566   }
14567   for (int j = 0; j < Shape::kEntrySize; j++) {
14568     set(index1 + j, get(index2 + j), mode);
14569   }
14570   for (int j = 0; j < Shape::kEntrySize; j++) {
14571     set(index2 + j, temp[j], mode);
14572   }
14573 }
14574
14575
14576 template<typename Derived, typename Shape, typename Key>
14577 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
14578   DisallowHeapAllocation no_gc;
14579   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
14580   uint32_t capacity = Capacity();
14581   bool done = false;
14582   for (int probe = 1; !done; probe++) {
14583     // All elements at entries given by one of the first _probe_ probes
14584     // are placed correctly. Other elements might need to be moved.
14585     done = true;
14586     for (uint32_t current = 0; current < capacity; current++) {
14587       Object* current_key = get(EntryToIndex(current));
14588       if (IsKey(current_key)) {
14589         uint32_t target = EntryForProbe(key, current_key, probe, current);
14590         if (current == target) continue;
14591         Object* target_key = get(EntryToIndex(target));
14592         if (!IsKey(target_key) ||
14593             EntryForProbe(key, target_key, probe, target) != target) {
14594           // Put the current element into the correct position.
14595           Swap(current, target, mode);
14596           // The other element will be processed on the next iteration.
14597           current--;
14598         } else {
14599           // The place for the current element is occupied. Leave the element
14600           // for the next probe.
14601           done = false;
14602         }
14603       }
14604     }
14605   }
14606 }
14607
14608
14609 template<typename Derived, typename Shape, typename Key>
14610 Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
14611     Handle<Derived> table,
14612     int n,
14613     Key key,
14614     PretenureFlag pretenure) {
14615   Isolate* isolate = table->GetIsolate();
14616   int capacity = table->Capacity();
14617   int nof = table->NumberOfElements() + n;
14618   int nod = table->NumberOfDeletedElements();
14619   // Return if:
14620   //   50% is still free after adding n elements and
14621   //   at most 50% of the free elements are deleted elements.
14622   if (nod <= (capacity - nof) >> 1) {
14623     int needed_free = nof >> 1;
14624     if (nof + needed_free <= capacity) return table;
14625   }
14626
14627   const int kMinCapacityForPretenure = 256;
14628   bool should_pretenure = pretenure == TENURED ||
14629       ((capacity > kMinCapacityForPretenure) &&
14630           !isolate->heap()->InNewSpace(*table));
14631   Handle<Derived> new_table = HashTable::New(
14632       isolate,
14633       nof * 2,
14634       USE_DEFAULT_MINIMUM_CAPACITY,
14635       should_pretenure ? TENURED : NOT_TENURED);
14636
14637   table->Rehash(new_table, key);
14638   return new_table;
14639 }
14640
14641
14642 template<typename Derived, typename Shape, typename Key>
14643 Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
14644                                                        Key key) {
14645   int capacity = table->Capacity();
14646   int nof = table->NumberOfElements();
14647
14648   // Shrink to fit the number of elements if only a quarter of the
14649   // capacity is filled with elements.
14650   if (nof > (capacity >> 2)) return table;
14651   // Allocate a new dictionary with room for at least the current
14652   // number of elements. The allocation method will make sure that
14653   // there is extra room in the dictionary for additions. Don't go
14654   // lower than room for 16 elements.
14655   int at_least_room_for = nof;
14656   if (at_least_room_for < 16) return table;
14657
14658   Isolate* isolate = table->GetIsolate();
14659   const int kMinCapacityForPretenure = 256;
14660   bool pretenure =
14661       (at_least_room_for > kMinCapacityForPretenure) &&
14662       !isolate->heap()->InNewSpace(*table);
14663   Handle<Derived> new_table = HashTable::New(
14664       isolate,
14665       at_least_room_for,
14666       USE_DEFAULT_MINIMUM_CAPACITY,
14667       pretenure ? TENURED : NOT_TENURED);
14668
14669   table->Rehash(new_table, key);
14670   return new_table;
14671 }
14672
14673
14674 template<typename Derived, typename Shape, typename Key>
14675 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
14676   uint32_t capacity = Capacity();
14677   uint32_t entry = FirstProbe(hash, capacity);
14678   uint32_t count = 1;
14679   // EnsureCapacity will guarantee the hash table is never full.
14680   while (true) {
14681     Object* element = KeyAt(entry);
14682     if (element->IsUndefined() || element->IsTheHole()) break;
14683     entry = NextProbe(entry, count++, capacity);
14684   }
14685   return entry;
14686 }
14687
14688
14689 // Force instantiation of template instances class.
14690 // Please note this list is compiler dependent.
14691
14692 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
14693
14694 template class HashTable<CompilationCacheTable,
14695                          CompilationCacheShape,
14696                          HashTableKey*>;
14697
14698 template class HashTable<MapCache, MapCacheShape, HashTableKey*>;
14699
14700 template class HashTable<ObjectHashTable,
14701                          ObjectHashTableShape,
14702                          Handle<Object> >;
14703
14704 template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
14705
14706 template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
14707
14708 template class Dictionary<SeededNumberDictionary,
14709                           SeededNumberDictionaryShape,
14710                           uint32_t>;
14711
14712 template class Dictionary<UnseededNumberDictionary,
14713                           UnseededNumberDictionaryShape,
14714                           uint32_t>;
14715
14716 template Handle<SeededNumberDictionary>
14717 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14718     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14719
14720 template Handle<UnseededNumberDictionary>
14721 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14722     New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14723
14724 template Handle<NameDictionary>
14725 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14726     New(Isolate*, int n, PretenureFlag pretenure);
14727
14728 template Handle<SeededNumberDictionary>
14729 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14730     AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
14731
14732 template Handle<UnseededNumberDictionary>
14733 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14734     AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
14735
14736 template Object*
14737 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14738     SlowReverseLookup(Object* value);
14739
14740 template Object*
14741 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14742     SlowReverseLookup(Object* value);
14743
14744 template Object*
14745 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14746     SlowReverseLookup(Object* value);
14747
14748 template void
14749 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14750     CopyKeysTo(
14751         FixedArray*,
14752         PropertyAttributes,
14753         Dictionary<SeededNumberDictionary,
14754                    SeededNumberDictionaryShape,
14755                    uint32_t>::SortMode);
14756
14757 template Handle<Object>
14758 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
14759     Handle<NameDictionary>, int, JSObject::DeleteMode);
14760
14761 template Handle<Object>
14762 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14763     DeleteProperty(Handle<SeededNumberDictionary>, int, JSObject::DeleteMode);
14764
14765 template Handle<NameDictionary>
14766 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14767     New(Isolate*, int, MinimumCapacity, PretenureFlag);
14768
14769 template Handle<NameDictionary>
14770 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14771     Shrink(Handle<NameDictionary>, Handle<Name>);
14772
14773 template Handle<SeededNumberDictionary>
14774 HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14775     Shrink(Handle<SeededNumberDictionary>, uint32_t);
14776
14777 template void Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14778     CopyKeysTo(
14779         FixedArray*,
14780         int,
14781         PropertyAttributes,
14782         Dictionary<
14783             NameDictionary, NameDictionaryShape, Handle<Name> >::SortMode);
14784
14785 template int
14786 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14787     NumberOfElementsFilterAttributes(PropertyAttributes);
14788
14789 template Handle<NameDictionary>
14790 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
14791     Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
14792
14793 template void
14794 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14795     GenerateNewEnumerationIndices(Handle<NameDictionary>);
14796
14797 template int
14798 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14799     NumberOfElementsFilterAttributes(PropertyAttributes);
14800
14801 template Handle<SeededNumberDictionary>
14802 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14803     Add(Handle<SeededNumberDictionary>,
14804         uint32_t,
14805         Handle<Object>,
14806         PropertyDetails);
14807
14808 template Handle<UnseededNumberDictionary>
14809 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14810     Add(Handle<UnseededNumberDictionary>,
14811         uint32_t,
14812         Handle<Object>,
14813         PropertyDetails);
14814
14815 template Handle<SeededNumberDictionary>
14816 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14817     EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
14818
14819 template Handle<UnseededNumberDictionary>
14820 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14821     EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
14822
14823 template Handle<NameDictionary>
14824 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14825     EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
14826
14827 template
14828 int Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14829     NumberOfEnumElements();
14830
14831 template
14832 int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14833     NumberOfEnumElements();
14834
14835 template
14836 int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14837     FindEntry(uint32_t);
14838
14839
14840 Handle<Object> JSObject::PrepareSlowElementsForSort(
14841     Handle<JSObject> object, uint32_t limit) {
14842   ASSERT(object->HasDictionaryElements());
14843   Isolate* isolate = object->GetIsolate();
14844   // Must stay in dictionary mode, either because of requires_slow_elements,
14845   // or because we are not going to sort (and therefore compact) all of the
14846   // elements.
14847   Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
14848   Handle<SeededNumberDictionary> new_dict =
14849       SeededNumberDictionary::New(isolate, dict->NumberOfElements());
14850
14851   uint32_t pos = 0;
14852   uint32_t undefs = 0;
14853   int capacity = dict->Capacity();
14854   Handle<Smi> bailout(Smi::FromInt(-1), isolate);
14855   // Entry to the new dictionary does not cause it to grow, as we have
14856   // allocated one that is large enough for all entries.
14857   DisallowHeapAllocation no_gc;
14858   for (int i = 0; i < capacity; i++) {
14859     Object* k = dict->KeyAt(i);
14860     if (!dict->IsKey(k)) continue;
14861
14862     ASSERT(k->IsNumber());
14863     ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
14864     ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
14865     ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
14866
14867     HandleScope scope(isolate);
14868     Handle<Object> value(dict->ValueAt(i), isolate);
14869     PropertyDetails details = dict->DetailsAt(i);
14870     if (details.type() == CALLBACKS || details.IsReadOnly()) {
14871       // Bail out and do the sorting of undefineds and array holes in JS.
14872       // Also bail out if the element is not supposed to be moved.
14873       return bailout;
14874     }
14875
14876     uint32_t key = NumberToUint32(k);
14877     if (key < limit) {
14878       if (value->IsUndefined()) {
14879         undefs++;
14880       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14881         // Adding an entry with the key beyond smi-range requires
14882         // allocation. Bailout.
14883         return bailout;
14884       } else {
14885         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14886             new_dict, pos, value, details);
14887         ASSERT(result.is_identical_to(new_dict));
14888         USE(result);
14889         pos++;
14890       }
14891     } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
14892       // Adding an entry with the key beyond smi-range requires
14893       // allocation. Bailout.
14894       return bailout;
14895     } else {
14896       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14897           new_dict, key, value, details);
14898       ASSERT(result.is_identical_to(new_dict));
14899       USE(result);
14900     }
14901   }
14902
14903   uint32_t result = pos;
14904   PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0);
14905   while (undefs > 0) {
14906     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14907       // Adding an entry with the key beyond smi-range requires
14908       // allocation. Bailout.
14909       return bailout;
14910     }
14911     HandleScope scope(isolate);
14912     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14913         new_dict, pos, isolate->factory()->undefined_value(), no_details);
14914     ASSERT(result.is_identical_to(new_dict));
14915     USE(result);
14916     pos++;
14917     undefs--;
14918   }
14919
14920   object->set_elements(*new_dict);
14921
14922   AllowHeapAllocation allocate_return_value;
14923   return isolate->factory()->NewNumberFromUint(result);
14924 }
14925
14926
14927 // Collects all defined (non-hole) and non-undefined (array) elements at
14928 // the start of the elements array.
14929 // If the object is in dictionary mode, it is converted to fast elements
14930 // mode.
14931 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
14932                                                 uint32_t limit) {
14933   Isolate* isolate = object->GetIsolate();
14934   if (object->HasSloppyArgumentsElements() ||
14935       object->map()->is_observed()) {
14936     return handle(Smi::FromInt(-1), isolate);
14937   }
14938
14939   if (object->HasDictionaryElements()) {
14940     // Convert to fast elements containing only the existing properties.
14941     // Ordering is irrelevant, since we are going to sort anyway.
14942     Handle<SeededNumberDictionary> dict(object->element_dictionary());
14943     if (object->IsJSArray() || dict->requires_slow_elements() ||
14944         dict->max_number_key() >= limit) {
14945       return JSObject::PrepareSlowElementsForSort(object, limit);
14946     }
14947     // Convert to fast elements.
14948
14949     Handle<Map> new_map =
14950         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
14951
14952     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
14953         NOT_TENURED: TENURED;
14954     Handle<FixedArray> fast_elements =
14955         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
14956     dict->CopyValuesTo(*fast_elements);
14957     JSObject::ValidateElements(object);
14958
14959     JSObject::SetMapAndElements(object, new_map, fast_elements);
14960   } else if (object->HasExternalArrayElements() ||
14961              object->HasFixedTypedArrayElements()) {
14962     // Typed arrays cannot have holes or undefined elements.
14963     return handle(Smi::FromInt(
14964         FixedArrayBase::cast(object->elements())->length()), isolate);
14965   } else if (!object->HasFastDoubleElements()) {
14966     EnsureWritableFastElements(object);
14967   }
14968   ASSERT(object->HasFastSmiOrObjectElements() ||
14969          object->HasFastDoubleElements());
14970
14971   // Collect holes at the end, undefined before that and the rest at the
14972   // start, and return the number of non-hole, non-undefined values.
14973
14974   Handle<FixedArrayBase> elements_base(object->elements());
14975   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
14976   if (limit > elements_length) {
14977     limit = elements_length ;
14978   }
14979   if (limit == 0) {
14980     return handle(Smi::FromInt(0), isolate);
14981   }
14982
14983   uint32_t result = 0;
14984   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
14985     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
14986     // Split elements into defined and the_hole, in that order.
14987     unsigned int holes = limit;
14988     // Assume most arrays contain no holes and undefined values, so minimize the
14989     // number of stores of non-undefined, non-the-hole values.
14990     for (unsigned int i = 0; i < holes; i++) {
14991       if (elements->is_the_hole(i)) {
14992         holes--;
14993       } else {
14994         continue;
14995       }
14996       // Position i needs to be filled.
14997       while (holes > i) {
14998         if (elements->is_the_hole(holes)) {
14999           holes--;
15000         } else {
15001           elements->set(i, elements->get_scalar(holes));
15002           break;
15003         }
15004       }
15005     }
15006     result = holes;
15007     while (holes < limit) {
15008       elements->set_the_hole(holes);
15009       holes++;
15010     }
15011   } else {
15012     FixedArray* elements = FixedArray::cast(*elements_base);
15013     DisallowHeapAllocation no_gc;
15014
15015     // Split elements into defined, undefined and the_hole, in that order.  Only
15016     // count locations for undefined and the hole, and fill them afterwards.
15017     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
15018     unsigned int undefs = limit;
15019     unsigned int holes = limit;
15020     // Assume most arrays contain no holes and undefined values, so minimize the
15021     // number of stores of non-undefined, non-the-hole values.
15022     for (unsigned int i = 0; i < undefs; i++) {
15023       Object* current = elements->get(i);
15024       if (current->IsTheHole()) {
15025         holes--;
15026         undefs--;
15027       } else if (current->IsUndefined()) {
15028         undefs--;
15029       } else {
15030         continue;
15031       }
15032       // Position i needs to be filled.
15033       while (undefs > i) {
15034         current = elements->get(undefs);
15035         if (current->IsTheHole()) {
15036           holes--;
15037           undefs--;
15038         } else if (current->IsUndefined()) {
15039           undefs--;
15040         } else {
15041           elements->set(i, current, write_barrier);
15042           break;
15043         }
15044       }
15045     }
15046     result = undefs;
15047     while (undefs < holes) {
15048       elements->set_undefined(undefs);
15049       undefs++;
15050     }
15051     while (holes < limit) {
15052       elements->set_the_hole(holes);
15053       holes++;
15054     }
15055   }
15056
15057   return isolate->factory()->NewNumberFromUint(result);
15058 }
15059
15060
15061 ExternalArrayType JSTypedArray::type() {
15062   switch (elements()->map()->instance_type()) {
15063 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
15064     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
15065     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
15066       return kExternal##Type##Array;
15067
15068     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
15069 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
15070
15071     default:
15072       UNREACHABLE();
15073       return static_cast<ExternalArrayType>(-1);
15074   }
15075 }
15076
15077
15078 size_t JSTypedArray::element_size() {
15079   switch (elements()->map()->instance_type()) {
15080 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)          \
15081     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
15082       return size;
15083
15084     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
15085 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
15086
15087     default:
15088       UNREACHABLE();
15089       return 0;
15090   }
15091 }
15092
15093
15094 Handle<Object> ExternalUint8ClampedArray::SetValue(
15095     Handle<ExternalUint8ClampedArray> array,
15096     uint32_t index,
15097     Handle<Object> value) {
15098   uint8_t clamped_value = 0;
15099   if (index < static_cast<uint32_t>(array->length())) {
15100     if (value->IsSmi()) {
15101       int int_value = Handle<Smi>::cast(value)->value();
15102       if (int_value < 0) {
15103         clamped_value = 0;
15104       } else if (int_value > 255) {
15105         clamped_value = 255;
15106       } else {
15107         clamped_value = static_cast<uint8_t>(int_value);
15108       }
15109     } else if (value->IsHeapNumber()) {
15110       double double_value = Handle<HeapNumber>::cast(value)->value();
15111       if (!(double_value > 0)) {
15112         // NaN and less than zero clamp to zero.
15113         clamped_value = 0;
15114       } else if (double_value > 255) {
15115         // Greater than 255 clamp to 255.
15116         clamped_value = 255;
15117       } else {
15118         // Other doubles are rounded to the nearest integer.
15119         clamped_value = static_cast<uint8_t>(lrint(double_value));
15120       }
15121     } else {
15122       // Clamp undefined to zero (default). All other types have been
15123       // converted to a number type further up in the call chain.
15124       ASSERT(value->IsUndefined());
15125     }
15126     array->set(index, clamped_value);
15127   }
15128   return handle(Smi::FromInt(clamped_value), array->GetIsolate());
15129 }
15130
15131
15132 template<typename ExternalArrayClass, typename ValueType>
15133 static Handle<Object> ExternalArrayIntSetter(
15134     Isolate* isolate,
15135     Handle<ExternalArrayClass> receiver,
15136     uint32_t index,
15137     Handle<Object> value) {
15138   ValueType cast_value = 0;
15139   if (index < static_cast<uint32_t>(receiver->length())) {
15140     if (value->IsSmi()) {
15141       int int_value = Handle<Smi>::cast(value)->value();
15142       cast_value = static_cast<ValueType>(int_value);
15143     } else if (value->IsHeapNumber()) {
15144       double double_value = Handle<HeapNumber>::cast(value)->value();
15145       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
15146     } else {
15147       // Clamp undefined to zero (default). All other types have been
15148       // converted to a number type further up in the call chain.
15149       ASSERT(value->IsUndefined());
15150     }
15151     receiver->set(index, cast_value);
15152   }
15153   return isolate->factory()->NewNumberFromInt(cast_value);
15154 }
15155
15156
15157 Handle<Object> ExternalInt8Array::SetValue(Handle<ExternalInt8Array> array,
15158                                            uint32_t index,
15159                                            Handle<Object> value) {
15160   return ExternalArrayIntSetter<ExternalInt8Array, int8_t>(
15161       array->GetIsolate(), array, index, value);
15162 }
15163
15164
15165 Handle<Object> ExternalUint8Array::SetValue(Handle<ExternalUint8Array> array,
15166                                             uint32_t index,
15167                                             Handle<Object> value) {
15168   return ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(
15169       array->GetIsolate(), array, index, value);
15170 }
15171
15172
15173 Handle<Object> ExternalInt16Array::SetValue(Handle<ExternalInt16Array> array,
15174                                             uint32_t index,
15175                                             Handle<Object> value) {
15176   return ExternalArrayIntSetter<ExternalInt16Array, int16_t>(
15177       array->GetIsolate(), array, index, value);
15178 }
15179
15180
15181 Handle<Object> ExternalUint16Array::SetValue(Handle<ExternalUint16Array> array,
15182                                              uint32_t index,
15183                                              Handle<Object> value) {
15184   return ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(
15185       array->GetIsolate(), array, index, value);
15186 }
15187
15188
15189 Handle<Object> ExternalInt32Array::SetValue(Handle<ExternalInt32Array> array,
15190                                             uint32_t index,
15191                                             Handle<Object> value) {
15192   return ExternalArrayIntSetter<ExternalInt32Array, int32_t>(
15193       array->GetIsolate(), array, index, value);
15194 }
15195
15196
15197 Handle<Object> ExternalUint32Array::SetValue(
15198     Handle<ExternalUint32Array> array,
15199     uint32_t index,
15200     Handle<Object> value) {
15201   uint32_t cast_value = 0;
15202   if (index < static_cast<uint32_t>(array->length())) {
15203     if (value->IsSmi()) {
15204       int int_value = Handle<Smi>::cast(value)->value();
15205       cast_value = static_cast<uint32_t>(int_value);
15206     } else if (value->IsHeapNumber()) {
15207       double double_value = Handle<HeapNumber>::cast(value)->value();
15208       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
15209     } else {
15210       // Clamp undefined to zero (default). All other types have been
15211       // converted to a number type further up in the call chain.
15212       ASSERT(value->IsUndefined());
15213     }
15214     array->set(index, cast_value);
15215   }
15216   return array->GetIsolate()->factory()->NewNumberFromUint(cast_value);
15217 }
15218
15219
15220 Handle<Object> ExternalFloat32Array::SetValue(
15221     Handle<ExternalFloat32Array> array,
15222     uint32_t index,
15223     Handle<Object> value) {
15224   float cast_value = static_cast<float>(OS::nan_value());
15225   if (index < static_cast<uint32_t>(array->length())) {
15226     if (value->IsSmi()) {
15227       int int_value = Handle<Smi>::cast(value)->value();
15228       cast_value = static_cast<float>(int_value);
15229     } else if (value->IsHeapNumber()) {
15230       double double_value = Handle<HeapNumber>::cast(value)->value();
15231       cast_value = static_cast<float>(double_value);
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       ASSERT(value->IsUndefined());
15236     }
15237     array->set(index, cast_value);
15238   }
15239   return array->GetIsolate()->factory()->NewNumber(cast_value);
15240 }
15241
15242
15243 Handle<Object> ExternalFloat64Array::SetValue(
15244     Handle<ExternalFloat64Array> array,
15245     uint32_t index,
15246     Handle<Object> value) {
15247   double double_value = OS::nan_value();
15248   if (index < static_cast<uint32_t>(array->length())) {
15249     if (value->IsNumber()) {
15250       double_value = value->Number();
15251     } else {
15252       // Clamp undefined to NaN (default). All other types have been
15253       // converted to a number type further up in the call chain.
15254       ASSERT(value->IsUndefined());
15255     }
15256     array->set(index, double_value);
15257   }
15258   return array->GetIsolate()->factory()->NewNumber(double_value);
15259 }
15260
15261
15262 Handle<Object> ExternalFloat32x4Array::SetValue(
15263     Handle<ExternalFloat32x4Array> array,
15264     uint32_t index,
15265     Handle<Object> value) {
15266   float32x4_value_t cast_value;
15267   cast_value.storage[0] = static_cast<float>(OS::nan_value());
15268   cast_value.storage[1] = static_cast<float>(OS::nan_value());
15269   cast_value.storage[2] = static_cast<float>(OS::nan_value());
15270   cast_value.storage[3] = static_cast<float>(OS::nan_value());
15271   if (index < static_cast<uint32_t>(array->length())) {
15272     if (value->IsFloat32x4()) {
15273       cast_value = Handle<Float32x4>::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       ASSERT(value->IsUndefined());
15278     }
15279     array->set(index, cast_value);
15280   }
15281   return array->GetIsolate()->factory()->NewFloat32x4(cast_value);
15282 }
15283
15284
15285 Handle<Object> ExternalInt32x4Array::SetValue(
15286     Handle<ExternalInt32x4Array> array, uint32_t index, Handle<Object> value) {
15287   int32x4_value_t cast_value;
15288   cast_value.storage[0] = 0;
15289   cast_value.storage[1] = 0;
15290   cast_value.storage[2] = 0;
15291   cast_value.storage[3] = 0;
15292   if (index < static_cast<uint32_t>(array->length())) {
15293     if (value->IsInt32x4()) {
15294       cast_value = Handle<Int32x4>::cast(value)->get();
15295     } else {
15296       // Clamp undefined to zero (default). All other types have been
15297       // converted to a number type further up in the call chain.
15298       ASSERT(value->IsUndefined());
15299     }
15300     array->set(index, cast_value);
15301   }
15302   return array->GetIsolate()->factory()->NewInt32x4(cast_value);
15303 }
15304
15305
15306 Handle<Object> ExternalFloat64x2Array::SetValue(
15307     Handle<ExternalFloat64x2Array> array,
15308     uint32_t index,
15309     Handle<Object> value) {
15310   float64x2_value_t cast_value;
15311   cast_value.storage[0] = OS::nan_value();
15312   cast_value.storage[1] = OS::nan_value();
15313   if (index < static_cast<uint32_t>(array->length())) {
15314     if (value->IsFloat64x2()) {
15315       cast_value = Handle<Float64x2>::cast(value)->get();
15316     } else {
15317       // Clamp undefined to NaN (default). All other types have been
15318       // converted to a number type further up in the call chain.
15319       ASSERT(value->IsUndefined());
15320     }
15321     array->set(index, cast_value);
15322   }
15323   return array->GetIsolate()->factory()->NewFloat64x2(cast_value);
15324 }
15325
15326
15327 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
15328   ASSERT(!HasFastProperties());
15329   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
15330   return PropertyCell::cast(value);
15331 }
15332
15333
15334 Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell(
15335     Handle<JSGlobalObject> global,
15336     Handle<Name> name) {
15337   ASSERT(!global->HasFastProperties());
15338   int entry = global->property_dictionary()->FindEntry(name);
15339   if (entry == NameDictionary::kNotFound) {
15340     Isolate* isolate = global->GetIsolate();
15341     Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(
15342         isolate->factory()->the_hole_value());
15343     PropertyDetails details(NONE, NORMAL, 0);
15344     details = details.AsDeleted();
15345     Handle<NameDictionary> dictionary = NameDictionary::Add(
15346         handle(global->property_dictionary()), name, cell, details);
15347     global->set_properties(*dictionary);
15348     return cell;
15349   } else {
15350     Object* value = global->property_dictionary()->ValueAt(entry);
15351     ASSERT(value->IsPropertyCell());
15352     return handle(PropertyCell::cast(value));
15353   }
15354 }
15355
15356
15357 // This class is used for looking up two character strings in the string table.
15358 // If we don't have a hit we don't want to waste much time so we unroll the
15359 // string hash calculation loop here for speed.  Doesn't work if the two
15360 // characters form a decimal integer, since such strings have a different hash
15361 // algorithm.
15362 class TwoCharHashTableKey : public HashTableKey {
15363  public:
15364   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
15365     : c1_(c1), c2_(c2) {
15366     // Char 1.
15367     uint32_t hash = seed;
15368     hash += c1;
15369     hash += hash << 10;
15370     hash ^= hash >> 6;
15371     // Char 2.
15372     hash += c2;
15373     hash += hash << 10;
15374     hash ^= hash >> 6;
15375     // GetHash.
15376     hash += hash << 3;
15377     hash ^= hash >> 11;
15378     hash += hash << 15;
15379     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
15380     hash_ = hash;
15381 #ifdef DEBUG
15382     // If this assert fails then we failed to reproduce the two-character
15383     // version of the string hashing algorithm above.  One reason could be
15384     // that we were passed two digits as characters, since the hash
15385     // algorithm is different in that case.
15386     uint16_t chars[2] = {c1, c2};
15387     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
15388     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
15389     ASSERT_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
15390 #endif
15391   }
15392
15393   bool IsMatch(Object* o) V8_OVERRIDE {
15394     if (!o->IsString()) return false;
15395     String* other = String::cast(o);
15396     if (other->length() != 2) return false;
15397     if (other->Get(0) != c1_) return false;
15398     return other->Get(1) == c2_;
15399   }
15400
15401   uint32_t Hash() V8_OVERRIDE { return hash_; }
15402   uint32_t HashForObject(Object* key) V8_OVERRIDE {
15403     if (!key->IsString()) return 0;
15404     return String::cast(key)->Hash();
15405   }
15406
15407   Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
15408     // The TwoCharHashTableKey is only used for looking in the string
15409     // table, not for adding to it.
15410     UNREACHABLE();
15411     return MaybeHandle<Object>().ToHandleChecked();
15412   }
15413
15414  private:
15415   uint16_t c1_;
15416   uint16_t c2_;
15417   uint32_t hash_;
15418 };
15419
15420
15421 MaybeHandle<String> StringTable::InternalizeStringIfExists(
15422     Isolate* isolate,
15423     Handle<String> string) {
15424   if (string->IsInternalizedString()) {
15425     return string;
15426   }
15427   return LookupStringIfExists(isolate, string);
15428 }
15429
15430
15431 MaybeHandle<String> StringTable::LookupStringIfExists(
15432     Isolate* isolate,
15433     Handle<String> string) {
15434   Handle<StringTable> string_table = isolate->factory()->string_table();
15435   InternalizedStringKey key(string);
15436   int entry = string_table->FindEntry(&key);
15437   if (entry == kNotFound) {
15438     return MaybeHandle<String>();
15439   } else {
15440     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
15441     ASSERT(StringShape(*result).IsInternalized());
15442     return result;
15443   }
15444 }
15445
15446
15447 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
15448     Isolate* isolate,
15449     uint16_t c1,
15450     uint16_t c2) {
15451   Handle<StringTable> string_table = isolate->factory()->string_table();
15452   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
15453   int entry = string_table->FindEntry(&key);
15454   if (entry == kNotFound) {
15455     return MaybeHandle<String>();
15456   } else {
15457     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
15458     ASSERT(StringShape(*result).IsInternalized());
15459     return result;
15460   }
15461 }
15462
15463
15464 Handle<String> StringTable::LookupString(Isolate* isolate,
15465                                          Handle<String> string) {
15466   InternalizedStringKey key(string);
15467   return LookupKey(isolate, &key);
15468 }
15469
15470
15471 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
15472   Handle<StringTable> table = isolate->factory()->string_table();
15473   int entry = table->FindEntry(key);
15474
15475   // String already in table.
15476   if (entry != kNotFound) {
15477     return handle(String::cast(table->KeyAt(entry)), isolate);
15478   }
15479
15480   // Adding new string. Grow table if needed.
15481   table = StringTable::EnsureCapacity(table, 1, key);
15482
15483   // Create string object.
15484   Handle<Object> string = key->AsHandle(isolate);
15485   // There must be no attempts to internalize strings that could throw
15486   // InvalidStringLength error.
15487   CHECK(!string.is_null());
15488
15489   // Add the new string and return it along with the string table.
15490   entry = table->FindInsertionEntry(key->Hash());
15491   table->set(EntryToIndex(entry), *string);
15492   table->ElementAdded();
15493
15494   isolate->factory()->set_string_table(table);
15495   return Handle<String>::cast(string);
15496 }
15497
15498
15499 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
15500                                              Handle<Context> context) {
15501   Isolate* isolate = GetIsolate();
15502   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15503   StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
15504                       RelocInfo::kNoPosition);
15505   int entry = FindEntry(&key);
15506   if (entry == kNotFound) return isolate->factory()->undefined_value();
15507   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15508 }
15509
15510
15511 Handle<Object> CompilationCacheTable::LookupEval(Handle<String> src,
15512                                                  Handle<Context> context,
15513                                                  StrictMode strict_mode,
15514                                                  int scope_position) {
15515   Isolate* isolate = GetIsolate();
15516   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15517   StringSharedKey key(src, shared, strict_mode, scope_position);
15518   int entry = FindEntry(&key);
15519   if (entry == kNotFound) return isolate->factory()->undefined_value();
15520   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15521 }
15522
15523
15524 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
15525                                                    JSRegExp::Flags flags) {
15526   Isolate* isolate = GetIsolate();
15527   DisallowHeapAllocation no_allocation;
15528   RegExpKey key(src, flags);
15529   int entry = FindEntry(&key);
15530   if (entry == kNotFound) return isolate->factory()->undefined_value();
15531   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
15532 }
15533
15534
15535 Handle<CompilationCacheTable> CompilationCacheTable::Put(
15536     Handle<CompilationCacheTable> cache, Handle<String> src,
15537     Handle<Context> context, Handle<Object> value) {
15538   Isolate* isolate = cache->GetIsolate();
15539   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15540   StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
15541                       RelocInfo::kNoPosition);
15542   cache = EnsureCapacity(cache, 1, &key);
15543   Handle<Object> k = key.AsHandle(isolate);
15544   int entry = cache->FindInsertionEntry(key.Hash());
15545   cache->set(EntryToIndex(entry), *k);
15546   cache->set(EntryToIndex(entry) + 1, *value);
15547   cache->ElementAdded();
15548   return cache;
15549 }
15550
15551
15552 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
15553     Handle<CompilationCacheTable> cache, Handle<String> src,
15554     Handle<Context> context, Handle<SharedFunctionInfo> value,
15555     int scope_position) {
15556   Isolate* isolate = cache->GetIsolate();
15557   Handle<SharedFunctionInfo> shared(context->closure()->shared());
15558   StringSharedKey key(src, shared, value->strict_mode(), scope_position);
15559   cache = EnsureCapacity(cache, 1, &key);
15560   Handle<Object> k = key.AsHandle(isolate);
15561   int entry = cache->FindInsertionEntry(key.Hash());
15562   cache->set(EntryToIndex(entry), *k);
15563   cache->set(EntryToIndex(entry) + 1, *value);
15564   cache->ElementAdded();
15565   return cache;
15566 }
15567
15568
15569 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
15570       Handle<CompilationCacheTable> cache, Handle<String> src,
15571       JSRegExp::Flags flags, Handle<FixedArray> value) {
15572   RegExpKey key(src, flags);
15573   cache = EnsureCapacity(cache, 1, &key);
15574   int entry = cache->FindInsertionEntry(key.Hash());
15575   // We store the value in the key slot, and compare the search key
15576   // to the stored value with a custon IsMatch function during lookups.
15577   cache->set(EntryToIndex(entry), *value);
15578   cache->set(EntryToIndex(entry) + 1, *value);
15579   cache->ElementAdded();
15580   return cache;
15581 }
15582
15583
15584 void CompilationCacheTable::Remove(Object* value) {
15585   DisallowHeapAllocation no_allocation;
15586   Object* the_hole_value = GetHeap()->the_hole_value();
15587   for (int entry = 0, size = Capacity(); entry < size; entry++) {
15588     int entry_index = EntryToIndex(entry);
15589     int value_index = entry_index + 1;
15590     if (get(value_index) == value) {
15591       NoWriteBarrierSet(this, entry_index, the_hole_value);
15592       NoWriteBarrierSet(this, value_index, the_hole_value);
15593       ElementRemoved();
15594     }
15595   }
15596   return;
15597 }
15598
15599
15600 // StringsKey used for HashTable where key is array of internalized strings.
15601 class StringsKey : public HashTableKey {
15602  public:
15603   explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
15604
15605   bool IsMatch(Object* strings) V8_OVERRIDE {
15606     FixedArray* o = FixedArray::cast(strings);
15607     int len = strings_->length();
15608     if (o->length() != len) return false;
15609     for (int i = 0; i < len; i++) {
15610       if (o->get(i) != strings_->get(i)) return false;
15611     }
15612     return true;
15613   }
15614
15615   uint32_t Hash() V8_OVERRIDE { return HashForObject(*strings_); }
15616
15617   uint32_t HashForObject(Object* obj) V8_OVERRIDE {
15618     FixedArray* strings = FixedArray::cast(obj);
15619     int len = strings->length();
15620     uint32_t hash = 0;
15621     for (int i = 0; i < len; i++) {
15622       hash ^= String::cast(strings->get(i))->Hash();
15623     }
15624     return hash;
15625   }
15626
15627   Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE { return strings_; }
15628
15629  private:
15630   Handle<FixedArray> strings_;
15631 };
15632
15633
15634 Object* MapCache::Lookup(FixedArray* array) {
15635   DisallowHeapAllocation no_alloc;
15636   StringsKey key(handle(array));
15637   int entry = FindEntry(&key);
15638   if (entry == kNotFound) return GetHeap()->undefined_value();
15639   return get(EntryToIndex(entry) + 1);
15640 }
15641
15642
15643 Handle<MapCache> MapCache::Put(
15644     Handle<MapCache> map_cache, Handle<FixedArray> array, Handle<Map> value) {
15645   StringsKey key(array);
15646
15647   Handle<MapCache> new_cache = EnsureCapacity(map_cache, 1, &key);
15648   int entry = new_cache->FindInsertionEntry(key.Hash());
15649   new_cache->set(EntryToIndex(entry), *array);
15650   new_cache->set(EntryToIndex(entry) + 1, *value);
15651   new_cache->ElementAdded();
15652   return new_cache;
15653 }
15654
15655
15656 template<typename Derived, typename Shape, typename Key>
15657 Handle<Derived> Dictionary<Derived, Shape, Key>::New(
15658     Isolate* isolate,
15659     int at_least_space_for,
15660     PretenureFlag pretenure) {
15661   ASSERT(0 <= at_least_space_for);
15662   Handle<Derived> dict = DerivedHashTable::New(isolate,
15663                                                at_least_space_for,
15664                                                USE_DEFAULT_MINIMUM_CAPACITY,
15665                                                pretenure);
15666
15667   // Initialize the next enumeration index.
15668   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
15669   return dict;
15670 }
15671
15672
15673 template<typename Derived, typename Shape, typename Key>
15674 void Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
15675     Handle<Derived> dictionary) {
15676   Factory* factory = dictionary->GetIsolate()->factory();
15677   int length = dictionary->NumberOfElements();
15678
15679   // Allocate and initialize iteration order array.
15680   Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
15681   for (int i = 0; i < length; i++) {
15682     iteration_order->set(i, Smi::FromInt(i));
15683   }
15684
15685   // Allocate array with enumeration order.
15686   Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
15687
15688   // Fill the enumeration order array with property details.
15689   int capacity = dictionary->Capacity();
15690   int pos = 0;
15691   for (int i = 0; i < capacity; i++) {
15692     if (dictionary->IsKey(dictionary->KeyAt(i))) {
15693       int index = dictionary->DetailsAt(i).dictionary_index();
15694       enumeration_order->set(pos++, Smi::FromInt(index));
15695     }
15696   }
15697
15698   // Sort the arrays wrt. enumeration order.
15699   iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
15700
15701   // Overwrite the enumeration_order with the enumeration indices.
15702   for (int i = 0; i < length; i++) {
15703     int index = Smi::cast(iteration_order->get(i))->value();
15704     int enum_index = PropertyDetails::kInitialIndex + i;
15705     enumeration_order->set(index, Smi::FromInt(enum_index));
15706   }
15707
15708   // Update the dictionary with new indices.
15709   capacity = dictionary->Capacity();
15710   pos = 0;
15711   for (int i = 0; i < capacity; i++) {
15712     if (dictionary->IsKey(dictionary->KeyAt(i))) {
15713       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
15714       PropertyDetails details = dictionary->DetailsAt(i);
15715       PropertyDetails new_details = PropertyDetails(
15716           details.attributes(), details.type(), enum_index);
15717       dictionary->DetailsAtPut(i, new_details);
15718     }
15719   }
15720
15721   // Set the next enumeration index.
15722   dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
15723 }
15724
15725
15726 template<typename Derived, typename Shape, typename Key>
15727 Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
15728     Handle<Derived> dictionary, int n, Key key) {
15729   // Check whether there are enough enumeration indices to add n elements.
15730   if (Shape::kIsEnumerable &&
15731       !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
15732     // If not, we generate new indices for the properties.
15733     GenerateNewEnumerationIndices(dictionary);
15734   }
15735   return DerivedHashTable::EnsureCapacity(dictionary, n, key);
15736 }
15737
15738
15739 template<typename Derived, typename Shape, typename Key>
15740 Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
15741     Handle<Derived> dictionary,
15742     int entry,
15743     JSObject::DeleteMode mode) {
15744   Factory* factory = dictionary->GetIsolate()->factory();
15745   PropertyDetails details = dictionary->DetailsAt(entry);
15746   // Ignore attributes if forcing a deletion.
15747   if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
15748     return factory->false_value();
15749   }
15750
15751   dictionary->SetEntry(
15752       entry, factory->the_hole_value(), factory->the_hole_value());
15753   dictionary->ElementRemoved();
15754   return factory->true_value();
15755 }
15756
15757
15758 template<typename Derived, typename Shape, typename Key>
15759 Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
15760     Handle<Derived> dictionary, Key key, Handle<Object> value) {
15761   int entry = dictionary->FindEntry(key);
15762
15763   // If the entry is present set the value;
15764   if (entry != Dictionary::kNotFound) {
15765     dictionary->ValueAtPut(entry, *value);
15766     return dictionary;
15767   }
15768
15769   // Check whether the dictionary should be extended.
15770   dictionary = EnsureCapacity(dictionary, 1, key);
15771 #ifdef DEBUG
15772   USE(Shape::AsHandle(dictionary->GetIsolate(), key));
15773 #endif
15774   PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
15775
15776   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15777   return dictionary;
15778 }
15779
15780
15781 template<typename Derived, typename Shape, typename Key>
15782 Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
15783     Handle<Derived> dictionary,
15784     Key key,
15785     Handle<Object> value,
15786     PropertyDetails details) {
15787   // Valdate key is absent.
15788   SLOW_ASSERT((dictionary->FindEntry(key) == Dictionary::kNotFound));
15789   // Check whether the dictionary should be extended.
15790   dictionary = EnsureCapacity(dictionary, 1, key);
15791
15792   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15793   return dictionary;
15794 }
15795
15796
15797 // Add a key, value pair to the dictionary.
15798 template<typename Derived, typename Shape, typename Key>
15799 void Dictionary<Derived, Shape, Key>::AddEntry(
15800     Handle<Derived> dictionary,
15801     Key key,
15802     Handle<Object> value,
15803     PropertyDetails details,
15804     uint32_t hash) {
15805   // Compute the key object.
15806   Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
15807
15808   uint32_t entry = dictionary->FindInsertionEntry(hash);
15809   // Insert element at empty or deleted entry
15810   if (!details.IsDeleted() &&
15811       details.dictionary_index() == 0 &&
15812       Shape::kIsEnumerable) {
15813     // Assign an enumeration index to the property and update
15814     // SetNextEnumerationIndex.
15815     int index = dictionary->NextEnumerationIndex();
15816     details = PropertyDetails(details.attributes(), details.type(), index);
15817     dictionary->SetNextEnumerationIndex(index + 1);
15818   }
15819   dictionary->SetEntry(entry, k, value, details);
15820   ASSERT((dictionary->KeyAt(entry)->IsNumber() ||
15821           dictionary->KeyAt(entry)->IsName()));
15822   dictionary->ElementAdded();
15823 }
15824
15825
15826 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
15827   DisallowHeapAllocation no_allocation;
15828   // If the dictionary requires slow elements an element has already
15829   // been added at a high index.
15830   if (requires_slow_elements()) return;
15831   // Check if this index is high enough that we should require slow
15832   // elements.
15833   if (key > kRequiresSlowElementsLimit) {
15834     set_requires_slow_elements();
15835     return;
15836   }
15837   // Update max key value.
15838   Object* max_index_object = get(kMaxNumberKeyIndex);
15839   if (!max_index_object->IsSmi() || max_number_key() < key) {
15840     FixedArray::set(kMaxNumberKeyIndex,
15841                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
15842   }
15843 }
15844
15845
15846 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
15847     Handle<SeededNumberDictionary> dictionary,
15848     uint32_t key,
15849     Handle<Object> value,
15850     PropertyDetails details) {
15851   dictionary->UpdateMaxNumberKey(key);
15852   SLOW_ASSERT(dictionary->FindEntry(key) == kNotFound);
15853   return Add(dictionary, key, value, details);
15854 }
15855
15856
15857 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
15858     Handle<UnseededNumberDictionary> dictionary,
15859     uint32_t key,
15860     Handle<Object> value) {
15861   SLOW_ASSERT(dictionary->FindEntry(key) == kNotFound);
15862   return Add(dictionary, key, value, PropertyDetails(NONE, NORMAL, 0));
15863 }
15864
15865
15866 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
15867     Handle<SeededNumberDictionary> dictionary,
15868     uint32_t key,
15869     Handle<Object> value) {
15870   dictionary->UpdateMaxNumberKey(key);
15871   return AtPut(dictionary, key, value);
15872 }
15873
15874
15875 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
15876     Handle<UnseededNumberDictionary> dictionary,
15877     uint32_t key,
15878     Handle<Object> value) {
15879   return AtPut(dictionary, key, value);
15880 }
15881
15882
15883 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
15884     Handle<SeededNumberDictionary> dictionary,
15885     uint32_t key,
15886     Handle<Object> value,
15887     PropertyDetails details) {
15888   int entry = dictionary->FindEntry(key);
15889   if (entry == kNotFound) {
15890     return AddNumberEntry(dictionary, key, value, details);
15891   }
15892   // Preserve enumeration index.
15893   details = PropertyDetails(details.attributes(),
15894                             details.type(),
15895                             dictionary->DetailsAt(entry).dictionary_index());
15896   Handle<Object> object_key =
15897       SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15898   dictionary->SetEntry(entry, object_key, value, details);
15899   return dictionary;
15900 }
15901
15902
15903 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
15904     Handle<UnseededNumberDictionary> dictionary,
15905     uint32_t key,
15906     Handle<Object> value) {
15907   int entry = dictionary->FindEntry(key);
15908   if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
15909   Handle<Object> object_key =
15910       UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15911   dictionary->SetEntry(entry, object_key, value);
15912   return dictionary;
15913 }
15914
15915
15916
15917 template<typename Derived, typename Shape, typename Key>
15918 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
15919     PropertyAttributes filter) {
15920   int capacity = DerivedHashTable::Capacity();
15921   int result = 0;
15922   for (int i = 0; i < capacity; i++) {
15923     Object* k = DerivedHashTable::KeyAt(i);
15924     if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15925       PropertyDetails details = DetailsAt(i);
15926       if (details.IsDeleted()) continue;
15927       PropertyAttributes attr = details.attributes();
15928       if ((attr & filter) == 0) result++;
15929     }
15930   }
15931   return result;
15932 }
15933
15934
15935 template<typename Derived, typename Shape, typename Key>
15936 int Dictionary<Derived, Shape, Key>::NumberOfEnumElements() {
15937   return NumberOfElementsFilterAttributes(
15938       static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC));
15939 }
15940
15941
15942 template<typename Derived, typename Shape, typename Key>
15943 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
15944     FixedArray* storage,
15945     PropertyAttributes filter,
15946     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
15947   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter));
15948   int capacity = DerivedHashTable::Capacity();
15949   int index = 0;
15950   for (int i = 0; i < capacity; i++) {
15951      Object* k = DerivedHashTable::KeyAt(i);
15952      if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15953        PropertyDetails details = DetailsAt(i);
15954        if (details.IsDeleted()) continue;
15955        PropertyAttributes attr = details.attributes();
15956        if ((attr & filter) == 0) storage->set(index++, k);
15957      }
15958   }
15959   if (sort_mode == Dictionary::SORTED) {
15960     storage->SortPairs(storage, index);
15961   }
15962   ASSERT(storage->length() >= index);
15963 }
15964
15965
15966 struct EnumIndexComparator {
15967   explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { }
15968   bool operator() (Smi* a, Smi* b) {
15969     PropertyDetails da(dict->DetailsAt(a->value()));
15970     PropertyDetails db(dict->DetailsAt(b->value()));
15971     return da.dictionary_index() < db.dictionary_index();
15972   }
15973   NameDictionary* dict;
15974 };
15975
15976
15977 void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
15978   int length = storage->length();
15979   int capacity = Capacity();
15980   int properties = 0;
15981   for (int i = 0; i < capacity; i++) {
15982      Object* k = KeyAt(i);
15983      if (IsKey(k) && !k->IsSymbol()) {
15984        PropertyDetails details = DetailsAt(i);
15985        if (details.IsDeleted() || details.IsDontEnum()) continue;
15986        storage->set(properties, Smi::FromInt(i));
15987        properties++;
15988        if (properties == length) break;
15989      }
15990   }
15991   CHECK_EQ(length, properties);
15992   EnumIndexComparator cmp(this);
15993   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
15994   std::sort(start, start + length, cmp);
15995   for (int i = 0; i < length; i++) {
15996     int index = Smi::cast(storage->get(i))->value();
15997     storage->set(i, KeyAt(index));
15998   }
15999 }
16000
16001
16002 template<typename Derived, typename Shape, typename Key>
16003 void Dictionary<Derived, Shape, Key>::CopyKeysTo(
16004     FixedArray* storage,
16005     int index,
16006     PropertyAttributes filter,
16007     typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
16008   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter));
16009   int capacity = DerivedHashTable::Capacity();
16010   for (int i = 0; i < capacity; i++) {
16011     Object* k = DerivedHashTable::KeyAt(i);
16012     if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
16013       PropertyDetails details = DetailsAt(i);
16014       if (details.IsDeleted()) continue;
16015       PropertyAttributes attr = details.attributes();
16016       if ((attr & filter) == 0) storage->set(index++, k);
16017     }
16018   }
16019   if (sort_mode == Dictionary::SORTED) {
16020     storage->SortPairs(storage, index);
16021   }
16022   ASSERT(storage->length() >= index);
16023 }
16024
16025
16026 // Backwards lookup (slow).
16027 template<typename Derived, typename Shape, typename Key>
16028 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
16029   int capacity = DerivedHashTable::Capacity();
16030   for (int i = 0; i < capacity; i++) {
16031     Object* k =  DerivedHashTable::KeyAt(i);
16032     if (Dictionary::IsKey(k)) {
16033       Object* e = ValueAt(i);
16034       if (e->IsPropertyCell()) {
16035         e = PropertyCell::cast(e)->value();
16036       }
16037       if (e == value) return k;
16038     }
16039   }
16040   Heap* heap = Dictionary::GetHeap();
16041   return heap->undefined_value();
16042 }
16043
16044
16045 Object* ObjectHashTable::Lookup(Handle<Object> key) {
16046   DisallowHeapAllocation no_gc;
16047   ASSERT(IsKey(*key));
16048
16049   // If the object does not have an identity hash, it was never used as a key.
16050   Object* hash = key->GetHash();
16051   if (hash->IsUndefined()) {
16052     return GetHeap()->the_hole_value();
16053   }
16054   int entry = FindEntry(key);
16055   if (entry == kNotFound) return GetHeap()->the_hole_value();
16056   return get(EntryToIndex(entry) + 1);
16057 }
16058
16059
16060 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
16061                                              Handle<Object> key,
16062                                              Handle<Object> value) {
16063   ASSERT(table->IsKey(*key));
16064   ASSERT(!value->IsTheHole());
16065
16066   Isolate* isolate = table->GetIsolate();
16067
16068   // Make sure the key object has an identity hash code.
16069   Handle<Smi> hash = Object::GetOrCreateHash(isolate, key);
16070
16071   int entry = table->FindEntry(key);
16072
16073   // Key is already in table, just overwrite value.
16074   if (entry != kNotFound) {
16075     table->set(EntryToIndex(entry) + 1, *value);
16076     return table;
16077   }
16078
16079   // Check whether the hash table should be extended.
16080   table = EnsureCapacity(table, 1, key);
16081   table->AddEntry(table->FindInsertionEntry(hash->value()),
16082                   *key,
16083                   *value);
16084   return table;
16085 }
16086
16087
16088 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
16089                                                 Handle<Object> key,
16090                                                 bool* was_present) {
16091   ASSERT(table->IsKey(*key));
16092
16093   Object* hash = key->GetHash();
16094   if (hash->IsUndefined()) {
16095     *was_present = false;
16096     return table;
16097   }
16098
16099   int entry = table->FindEntry(key);
16100   if (entry == kNotFound) {
16101     *was_present = false;
16102     return table;
16103   }
16104
16105   *was_present = true;
16106   table->RemoveEntry(entry);
16107   return Shrink(table, key);
16108 }
16109
16110
16111 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
16112   set(EntryToIndex(entry), key);
16113   set(EntryToIndex(entry) + 1, value);
16114   ElementAdded();
16115 }
16116
16117
16118 void ObjectHashTable::RemoveEntry(int entry) {
16119   set_the_hole(EntryToIndex(entry));
16120   set_the_hole(EntryToIndex(entry) + 1);
16121   ElementRemoved();
16122 }
16123
16124
16125 Object* WeakHashTable::Lookup(Handle<Object> key) {
16126   DisallowHeapAllocation no_gc;
16127   ASSERT(IsKey(*key));
16128   int entry = FindEntry(key);
16129   if (entry == kNotFound) return GetHeap()->the_hole_value();
16130   return get(EntryToValueIndex(entry));
16131 }
16132
16133
16134 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
16135                                          Handle<Object> key,
16136                                          Handle<Object> value) {
16137   ASSERT(table->IsKey(*key));
16138   int entry = table->FindEntry(key);
16139   // Key is already in table, just overwrite value.
16140   if (entry != kNotFound) {
16141     // TODO(ulan): Skipping write barrier is a temporary solution to avoid
16142     // memory leaks. Remove this once we have special visitor for weak fixed
16143     // arrays.
16144     table->set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
16145     return table;
16146   }
16147
16148   // Check whether the hash table should be extended.
16149   table = EnsureCapacity(table, 1, key, TENURED);
16150
16151   table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key, value);
16152   return table;
16153 }
16154
16155
16156 void WeakHashTable::AddEntry(int entry,
16157                              Handle<Object> key,
16158                              Handle<Object> value) {
16159   DisallowHeapAllocation no_allocation;
16160   // TODO(ulan): Skipping write barrier is a temporary solution to avoid
16161   // memory leaks. Remove this once we have special visitor for weak fixed
16162   // arrays.
16163   set(EntryToIndex(entry), *key, SKIP_WRITE_BARRIER);
16164   set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
16165   ElementAdded();
16166 }
16167
16168
16169 template<class Derived, class Iterator, int entrysize>
16170 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
16171     Isolate* isolate, int capacity, PretenureFlag pretenure) {
16172   // Capacity must be a power of two, since we depend on being able
16173   // to divide and multiple by 2 (kLoadFactor) to derive capacity
16174   // from number of buckets. If we decide to change kLoadFactor
16175   // to something other than 2, capacity should be stored as another
16176   // field of this object.
16177   capacity = RoundUpToPowerOf2(Max(kMinCapacity, capacity));
16178   if (capacity > kMaxCapacity) {
16179     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
16180   }
16181   int num_buckets = capacity / kLoadFactor;
16182   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
16183       kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
16184   backing_store->set_map_no_write_barrier(
16185       isolate->heap()->ordered_hash_table_map());
16186   Handle<Derived> table = Handle<Derived>::cast(backing_store);
16187   for (int i = 0; i < num_buckets; ++i) {
16188     table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
16189   }
16190   table->SetNumberOfBuckets(num_buckets);
16191   table->SetNumberOfElements(0);
16192   table->SetNumberOfDeletedElements(0);
16193   return table;
16194 }
16195
16196
16197 template<class Derived, class Iterator, int entrysize>
16198 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
16199     Handle<Derived> table) {
16200   ASSERT(!table->IsObsolete());
16201
16202   int nof = table->NumberOfElements();
16203   int nod = table->NumberOfDeletedElements();
16204   int capacity = table->Capacity();
16205   if ((nof + nod) < capacity) return table;
16206   // Don't need to grow if we can simply clear out deleted entries instead.
16207   // Note that we can't compact in place, though, so we always allocate
16208   // a new table.
16209   return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
16210 }
16211
16212
16213 template<class Derived, class Iterator, int entrysize>
16214 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
16215     Handle<Derived> table) {
16216   ASSERT(!table->IsObsolete());
16217
16218   int nof = table->NumberOfElements();
16219   int capacity = table->Capacity();
16220   if (nof >= (capacity >> 2)) return table;
16221   return Rehash(table, capacity / 2);
16222 }
16223
16224
16225 template<class Derived, class Iterator, int entrysize>
16226 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
16227     Handle<Derived> table) {
16228   ASSERT(!table->IsObsolete());
16229
16230   Handle<Derived> new_table =
16231       Allocate(table->GetIsolate(),
16232                kMinCapacity,
16233                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
16234
16235   table->SetNextTable(*new_table);
16236   table->SetNumberOfDeletedElements(-1);
16237
16238   return new_table;
16239 }
16240
16241
16242 template<class Derived, class Iterator, int entrysize>
16243 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Remove(
16244     Handle<Derived> table, Handle<Object> key, bool* was_present) {
16245   int entry = table->FindEntry(key);
16246   if (entry == kNotFound) {
16247     *was_present = false;
16248     return table;
16249   }
16250   *was_present = true;
16251   table->RemoveEntry(entry);
16252   return Shrink(table);
16253 }
16254
16255
16256 template<class Derived, class Iterator, int entrysize>
16257 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
16258     Handle<Derived> table, int new_capacity) {
16259   ASSERT(!table->IsObsolete());
16260
16261   Handle<Derived> new_table =
16262       Allocate(table->GetIsolate(),
16263                new_capacity,
16264                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
16265   int nof = table->NumberOfElements();
16266   int nod = table->NumberOfDeletedElements();
16267   int new_buckets = new_table->NumberOfBuckets();
16268   int new_entry = 0;
16269   int removed_holes_index = 0;
16270
16271   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
16272     Object* key = table->KeyAt(old_entry);
16273     if (key->IsTheHole()) {
16274       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
16275       continue;
16276     }
16277
16278     Object* hash = key->GetHash();
16279     int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
16280     Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
16281     new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
16282     int new_index = new_table->EntryToIndex(new_entry);
16283     int old_index = table->EntryToIndex(old_entry);
16284     for (int i = 0; i < entrysize; ++i) {
16285       Object* value = table->get(old_index + i);
16286       new_table->set(new_index + i, value);
16287     }
16288     new_table->set(new_index + kChainOffset, chain_entry);
16289     ++new_entry;
16290   }
16291
16292   ASSERT_EQ(nod, removed_holes_index);
16293
16294   new_table->SetNumberOfElements(nof);
16295   table->SetNextTable(*new_table);
16296
16297   return new_table;
16298 }
16299
16300
16301 template<class Derived, class Iterator, int entrysize>
16302 int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(
16303     Handle<Object> key) {
16304   ASSERT(!IsObsolete());
16305
16306   DisallowHeapAllocation no_gc;
16307   ASSERT(!key->IsTheHole());
16308   Object* hash = key->GetHash();
16309   if (hash->IsUndefined()) return kNotFound;
16310   for (int entry = HashToEntry(Smi::cast(hash)->value());
16311        entry != kNotFound;
16312        entry = ChainAt(entry)) {
16313     Object* candidate = KeyAt(entry);
16314     if (candidate->SameValueZero(*key))
16315       return entry;
16316   }
16317   return kNotFound;
16318 }
16319
16320
16321 template<class Derived, class Iterator, int entrysize>
16322 int OrderedHashTable<Derived, Iterator, entrysize>::AddEntry(int hash) {
16323   ASSERT(!IsObsolete());
16324
16325   int entry = UsedCapacity();
16326   int bucket = HashToBucket(hash);
16327   int index = EntryToIndex(entry);
16328   Object* chain_entry = get(kHashTableStartIndex + bucket);
16329   set(kHashTableStartIndex + bucket, Smi::FromInt(entry));
16330   set(index + kChainOffset, chain_entry);
16331   SetNumberOfElements(NumberOfElements() + 1);
16332   return index;
16333 }
16334
16335
16336 template<class Derived, class Iterator, int entrysize>
16337 void OrderedHashTable<Derived, Iterator, entrysize>::RemoveEntry(int entry) {
16338   ASSERT(!IsObsolete());
16339
16340   int index = EntryToIndex(entry);
16341   for (int i = 0; i < entrysize; ++i) {
16342     set_the_hole(index + i);
16343   }
16344   SetNumberOfElements(NumberOfElements() - 1);
16345   SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
16346 }
16347
16348
16349 template Handle<OrderedHashSet>
16350 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
16351     Isolate* isolate, int capacity, PretenureFlag pretenure);
16352
16353 template Handle<OrderedHashSet>
16354 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
16355     Handle<OrderedHashSet> table);
16356
16357 template Handle<OrderedHashSet>
16358 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
16359     Handle<OrderedHashSet> table);
16360
16361 template Handle<OrderedHashSet>
16362 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
16363     Handle<OrderedHashSet> table);
16364
16365 template Handle<OrderedHashSet>
16366 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Remove(
16367     Handle<OrderedHashSet> table, Handle<Object> key, bool* was_present);
16368
16369 template int
16370 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(
16371     Handle<Object> key);
16372
16373 template int
16374 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::AddEntry(int hash);
16375
16376 template void
16377 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::RemoveEntry(int entry);
16378
16379
16380 template Handle<OrderedHashMap>
16381 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
16382     Isolate* isolate, int capacity, PretenureFlag pretenure);
16383
16384 template Handle<OrderedHashMap>
16385 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
16386     Handle<OrderedHashMap> table);
16387
16388 template Handle<OrderedHashMap>
16389 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
16390     Handle<OrderedHashMap> table);
16391
16392 template Handle<OrderedHashMap>
16393 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
16394     Handle<OrderedHashMap> table);
16395
16396 template Handle<OrderedHashMap>
16397 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Remove(
16398     Handle<OrderedHashMap> table, Handle<Object> key, bool* was_present);
16399
16400 template int
16401 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(
16402     Handle<Object> key);
16403
16404 template int
16405 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::AddEntry(int hash);
16406
16407 template void
16408 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::RemoveEntry(int entry);
16409
16410
16411 bool OrderedHashSet::Contains(Handle<Object> key) {
16412   return FindEntry(key) != kNotFound;
16413 }
16414
16415
16416 Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
16417                                            Handle<Object> key) {
16418   if (table->FindEntry(key) != kNotFound) return table;
16419
16420   table = EnsureGrowable(table);
16421
16422   Handle<Smi> hash = GetOrCreateHash(table->GetIsolate(), key);
16423   int index = table->AddEntry(hash->value());
16424   table->set(index, *key);
16425   return table;
16426 }
16427
16428
16429 Object* OrderedHashMap::Lookup(Handle<Object> key) {
16430   DisallowHeapAllocation no_gc;
16431   int entry = FindEntry(key);
16432   if (entry == kNotFound) return GetHeap()->the_hole_value();
16433   return ValueAt(entry);
16434 }
16435
16436
16437 Handle<OrderedHashMap> OrderedHashMap::Put(Handle<OrderedHashMap> table,
16438                                            Handle<Object> key,
16439                                            Handle<Object> value) {
16440   ASSERT(!key->IsTheHole());
16441
16442   int entry = table->FindEntry(key);
16443
16444   if (entry != kNotFound) {
16445     table->set(table->EntryToIndex(entry) + kValueOffset, *value);
16446     return table;
16447   }
16448
16449   table = EnsureGrowable(table);
16450
16451   Handle<Smi> hash = GetOrCreateHash(table->GetIsolate(), key);
16452   int index = table->AddEntry(hash->value());
16453   table->set(index, *key);
16454   table->set(index + kValueOffset, *value);
16455   return table;
16456 }
16457
16458
16459 template<class Derived, class TableType>
16460 Handle<JSObject> OrderedHashTableIterator<Derived, TableType>::Next(
16461     Handle<Derived> iterator) {
16462   Isolate* isolate = iterator->GetIsolate();
16463   Factory* factory = isolate->factory();
16464
16465   Handle<Object> maybe_table(iterator->table(), isolate);
16466   if (!maybe_table->IsUndefined()) {
16467     iterator->Transition();
16468
16469     Handle<TableType> table(TableType::cast(iterator->table()), isolate);
16470     int index = Smi::cast(iterator->index())->value();
16471     int used_capacity = table->UsedCapacity();
16472
16473     while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
16474       index++;
16475     }
16476
16477     if (index < used_capacity) {
16478       int entry_index = table->EntryToIndex(index);
16479       Handle<Object> value =
16480           Derived::ValueForKind(iterator, entry_index);
16481       iterator->set_index(Smi::FromInt(index + 1));
16482       return factory->NewIteratorResultObject(value, false);
16483     }
16484
16485     iterator->set_table(iterator->GetHeap()->undefined_value());
16486   }
16487
16488   return factory->NewIteratorResultObject(factory->undefined_value(), true);
16489 }
16490
16491
16492 template<class Derived, class TableType>
16493 void OrderedHashTableIterator<Derived, TableType>::Transition() {
16494   Isolate* isolate = GetIsolate();
16495   Handle<TableType> table(TableType::cast(this->table()), isolate);
16496   if (!table->IsObsolete()) return;
16497
16498   int index = Smi::cast(this->index())->value();
16499   while (table->IsObsolete()) {
16500     Handle<TableType> next_table(table->NextTable(), isolate);
16501
16502     if (index > 0) {
16503       int nod = table->NumberOfDeletedElements();
16504
16505       // When we clear the table we set the number of deleted elements to -1.
16506       if (nod == -1) {
16507         index = 0;
16508       } else {
16509         int old_index = index;
16510         for (int i = 0; i < nod; ++i) {
16511           int removed_index = table->RemovedIndexAt(i);
16512           if (removed_index >= old_index) break;
16513           --index;
16514         }
16515       }
16516     }
16517
16518     table = next_table;
16519   }
16520
16521   set_table(*table);
16522   set_index(Smi::FromInt(index));
16523 }
16524
16525
16526 template Handle<JSObject>
16527 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
16528     Handle<JSSetIterator> iterator);
16529
16530 template void
16531 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
16532
16533
16534 template Handle<JSObject>
16535 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
16536     Handle<JSMapIterator> iterator);
16537
16538 template void
16539 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
16540
16541
16542 Handle<Object> JSSetIterator::ValueForKind(
16543     Handle<JSSetIterator> iterator, int entry_index) {
16544   int kind = iterator->kind()->value();
16545   // Set.prototype only has values and entries.
16546   ASSERT(kind == kKindValues || kind == kKindEntries);
16547
16548   Isolate* isolate = iterator->GetIsolate();
16549   Factory* factory = isolate->factory();
16550
16551   Handle<OrderedHashSet> table(
16552       OrderedHashSet::cast(iterator->table()), isolate);
16553   Handle<Object> value = Handle<Object>(table->get(entry_index), isolate);
16554
16555   if (kind == kKindEntries) {
16556     Handle<FixedArray> array = factory->NewFixedArray(2);
16557     array->set(0, *value);
16558     array->set(1, *value);
16559     return factory->NewJSArrayWithElements(array);
16560   }
16561
16562   return value;
16563 }
16564
16565
16566 Handle<Object> JSMapIterator::ValueForKind(
16567     Handle<JSMapIterator> iterator, int entry_index) {
16568   int kind = iterator->kind()->value();
16569   ASSERT(kind == kKindKeys || kind == kKindValues || kind == kKindEntries);
16570
16571   Isolate* isolate = iterator->GetIsolate();
16572   Factory* factory = isolate->factory();
16573
16574   Handle<OrderedHashMap> table(
16575       OrderedHashMap::cast(iterator->table()), isolate);
16576
16577   switch (kind) {
16578     case kKindKeys:
16579       return Handle<Object>(table->get(entry_index), isolate);
16580
16581     case kKindValues:
16582       return Handle<Object>(table->get(entry_index + 1), isolate);
16583
16584     case kKindEntries: {
16585       Handle<Object> key(table->get(entry_index), isolate);
16586       Handle<Object> value(table->get(entry_index + 1), isolate);
16587       Handle<FixedArray> array = factory->NewFixedArray(2);
16588       array->set(0, *key);
16589       array->set(1, *value);
16590       return factory->NewJSArrayWithElements(array);
16591     }
16592   }
16593
16594   UNREACHABLE();
16595   return factory->undefined_value();
16596 }
16597
16598
16599 DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator(
16600     DeclaredAccessorDescriptor* descriptor)
16601     : array_(descriptor->serialized_data()->GetDataStartAddress()),
16602       length_(descriptor->serialized_data()->length()),
16603       offset_(0) {
16604 }
16605
16606
16607 const DeclaredAccessorDescriptorData*
16608   DeclaredAccessorDescriptorIterator::Next() {
16609   ASSERT(offset_ < length_);
16610   uint8_t* ptr = &array_[offset_];
16611   ASSERT(reinterpret_cast<uintptr_t>(ptr) % sizeof(uintptr_t) == 0);
16612   const DeclaredAccessorDescriptorData* data =
16613       reinterpret_cast<const DeclaredAccessorDescriptorData*>(ptr);
16614   offset_ += sizeof(*data);
16615   ASSERT(offset_ <= length_);
16616   return data;
16617 }
16618
16619
16620 Handle<DeclaredAccessorDescriptor> DeclaredAccessorDescriptor::Create(
16621     Isolate* isolate,
16622     const DeclaredAccessorDescriptorData& descriptor,
16623     Handle<DeclaredAccessorDescriptor> previous) {
16624   int previous_length =
16625       previous.is_null() ? 0 : previous->serialized_data()->length();
16626   int length = sizeof(descriptor) + previous_length;
16627   Handle<ByteArray> serialized_descriptor =
16628       isolate->factory()->NewByteArray(length);
16629   Handle<DeclaredAccessorDescriptor> value =
16630       isolate->factory()->NewDeclaredAccessorDescriptor();
16631   value->set_serialized_data(*serialized_descriptor);
16632   // Copy in the data.
16633   {
16634     DisallowHeapAllocation no_allocation;
16635     uint8_t* array = serialized_descriptor->GetDataStartAddress();
16636     if (previous_length != 0) {
16637       uint8_t* previous_array =
16638           previous->serialized_data()->GetDataStartAddress();
16639       MemCopy(array, previous_array, previous_length);
16640       array += previous_length;
16641     }
16642     ASSERT(reinterpret_cast<uintptr_t>(array) % sizeof(uintptr_t) == 0);
16643     DeclaredAccessorDescriptorData* data =
16644         reinterpret_cast<DeclaredAccessorDescriptorData*>(array);
16645     *data = descriptor;
16646   }
16647   return value;
16648 }
16649
16650
16651 // Check if there is a break point at this code position.
16652 bool DebugInfo::HasBreakPoint(int code_position) {
16653   // Get the break point info object for this code position.
16654   Object* break_point_info = GetBreakPointInfo(code_position);
16655
16656   // If there is no break point info object or no break points in the break
16657   // point info object there is no break point at this code position.
16658   if (break_point_info->IsUndefined()) return false;
16659   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
16660 }
16661
16662
16663 // Get the break point info object for this code position.
16664 Object* DebugInfo::GetBreakPointInfo(int code_position) {
16665   // Find the index of the break point info object for this code position.
16666   int index = GetBreakPointInfoIndex(code_position);
16667
16668   // Return the break point info object if any.
16669   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
16670   return BreakPointInfo::cast(break_points()->get(index));
16671 }
16672
16673
16674 // Clear a break point at the specified code position.
16675 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
16676                                 int code_position,
16677                                 Handle<Object> break_point_object) {
16678   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16679                                   debug_info->GetIsolate());
16680   if (break_point_info->IsUndefined()) return;
16681   BreakPointInfo::ClearBreakPoint(
16682       Handle<BreakPointInfo>::cast(break_point_info),
16683       break_point_object);
16684 }
16685
16686
16687 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
16688                               int code_position,
16689                               int source_position,
16690                               int statement_position,
16691                               Handle<Object> break_point_object) {
16692   Isolate* isolate = debug_info->GetIsolate();
16693   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16694                                   isolate);
16695   if (!break_point_info->IsUndefined()) {
16696     BreakPointInfo::SetBreakPoint(
16697         Handle<BreakPointInfo>::cast(break_point_info),
16698         break_point_object);
16699     return;
16700   }
16701
16702   // Adding a new break point for a code position which did not have any
16703   // break points before. Try to find a free slot.
16704   int index = kNoBreakPointInfo;
16705   for (int i = 0; i < debug_info->break_points()->length(); i++) {
16706     if (debug_info->break_points()->get(i)->IsUndefined()) {
16707       index = i;
16708       break;
16709     }
16710   }
16711   if (index == kNoBreakPointInfo) {
16712     // No free slot - extend break point info array.
16713     Handle<FixedArray> old_break_points =
16714         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
16715     Handle<FixedArray> new_break_points =
16716         isolate->factory()->NewFixedArray(
16717             old_break_points->length() +
16718             DebugInfo::kEstimatedNofBreakPointsInFunction);
16719
16720     debug_info->set_break_points(*new_break_points);
16721     for (int i = 0; i < old_break_points->length(); i++) {
16722       new_break_points->set(i, old_break_points->get(i));
16723     }
16724     index = old_break_points->length();
16725   }
16726   ASSERT(index != kNoBreakPointInfo);
16727
16728   // Allocate new BreakPointInfo object and set the break point.
16729   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
16730       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
16731   new_break_point_info->set_code_position(Smi::FromInt(code_position));
16732   new_break_point_info->set_source_position(Smi::FromInt(source_position));
16733   new_break_point_info->
16734       set_statement_position(Smi::FromInt(statement_position));
16735   new_break_point_info->set_break_point_objects(
16736       isolate->heap()->undefined_value());
16737   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
16738   debug_info->break_points()->set(index, *new_break_point_info);
16739 }
16740
16741
16742 // Get the break point objects for a code position.
16743 Object* DebugInfo::GetBreakPointObjects(int code_position) {
16744   Object* break_point_info = GetBreakPointInfo(code_position);
16745   if (break_point_info->IsUndefined()) {
16746     return GetHeap()->undefined_value();
16747   }
16748   return BreakPointInfo::cast(break_point_info)->break_point_objects();
16749 }
16750
16751
16752 // Get the total number of break points.
16753 int DebugInfo::GetBreakPointCount() {
16754   if (break_points()->IsUndefined()) return 0;
16755   int count = 0;
16756   for (int i = 0; i < break_points()->length(); i++) {
16757     if (!break_points()->get(i)->IsUndefined()) {
16758       BreakPointInfo* break_point_info =
16759           BreakPointInfo::cast(break_points()->get(i));
16760       count += break_point_info->GetBreakPointCount();
16761     }
16762   }
16763   return count;
16764 }
16765
16766
16767 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
16768                                       Handle<Object> break_point_object) {
16769   Heap* heap = debug_info->GetHeap();
16770   if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
16771   for (int i = 0; i < debug_info->break_points()->length(); i++) {
16772     if (!debug_info->break_points()->get(i)->IsUndefined()) {
16773       Handle<BreakPointInfo> break_point_info =
16774           Handle<BreakPointInfo>(BreakPointInfo::cast(
16775               debug_info->break_points()->get(i)));
16776       if (BreakPointInfo::HasBreakPointObject(break_point_info,
16777                                               break_point_object)) {
16778         return *break_point_info;
16779       }
16780     }
16781   }
16782   return heap->undefined_value();
16783 }
16784
16785
16786 // Find the index of the break point info object for the specified code
16787 // position.
16788 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
16789   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
16790   for (int i = 0; i < break_points()->length(); i++) {
16791     if (!break_points()->get(i)->IsUndefined()) {
16792       BreakPointInfo* break_point_info =
16793           BreakPointInfo::cast(break_points()->get(i));
16794       if (break_point_info->code_position()->value() == code_position) {
16795         return i;
16796       }
16797     }
16798   }
16799   return kNoBreakPointInfo;
16800 }
16801
16802
16803 // Remove the specified break point object.
16804 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
16805                                      Handle<Object> break_point_object) {
16806   Isolate* isolate = break_point_info->GetIsolate();
16807   // If there are no break points just ignore.
16808   if (break_point_info->break_point_objects()->IsUndefined()) return;
16809   // If there is a single break point clear it if it is the same.
16810   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16811     if (break_point_info->break_point_objects() == *break_point_object) {
16812       break_point_info->set_break_point_objects(
16813           isolate->heap()->undefined_value());
16814     }
16815     return;
16816   }
16817   // If there are multiple break points shrink the array
16818   ASSERT(break_point_info->break_point_objects()->IsFixedArray());
16819   Handle<FixedArray> old_array =
16820       Handle<FixedArray>(
16821           FixedArray::cast(break_point_info->break_point_objects()));
16822   Handle<FixedArray> new_array =
16823       isolate->factory()->NewFixedArray(old_array->length() - 1);
16824   int found_count = 0;
16825   for (int i = 0; i < old_array->length(); i++) {
16826     if (old_array->get(i) == *break_point_object) {
16827       ASSERT(found_count == 0);
16828       found_count++;
16829     } else {
16830       new_array->set(i - found_count, old_array->get(i));
16831     }
16832   }
16833   // If the break point was found in the list change it.
16834   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
16835 }
16836
16837
16838 // Add the specified break point object.
16839 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
16840                                    Handle<Object> break_point_object) {
16841   Isolate* isolate = break_point_info->GetIsolate();
16842
16843   // If there was no break point objects before just set it.
16844   if (break_point_info->break_point_objects()->IsUndefined()) {
16845     break_point_info->set_break_point_objects(*break_point_object);
16846     return;
16847   }
16848   // If the break point object is the same as before just ignore.
16849   if (break_point_info->break_point_objects() == *break_point_object) return;
16850   // If there was one break point object before replace with array.
16851   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16852     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
16853     array->set(0, break_point_info->break_point_objects());
16854     array->set(1, *break_point_object);
16855     break_point_info->set_break_point_objects(*array);
16856     return;
16857   }
16858   // If there was more than one break point before extend array.
16859   Handle<FixedArray> old_array =
16860       Handle<FixedArray>(
16861           FixedArray::cast(break_point_info->break_point_objects()));
16862   Handle<FixedArray> new_array =
16863       isolate->factory()->NewFixedArray(old_array->length() + 1);
16864   for (int i = 0; i < old_array->length(); i++) {
16865     // If the break point was there before just ignore.
16866     if (old_array->get(i) == *break_point_object) return;
16867     new_array->set(i, old_array->get(i));
16868   }
16869   // Add the new break point.
16870   new_array->set(old_array->length(), *break_point_object);
16871   break_point_info->set_break_point_objects(*new_array);
16872 }
16873
16874
16875 bool BreakPointInfo::HasBreakPointObject(
16876     Handle<BreakPointInfo> break_point_info,
16877     Handle<Object> break_point_object) {
16878   // No break point.
16879   if (break_point_info->break_point_objects()->IsUndefined()) return false;
16880   // Single break point.
16881   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16882     return break_point_info->break_point_objects() == *break_point_object;
16883   }
16884   // Multiple break points.
16885   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
16886   for (int i = 0; i < array->length(); i++) {
16887     if (array->get(i) == *break_point_object) {
16888       return true;
16889     }
16890   }
16891   return false;
16892 }
16893
16894
16895 // Get the number of break points.
16896 int BreakPointInfo::GetBreakPointCount() {
16897   // No break point.
16898   if (break_point_objects()->IsUndefined()) return 0;
16899   // Single break point.
16900   if (!break_point_objects()->IsFixedArray()) return 1;
16901   // Multiple break points.
16902   return FixedArray::cast(break_point_objects())->length();
16903 }
16904
16905
16906 Object* JSDate::GetField(Object* object, Smi* index) {
16907   return JSDate::cast(object)->DoGetField(
16908       static_cast<FieldIndex>(index->value()));
16909 }
16910
16911
16912 Object* JSDate::DoGetField(FieldIndex index) {
16913   ASSERT(index != kDateValue);
16914
16915   DateCache* date_cache = GetIsolate()->date_cache();
16916
16917   if (index < kFirstUncachedField) {
16918     Object* stamp = cache_stamp();
16919     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
16920       // Since the stamp is not NaN, the value is also not NaN.
16921       int64_t local_time_ms =
16922           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
16923       SetCachedFields(local_time_ms, date_cache);
16924     }
16925     switch (index) {
16926       case kYear: return year();
16927       case kMonth: return month();
16928       case kDay: return day();
16929       case kWeekday: return weekday();
16930       case kHour: return hour();
16931       case kMinute: return min();
16932       case kSecond: return sec();
16933       default: UNREACHABLE();
16934     }
16935   }
16936
16937   if (index >= kFirstUTCField) {
16938     return GetUTCField(index, value()->Number(), date_cache);
16939   }
16940
16941   double time = value()->Number();
16942   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
16943
16944   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
16945   int days = DateCache::DaysFromTime(local_time_ms);
16946
16947   if (index == kDays) return Smi::FromInt(days);
16948
16949   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16950   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
16951   ASSERT(index == kTimeInDay);
16952   return Smi::FromInt(time_in_day_ms);
16953 }
16954
16955
16956 Object* JSDate::GetUTCField(FieldIndex index,
16957                             double value,
16958                             DateCache* date_cache) {
16959   ASSERT(index >= kFirstUTCField);
16960
16961   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
16962
16963   int64_t time_ms = static_cast<int64_t>(value);
16964
16965   if (index == kTimezoneOffset) {
16966     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
16967   }
16968
16969   int days = DateCache::DaysFromTime(time_ms);
16970
16971   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
16972
16973   if (index <= kDayUTC) {
16974     int year, month, day;
16975     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16976     if (index == kYearUTC) return Smi::FromInt(year);
16977     if (index == kMonthUTC) return Smi::FromInt(month);
16978     ASSERT(index == kDayUTC);
16979     return Smi::FromInt(day);
16980   }
16981
16982   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
16983   switch (index) {
16984     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
16985     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
16986     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
16987     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
16988     case kDaysUTC: return Smi::FromInt(days);
16989     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
16990     default: UNREACHABLE();
16991   }
16992
16993   UNREACHABLE();
16994   return NULL;
16995 }
16996
16997
16998 void JSDate::SetValue(Object* value, bool is_value_nan) {
16999   set_value(value);
17000   if (is_value_nan) {
17001     HeapNumber* nan = GetIsolate()->heap()->nan_value();
17002     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
17003     set_year(nan, SKIP_WRITE_BARRIER);
17004     set_month(nan, SKIP_WRITE_BARRIER);
17005     set_day(nan, SKIP_WRITE_BARRIER);
17006     set_hour(nan, SKIP_WRITE_BARRIER);
17007     set_min(nan, SKIP_WRITE_BARRIER);
17008     set_sec(nan, SKIP_WRITE_BARRIER);
17009     set_weekday(nan, SKIP_WRITE_BARRIER);
17010   } else {
17011     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
17012   }
17013 }
17014
17015
17016 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
17017   int days = DateCache::DaysFromTime(local_time_ms);
17018   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
17019   int year, month, day;
17020   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
17021   int weekday = date_cache->Weekday(days);
17022   int hour = time_in_day_ms / (60 * 60 * 1000);
17023   int min = (time_in_day_ms / (60 * 1000)) % 60;
17024   int sec = (time_in_day_ms / 1000) % 60;
17025   set_cache_stamp(date_cache->stamp());
17026   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
17027   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
17028   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
17029   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
17030   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
17031   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
17032   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
17033 }
17034
17035
17036 void JSArrayBuffer::Neuter() {
17037   ASSERT(is_external());
17038   set_backing_store(NULL);
17039   set_byte_length(Smi::FromInt(0));
17040 }
17041
17042
17043 void JSArrayBufferView::NeuterView() {
17044   set_byte_offset(Smi::FromInt(0));
17045   set_byte_length(Smi::FromInt(0));
17046 }
17047
17048
17049 void JSDataView::Neuter() {
17050   NeuterView();
17051 }
17052
17053
17054 void JSTypedArray::Neuter() {
17055   NeuterView();
17056   set_length(Smi::FromInt(0));
17057   set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
17058 }
17059
17060
17061 static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) {
17062   switch (elements_kind) {
17063 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
17064     case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
17065
17066     TYPED_ARRAYS(TYPED_ARRAY_CASE)
17067 #undef TYPED_ARRAY_CASE
17068
17069     default:
17070       UNREACHABLE();
17071       return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
17072   }
17073 }
17074
17075
17076 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
17077     Handle<JSTypedArray> typed_array) {
17078
17079   Handle<Map> map(typed_array->map());
17080   Isolate* isolate = typed_array->GetIsolate();
17081
17082   ASSERT(IsFixedTypedArrayElementsKind(map->elements_kind()));
17083
17084   Handle<Map> new_map = Map::TransitionElementsTo(
17085           map,
17086           FixedToExternalElementsKind(map->elements_kind()));
17087
17088   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
17089   Handle<FixedTypedArrayBase> fixed_typed_array(
17090       FixedTypedArrayBase::cast(typed_array->elements()));
17091   Runtime::SetupArrayBufferAllocatingData(isolate, buffer,
17092       fixed_typed_array->DataSize(), false);
17093   memcpy(buffer->backing_store(),
17094          fixed_typed_array->DataPtr(),
17095          fixed_typed_array->DataSize());
17096   Handle<ExternalArray> new_elements =
17097       isolate->factory()->NewExternalArray(
17098           fixed_typed_array->length(), typed_array->type(),
17099           static_cast<uint8_t*>(buffer->backing_store()));
17100
17101   buffer->set_weak_first_view(*typed_array);
17102   ASSERT(typed_array->weak_next() == isolate->heap()->undefined_value());
17103   typed_array->set_buffer(*buffer);
17104   JSObject::SetMapAndElements(typed_array, new_map, new_elements);
17105
17106   return buffer;
17107 }
17108
17109
17110 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
17111   Handle<Object> result(buffer(), GetIsolate());
17112   if (*result != Smi::FromInt(0)) {
17113     ASSERT(IsExternalArrayElementsKind(map()->elements_kind()));
17114     return Handle<JSArrayBuffer>::cast(result);
17115   }
17116   Handle<JSTypedArray> self(this);
17117   return MaterializeArrayBuffer(self);
17118 }
17119
17120
17121 HeapType* PropertyCell::type() {
17122   return static_cast<HeapType*>(type_raw());
17123 }
17124
17125
17126 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) {
17127   ASSERT(IsPropertyCell());
17128   set_type_raw(type, ignored);
17129 }
17130
17131
17132 Handle<HeapType> PropertyCell::UpdatedType(Handle<PropertyCell> cell,
17133                                            Handle<Object> value) {
17134   Isolate* isolate = cell->GetIsolate();
17135   Handle<HeapType> old_type(cell->type(), isolate);
17136   // TODO(2803): Do not track ConsString as constant because they cannot be
17137   // embedded into code.
17138   Handle<HeapType> new_type = value->IsConsString() || value->IsTheHole()
17139       ? HeapType::Any(isolate) : HeapType::Constant(value, isolate);
17140
17141   if (new_type->Is(old_type)) {
17142     return old_type;
17143   }
17144
17145   cell->dependent_code()->DeoptimizeDependentCodeGroup(
17146       isolate, DependentCode::kPropertyCellChangedGroup);
17147
17148   if (old_type->Is(HeapType::None()) || old_type->Is(HeapType::Undefined())) {
17149     return new_type;
17150   }
17151
17152   return HeapType::Any(isolate);
17153 }
17154
17155
17156 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell,
17157                                      Handle<Object> value) {
17158   cell->set_value(*value);
17159   if (!HeapType::Any()->Is(cell->type())) {
17160     Handle<HeapType> new_type = UpdatedType(cell, value);
17161     cell->set_type(*new_type);
17162   }
17163 }
17164
17165
17166 // static
17167 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell,
17168                                                CompilationInfo* info) {
17169   Handle<DependentCode> codes =
17170       DependentCode::Insert(handle(cell->dependent_code(), info->isolate()),
17171                             DependentCode::kPropertyCellChangedGroup,
17172                             info->object_wrapper());
17173   if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
17174   info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
17175       cell, info->zone());
17176 }
17177
17178
17179 const char* GetBailoutReason(BailoutReason reason) {
17180   ASSERT(reason < kLastErrorMessage);
17181 #define ERROR_MESSAGES_TEXTS(C, T) T,
17182   static const char* error_messages_[] = {
17183       ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
17184   };
17185 #undef ERROR_MESSAGES_TEXTS
17186   return error_messages_[reason];
17187 }
17188
17189
17190 } }  // namespace v8::internal