Fix compilation with Intel CC.
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / objects.cc
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "api.h"
31 #include "arguments.h"
32 #include "bootstrapper.h"
33 #include "codegen.h"
34 #include "debug.h"
35 #include "deoptimizer.h"
36 #include "elements.h"
37 #include "execution.h"
38 #include "full-codegen.h"
39 #include "hydrogen.h"
40 #include "objects-inl.h"
41 #include "objects-visiting.h"
42 #include "objects-visiting-inl.h"
43 #include "macro-assembler.h"
44 #include "mark-compact.h"
45 #include "safepoint-table.h"
46 #include "string-stream.h"
47 #include "utils.h"
48 #include "vm-state-inl.h"
49
50 #ifdef ENABLE_DISASSEMBLER
51 #include "disasm.h"
52 #include "disassembler.h"
53 #endif
54
55 namespace v8 {
56 namespace internal {
57
58 void PrintElementsKind(FILE* out, ElementsKind kind) {
59   switch (kind) {
60     case FAST_SMI_ONLY_ELEMENTS:
61       PrintF(out, "FAST_SMI_ONLY_ELEMENTS");
62       break;
63     case FAST_ELEMENTS:
64       PrintF(out, "FAST_ELEMENTS");
65       break;
66     case FAST_DOUBLE_ELEMENTS:
67       PrintF(out, "FAST_DOUBLE_ELEMENTS");
68       break;
69     case DICTIONARY_ELEMENTS:
70       PrintF(out, "DICTIONARY_ELEMENTS");
71       break;
72     case NON_STRICT_ARGUMENTS_ELEMENTS:
73       PrintF(out, "NON_STRICT_ARGUMENTS_ELEMENTS");
74       break;
75     case EXTERNAL_BYTE_ELEMENTS:
76       PrintF(out, "EXTERNAL_BYTE_ELEMENTS");
77       break;
78     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
79       PrintF(out, "EXTERNAL_UNSIGNED_BYTE_ELEMENTS");
80       break;
81     case EXTERNAL_SHORT_ELEMENTS:
82       PrintF(out, "EXTERNAL_SHORT_ELEMENTS");
83       break;
84     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
85       PrintF(out, "EXTERNAL_UNSIGNED_SHORT_ELEMENTS");
86       break;
87     case EXTERNAL_INT_ELEMENTS:
88       PrintF(out, "EXTERNAL_INT_ELEMENTS");
89       break;
90     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
91       PrintF(out, "EXTERNAL_UNSIGNED_INT_ELEMENTS");
92       break;
93     case EXTERNAL_FLOAT_ELEMENTS:
94       PrintF(out, "EXTERNAL_FLOAT_ELEMENTS");
95       break;
96     case EXTERNAL_DOUBLE_ELEMENTS:
97       PrintF(out, "EXTERNAL_DOUBLE_ELEMENTS");
98       break;
99     case EXTERNAL_PIXEL_ELEMENTS:
100       PrintF(out, "EXTERNAL_DOUBLE_ELEMENTS");
101       break;
102   }
103 }
104
105
106 // Getters and setters are stored in a fixed array property.  These are
107 // constants for their indices.
108 const int kGetterIndex = 0;
109 const int kSetterIndex = 1;
110
111 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
112                                                   Object* value) {
113   Object* result;
114   { MaybeObject* maybe_result =
115         constructor->GetHeap()->AllocateJSObject(constructor);
116     if (!maybe_result->ToObject(&result)) return maybe_result;
117   }
118   JSValue::cast(result)->set_value(value);
119   return result;
120 }
121
122
123 MaybeObject* Object::ToObject(Context* global_context) {
124   if (IsNumber()) {
125     return CreateJSValue(global_context->number_function(), this);
126   } else if (IsBoolean()) {
127     return CreateJSValue(global_context->boolean_function(), this);
128   } else if (IsString()) {
129     return CreateJSValue(global_context->string_function(), this);
130   }
131   ASSERT(IsJSObject());
132   return this;
133 }
134
135
136 MaybeObject* Object::ToObject() {
137   if (IsJSReceiver()) {
138     return this;
139   } else if (IsNumber()) {
140     Isolate* isolate = Isolate::Current();
141     Context* global_context = isolate->context()->global_context();
142     return CreateJSValue(global_context->number_function(), this);
143   } else if (IsBoolean()) {
144     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
145     Context* global_context = isolate->context()->global_context();
146     return CreateJSValue(global_context->boolean_function(), this);
147   } else if (IsString()) {
148     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
149     Context* global_context = isolate->context()->global_context();
150     return CreateJSValue(global_context->string_function(), this);
151   }
152
153   // Throw a type error.
154   return Failure::InternalError();
155 }
156
157
158 Object* Object::ToBoolean() {
159   if (IsTrue()) return this;
160   if (IsFalse()) return this;
161   if (IsSmi()) {
162     return Isolate::Current()->heap()->ToBoolean(Smi::cast(this)->value() != 0);
163   }
164   HeapObject* heap_object = HeapObject::cast(this);
165   if (heap_object->IsUndefined() || heap_object->IsNull()) {
166     return heap_object->GetHeap()->false_value();
167   }
168   // Undetectable object is false
169   if (heap_object->IsUndetectableObject()) {
170     return heap_object->GetHeap()->false_value();
171   }
172   if (heap_object->IsString()) {
173     return heap_object->GetHeap()->ToBoolean(
174         String::cast(this)->length() != 0);
175   }
176   if (heap_object->IsHeapNumber()) {
177     return HeapNumber::cast(this)->HeapNumberToBoolean();
178   }
179   return heap_object->GetHeap()->true_value();
180 }
181
182
183 void Object::Lookup(String* name, LookupResult* result) {
184   Object* holder = NULL;
185   if (IsJSReceiver()) {
186     holder = this;
187   } else {
188     Context* global_context = Isolate::Current()->context()->global_context();
189     if (IsNumber()) {
190       holder = global_context->number_function()->instance_prototype();
191     } else if (IsString()) {
192       holder = global_context->string_function()->instance_prototype();
193     } else if (IsBoolean()) {
194       holder = global_context->boolean_function()->instance_prototype();
195     }
196   }
197   ASSERT(holder != NULL);  // Cannot handle null or undefined.
198   JSReceiver::cast(holder)->Lookup(name, result);
199 }
200
201
202 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
203                                              String* name,
204                                              PropertyAttributes* attributes) {
205   LookupResult result(name->GetIsolate());
206   Lookup(name, &result);
207   MaybeObject* value = GetProperty(receiver, &result, name, attributes);
208   ASSERT(*attributes <= ABSENT);
209   return value;
210 }
211
212
213 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver,
214                                                Object* structure,
215                                                String* name) {
216   Isolate* isolate = name->GetIsolate();
217   // To accommodate both the old and the new api we switch on the
218   // data structure used to store the callbacks.  Eventually foreign
219   // callbacks should be phased out.
220   if (structure->IsForeign()) {
221     AccessorDescriptor* callback =
222         reinterpret_cast<AccessorDescriptor*>(
223             Foreign::cast(structure)->foreign_address());
224     MaybeObject* value = (callback->getter)(receiver, callback->data);
225     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
226     return value;
227   }
228
229   // api style callbacks.
230   if (structure->IsAccessorInfo()) {
231     AccessorInfo* data = AccessorInfo::cast(structure);
232     Object* fun_obj = data->getter();
233     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
234     HandleScope scope(isolate);
235     JSObject* self = JSObject::cast(receiver);
236     Handle<String> key(name);
237     LOG(isolate, ApiNamedPropertyAccess("load", self, name));
238     CustomArguments args(isolate, data->data(), self, this);
239     v8::AccessorInfo info(args.end());
240     v8::Handle<v8::Value> result;
241     {
242       // Leaving JavaScript.
243       VMState state(isolate, EXTERNAL);
244       result = call_fun(v8::Utils::ToLocal(key), info);
245     }
246     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
247     if (result.IsEmpty()) {
248       return isolate->heap()->undefined_value();
249     }
250     return *v8::Utils::OpenHandle(*result);
251   }
252
253   // __defineGetter__ callback
254   if (structure->IsFixedArray()) {
255     Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
256     if (getter->IsSpecFunction()) {
257       // TODO(rossberg): nicer would be to cast to some JSCallable here...
258       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
259     }
260     // Getter is not a function.
261     return isolate->heap()->undefined_value();
262   }
263
264   UNREACHABLE();
265   return NULL;
266 }
267
268
269 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
270                                              String* name_raw) {
271   Isolate* isolate = GetIsolate();
272   HandleScope scope(isolate);
273   Handle<Object> receiver(receiver_raw);
274   Handle<Object> name(name_raw);
275
276   Handle<Object> args[] = { receiver, name };
277   Handle<Object> result = CallTrap(
278     "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
279   if (isolate->has_pending_exception()) return Failure::Exception();
280
281   return *result;
282 }
283
284
285 Handle<Object> Object::GetElement(Handle<Object> object, uint32_t index) {
286   Isolate* isolate = object->IsHeapObject()
287       ? Handle<HeapObject>::cast(object)->GetIsolate()
288       : Isolate::Current();
289   CALL_HEAP_FUNCTION(isolate, object->GetElement(index), Object);
290 }
291
292
293 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
294                                             uint32_t index) {
295   String* name;
296   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
297   if (!maybe->To<String>(&name)) return maybe;
298   return GetPropertyWithHandler(receiver, name);
299 }
300
301
302 MaybeObject* JSProxy::SetElementWithHandler(uint32_t index,
303                                             Object* value,
304                                             StrictModeFlag strict_mode) {
305   String* name;
306   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
307   if (!maybe->To<String>(&name)) return maybe;
308   return SetPropertyWithHandler(name, value, NONE, strict_mode);
309 }
310
311
312 bool JSProxy::HasElementWithHandler(uint32_t index) {
313   String* name;
314   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
315   if (!maybe->To<String>(&name)) return maybe;
316   return HasPropertyWithHandler(name);
317 }
318
319
320 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver,
321                                                   JSReceiver* getter) {
322   HandleScope scope;
323   Handle<JSReceiver> fun(getter);
324   Handle<Object> self(receiver);
325 #ifdef ENABLE_DEBUGGER_SUPPORT
326   Debug* debug = fun->GetHeap()->isolate()->debug();
327   // Handle stepping into a getter if step into is active.
328   // TODO(rossberg): should this apply to getters that are function proxies?
329   if (debug->StepInActive() && fun->IsJSFunction()) {
330     debug->HandleStepIn(
331         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
332   }
333 #endif
334
335   bool has_pending_exception;
336   Handle<Object> result =
337       Execution::Call(fun, self, 0, NULL, &has_pending_exception);
338   // Check for pending exception and return the result.
339   if (has_pending_exception) return Failure::Exception();
340   return *result;
341 }
342
343
344 // Only deal with CALLBACKS and INTERCEPTOR
345 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck(
346     Object* receiver,
347     LookupResult* result,
348     String* name,
349     PropertyAttributes* attributes) {
350   if (result->IsProperty()) {
351     switch (result->type()) {
352       case CALLBACKS: {
353         // Only allow API accessors.
354         Object* obj = result->GetCallbackObject();
355         if (obj->IsAccessorInfo()) {
356           AccessorInfo* info = AccessorInfo::cast(obj);
357           if (info->all_can_read()) {
358             *attributes = result->GetAttributes();
359             return result->holder()->GetPropertyWithCallback(
360                 receiver, result->GetCallbackObject(), name);
361           }
362         }
363         break;
364       }
365       case NORMAL:
366       case FIELD:
367       case CONSTANT_FUNCTION: {
368         // Search ALL_CAN_READ accessors in prototype chain.
369         LookupResult r(GetIsolate());
370         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
371         if (r.IsProperty()) {
372           return GetPropertyWithFailedAccessCheck(receiver,
373                                                   &r,
374                                                   name,
375                                                   attributes);
376         }
377         break;
378       }
379       case INTERCEPTOR: {
380         // If the object has an interceptor, try real named properties.
381         // No access check in GetPropertyAttributeWithInterceptor.
382         LookupResult r(GetIsolate());
383         result->holder()->LookupRealNamedProperty(name, &r);
384         if (r.IsProperty()) {
385           return GetPropertyWithFailedAccessCheck(receiver,
386                                                   &r,
387                                                   name,
388                                                   attributes);
389         }
390         break;
391       }
392       default:
393         UNREACHABLE();
394     }
395   }
396
397   // No accessible property found.
398   *attributes = ABSENT;
399   Heap* heap = name->GetHeap();
400   heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET);
401   return heap->undefined_value();
402 }
403
404
405 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
406     Object* receiver,
407     LookupResult* result,
408     String* name,
409     bool continue_search) {
410   if (result->IsProperty()) {
411     switch (result->type()) {
412       case CALLBACKS: {
413         // Only allow API accessors.
414         Object* obj = result->GetCallbackObject();
415         if (obj->IsAccessorInfo()) {
416           AccessorInfo* info = AccessorInfo::cast(obj);
417           if (info->all_can_read()) {
418             return result->GetAttributes();
419           }
420         }
421         break;
422       }
423
424       case NORMAL:
425       case FIELD:
426       case CONSTANT_FUNCTION: {
427         if (!continue_search) break;
428         // Search ALL_CAN_READ accessors in prototype chain.
429         LookupResult r(GetIsolate());
430         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
431         if (r.IsProperty()) {
432           return GetPropertyAttributeWithFailedAccessCheck(receiver,
433                                                            &r,
434                                                            name,
435                                                            continue_search);
436         }
437         break;
438       }
439
440       case INTERCEPTOR: {
441         // If the object has an interceptor, try real named properties.
442         // No access check in GetPropertyAttributeWithInterceptor.
443         LookupResult r(GetIsolate());
444         if (continue_search) {
445           result->holder()->LookupRealNamedProperty(name, &r);
446         } else {
447           result->holder()->LocalLookupRealNamedProperty(name, &r);
448         }
449         if (r.IsProperty()) {
450           return GetPropertyAttributeWithFailedAccessCheck(receiver,
451                                                            &r,
452                                                            name,
453                                                            continue_search);
454         }
455         break;
456       }
457
458       default:
459         UNREACHABLE();
460     }
461   }
462
463   GetIsolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
464   return ABSENT;
465 }
466
467
468 Object* JSObject::GetNormalizedProperty(LookupResult* result) {
469   ASSERT(!HasFastProperties());
470   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
471   if (IsGlobalObject()) {
472     value = JSGlobalPropertyCell::cast(value)->value();
473   }
474   ASSERT(!value->IsJSGlobalPropertyCell());
475   return value;
476 }
477
478
479 Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
480   ASSERT(!HasFastProperties());
481   if (IsGlobalObject()) {
482     JSGlobalPropertyCell* cell =
483         JSGlobalPropertyCell::cast(
484             property_dictionary()->ValueAt(result->GetDictionaryEntry()));
485     cell->set_value(value);
486   } else {
487     property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
488   }
489   return value;
490 }
491
492
493 MaybeObject* JSObject::SetNormalizedProperty(String* name,
494                                              Object* value,
495                                              PropertyDetails details) {
496   ASSERT(!HasFastProperties());
497   int entry = property_dictionary()->FindEntry(name);
498   if (entry == StringDictionary::kNotFound) {
499     Object* store_value = value;
500     if (IsGlobalObject()) {
501       Heap* heap = name->GetHeap();
502       MaybeObject* maybe_store_value =
503           heap->AllocateJSGlobalPropertyCell(value);
504       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
505     }
506     Object* dict;
507     { MaybeObject* maybe_dict =
508           property_dictionary()->Add(name, store_value, details);
509       if (!maybe_dict->ToObject(&dict)) return maybe_dict;
510     }
511     set_properties(StringDictionary::cast(dict));
512     return value;
513   }
514   // Preserve enumeration index.
515   details = PropertyDetails(details.attributes(),
516                             details.type(),
517                             property_dictionary()->DetailsAt(entry).index());
518   if (IsGlobalObject()) {
519     JSGlobalPropertyCell* cell =
520         JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
521     cell->set_value(value);
522     // Please note we have to update the property details.
523     property_dictionary()->DetailsAtPut(entry, details);
524   } else {
525     property_dictionary()->SetEntry(entry, name, value, details);
526   }
527   return value;
528 }
529
530
531 MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
532   ASSERT(!HasFastProperties());
533   StringDictionary* dictionary = property_dictionary();
534   int entry = dictionary->FindEntry(name);
535   if (entry != StringDictionary::kNotFound) {
536     // If we have a global object set the cell to the hole.
537     if (IsGlobalObject()) {
538       PropertyDetails details = dictionary->DetailsAt(entry);
539       if (details.IsDontDelete()) {
540         if (mode != FORCE_DELETION) return GetHeap()->false_value();
541         // When forced to delete global properties, we have to make a
542         // map change to invalidate any ICs that think they can load
543         // from the DontDelete cell without checking if it contains
544         // the hole value.
545         Object* new_map;
546         { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
547           if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
548         }
549         set_map(Map::cast(new_map));
550       }
551       JSGlobalPropertyCell* cell =
552           JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
553       cell->set_value(cell->GetHeap()->the_hole_value());
554       dictionary->DetailsAtPut(entry, details.AsDeleted());
555     } else {
556       Object* deleted = dictionary->DeleteProperty(entry, mode);
557       if (deleted == GetHeap()->true_value()) {
558         FixedArray* new_properties = NULL;
559         MaybeObject* maybe_properties = dictionary->Shrink(name);
560         if (!maybe_properties->To(&new_properties)) {
561           return maybe_properties;
562         }
563         set_properties(new_properties);
564       }
565       return deleted;
566     }
567   }
568   return GetHeap()->true_value();
569 }
570
571
572 bool JSObject::IsDirty() {
573   Object* cons_obj = map()->constructor();
574   if (!cons_obj->IsJSFunction())
575     return true;
576   JSFunction* fun = JSFunction::cast(cons_obj);
577   if (!fun->shared()->IsApiFunction())
578     return true;
579   // If the object is fully fast case and has the same map it was
580   // created with then no changes can have been made to it.
581   return map() != fun->initial_map()
582       || !HasFastElements()
583       || !HasFastProperties();
584 }
585
586
587 Handle<Object> Object::GetProperty(Handle<Object> object,
588                                    Handle<Object> receiver,
589                                    LookupResult* result,
590                                    Handle<String> key,
591                                    PropertyAttributes* attributes) {
592   Isolate* isolate = object->IsHeapObject()
593       ? Handle<HeapObject>::cast(object)->GetIsolate()
594       : Isolate::Current();
595   CALL_HEAP_FUNCTION(
596       isolate,
597       object->GetProperty(*receiver, result, *key, attributes),
598       Object);
599 }
600
601
602 MaybeObject* Object::GetProperty(Object* receiver,
603                                  LookupResult* result,
604                                  String* name,
605                                  PropertyAttributes* attributes) {
606   // Make sure that the top context does not change when doing
607   // callbacks or interceptor calls.
608   AssertNoContextChange ncc;
609   Heap* heap = name->GetHeap();
610
611   // Traverse the prototype chain from the current object (this) to
612   // the holder and check for access rights. This avoids traversing the
613   // objects more than once in case of interceptors, because the
614   // holder will always be the interceptor holder and the search may
615   // only continue with a current object just after the interceptor
616   // holder in the prototype chain.
617   // Proxy handlers do not use the proxy's prototype, so we can skip this.
618   if (!result->IsHandler()) {
619     Object* last = result->IsProperty()
620         ? result->holder()
621         : Object::cast(heap->null_value());
622     ASSERT(this != this->GetPrototype());
623     for (Object* current = this; true; current = current->GetPrototype()) {
624       if (current->IsAccessCheckNeeded()) {
625         // Check if we're allowed to read from the current object. Note
626         // that even though we may not actually end up loading the named
627         // property from the current object, we still check that we have
628         // access to it.
629         JSObject* checked = JSObject::cast(current);
630         if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
631           return checked->GetPropertyWithFailedAccessCheck(receiver,
632                                                            result,
633                                                            name,
634                                                            attributes);
635         }
636       }
637       // Stop traversing the chain once we reach the last object in the
638       // chain; either the holder of the result or null in case of an
639       // absent property.
640       if (current == last) break;
641     }
642   }
643
644   if (!result->IsProperty()) {
645     *attributes = ABSENT;
646     return heap->undefined_value();
647   }
648   *attributes = result->GetAttributes();
649   Object* value;
650   switch (result->type()) {
651     case NORMAL:
652       value = result->holder()->GetNormalizedProperty(result);
653       ASSERT(!value->IsTheHole() || result->IsReadOnly());
654       return value->IsTheHole() ? heap->undefined_value() : value;
655     case FIELD:
656       value = result->holder()->FastPropertyAt(result->GetFieldIndex());
657       ASSERT(!value->IsTheHole() || result->IsReadOnly());
658       return value->IsTheHole() ? heap->undefined_value() : value;
659     case CONSTANT_FUNCTION:
660       return result->GetConstantFunction();
661     case CALLBACKS:
662       return result->holder()->GetPropertyWithCallback(
663           receiver, result->GetCallbackObject(), name);
664     case HANDLER:
665       return result->proxy()->GetPropertyWithHandler(receiver, name);
666     case INTERCEPTOR: {
667       JSObject* recvr = JSObject::cast(receiver);
668       return result->holder()->GetPropertyWithInterceptor(
669           recvr, name, attributes);
670     }
671     case MAP_TRANSITION:
672     case ELEMENTS_TRANSITION:
673     case CONSTANT_TRANSITION:
674     case NULL_DESCRIPTOR:
675       break;
676   }
677   UNREACHABLE();
678   return NULL;
679 }
680
681
682 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
683   Heap* heap = IsSmi()
684       ? Isolate::Current()->heap()
685       : HeapObject::cast(this)->GetHeap();
686   Object* holder = this;
687
688   // Iterate up the prototype chain until an element is found or the null
689   // prototype is encountered.
690   for (holder = this;
691        holder != heap->null_value();
692        holder = holder->GetPrototype()) {
693     if (!holder->IsJSObject()) {
694       Isolate* isolate = heap->isolate();
695       Context* global_context = isolate->context()->global_context();
696       if (holder->IsNumber()) {
697         holder = global_context->number_function()->instance_prototype();
698       } else if (holder->IsString()) {
699         holder = global_context->string_function()->instance_prototype();
700       } else if (holder->IsBoolean()) {
701         holder = global_context->boolean_function()->instance_prototype();
702       } else if (holder->IsJSProxy()) {
703         return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
704       } else {
705         // Undefined and null have no indexed properties.
706         ASSERT(holder->IsUndefined() || holder->IsNull());
707         return heap->undefined_value();
708       }
709     }
710
711     // Inline the case for JSObjects. Doing so significantly improves the
712     // performance of fetching elements where checking the prototype chain is
713     // necessary.
714     JSObject* js_object = JSObject::cast(holder);
715
716     // Check access rights if needed.
717     if (js_object->IsAccessCheckNeeded()) {
718       Isolate* isolate = heap->isolate();
719       if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
720         isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
721         return heap->undefined_value();
722       }
723     }
724
725     if (js_object->HasIndexedInterceptor()) {
726       return js_object->GetElementWithInterceptor(receiver, index);
727     }
728
729     if (js_object->elements() != heap->empty_fixed_array()) {
730       MaybeObject* result = js_object->GetElementsAccessor()->Get(
731           js_object->elements(),
732           index,
733           js_object,
734           receiver);
735       if (result != heap->the_hole_value()) return result;
736     }
737   }
738
739   return heap->undefined_value();
740 }
741
742
743 Object* Object::GetPrototype() {
744   if (IsSmi()) {
745     Heap* heap = Isolate::Current()->heap();
746     Context* context = heap->isolate()->context()->global_context();
747     return context->number_function()->instance_prototype();
748   }
749
750   HeapObject* heap_object = HeapObject::cast(this);
751
752   // The object is either a number, a string, a boolean,
753   // a real JS object, or a Harmony proxy.
754   if (heap_object->IsJSReceiver()) {
755     return heap_object->map()->prototype();
756   }
757   Heap* heap = heap_object->GetHeap();
758   Context* context = heap->isolate()->context()->global_context();
759
760   if (heap_object->IsHeapNumber()) {
761     return context->number_function()->instance_prototype();
762   }
763   if (heap_object->IsString()) {
764     return context->string_function()->instance_prototype();
765   }
766   if (heap_object->IsBoolean()) {
767     return context->boolean_function()->instance_prototype();
768   } else {
769     return heap->null_value();
770   }
771 }
772
773
774 MaybeObject* Object::GetHash(CreationFlag flag) {
775   // The object is either a number, a string, an odd-ball,
776   // a real JS object, or a Harmony proxy.
777   if (IsNumber()) {
778     uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
779     return Smi::FromInt(hash & Smi::kMaxValue);
780   }
781   if (IsString()) {
782     uint32_t hash = String::cast(this)->Hash();
783     return Smi::FromInt(hash);
784   }
785   if (IsOddball()) {
786     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
787     return Smi::FromInt(hash);
788   }
789   if (IsJSReceiver()) {
790     return JSReceiver::cast(this)->GetIdentityHash(flag);
791   }
792
793   UNREACHABLE();
794   return Smi::FromInt(0);
795 }
796
797
798 bool Object::SameValue(Object* other) {
799   if (other == this) return true;
800   if (!IsHeapObject() || !other->IsHeapObject()) return false;
801
802   // The object is either a number, a string, an odd-ball,
803   // a real JS object, or a Harmony proxy.
804   if (IsNumber() && other->IsNumber()) {
805     double this_value = Number();
806     double other_value = other->Number();
807     return (this_value == other_value) ||
808         (isnan(this_value) && isnan(other_value));
809   }
810   if (IsString() && other->IsString()) {
811     return String::cast(this)->Equals(String::cast(other));
812   }
813   return false;
814 }
815
816
817 void Object::ShortPrint(FILE* out) {
818   HeapStringAllocator allocator;
819   StringStream accumulator(&allocator);
820   ShortPrint(&accumulator);
821   accumulator.OutputToFile(out);
822 }
823
824
825 void Object::ShortPrint(StringStream* accumulator) {
826   if (IsSmi()) {
827     Smi::cast(this)->SmiPrint(accumulator);
828   } else if (IsFailure()) {
829     Failure::cast(this)->FailurePrint(accumulator);
830   } else {
831     HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
832   }
833 }
834
835
836 void Smi::SmiPrint(FILE* out) {
837   PrintF(out, "%d", value());
838 }
839
840
841 void Smi::SmiPrint(StringStream* accumulator) {
842   accumulator->Add("%d", value());
843 }
844
845
846 void Failure::FailurePrint(StringStream* accumulator) {
847   accumulator->Add("Failure(%p)", reinterpret_cast<void*>(value()));
848 }
849
850
851 void Failure::FailurePrint(FILE* out) {
852   PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
853 }
854
855
856 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
857 // English?  Returns false for non-ASCII or words that don't start with
858 // a capital letter.  The a/an rule follows pronunciation in English.
859 // We don't use the BBC's overcorrect "an historic occasion" though if
860 // you speak a dialect you may well say "an 'istoric occasion".
861 static bool AnWord(String* str) {
862   if (str->length() == 0) return false;  // A nothing.
863   int c0 = str->Get(0);
864   int c1 = str->length() > 1 ? str->Get(1) : 0;
865   if (c0 == 'U') {
866     if (c1 > 'Z') {
867       return true;  // An Umpire, but a UTF8String, a U.
868     }
869   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
870     return true;    // An Ape, an ABCBook.
871   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
872            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
873             c0 == 'S' || c0 == 'X')) {
874     return true;    // An MP3File, an M.
875   }
876   return false;
877 }
878
879
880 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
881 #ifdef DEBUG
882   // Do not attempt to flatten in debug mode when allocation is not
883   // allowed.  This is to avoid an assertion failure when allocating.
884   // Flattening strings is the only case where we always allow
885   // allocation because no GC is performed if the allocation fails.
886   if (!HEAP->IsAllocationAllowed()) return this;
887 #endif
888
889   Heap* heap = GetHeap();
890   switch (StringShape(this).representation_tag()) {
891     case kConsStringTag: {
892       ConsString* cs = ConsString::cast(this);
893       if (cs->second()->length() == 0) {
894         return cs->first();
895       }
896       // There's little point in putting the flat string in new space if the
897       // cons string is in old space.  It can never get GCed until there is
898       // an old space GC.
899       PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
900       int len = length();
901       Object* object;
902       String* result;
903       if (IsAsciiRepresentation()) {
904         { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure);
905           if (!maybe_object->ToObject(&object)) return maybe_object;
906         }
907         result = String::cast(object);
908         String* first = cs->first();
909         int first_length = first->length();
910         char* dest = SeqAsciiString::cast(result)->GetChars();
911         WriteToFlat(first, dest, 0, first_length);
912         String* second = cs->second();
913         WriteToFlat(second,
914                     dest + first_length,
915                     0,
916                     len - first_length);
917       } else {
918         { MaybeObject* maybe_object =
919               heap->AllocateRawTwoByteString(len, tenure);
920           if (!maybe_object->ToObject(&object)) return maybe_object;
921         }
922         result = String::cast(object);
923         uc16* dest = SeqTwoByteString::cast(result)->GetChars();
924         String* first = cs->first();
925         int first_length = first->length();
926         WriteToFlat(first, dest, 0, first_length);
927         String* second = cs->second();
928         WriteToFlat(second,
929                     dest + first_length,
930                     0,
931                     len - first_length);
932       }
933       cs->set_first(result);
934       cs->set_second(heap->empty_string());
935       return result;
936     }
937     default:
938       return this;
939   }
940 }
941
942
943 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
944   // Externalizing twice leaks the external resource, so it's
945   // prohibited by the API.
946   ASSERT(!this->IsExternalString());
947 #ifdef DEBUG
948   if (FLAG_enable_slow_asserts) {
949     // Assert that the resource and the string are equivalent.
950     ASSERT(static_cast<size_t>(this->length()) == resource->length());
951     ScopedVector<uc16> smart_chars(this->length());
952     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
953     ASSERT(memcmp(smart_chars.start(),
954                   resource->data(),
955                   resource->length() * sizeof(smart_chars[0])) == 0);
956   }
957 #endif  // DEBUG
958   Heap* heap = GetHeap();
959   int size = this->Size();  // Byte size of the original string.
960   if (size < ExternalString::kSize) {
961     // The string is too small to fit an external String in its place. This can
962     // only happen for zero length strings.
963     return false;
964   }
965   ASSERT(size >= ExternalString::kSize);
966   bool is_ascii = this->IsAsciiRepresentation();
967   bool is_symbol = this->IsSymbol();
968   int length = this->length();
969   int hash_field = this->hash_field();
970
971   // Morph the object to an external string by adjusting the map and
972   // reinitializing the fields.
973   this->set_map(is_ascii ?
974                 heap->external_string_with_ascii_data_map() :
975                 heap->external_string_map());
976   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
977   self->set_length(length);
978   self->set_hash_field(hash_field);
979   self->set_resource(resource);
980   // Additionally make the object into an external symbol if the original string
981   // was a symbol to start with.
982   if (is_symbol) {
983     self->Hash();  // Force regeneration of the hash value.
984     // Now morph this external string into a external symbol.
985     this->set_map(is_ascii ?
986                   heap->external_symbol_with_ascii_data_map() :
987                   heap->external_symbol_map());
988   }
989
990   // Fill the remainder of the string with dead wood.
991   int new_size = this->Size();  // Byte size of the external String object.
992   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
993   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
994     MemoryChunk::IncrementLiveBytes(this->address(), new_size - size);
995   }
996   return true;
997 }
998
999
1000 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
1001 #ifdef DEBUG
1002   if (FLAG_enable_slow_asserts) {
1003     // Assert that the resource and the string are equivalent.
1004     ASSERT(static_cast<size_t>(this->length()) == resource->length());
1005     ScopedVector<char> smart_chars(this->length());
1006     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1007     ASSERT(memcmp(smart_chars.start(),
1008                   resource->data(),
1009                   resource->length() * sizeof(smart_chars[0])) == 0);
1010   }
1011 #endif  // DEBUG
1012   Heap* heap = GetHeap();
1013   int size = this->Size();  // Byte size of the original string.
1014   if (size < ExternalString::kSize) {
1015     // The string is too small to fit an external String in its place. This can
1016     // only happen for zero length strings.
1017     return false;
1018   }
1019   ASSERT(size >= ExternalString::kSize);
1020   bool is_symbol = this->IsSymbol();
1021   int length = this->length();
1022   int hash_field = this->hash_field();
1023
1024   // Morph the object to an external string by adjusting the map and
1025   // reinitializing the fields.
1026   this->set_map(heap->external_ascii_string_map());
1027   ExternalAsciiString* self = ExternalAsciiString::cast(this);
1028   self->set_length(length);
1029   self->set_hash_field(hash_field);
1030   self->set_resource(resource);
1031   // Additionally make the object into an external symbol if the original string
1032   // was a symbol to start with.
1033   if (is_symbol) {
1034     self->Hash();  // Force regeneration of the hash value.
1035     // Now morph this external string into a external symbol.
1036     this->set_map(heap->external_ascii_symbol_map());
1037   }
1038
1039   // Fill the remainder of the string with dead wood.
1040   int new_size = this->Size();  // Byte size of the external String object.
1041   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1042   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
1043     MemoryChunk::IncrementLiveBytes(this->address(), new_size - size);
1044   }
1045
1046   return true;
1047 }
1048
1049
1050 void String::StringShortPrint(StringStream* accumulator) {
1051   int len = length();
1052   if (len > kMaxShortPrintLength) {
1053     accumulator->Add("<Very long string[%u]>", len);
1054     return;
1055   }
1056
1057   if (!LooksValid()) {
1058     accumulator->Add("<Invalid String>");
1059     return;
1060   }
1061
1062   StringInputBuffer buf(this);
1063
1064   bool truncated = false;
1065   if (len > kMaxShortPrintLength) {
1066     len = kMaxShortPrintLength;
1067     truncated = true;
1068   }
1069   bool ascii = true;
1070   for (int i = 0; i < len; i++) {
1071     int c = buf.GetNext();
1072
1073     if (c < 32 || c >= 127) {
1074       ascii = false;
1075     }
1076   }
1077   buf.Reset(this);
1078   if (ascii) {
1079     accumulator->Add("<String[%u]: ", length());
1080     for (int i = 0; i < len; i++) {
1081       accumulator->Put(buf.GetNext());
1082     }
1083     accumulator->Put('>');
1084   } else {
1085     // Backslash indicates that the string contains control
1086     // characters and that backslashes are therefore escaped.
1087     accumulator->Add("<String[%u]\\: ", length());
1088     for (int i = 0; i < len; i++) {
1089       int c = buf.GetNext();
1090       if (c == '\n') {
1091         accumulator->Add("\\n");
1092       } else if (c == '\r') {
1093         accumulator->Add("\\r");
1094       } else if (c == '\\') {
1095         accumulator->Add("\\\\");
1096       } else if (c < 32 || c > 126) {
1097         accumulator->Add("\\x%02x", c);
1098       } else {
1099         accumulator->Put(c);
1100       }
1101     }
1102     if (truncated) {
1103       accumulator->Put('.');
1104       accumulator->Put('.');
1105       accumulator->Put('.');
1106     }
1107     accumulator->Put('>');
1108   }
1109   return;
1110 }
1111
1112
1113 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1114   switch (map()->instance_type()) {
1115     case JS_ARRAY_TYPE: {
1116       double length = JSArray::cast(this)->length()->Number();
1117       accumulator->Add("<JS array[%u]>", static_cast<uint32_t>(length));
1118       break;
1119     }
1120     case JS_WEAK_MAP_TYPE: {
1121       accumulator->Add("<JS WeakMap>");
1122       break;
1123     }
1124     case JS_REGEXP_TYPE: {
1125       accumulator->Add("<JS RegExp>");
1126       break;
1127     }
1128     case JS_FUNCTION_TYPE: {
1129       Object* fun_name = JSFunction::cast(this)->shared()->name();
1130       bool printed = false;
1131       if (fun_name->IsString()) {
1132         String* str = String::cast(fun_name);
1133         if (str->length() > 0) {
1134           accumulator->Add("<JS Function ");
1135           accumulator->Put(str);
1136           accumulator->Put('>');
1137           printed = true;
1138         }
1139       }
1140       if (!printed) {
1141         accumulator->Add("<JS Function>");
1142       }
1143       break;
1144     }
1145     // All other JSObjects are rather similar to each other (JSObject,
1146     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1147     default: {
1148       Map* map_of_this = map();
1149       Heap* heap = GetHeap();
1150       Object* constructor = map_of_this->constructor();
1151       bool printed = false;
1152       if (constructor->IsHeapObject() &&
1153           !heap->Contains(HeapObject::cast(constructor))) {
1154         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1155       } else {
1156         bool global_object = IsJSGlobalProxy();
1157         if (constructor->IsJSFunction()) {
1158           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1159             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1160           } else {
1161             Object* constructor_name =
1162                 JSFunction::cast(constructor)->shared()->name();
1163             if (constructor_name->IsString()) {
1164               String* str = String::cast(constructor_name);
1165               if (str->length() > 0) {
1166                 bool vowel = AnWord(str);
1167                 accumulator->Add("<%sa%s ",
1168                        global_object ? "Global Object: " : "",
1169                        vowel ? "n" : "");
1170                 accumulator->Put(str);
1171                 printed = true;
1172               }
1173             }
1174           }
1175         }
1176         if (!printed) {
1177           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1178         }
1179       }
1180       if (IsJSValue()) {
1181         accumulator->Add(" value = ");
1182         JSValue::cast(this)->value()->ShortPrint(accumulator);
1183       }
1184       accumulator->Put('>');
1185       break;
1186     }
1187   }
1188 }
1189
1190
1191 void JSObject::PrintElementsTransition(
1192     FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
1193     ElementsKind to_kind, FixedArrayBase* to_elements) {
1194   if (from_kind != to_kind) {
1195     PrintF(file, "elements transition [");
1196     PrintElementsKind(file, from_kind);
1197     PrintF(file, " -> ");
1198     PrintElementsKind(file, to_kind);
1199     PrintF(file, "] in ");
1200     JavaScriptFrame::PrintTop(file, false, true);
1201     PrintF(file, " for ");
1202     ShortPrint(file);
1203     PrintF(file, " from ");
1204     from_elements->ShortPrint(file);
1205     PrintF(file, " to ");
1206     to_elements->ShortPrint(file);
1207     PrintF(file, "\n");
1208   }
1209 }
1210
1211
1212 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
1213   Heap* heap = GetHeap();
1214   if (!heap->Contains(this)) {
1215     accumulator->Add("!!!INVALID POINTER!!!");
1216     return;
1217   }
1218   if (!heap->Contains(map())) {
1219     accumulator->Add("!!!INVALID MAP!!!");
1220     return;
1221   }
1222
1223   accumulator->Add("%p ", this);
1224
1225   if (IsString()) {
1226     String::cast(this)->StringShortPrint(accumulator);
1227     return;
1228   }
1229   if (IsJSObject()) {
1230     JSObject::cast(this)->JSObjectShortPrint(accumulator);
1231     return;
1232   }
1233   switch (map()->instance_type()) {
1234     case MAP_TYPE:
1235       accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind());
1236       break;
1237     case FIXED_ARRAY_TYPE:
1238       accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
1239       break;
1240     case FIXED_DOUBLE_ARRAY_TYPE:
1241       accumulator->Add("<FixedDoubleArray[%u]>",
1242                        FixedDoubleArray::cast(this)->length());
1243       break;
1244     case BYTE_ARRAY_TYPE:
1245       accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
1246       break;
1247     case FREE_SPACE_TYPE:
1248       accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size());
1249       break;
1250     case EXTERNAL_PIXEL_ARRAY_TYPE:
1251       accumulator->Add("<ExternalPixelArray[%u]>",
1252                        ExternalPixelArray::cast(this)->length());
1253       break;
1254     case EXTERNAL_BYTE_ARRAY_TYPE:
1255       accumulator->Add("<ExternalByteArray[%u]>",
1256                        ExternalByteArray::cast(this)->length());
1257       break;
1258     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1259       accumulator->Add("<ExternalUnsignedByteArray[%u]>",
1260                        ExternalUnsignedByteArray::cast(this)->length());
1261       break;
1262     case EXTERNAL_SHORT_ARRAY_TYPE:
1263       accumulator->Add("<ExternalShortArray[%u]>",
1264                        ExternalShortArray::cast(this)->length());
1265       break;
1266     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1267       accumulator->Add("<ExternalUnsignedShortArray[%u]>",
1268                        ExternalUnsignedShortArray::cast(this)->length());
1269       break;
1270     case EXTERNAL_INT_ARRAY_TYPE:
1271       accumulator->Add("<ExternalIntArray[%u]>",
1272                        ExternalIntArray::cast(this)->length());
1273       break;
1274     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1275       accumulator->Add("<ExternalUnsignedIntArray[%u]>",
1276                        ExternalUnsignedIntArray::cast(this)->length());
1277       break;
1278     case EXTERNAL_FLOAT_ARRAY_TYPE:
1279       accumulator->Add("<ExternalFloatArray[%u]>",
1280                        ExternalFloatArray::cast(this)->length());
1281       break;
1282     case EXTERNAL_DOUBLE_ARRAY_TYPE:
1283       accumulator->Add("<ExternalDoubleArray[%u]>",
1284                        ExternalDoubleArray::cast(this)->length());
1285       break;
1286     case SHARED_FUNCTION_INFO_TYPE:
1287       accumulator->Add("<SharedFunctionInfo>");
1288       break;
1289     case JS_MESSAGE_OBJECT_TYPE:
1290       accumulator->Add("<JSMessageObject>");
1291       break;
1292 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1293   case NAME##_TYPE:                        \
1294     accumulator->Put('<');                 \
1295     accumulator->Add(#Name);               \
1296     accumulator->Put('>');                 \
1297     break;
1298   STRUCT_LIST(MAKE_STRUCT_CASE)
1299 #undef MAKE_STRUCT_CASE
1300     case CODE_TYPE:
1301       accumulator->Add("<Code>");
1302       break;
1303     case ODDBALL_TYPE: {
1304       if (IsUndefined())
1305         accumulator->Add("<undefined>");
1306       else if (IsTheHole())
1307         accumulator->Add("<the hole>");
1308       else if (IsNull())
1309         accumulator->Add("<null>");
1310       else if (IsTrue())
1311         accumulator->Add("<true>");
1312       else if (IsFalse())
1313         accumulator->Add("<false>");
1314       else
1315         accumulator->Add("<Odd Oddball>");
1316       break;
1317     }
1318     case HEAP_NUMBER_TYPE:
1319       accumulator->Add("<Number: ");
1320       HeapNumber::cast(this)->HeapNumberPrint(accumulator);
1321       accumulator->Put('>');
1322       break;
1323     case JS_PROXY_TYPE:
1324       accumulator->Add("<JSProxy>");
1325       break;
1326     case JS_FUNCTION_PROXY_TYPE:
1327       accumulator->Add("<JSFunctionProxy>");
1328       break;
1329     case FOREIGN_TYPE:
1330       accumulator->Add("<Foreign>");
1331       break;
1332     case JS_GLOBAL_PROPERTY_CELL_TYPE:
1333       accumulator->Add("Cell for ");
1334       JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
1335       break;
1336     default:
1337       accumulator->Add("<Other heap object (%d)>", map()->instance_type());
1338       break;
1339   }
1340 }
1341
1342
1343 void HeapObject::Iterate(ObjectVisitor* v) {
1344   // Handle header
1345   IteratePointer(v, kMapOffset);
1346   // Handle object body
1347   Map* m = map();
1348   IterateBody(m->instance_type(), SizeFromMap(m), v);
1349 }
1350
1351
1352 void HeapObject::IterateBody(InstanceType type, int object_size,
1353                              ObjectVisitor* v) {
1354   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1355   // During GC, the map pointer field is encoded.
1356   if (type < FIRST_NONSTRING_TYPE) {
1357     switch (type & kStringRepresentationMask) {
1358       case kSeqStringTag:
1359         break;
1360       case kConsStringTag:
1361         ConsString::BodyDescriptor::IterateBody(this, v);
1362         break;
1363       case kSlicedStringTag:
1364         SlicedString::BodyDescriptor::IterateBody(this, v);
1365         break;
1366       case kExternalStringTag:
1367         if ((type & kStringEncodingMask) == kAsciiStringTag) {
1368           reinterpret_cast<ExternalAsciiString*>(this)->
1369               ExternalAsciiStringIterateBody(v);
1370         } else {
1371           reinterpret_cast<ExternalTwoByteString*>(this)->
1372               ExternalTwoByteStringIterateBody(v);
1373         }
1374         break;
1375     }
1376     return;
1377   }
1378
1379   switch (type) {
1380     case FIXED_ARRAY_TYPE:
1381       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1382       break;
1383     case FIXED_DOUBLE_ARRAY_TYPE:
1384       break;
1385     case JS_OBJECT_TYPE:
1386     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1387     case JS_VALUE_TYPE:
1388     case JS_ARRAY_TYPE:
1389     case JS_SET_TYPE:
1390     case JS_MAP_TYPE:
1391     case JS_WEAK_MAP_TYPE:
1392     case JS_REGEXP_TYPE:
1393     case JS_GLOBAL_PROXY_TYPE:
1394     case JS_GLOBAL_OBJECT_TYPE:
1395     case JS_BUILTINS_OBJECT_TYPE:
1396     case JS_MESSAGE_OBJECT_TYPE:
1397       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1398       break;
1399     case JS_FUNCTION_TYPE:
1400       reinterpret_cast<JSFunction*>(this)
1401           ->JSFunctionIterateBody(object_size, v);
1402       break;
1403     case ODDBALL_TYPE:
1404       Oddball::BodyDescriptor::IterateBody(this, v);
1405       break;
1406     case JS_PROXY_TYPE:
1407       JSProxy::BodyDescriptor::IterateBody(this, v);
1408       break;
1409     case JS_FUNCTION_PROXY_TYPE:
1410       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1411       break;
1412     case FOREIGN_TYPE:
1413       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1414       break;
1415     case MAP_TYPE:
1416       Map::BodyDescriptor::IterateBody(this, v);
1417       break;
1418     case CODE_TYPE:
1419       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1420       break;
1421     case JS_GLOBAL_PROPERTY_CELL_TYPE:
1422       JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v);
1423       break;
1424     case HEAP_NUMBER_TYPE:
1425     case FILLER_TYPE:
1426     case BYTE_ARRAY_TYPE:
1427     case FREE_SPACE_TYPE:
1428     case EXTERNAL_PIXEL_ARRAY_TYPE:
1429     case EXTERNAL_BYTE_ARRAY_TYPE:
1430     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1431     case EXTERNAL_SHORT_ARRAY_TYPE:
1432     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1433     case EXTERNAL_INT_ARRAY_TYPE:
1434     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1435     case EXTERNAL_FLOAT_ARRAY_TYPE:
1436     case EXTERNAL_DOUBLE_ARRAY_TYPE:
1437       break;
1438     case SHARED_FUNCTION_INFO_TYPE:
1439       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1440       break;
1441
1442 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1443         case NAME##_TYPE:
1444       STRUCT_LIST(MAKE_STRUCT_CASE)
1445 #undef MAKE_STRUCT_CASE
1446       StructBodyDescriptor::IterateBody(this, object_size, v);
1447       break;
1448     default:
1449       PrintF("Unknown type: %d\n", type);
1450       UNREACHABLE();
1451   }
1452 }
1453
1454
1455 Object* HeapNumber::HeapNumberToBoolean() {
1456   // NaN, +0, and -0 should return the false object
1457 #if __BYTE_ORDER == __LITTLE_ENDIAN
1458   union IeeeDoubleLittleEndianArchType u;
1459 #elif __BYTE_ORDER == __BIG_ENDIAN
1460   union IeeeDoubleBigEndianArchType u;
1461 #endif
1462   u.d = value();
1463   if (u.bits.exp == 2047) {
1464     // Detect NaN for IEEE double precision floating point.
1465     if ((u.bits.man_low | u.bits.man_high) != 0)
1466       return GetHeap()->false_value();
1467   }
1468   if (u.bits.exp == 0) {
1469     // Detect +0, and -0 for IEEE double precision floating point.
1470     if ((u.bits.man_low | u.bits.man_high) == 0)
1471       return GetHeap()->false_value();
1472   }
1473   return GetHeap()->true_value();
1474 }
1475
1476
1477 void HeapNumber::HeapNumberPrint(FILE* out) {
1478   PrintF(out, "%.16g", Number());
1479 }
1480
1481
1482 void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
1483   // The Windows version of vsnprintf can allocate when printing a %g string
1484   // into a buffer that may not be big enough.  We don't want random memory
1485   // allocation when producing post-crash stack traces, so we print into a
1486   // buffer that is plenty big enough for any floating point number, then
1487   // print that using vsnprintf (which may truncate but never allocate if
1488   // there is no more space in the buffer).
1489   EmbeddedVector<char, 100> buffer;
1490   OS::SNPrintF(buffer, "%.16g", Number());
1491   accumulator->Add("%s", buffer.start());
1492 }
1493
1494
1495 String* JSReceiver::class_name() {
1496   if (IsJSFunction() && IsJSFunctionProxy()) {
1497     return GetHeap()->function_class_symbol();
1498   }
1499   if (map()->constructor()->IsJSFunction()) {
1500     JSFunction* constructor = JSFunction::cast(map()->constructor());
1501     return String::cast(constructor->shared()->instance_class_name());
1502   }
1503   // If the constructor is not present, return "Object".
1504   return GetHeap()->Object_symbol();
1505 }
1506
1507
1508 String* JSReceiver::constructor_name() {
1509   if (map()->constructor()->IsJSFunction()) {
1510     JSFunction* constructor = JSFunction::cast(map()->constructor());
1511     String* name = String::cast(constructor->shared()->name());
1512     if (name->length() > 0) return name;
1513     String* inferred_name = constructor->shared()->inferred_name();
1514     if (inferred_name->length() > 0) return inferred_name;
1515     Object* proto = GetPrototype();
1516     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1517   }
1518   // TODO(rossberg): what about proxies?
1519   // If the constructor is not present, return "Object".
1520   return GetHeap()->Object_symbol();
1521 }
1522
1523
1524 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
1525                                                String* name,
1526                                                Object* value) {
1527   int index = new_map->PropertyIndexFor(name);
1528   if (map()->unused_property_fields() == 0) {
1529     ASSERT(map()->unused_property_fields() == 0);
1530     int new_unused = new_map->unused_property_fields();
1531     Object* values;
1532     { MaybeObject* maybe_values =
1533           properties()->CopySize(properties()->length() + new_unused + 1);
1534       if (!maybe_values->ToObject(&values)) return maybe_values;
1535     }
1536     set_properties(FixedArray::cast(values));
1537   }
1538   set_map(new_map);
1539   return FastPropertyAtPut(index, value);
1540 }
1541
1542
1543 static bool IsIdentifier(UnicodeCache* cache,
1544                          unibrow::CharacterStream* buffer) {
1545   // Checks whether the buffer contains an identifier (no escape).
1546   if (!buffer->has_more()) return false;
1547   if (!cache->IsIdentifierStart(buffer->GetNext())) {
1548     return false;
1549   }
1550   while (buffer->has_more()) {
1551     if (!cache->IsIdentifierPart(buffer->GetNext())) {
1552       return false;
1553     }
1554   }
1555   return true;
1556 }
1557
1558
1559 MaybeObject* JSObject::AddFastProperty(String* name,
1560                                        Object* value,
1561                                        PropertyAttributes attributes) {
1562   ASSERT(!IsJSGlobalProxy());
1563
1564   // Normalize the object if the name is an actual string (not the
1565   // hidden symbols) and is not a real identifier.
1566   Isolate* isolate = GetHeap()->isolate();
1567   StringInputBuffer buffer(name);
1568   if (!IsIdentifier(isolate->unicode_cache(), &buffer)
1569       && name != isolate->heap()->hidden_symbol()) {
1570     Object* obj;
1571     { MaybeObject* maybe_obj =
1572           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1573       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1574     }
1575     return AddSlowProperty(name, value, attributes);
1576   }
1577
1578   DescriptorArray* old_descriptors = map()->instance_descriptors();
1579   // Compute the new index for new field.
1580   int index = map()->NextFreePropertyIndex();
1581
1582   // Allocate new instance descriptors with (name, index) added
1583   FieldDescriptor new_field(name, index, attributes);
1584   Object* new_descriptors;
1585   { MaybeObject* maybe_new_descriptors =
1586         old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
1587     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1588       return maybe_new_descriptors;
1589     }
1590   }
1591
1592   // Only allow map transition if the object isn't the global object and there
1593   // is not a transition for the name, or there's a transition for the name but
1594   // it's unrelated to properties.
1595   int descriptor_index = old_descriptors->Search(name);
1596
1597   // Element transitions are stored in the descriptor for property "", which is
1598   // not a identifier and should have forced a switch to slow properties above.
1599   ASSERT(descriptor_index == DescriptorArray::kNotFound ||
1600       old_descriptors->GetType(descriptor_index) != ELEMENTS_TRANSITION);
1601   bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound ||
1602       old_descriptors->GetType(descriptor_index) == ELEMENTS_TRANSITION;
1603   bool allow_map_transition =
1604       can_insert_transition &&
1605       (isolate->context()->global_context()->object_function()->map() != map());
1606
1607   ASSERT(index < map()->inobject_properties() ||
1608          (index - map()->inobject_properties()) < properties()->length() ||
1609          map()->unused_property_fields() == 0);
1610   // Allocate a new map for the object.
1611   Object* r;
1612   { MaybeObject* maybe_r = map()->CopyDropDescriptors();
1613     if (!maybe_r->ToObject(&r)) return maybe_r;
1614   }
1615   Map* new_map = Map::cast(r);
1616   if (allow_map_transition) {
1617     // Allocate new instance descriptors for the old map with map transition.
1618     MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
1619     Object* r;
1620     { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
1621       if (!maybe_r->ToObject(&r)) return maybe_r;
1622     }
1623     old_descriptors = DescriptorArray::cast(r);
1624   }
1625
1626   if (map()->unused_property_fields() == 0) {
1627     if (properties()->length() > MaxFastProperties()) {
1628       Object* obj;
1629       { MaybeObject* maybe_obj =
1630             NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1631         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1632       }
1633       return AddSlowProperty(name, value, attributes);
1634     }
1635     // Make room for the new value
1636     Object* values;
1637     { MaybeObject* maybe_values =
1638           properties()->CopySize(properties()->length() + kFieldsAdded);
1639       if (!maybe_values->ToObject(&values)) return maybe_values;
1640     }
1641     set_properties(FixedArray::cast(values));
1642     new_map->set_unused_property_fields(kFieldsAdded - 1);
1643   } else {
1644     new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
1645   }
1646   // We have now allocated all the necessary objects.
1647   // All the changes can be applied at once, so they are atomic.
1648   map()->set_instance_descriptors(old_descriptors);
1649   new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1650   set_map(new_map);
1651   return FastPropertyAtPut(index, value);
1652 }
1653
1654
1655 MaybeObject* JSObject::AddConstantFunctionProperty(
1656     String* name,
1657     JSFunction* function,
1658     PropertyAttributes attributes) {
1659   ASSERT(!GetHeap()->InNewSpace(function));
1660
1661   // Allocate new instance descriptors with (name, function) added
1662   ConstantFunctionDescriptor d(name, function, attributes);
1663   Object* new_descriptors;
1664   { MaybeObject* maybe_new_descriptors =
1665         map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS);
1666     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1667       return maybe_new_descriptors;
1668     }
1669   }
1670
1671   // Allocate a new map for the object.
1672   Object* new_map;
1673   { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
1674     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1675   }
1676
1677   DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
1678   Map::cast(new_map)->set_instance_descriptors(descriptors);
1679   Map* old_map = map();
1680   set_map(Map::cast(new_map));
1681
1682   // If the old map is the global object map (from new Object()),
1683   // then transitions are not added to it, so we are done.
1684   Heap* heap = GetHeap();
1685   if (old_map == heap->isolate()->context()->global_context()->
1686       object_function()->map()) {
1687     return function;
1688   }
1689
1690   // Do not add CONSTANT_TRANSITIONS to global objects
1691   if (IsGlobalObject()) {
1692     return function;
1693   }
1694
1695   // Add a CONSTANT_TRANSITION descriptor to the old map,
1696   // so future assignments to this property on other objects
1697   // of the same type will create a normal field, not a constant function.
1698   // Don't do this for special properties, with non-trival attributes.
1699   if (attributes != NONE) {
1700     return function;
1701   }
1702   ConstTransitionDescriptor mark(name, Map::cast(new_map));
1703   { MaybeObject* maybe_new_descriptors =
1704         old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS);
1705     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1706       // We have accomplished the main goal, so return success.
1707       return function;
1708     }
1709   }
1710   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1711
1712   return function;
1713 }
1714
1715
1716 // Add property in slow mode
1717 MaybeObject* JSObject::AddSlowProperty(String* name,
1718                                        Object* value,
1719                                        PropertyAttributes attributes) {
1720   ASSERT(!HasFastProperties());
1721   StringDictionary* dict = property_dictionary();
1722   Object* store_value = value;
1723   if (IsGlobalObject()) {
1724     // In case name is an orphaned property reuse the cell.
1725     int entry = dict->FindEntry(name);
1726     if (entry != StringDictionary::kNotFound) {
1727       store_value = dict->ValueAt(entry);
1728       JSGlobalPropertyCell::cast(store_value)->set_value(value);
1729       // Assign an enumeration index to the property and update
1730       // SetNextEnumerationIndex.
1731       int index = dict->NextEnumerationIndex();
1732       PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
1733       dict->SetNextEnumerationIndex(index + 1);
1734       dict->SetEntry(entry, name, store_value, details);
1735       return value;
1736     }
1737     Heap* heap = GetHeap();
1738     { MaybeObject* maybe_store_value =
1739           heap->AllocateJSGlobalPropertyCell(value);
1740       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
1741     }
1742     JSGlobalPropertyCell::cast(store_value)->set_value(value);
1743   }
1744   PropertyDetails details = PropertyDetails(attributes, NORMAL);
1745   Object* result;
1746   { MaybeObject* maybe_result = dict->Add(name, store_value, details);
1747     if (!maybe_result->ToObject(&result)) return maybe_result;
1748   }
1749   if (dict != result) set_properties(StringDictionary::cast(result));
1750   return value;
1751 }
1752
1753
1754 MaybeObject* JSObject::AddProperty(String* name,
1755                                    Object* value,
1756                                    PropertyAttributes attributes,
1757                                    StrictModeFlag strict_mode) {
1758   ASSERT(!IsJSGlobalProxy());
1759   Map* map_of_this = map();
1760   Heap* heap = GetHeap();
1761   if (!map_of_this->is_extensible()) {
1762     if (strict_mode == kNonStrictMode) {
1763       return heap->undefined_value();
1764     } else {
1765       Handle<Object> args[1] = {Handle<String>(name)};
1766       return heap->isolate()->Throw(
1767           *FACTORY->NewTypeError("object_not_extensible",
1768                                  HandleVector(args, 1)));
1769     }
1770   }
1771   if (HasFastProperties()) {
1772     // Ensure the descriptor array does not get too big.
1773     if (map_of_this->instance_descriptors()->number_of_descriptors() <
1774         DescriptorArray::kMaxNumberOfDescriptors) {
1775       if (value->IsJSFunction() && !heap->InNewSpace(value)) {
1776         return AddConstantFunctionProperty(name,
1777                                            JSFunction::cast(value),
1778                                            attributes);
1779       } else {
1780         return AddFastProperty(name, value, attributes);
1781       }
1782     } else {
1783       // Normalize the object to prevent very large instance descriptors.
1784       // This eliminates unwanted N^2 allocation and lookup behavior.
1785       Object* obj;
1786       { MaybeObject* maybe_obj =
1787             NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1788         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1789       }
1790     }
1791   }
1792   return AddSlowProperty(name, value, attributes);
1793 }
1794
1795
1796 MaybeObject* JSObject::SetPropertyPostInterceptor(
1797     String* name,
1798     Object* value,
1799     PropertyAttributes attributes,
1800     StrictModeFlag strict_mode) {
1801   // Check local property, ignore interceptor.
1802   LookupResult result(GetIsolate());
1803   LocalLookupRealNamedProperty(name, &result);
1804   if (result.IsFound()) {
1805     // An existing property, a map transition or a null descriptor was
1806     // found.  Use set property to handle all these cases.
1807     return SetProperty(&result, name, value, attributes, strict_mode);
1808   }
1809   bool found = false;
1810   MaybeObject* result_object;
1811   result_object = SetPropertyWithCallbackSetterInPrototypes(name,
1812                                                             value,
1813                                                             attributes,
1814                                                             &found,
1815                                                             strict_mode);
1816   if (found) return result_object;
1817   // Add a new real property.
1818   return AddProperty(name, value, attributes, strict_mode);
1819 }
1820
1821
1822 MaybeObject* JSObject::ReplaceSlowProperty(String* name,
1823                                            Object* value,
1824                                            PropertyAttributes attributes) {
1825   StringDictionary* dictionary = property_dictionary();
1826   int old_index = dictionary->FindEntry(name);
1827   int new_enumeration_index = 0;  // 0 means "Use the next available index."
1828   if (old_index != -1) {
1829     // All calls to ReplaceSlowProperty have had all transitions removed.
1830     ASSERT(!dictionary->DetailsAt(old_index).IsTransition());
1831     new_enumeration_index = dictionary->DetailsAt(old_index).index();
1832   }
1833
1834   PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
1835   return SetNormalizedProperty(name, value, new_details);
1836 }
1837
1838
1839 MaybeObject* JSObject::ConvertDescriptorToFieldAndMapTransition(
1840     String* name,
1841     Object* new_value,
1842     PropertyAttributes attributes) {
1843   Map* old_map = map();
1844   Object* result;
1845   { MaybeObject* maybe_result =
1846         ConvertDescriptorToField(name, new_value, attributes);
1847     if (!maybe_result->ToObject(&result)) return maybe_result;
1848   }
1849   // If we get to this point we have succeeded - do not return failure
1850   // after this point.  Later stuff is optional.
1851   if (!HasFastProperties()) {
1852     return result;
1853   }
1854   // Do not add transitions to the map of "new Object()".
1855   if (map() == GetIsolate()->context()->global_context()->
1856       object_function()->map()) {
1857     return result;
1858   }
1859
1860   MapTransitionDescriptor transition(name,
1861                                      map(),
1862                                      attributes);
1863   Object* new_descriptors;
1864   { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()->
1865         CopyInsert(&transition, KEEP_TRANSITIONS);
1866     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1867       return result;  // Yes, return _result_.
1868     }
1869   }
1870   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1871   return result;
1872 }
1873
1874
1875 MaybeObject* JSObject::ConvertDescriptorToField(String* name,
1876                                                 Object* new_value,
1877                                                 PropertyAttributes attributes) {
1878   if (map()->unused_property_fields() == 0 &&
1879       properties()->length() > MaxFastProperties()) {
1880     Object* obj;
1881     { MaybeObject* maybe_obj =
1882           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1883       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1884     }
1885     return ReplaceSlowProperty(name, new_value, attributes);
1886   }
1887
1888   int index = map()->NextFreePropertyIndex();
1889   FieldDescriptor new_field(name, index, attributes);
1890   // Make a new DescriptorArray replacing an entry with FieldDescriptor.
1891   Object* descriptors_unchecked;
1892   { MaybeObject* maybe_descriptors_unchecked = map()->instance_descriptors()->
1893                                   CopyInsert(&new_field, REMOVE_TRANSITIONS);
1894     if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
1895       return maybe_descriptors_unchecked;
1896     }
1897   }
1898   DescriptorArray* new_descriptors =
1899       DescriptorArray::cast(descriptors_unchecked);
1900
1901   // Make a new map for the object.
1902   Object* new_map_unchecked;
1903   { MaybeObject* maybe_new_map_unchecked = map()->CopyDropDescriptors();
1904     if (!maybe_new_map_unchecked->ToObject(&new_map_unchecked)) {
1905       return maybe_new_map_unchecked;
1906     }
1907   }
1908   Map* new_map = Map::cast(new_map_unchecked);
1909   new_map->set_instance_descriptors(new_descriptors);
1910
1911   // Make new properties array if necessary.
1912   FixedArray* new_properties = 0;  // Will always be NULL or a valid pointer.
1913   int new_unused_property_fields = map()->unused_property_fields() - 1;
1914   if (map()->unused_property_fields() == 0) {
1915     new_unused_property_fields = kFieldsAdded - 1;
1916     Object* new_properties_object;
1917     { MaybeObject* maybe_new_properties_object =
1918           properties()->CopySize(properties()->length() + kFieldsAdded);
1919       if (!maybe_new_properties_object->ToObject(&new_properties_object)) {
1920         return maybe_new_properties_object;
1921       }
1922     }
1923     new_properties = FixedArray::cast(new_properties_object);
1924   }
1925
1926   // Update pointers to commit changes.
1927   // Object points to the new map.
1928   new_map->set_unused_property_fields(new_unused_property_fields);
1929   set_map(new_map);
1930   if (new_properties) {
1931     set_properties(FixedArray::cast(new_properties));
1932   }
1933   return FastPropertyAtPut(index, new_value);
1934 }
1935
1936
1937
1938 MaybeObject* JSObject::SetPropertyWithInterceptor(
1939     String* name,
1940     Object* value,
1941     PropertyAttributes attributes,
1942     StrictModeFlag strict_mode) {
1943   Isolate* isolate = GetIsolate();
1944   HandleScope scope(isolate);
1945   Handle<JSObject> this_handle(this);
1946   Handle<String> name_handle(name);
1947   Handle<Object> value_handle(value, isolate);
1948   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
1949   if (!interceptor->setter()->IsUndefined()) {
1950     LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name));
1951     CustomArguments args(isolate, interceptor->data(), this, this);
1952     v8::AccessorInfo info(args.end());
1953     v8::NamedPropertySetter setter =
1954         v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
1955     v8::Handle<v8::Value> result;
1956     {
1957       // Leaving JavaScript.
1958       VMState state(isolate, EXTERNAL);
1959       Handle<Object> value_unhole(value->IsTheHole() ?
1960                                   isolate->heap()->undefined_value() :
1961                                   value,
1962                                   isolate);
1963       result = setter(v8::Utils::ToLocal(name_handle),
1964                       v8::Utils::ToLocal(value_unhole),
1965                       info);
1966     }
1967     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1968     if (!result.IsEmpty()) return *value_handle;
1969   }
1970   MaybeObject* raw_result =
1971       this_handle->SetPropertyPostInterceptor(*name_handle,
1972                                               *value_handle,
1973                                               attributes,
1974                                               strict_mode);
1975   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1976   return raw_result;
1977 }
1978
1979
1980 MaybeObject* JSReceiver::SetProperty(String* name,
1981                                      Object* value,
1982                                      PropertyAttributes attributes,
1983                                      StrictModeFlag strict_mode,
1984                                      bool skip_fallback_interceptor) {
1985   LookupResult result(GetIsolate());
1986   LocalLookup(name, &result, skip_fallback_interceptor);
1987   return SetProperty(&result, name, value, attributes, strict_mode);
1988 }
1989
1990
1991 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
1992                                                String* name,
1993                                                Object* value,
1994                                                JSObject* holder,
1995                                                StrictModeFlag strict_mode) {
1996   Isolate* isolate = GetIsolate();
1997   HandleScope scope(isolate);
1998
1999   // We should never get here to initialize a const with the hole
2000   // value since a const declaration would conflict with the setter.
2001   ASSERT(!value->IsTheHole());
2002   Handle<Object> value_handle(value, isolate);
2003
2004   // To accommodate both the old and the new api we switch on the
2005   // data structure used to store the callbacks.  Eventually foreign
2006   // callbacks should be phased out.
2007   if (structure->IsForeign()) {
2008     AccessorDescriptor* callback =
2009         reinterpret_cast<AccessorDescriptor*>(
2010             Foreign::cast(structure)->foreign_address());
2011     MaybeObject* obj = (callback->setter)(this,  value, callback->data);
2012     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
2013     if (obj->IsFailure()) return obj;
2014     return *value_handle;
2015   }
2016
2017   if (structure->IsAccessorInfo()) {
2018     // api style callbacks
2019     AccessorInfo* data = AccessorInfo::cast(structure);
2020     Object* call_obj = data->setter();
2021     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
2022     if (call_fun == NULL) return value;
2023     Handle<String> key(name);
2024     LOG(isolate, ApiNamedPropertyAccess("store", this, name));
2025     CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
2026     v8::AccessorInfo info(args.end());
2027     {
2028       // Leaving JavaScript.
2029       VMState state(isolate, EXTERNAL);
2030       call_fun(v8::Utils::ToLocal(key),
2031                v8::Utils::ToLocal(value_handle),
2032                info);
2033     }
2034     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
2035     return *value_handle;
2036   }
2037
2038   if (structure->IsFixedArray()) {
2039     Object* setter = FixedArray::cast(structure)->get(kSetterIndex);
2040     if (setter->IsSpecFunction()) {
2041       // TODO(rossberg): nicer would be to cast to some JSCallable here...
2042      return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
2043     } else {
2044       if (strict_mode == kNonStrictMode) {
2045         return value;
2046       }
2047       Handle<String> key(name);
2048       Handle<Object> holder_handle(holder, isolate);
2049       Handle<Object> args[2] = { key, holder_handle };
2050       return isolate->Throw(
2051           *isolate->factory()->NewTypeError("no_setter_in_callback",
2052                                             HandleVector(args, 2)));
2053     }
2054   }
2055
2056   UNREACHABLE();
2057   return NULL;
2058 }
2059
2060
2061 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter,
2062                                                       Object* value) {
2063   Isolate* isolate = GetIsolate();
2064   Handle<Object> value_handle(value, isolate);
2065   Handle<JSReceiver> fun(setter, isolate);
2066   Handle<JSReceiver> self(this, isolate);
2067 #ifdef ENABLE_DEBUGGER_SUPPORT
2068   Debug* debug = isolate->debug();
2069   // Handle stepping into a setter if step into is active.
2070   // TODO(rossberg): should this apply to getters that are function proxies?
2071   if (debug->StepInActive() && fun->IsJSFunction()) {
2072     debug->HandleStepIn(
2073         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
2074   }
2075 #endif
2076   bool has_pending_exception;
2077   Handle<Object> argv[] = { value_handle };
2078   Execution::Call(fun, self, ARRAY_SIZE(argv), argv, &has_pending_exception);
2079   // Check for pending exception and return the result.
2080   if (has_pending_exception) return Failure::Exception();
2081   return *value_handle;
2082 }
2083
2084
2085 void JSObject::LookupCallbackSetterInPrototypes(String* name,
2086                                                 LookupResult* result) {
2087   Heap* heap = GetHeap();
2088   for (Object* pt = GetPrototype();
2089        pt != heap->null_value();
2090        pt = pt->GetPrototype()) {
2091     if (pt->IsJSProxy()) {
2092       return result->HandlerResult(JSProxy::cast(pt));
2093     }
2094     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
2095     if (result->IsProperty()) {
2096       if (result->type() == CALLBACKS && !result->IsReadOnly()) return;
2097       // Found non-callback or read-only callback, stop looking.
2098       break;
2099     }
2100   }
2101   result->NotFound();
2102 }
2103
2104
2105 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
2106     uint32_t index,
2107     Object* value,
2108     bool* found,
2109     StrictModeFlag strict_mode) {
2110   Heap* heap = GetHeap();
2111   for (Object* pt = GetPrototype();
2112        pt != heap->null_value();
2113        pt = pt->GetPrototype()) {
2114     if (pt->IsJSProxy()) {
2115       String* name;
2116       MaybeObject* maybe = GetHeap()->Uint32ToString(index);
2117       if (!maybe->To<String>(&name)) {
2118         *found = true;  // Force abort
2119         return maybe;
2120       }
2121       return JSProxy::cast(pt)->SetPropertyWithHandlerIfDefiningSetter(
2122           name, value, NONE, strict_mode, found);
2123     }
2124     if (!JSObject::cast(pt)->HasDictionaryElements()) {
2125       continue;
2126     }
2127     NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
2128     int entry = dictionary->FindEntry(index);
2129     if (entry != NumberDictionary::kNotFound) {
2130       PropertyDetails details = dictionary->DetailsAt(entry);
2131       if (details.type() == CALLBACKS) {
2132         *found = true;
2133         return SetElementWithCallback(dictionary->ValueAt(entry),
2134                                       index,
2135                                       value,
2136                                       JSObject::cast(pt),
2137                                       strict_mode);
2138       }
2139     }
2140   }
2141   *found = false;
2142   return heap->the_hole_value();
2143 }
2144
2145 MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes(
2146     String* name,
2147     Object* value,
2148     PropertyAttributes attributes,
2149     bool* found,
2150     StrictModeFlag strict_mode) {
2151   Heap* heap = GetHeap();
2152   // We could not find a local property so let's check whether there is an
2153   // accessor that wants to handle the property.
2154   LookupResult accessor_result(heap->isolate());
2155   LookupCallbackSetterInPrototypes(name, &accessor_result);
2156   if (accessor_result.IsFound()) {
2157     *found = true;
2158     if (accessor_result.type() == CALLBACKS) {
2159       return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
2160                                      name,
2161                                      value,
2162                                      accessor_result.holder(),
2163                                      strict_mode);
2164     } else if (accessor_result.type() == HANDLER) {
2165       // There is a proxy in the prototype chain. Invoke its
2166       // getPropertyDescriptor trap.
2167       bool found = false;
2168       // SetPropertyWithHandlerIfDefiningSetter can cause GC,
2169       // make sure to use the handlified references after calling
2170       // the function.
2171       Handle<JSObject> self(this);
2172       Handle<String> hname(name);
2173       Handle<Object> hvalue(value);
2174       MaybeObject* result =
2175           accessor_result.proxy()->SetPropertyWithHandlerIfDefiningSetter(
2176               name, value, attributes, strict_mode, &found);
2177       if (found) return result;
2178       // The proxy does not define the property as an accessor.
2179       // Consequently, it has no effect on setting the receiver.
2180       return self->AddProperty(*hname, *hvalue, attributes, strict_mode);
2181     }
2182   }
2183   *found = false;
2184   return heap->the_hole_value();
2185 }
2186
2187
2188 void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
2189   DescriptorArray* descriptors = map()->instance_descriptors();
2190   int number = descriptors->SearchWithCache(name);
2191   if (number != DescriptorArray::kNotFound) {
2192     result->DescriptorResult(this, descriptors->GetDetails(number), number);
2193   } else {
2194     result->NotFound();
2195   }
2196 }
2197
2198
2199 void Map::LookupInDescriptors(JSObject* holder,
2200                               String* name,
2201                               LookupResult* result) {
2202   DescriptorArray* descriptors = instance_descriptors();
2203   DescriptorLookupCache* cache =
2204       GetHeap()->isolate()->descriptor_lookup_cache();
2205   int number = cache->Lookup(descriptors, name);
2206   if (number == DescriptorLookupCache::kAbsent) {
2207     number = descriptors->Search(name);
2208     cache->Update(descriptors, name, number);
2209   }
2210   if (number != DescriptorArray::kNotFound) {
2211     result->DescriptorResult(holder, descriptors->GetDetails(number), number);
2212   } else {
2213     result->NotFound();
2214   }
2215 }
2216
2217
2218 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
2219   ASSERT(!map.is_null());
2220   for (int i = 0; i < maps->length(); ++i) {
2221     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
2222   }
2223   return false;
2224 }
2225
2226
2227 template <class T>
2228 static Handle<T> MaybeNull(T* p) {
2229   if (p == NULL) return Handle<T>::null();
2230   return Handle<T>(p);
2231 }
2232
2233
2234 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
2235   ElementsKind elms_kind = elements_kind();
2236   if (elms_kind == FAST_DOUBLE_ELEMENTS) {
2237     bool dummy = true;
2238     Handle<Map> fast_map =
2239         MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy));
2240     if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
2241       return fast_map;
2242     }
2243     return Handle<Map>::null();
2244   }
2245   if (elms_kind == FAST_SMI_ONLY_ELEMENTS) {
2246     bool dummy = true;
2247     Handle<Map> double_map =
2248         MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy));
2249     // In the current implementation, if the DOUBLE map doesn't exist, the
2250     // FAST map can't exist either.
2251     if (double_map.is_null()) return Handle<Map>::null();
2252     Handle<Map> fast_map =
2253         MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
2254                                                           &dummy));
2255     if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
2256       return fast_map;
2257     }
2258     if (ContainsMap(candidates, double_map)) return double_map;
2259   }
2260   return Handle<Map>::null();
2261 }
2262
2263 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents,
2264                                                    ElementsKind elements_kind) {
2265   if (descriptor_contents->IsMap()) {
2266     Map* map = Map::cast(descriptor_contents);
2267     if (map->elements_kind() == elements_kind) {
2268       return map;
2269     }
2270     return NULL;
2271   }
2272
2273   FixedArray* map_array = FixedArray::cast(descriptor_contents);
2274   for (int i = 0; i < map_array->length(); ++i) {
2275     Object* current = map_array->get(i);
2276     // Skip undefined slots, they are sentinels for reclaimed maps.
2277     if (!current->IsUndefined()) {
2278       Map* current_map = Map::cast(map_array->get(i));
2279       if (current_map->elements_kind() == elements_kind) {
2280         return current_map;
2281       }
2282     }
2283   }
2284
2285   return NULL;
2286 }
2287
2288
2289 static MaybeObject* AddElementsTransitionMapToDescriptor(
2290     Object* descriptor_contents,
2291     Map* new_map) {
2292   // Nothing was in the descriptor for an ELEMENTS_TRANSITION,
2293   // simply add the map.
2294   if (descriptor_contents == NULL) {
2295     return new_map;
2296   }
2297
2298   // There was already a map in the descriptor, create a 2-element FixedArray
2299   // to contain the existing map plus the new one.
2300   FixedArray* new_array;
2301   Heap* heap = new_map->GetHeap();
2302   if (descriptor_contents->IsMap()) {
2303     // Must tenure, DescriptorArray expects no new-space objects.
2304     MaybeObject* maybe_new_array = heap->AllocateFixedArray(2, TENURED);
2305     if (!maybe_new_array->To<FixedArray>(&new_array)) {
2306       return maybe_new_array;
2307     }
2308     new_array->set(0, descriptor_contents);
2309     new_array->set(1, new_map);
2310     return new_array;
2311   }
2312
2313   // The descriptor already contained a list of maps for different ElementKinds
2314   // of ELEMENTS_TRANSITION, first check the existing array for an undefined
2315   // slot, and if that's not available, create a FixedArray to hold the existing
2316   // maps plus the new one and fill it in.
2317   FixedArray* array = FixedArray::cast(descriptor_contents);
2318   for (int i = 0; i < array->length(); ++i) {
2319     if (array->get(i)->IsUndefined()) {
2320       array->set(i, new_map);
2321       return array;
2322     }
2323   }
2324
2325   // Must tenure, DescriptorArray expects no new-space objects.
2326   MaybeObject* maybe_new_array =
2327       heap->AllocateFixedArray(array->length() + 1, TENURED);
2328   if (!maybe_new_array->To<FixedArray>(&new_array)) {
2329     return maybe_new_array;
2330   }
2331   int i = 0;
2332   while (i < array->length()) {
2333     new_array->set(i, array->get(i));
2334     ++i;
2335   }
2336   new_array->set(i, new_map);
2337   return new_array;
2338 }
2339
2340
2341 String* Map::elements_transition_sentinel_name() {
2342   return GetHeap()->empty_symbol();
2343 }
2344
2345
2346 Object* Map::GetDescriptorContents(String* sentinel_name,
2347                                    bool* safe_to_add_transition) {
2348   // Get the cached index for the descriptors lookup, or find and cache it.
2349   DescriptorArray* descriptors = instance_descriptors();
2350   DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
2351   int index = cache->Lookup(descriptors, sentinel_name);
2352   if (index == DescriptorLookupCache::kAbsent) {
2353     index = descriptors->Search(sentinel_name);
2354     cache->Update(descriptors, sentinel_name, index);
2355   }
2356   // If the transition already exists, return its descriptor.
2357   if (index != DescriptorArray::kNotFound) {
2358     PropertyDetails details(descriptors->GetDetails(index));
2359     if (details.type() == ELEMENTS_TRANSITION) {
2360       return descriptors->GetValue(index);
2361     } else {
2362       *safe_to_add_transition = false;
2363     }
2364   }
2365   return NULL;
2366 }
2367
2368
2369 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind,
2370                                       bool* safe_to_add_transition) {
2371   // Special case: indirect SMI->FAST transition (cf. comment in
2372   // AddElementsTransition()).
2373   if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2374       elements_kind == FAST_ELEMENTS) {
2375     Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
2376                                                         safe_to_add_transition);
2377     if (double_map == NULL) return double_map;
2378     return double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
2379                                                    safe_to_add_transition);
2380   }
2381   Object* descriptor_contents = GetDescriptorContents(
2382       elements_transition_sentinel_name(), safe_to_add_transition);
2383   if (descriptor_contents != NULL) {
2384     Map* maybe_transition_map =
2385         GetElementsTransitionMapFromDescriptor(descriptor_contents,
2386                                                elements_kind);
2387     ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap());
2388     return maybe_transition_map;
2389   }
2390   return NULL;
2391 }
2392
2393
2394 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind,
2395                                         Map* transitioned_map) {
2396   // The map transition graph should be a tree, therefore the transition
2397   // from SMI to FAST elements is not done directly, but by going through
2398   // DOUBLE elements first.
2399   if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2400       elements_kind == FAST_ELEMENTS) {
2401     bool safe_to_add = true;
2402     Map* double_map = this->LookupElementsTransitionMap(
2403         FAST_DOUBLE_ELEMENTS, &safe_to_add);
2404     // This method is only called when safe_to_add_transition has been found
2405     // to be true earlier.
2406     ASSERT(safe_to_add);
2407
2408     if (double_map == NULL) {
2409       MaybeObject* maybe_map = this->CopyDropTransitions();
2410       if (!maybe_map->To(&double_map)) return maybe_map;
2411       double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
2412       MaybeObject* maybe_double_transition = this->AddElementsTransition(
2413           FAST_DOUBLE_ELEMENTS, double_map);
2414       if (maybe_double_transition->IsFailure()) return maybe_double_transition;
2415     }
2416     return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map);
2417   }
2418
2419   bool safe_to_add_transition = true;
2420   Object* descriptor_contents = GetDescriptorContents(
2421       elements_transition_sentinel_name(), &safe_to_add_transition);
2422   // This method is only called when safe_to_add_transition has been found
2423   // to be true earlier.
2424   ASSERT(safe_to_add_transition);
2425   MaybeObject* maybe_new_contents =
2426       AddElementsTransitionMapToDescriptor(descriptor_contents,
2427                                            transitioned_map);
2428   Object* new_contents;
2429   if (!maybe_new_contents->ToObject(&new_contents)) {
2430     return maybe_new_contents;
2431   }
2432
2433   ElementsTransitionDescriptor desc(elements_transition_sentinel_name(),
2434                                     new_contents);
2435   Object* new_descriptors;
2436   MaybeObject* maybe_new_descriptors =
2437       instance_descriptors()->CopyInsert(&desc, KEEP_TRANSITIONS);
2438   if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
2439     return maybe_new_descriptors;
2440   }
2441   set_instance_descriptors(DescriptorArray::cast(new_descriptors));
2442   return this;
2443 }
2444
2445
2446 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
2447                                                ElementsKind to_kind) {
2448   Isolate* isolate = object->GetIsolate();
2449   CALL_HEAP_FUNCTION(isolate,
2450                      object->GetElementsTransitionMap(to_kind),
2451                      Map);
2452 }
2453
2454
2455 MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind to_kind) {
2456   Map* current_map = map();
2457   ElementsKind from_kind = current_map->elements_kind();
2458
2459   if (from_kind == to_kind) return current_map;
2460
2461   // Only objects with FastProperties can have DescriptorArrays and can track
2462   // element-related maps. Also don't add descriptors to maps that are shared.
2463   bool safe_to_add_transition = HasFastProperties() &&
2464       !current_map->IsUndefined() &&
2465       !current_map->is_shared();
2466
2467   // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects
2468   // with elements that switch back and forth between dictionary and fast
2469   // element mode.
2470   if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) {
2471     safe_to_add_transition = false;
2472   }
2473
2474   if (safe_to_add_transition) {
2475     // It's only safe to manipulate the descriptor array if it would be
2476     // safe to add a transition.
2477     Map* maybe_transition_map = current_map->LookupElementsTransitionMap(
2478         to_kind, &safe_to_add_transition);
2479     if (maybe_transition_map != NULL) {
2480       return maybe_transition_map;
2481     }
2482   }
2483
2484   Map* new_map = NULL;
2485
2486   // No transition to an existing map for the given ElementsKind. Make a new
2487   // one.
2488   { MaybeObject* maybe_map = current_map->CopyDropTransitions();
2489     if (!maybe_map->To(&new_map)) return maybe_map;
2490   }
2491
2492   new_map->set_elements_kind(to_kind);
2493
2494   // Only remember the map transition if the object's map is NOT equal to the
2495   // global object_function's map and there is not an already existing
2496   // non-matching element transition.
2497   bool allow_map_transition = safe_to_add_transition &&
2498       (GetIsolate()->context()->global_context()->object_function()->map() !=
2499        map());
2500   if (allow_map_transition) {
2501     MaybeObject* maybe_transition =
2502         current_map->AddElementsTransition(to_kind, new_map);
2503     if (maybe_transition->IsFailure()) return maybe_transition;
2504   }
2505   return new_map;
2506 }
2507
2508
2509 void JSObject::LocalLookupRealNamedProperty(String* name,
2510                                             LookupResult* result) {
2511   if (IsJSGlobalProxy()) {
2512     Object* proto = GetPrototype();
2513     if (proto->IsNull()) return result->NotFound();
2514     ASSERT(proto->IsJSGlobalObject());
2515     // A GlobalProxy's prototype should always be a proper JSObject.
2516     return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
2517   }
2518
2519   if (HasFastProperties()) {
2520     LookupInDescriptor(name, result);
2521     if (result->IsFound()) {
2522       // A property, a map transition or a null descriptor was found.
2523       // We return all of these result types because
2524       // LocalLookupRealNamedProperty is used when setting properties
2525       // where map transitions and null descriptors are handled.
2526       ASSERT(result->holder() == this && result->type() != NORMAL);
2527       // Disallow caching for uninitialized constants. These can only
2528       // occur as fields.
2529       if (result->IsReadOnly() && result->type() == FIELD &&
2530           FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
2531         result->DisallowCaching();
2532       }
2533       return;
2534     }
2535   } else {
2536     int entry = property_dictionary()->FindEntry(name);
2537     if (entry != StringDictionary::kNotFound) {
2538       Object* value = property_dictionary()->ValueAt(entry);
2539       if (IsGlobalObject()) {
2540         PropertyDetails d = property_dictionary()->DetailsAt(entry);
2541         if (d.IsDeleted()) {
2542           result->NotFound();
2543           return;
2544         }
2545         value = JSGlobalPropertyCell::cast(value)->value();
2546       }
2547       // Make sure to disallow caching for uninitialized constants
2548       // found in the dictionary-mode objects.
2549       if (value->IsTheHole()) result->DisallowCaching();
2550       result->DictionaryResult(this, entry);
2551       return;
2552     }
2553   }
2554   result->NotFound();
2555 }
2556
2557
2558 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
2559   LocalLookupRealNamedProperty(name, result);
2560   if (result->IsProperty()) return;
2561
2562   LookupRealNamedPropertyInPrototypes(name, result);
2563 }
2564
2565
2566 void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
2567                                                    LookupResult* result) {
2568   Heap* heap = GetHeap();
2569   for (Object* pt = GetPrototype();
2570        pt != heap->null_value();
2571        pt = JSObject::cast(pt)->GetPrototype()) {
2572     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
2573     if (result->IsProperty() && (result->type() != INTERCEPTOR)) return;
2574   }
2575   result->NotFound();
2576 }
2577
2578
2579 // We only need to deal with CALLBACKS and INTERCEPTORS
2580 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
2581     LookupResult* result,
2582     String* name,
2583     Object* value,
2584     bool check_prototype,
2585     StrictModeFlag strict_mode) {
2586   if (check_prototype && !result->IsProperty()) {
2587     LookupCallbackSetterInPrototypes(name, result);
2588   }
2589
2590   if (result->IsProperty()) {
2591     if (!result->IsReadOnly()) {
2592       switch (result->type()) {
2593         case CALLBACKS: {
2594           Object* obj = result->GetCallbackObject();
2595           if (obj->IsAccessorInfo()) {
2596             AccessorInfo* info = AccessorInfo::cast(obj);
2597             if (info->all_can_write()) {
2598               return SetPropertyWithCallback(result->GetCallbackObject(),
2599                                              name,
2600                                              value,
2601                                              result->holder(),
2602                                              strict_mode);
2603             }
2604           }
2605           break;
2606         }
2607         case INTERCEPTOR: {
2608           // Try lookup real named properties. Note that only property can be
2609           // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
2610           LookupResult r(GetIsolate());
2611           LookupRealNamedProperty(name, &r);
2612           if (r.IsProperty()) {
2613             return SetPropertyWithFailedAccessCheck(&r,
2614                                                     name,
2615                                                     value,
2616                                                     check_prototype,
2617                                                     strict_mode);
2618           }
2619           break;
2620         }
2621         default: {
2622           break;
2623         }
2624       }
2625     }
2626   }
2627
2628   Isolate* isolate = GetIsolate();
2629   HandleScope scope(isolate);
2630   Handle<Object> value_handle(value);
2631   isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
2632   return *value_handle;
2633 }
2634
2635
2636 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
2637                                      String* key,
2638                                      Object* value,
2639                                      PropertyAttributes attributes,
2640                                      StrictModeFlag strict_mode) {
2641   if (result->IsFound() && result->type() == HANDLER) {
2642     return result->proxy()->SetPropertyWithHandler(
2643         key, value, attributes, strict_mode);
2644   } else {
2645     return JSObject::cast(this)->SetPropertyForResult(
2646         result, key, value, attributes, strict_mode);
2647   }
2648 }
2649
2650
2651 bool JSProxy::HasPropertyWithHandler(String* name_raw) {
2652   Isolate* isolate = GetIsolate();
2653   HandleScope scope(isolate);
2654   Handle<Object> receiver(this);
2655   Handle<Object> name(name_raw);
2656
2657   Handle<Object> args[] = { name };
2658   Handle<Object> result = CallTrap(
2659     "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
2660   if (isolate->has_pending_exception()) return Failure::Exception();
2661
2662   return result->ToBoolean()->IsTrue();
2663 }
2664
2665
2666 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
2667     String* name_raw,
2668     Object* value_raw,
2669     PropertyAttributes attributes,
2670     StrictModeFlag strict_mode) {
2671   Isolate* isolate = GetIsolate();
2672   HandleScope scope(isolate);
2673   Handle<Object> receiver(this);
2674   Handle<Object> name(name_raw);
2675   Handle<Object> value(value_raw);
2676
2677   Handle<Object> args[] = { receiver, name, value };
2678   CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
2679   if (isolate->has_pending_exception()) return Failure::Exception();
2680
2681   return *value;
2682 }
2683
2684
2685 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandlerIfDefiningSetter(
2686     String* name_raw,
2687     Object* value_raw,
2688     PropertyAttributes attributes,
2689     StrictModeFlag strict_mode,
2690     bool* found) {
2691   *found = true;  // except where defined otherwise...
2692   Isolate* isolate = GetHeap()->isolate();
2693   Handle<JSProxy> proxy(this);
2694   Handle<Object> handler(this->handler());  // Trap might morph proxy.
2695   Handle<String> name(name_raw);
2696   Handle<Object> value(value_raw);
2697   Handle<Object> args[] = { name };
2698   Handle<Object> result = proxy->CallTrap(
2699       "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2700   if (isolate->has_pending_exception()) return Failure::Exception();
2701
2702   if (!result->IsUndefined()) {
2703     // The proxy handler cares about this property.
2704     // Check whether it is virtualized as an accessor.
2705     // Emulate [[GetProperty]] semantics for proxies.
2706     bool has_pending_exception;
2707     Handle<Object> argv[] = { result };
2708     Handle<Object> desc =
2709         Execution::Call(isolate->to_complete_property_descriptor(), result,
2710                         ARRAY_SIZE(argv), argv, &has_pending_exception);
2711     if (has_pending_exception) return Failure::Exception();
2712
2713     Handle<String> conf_name =
2714         isolate->factory()->LookupAsciiSymbol("configurable_");
2715     Handle<Object> configurable(v8::internal::GetProperty(desc, conf_name));
2716     ASSERT(!isolate->has_pending_exception());
2717     if (configurable->IsFalse()) {
2718       Handle<String> trap =
2719           isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2720       Handle<Object> args[] = { handler, trap, name };
2721       Handle<Object> error = isolate->factory()->NewTypeError(
2722           "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2723       return isolate->Throw(*error);
2724     }
2725     ASSERT(configurable->IsTrue());
2726
2727     // Check for AccessorDescriptor.
2728     Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_");
2729     Handle<Object> setter(v8::internal::GetProperty(desc, set_name));
2730     ASSERT(!isolate->has_pending_exception());
2731     if (!setter->IsUndefined()) {
2732       // We have a setter -- invoke it.
2733       // TODO(rossberg): nicer would be to cast to some JSCallable here...
2734       return proxy->SetPropertyWithDefinedSetter(
2735           JSReceiver::cast(*setter), *value);
2736     } else {
2737       Handle<String> get_name = isolate->factory()->LookupAsciiSymbol("get_");
2738       Handle<Object> getter(v8::internal::GetProperty(desc, get_name));
2739       ASSERT(!isolate->has_pending_exception());
2740       if (!getter->IsUndefined()) {
2741         // We have a getter but no setter -- the property may not be
2742         // written. In strict mode, throw an error.
2743         if (strict_mode == kNonStrictMode) return *value;
2744         Handle<Object> args[] = { name, proxy };
2745         Handle<Object> error = isolate->factory()->NewTypeError(
2746             "no_setter_in_callback", HandleVector(args, ARRAY_SIZE(args)));
2747         return isolate->Throw(*error);
2748       }
2749     }
2750     // Fall-through.
2751   }
2752
2753   // The proxy does not define the property as an accessor.
2754   *found = false;
2755   return *value;
2756 }
2757
2758
2759 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
2760     String* name_raw, DeleteMode mode) {
2761   Isolate* isolate = GetIsolate();
2762   HandleScope scope(isolate);
2763   Handle<Object> receiver(this);
2764   Handle<Object> name(name_raw);
2765
2766   Handle<Object> args[] = { name };
2767   Handle<Object> result = CallTrap(
2768     "delete", Handle<Object>(), ARRAY_SIZE(args), args);
2769   if (isolate->has_pending_exception()) return Failure::Exception();
2770
2771   Object* bool_result = result->ToBoolean();
2772   if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
2773     Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
2774     Handle<Object> args[] = { Handle<Object>(handler()), trap_name };
2775     Handle<Object> error = isolate->factory()->NewTypeError(
2776         "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
2777     isolate->Throw(*error);
2778     return Failure::Exception();
2779   }
2780   return bool_result;
2781 }
2782
2783
2784 MUST_USE_RESULT MaybeObject* JSProxy::DeleteElementWithHandler(
2785     uint32_t index,
2786     DeleteMode mode) {
2787   Isolate* isolate = GetIsolate();
2788   HandleScope scope(isolate);
2789   Handle<String> name = isolate->factory()->Uint32ToString(index);
2790   return JSProxy::DeletePropertyWithHandler(*name, mode);
2791 }
2792
2793
2794 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
2795     JSReceiver* receiver_raw,
2796     String* name_raw) {
2797   Isolate* isolate = GetIsolate();
2798   HandleScope scope(isolate);
2799   Handle<JSProxy> proxy(this);
2800   Handle<Object> handler(this->handler());  // Trap might morph proxy.
2801   Handle<JSReceiver> receiver(receiver_raw);
2802   Handle<Object> name(name_raw);
2803
2804   Handle<Object> args[] = { name };
2805   Handle<Object> result = CallTrap(
2806     "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2807   if (isolate->has_pending_exception()) return NONE;
2808
2809   if (result->IsUndefined()) return ABSENT;
2810
2811   bool has_pending_exception;
2812   Handle<Object> argv[] = { result };
2813   Handle<Object> desc =
2814       Execution::Call(isolate->to_complete_property_descriptor(), result,
2815                       ARRAY_SIZE(argv), argv, &has_pending_exception);
2816   if (has_pending_exception) return NONE;
2817
2818   // Convert result to PropertyAttributes.
2819   Handle<String> enum_n = isolate->factory()->LookupAsciiSymbol("enumerable");
2820   Handle<Object> enumerable(v8::internal::GetProperty(desc, enum_n));
2821   if (isolate->has_pending_exception()) return NONE;
2822   Handle<String> conf_n = isolate->factory()->LookupAsciiSymbol("configurable");
2823   Handle<Object> configurable(v8::internal::GetProperty(desc, conf_n));
2824   if (isolate->has_pending_exception()) return NONE;
2825   Handle<String> writ_n = isolate->factory()->LookupAsciiSymbol("writable");
2826   Handle<Object> writable(v8::internal::GetProperty(desc, writ_n));
2827   if (isolate->has_pending_exception()) return NONE;
2828
2829   if (configurable->IsFalse()) {
2830     Handle<String> trap =
2831         isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2832     Handle<Object> args[] = { handler, trap, name };
2833     Handle<Object> error = isolate->factory()->NewTypeError(
2834         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2835     isolate->Throw(*error);
2836     return NONE;
2837   }
2838
2839   int attributes = NONE;
2840   if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM;
2841   if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE;
2842   if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY;
2843   return static_cast<PropertyAttributes>(attributes);
2844 }
2845
2846
2847 MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler(
2848     JSReceiver* receiver,
2849     uint32_t index) {
2850   Isolate* isolate = GetIsolate();
2851   HandleScope scope(isolate);
2852   Handle<String> name = isolate->factory()->Uint32ToString(index);
2853   return GetPropertyAttributeWithHandler(receiver, *name);
2854 }
2855
2856
2857 void JSProxy::Fix() {
2858   Isolate* isolate = GetIsolate();
2859   HandleScope scope(isolate);
2860   Handle<JSProxy> self(this);
2861
2862   // Save identity hash.
2863   MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
2864
2865   if (IsJSFunctionProxy()) {
2866     isolate->factory()->BecomeJSFunction(self);
2867     // Code will be set on the JavaScript side.
2868   } else {
2869     isolate->factory()->BecomeJSObject(self);
2870   }
2871   ASSERT(self->IsJSObject());
2872
2873   // Inherit identity, if it was present.
2874   Object* hash;
2875   if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
2876     Handle<JSObject> new_self(JSObject::cast(*self));
2877     isolate->factory()->SetIdentityHash(new_self, hash);
2878   }
2879 }
2880
2881
2882 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
2883                                                  Handle<Object> derived,
2884                                                  int argc,
2885                                                  Handle<Object> argv[]) {
2886   Isolate* isolate = GetIsolate();
2887   Handle<Object> handler(this->handler());
2888
2889   Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol(name);
2890   Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2891   if (isolate->has_pending_exception()) return trap;
2892
2893   if (trap->IsUndefined()) {
2894     if (derived.is_null()) {
2895       Handle<Object> args[] = { handler, trap_name };
2896       Handle<Object> error = isolate->factory()->NewTypeError(
2897         "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2898       isolate->Throw(*error);
2899       return Handle<Object>();
2900     }
2901     trap = Handle<Object>(derived);
2902   }
2903
2904   bool threw;
2905   return Execution::Call(trap, handler, argc, argv, &threw);
2906 }
2907
2908
2909 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
2910                                             String* name,
2911                                             Object* value,
2912                                             PropertyAttributes attributes,
2913                                             StrictModeFlag strict_mode) {
2914   Heap* heap = GetHeap();
2915   // Make sure that the top context does not change when doing callbacks or
2916   // interceptor calls.
2917   AssertNoContextChange ncc;
2918
2919   // Optimization for 2-byte strings often used as keys in a decompression
2920   // dictionary.  We make these short keys into symbols to avoid constantly
2921   // reallocating them.
2922   if (!name->IsSymbol() && name->length() <= 2) {
2923     Object* symbol_version;
2924     { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
2925       if (maybe_symbol_version->ToObject(&symbol_version)) {
2926         name = String::cast(symbol_version);
2927       }
2928     }
2929   }
2930
2931   // Check access rights if needed.
2932   if (IsAccessCheckNeeded()) {
2933     if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
2934       return SetPropertyWithFailedAccessCheck(
2935           result, name, value, true, strict_mode);
2936     }
2937   }
2938
2939   if (IsJSGlobalProxy()) {
2940     Object* proto = GetPrototype();
2941     if (proto->IsNull()) return value;
2942     ASSERT(proto->IsJSGlobalObject());
2943     return JSObject::cast(proto)->SetPropertyForResult(
2944         result, name, value, attributes, strict_mode);
2945   }
2946
2947   if (!result->IsProperty() && !IsJSContextExtensionObject()) {
2948     bool found = false;
2949     MaybeObject* result_object;
2950     result_object = SetPropertyWithCallbackSetterInPrototypes(name,
2951                                                               value,
2952                                                               attributes,
2953                                                               &found,
2954                                                               strict_mode);
2955     if (found) return result_object;
2956   }
2957
2958   // At this point, no GC should have happened, as this would invalidate
2959   // 'result', which we cannot handlify!
2960
2961   if (!result->IsFound()) {
2962     // Neither properties nor transitions found.
2963     return AddProperty(name, value, attributes, strict_mode);
2964   }
2965   if (result->IsReadOnly() && result->IsProperty()) {
2966     if (strict_mode == kStrictMode) {
2967       Handle<JSObject> self(this);
2968       Handle<String> hname(name);
2969       Handle<Object> args[] = { hname, self };
2970       return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
2971           "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2972     } else {
2973       return value;
2974     }
2975   }
2976   // This is a real property that is not read-only, or it is a
2977   // transition or null descriptor and there are no setters in the prototypes.
2978   switch (result->type()) {
2979     case NORMAL:
2980       return SetNormalizedProperty(result, value);
2981     case FIELD:
2982       return FastPropertyAtPut(result->GetFieldIndex(), value);
2983     case MAP_TRANSITION:
2984       if (attributes == result->GetAttributes()) {
2985         // Only use map transition if the attributes match.
2986         return AddFastPropertyUsingMap(result->GetTransitionMap(),
2987                                        name,
2988                                        value);
2989       }
2990       return ConvertDescriptorToField(name, value, attributes);
2991     case CONSTANT_FUNCTION:
2992       // Only replace the function if necessary.
2993       if (value == result->GetConstantFunction()) return value;
2994       // Preserve the attributes of this existing property.
2995       attributes = result->GetAttributes();
2996       return ConvertDescriptorToField(name, value, attributes);
2997     case CALLBACKS:
2998       return SetPropertyWithCallback(result->GetCallbackObject(),
2999                                      name,
3000                                      value,
3001                                      result->holder(),
3002                                      strict_mode);
3003     case INTERCEPTOR:
3004       return SetPropertyWithInterceptor(name, value, attributes, strict_mode);
3005     case CONSTANT_TRANSITION: {
3006       // If the same constant function is being added we can simply
3007       // transition to the target map.
3008       Map* target_map = result->GetTransitionMap();
3009       DescriptorArray* target_descriptors = target_map->instance_descriptors();
3010       int number = target_descriptors->SearchWithCache(name);
3011       ASSERT(number != DescriptorArray::kNotFound);
3012       ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
3013       JSFunction* function =
3014           JSFunction::cast(target_descriptors->GetValue(number));
3015       ASSERT(!HEAP->InNewSpace(function));
3016       if (value == function) {
3017         set_map(target_map);
3018         return value;
3019       }
3020       // Otherwise, replace with a MAP_TRANSITION to a new map with a
3021       // FIELD, even if the value is a constant function.
3022       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3023     }
3024     case NULL_DESCRIPTOR:
3025     case ELEMENTS_TRANSITION:
3026       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3027     default:
3028       UNREACHABLE();
3029   }
3030   UNREACHABLE();
3031   return value;
3032 }
3033
3034
3035 // Set a real local property, even if it is READ_ONLY.  If the property is not
3036 // present, add it with attributes NONE.  This code is an exact clone of
3037 // SetProperty, with the check for IsReadOnly and the check for a
3038 // callback setter removed.  The two lines looking up the LookupResult
3039 // result are also added.  If one of the functions is changed, the other
3040 // should be.
3041 // Note that this method cannot be used to set the prototype of a function
3042 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
3043 // doesn't handle function prototypes correctly.
3044 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
3045     String* name,
3046     Object* value,
3047     PropertyAttributes attributes) {
3048
3049   // Make sure that the top context does not change when doing callbacks or
3050   // interceptor calls.
3051   AssertNoContextChange ncc;
3052   Isolate* isolate = GetIsolate();
3053   LookupResult result(isolate);
3054   LocalLookup(name, &result);
3055   // Check access rights if needed.
3056   if (IsAccessCheckNeeded()) {
3057     if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
3058       return SetPropertyWithFailedAccessCheck(&result,
3059                                               name,
3060                                               value,
3061                                               false,
3062                                               kNonStrictMode);
3063     }
3064   }
3065
3066   if (IsJSGlobalProxy()) {
3067     Object* proto = GetPrototype();
3068     if (proto->IsNull()) return value;
3069     ASSERT(proto->IsJSGlobalObject());
3070     return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
3071         name,
3072         value,
3073         attributes);
3074   }
3075
3076   // Check for accessor in prototype chain removed here in clone.
3077   if (!result.IsFound()) {
3078     // Neither properties nor transitions found.
3079     return AddProperty(name, value, attributes, kNonStrictMode);
3080   }
3081
3082   PropertyDetails details = PropertyDetails(attributes, NORMAL);
3083
3084   // Check of IsReadOnly removed from here in clone.
3085   switch (result.type()) {
3086     case NORMAL:
3087       return SetNormalizedProperty(name, value, details);
3088     case FIELD:
3089       return FastPropertyAtPut(result.GetFieldIndex(), value);
3090     case MAP_TRANSITION:
3091       if (attributes == result.GetAttributes()) {
3092         // Only use map transition if the attributes match.
3093         return AddFastPropertyUsingMap(result.GetTransitionMap(),
3094                                        name,
3095                                        value);
3096       }
3097       return ConvertDescriptorToField(name, value, attributes);
3098     case CONSTANT_FUNCTION:
3099       // Only replace the function if necessary.
3100       if (value == result.GetConstantFunction()) return value;
3101       // Preserve the attributes of this existing property.
3102       attributes = result.GetAttributes();
3103       return ConvertDescriptorToField(name, value, attributes);
3104     case CALLBACKS:
3105     case INTERCEPTOR:
3106       // Override callback in clone
3107       return ConvertDescriptorToField(name, value, attributes);
3108     case CONSTANT_TRANSITION:
3109       // Replace with a MAP_TRANSITION to a new map with a FIELD, even
3110       // if the value is a function.
3111       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3112     case NULL_DESCRIPTOR:
3113     case ELEMENTS_TRANSITION:
3114       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3115     default:
3116       UNREACHABLE();
3117   }
3118   UNREACHABLE();
3119   return value;
3120 }
3121
3122
3123 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
3124       JSObject* receiver,
3125       String* name,
3126       bool continue_search) {
3127   // Check local property, ignore interceptor.
3128   LookupResult result(GetIsolate());
3129   LocalLookupRealNamedProperty(name, &result);
3130   if (result.IsProperty()) return result.GetAttributes();
3131
3132   if (continue_search) {
3133     // Continue searching via the prototype chain.
3134     Object* pt = GetPrototype();
3135     if (!pt->IsNull()) {
3136       return JSObject::cast(pt)->
3137         GetPropertyAttributeWithReceiver(receiver, name);
3138     }
3139   }
3140   return ABSENT;
3141 }
3142
3143
3144 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
3145       JSObject* receiver,
3146       String* name,
3147       bool continue_search) {
3148   Isolate* isolate = GetIsolate();
3149
3150   // Make sure that the top context does not change when doing
3151   // callbacks or interceptor calls.
3152   AssertNoContextChange ncc;
3153
3154   HandleScope scope(isolate);
3155   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
3156   Handle<JSObject> receiver_handle(receiver);
3157   Handle<JSObject> holder_handle(this);
3158   Handle<String> name_handle(name);
3159   CustomArguments args(isolate, interceptor->data(), receiver, this);
3160   v8::AccessorInfo info(args.end());
3161   if (!interceptor->query()->IsUndefined()) {
3162     v8::NamedPropertyQuery query =
3163         v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
3164     LOG(isolate,
3165         ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
3166     v8::Handle<v8::Integer> result;
3167     {
3168       // Leaving JavaScript.
3169       VMState state(isolate, EXTERNAL);
3170       result = query(v8::Utils::ToLocal(name_handle), info);
3171     }
3172     if (!result.IsEmpty()) {
3173       ASSERT(result->IsInt32());
3174       return static_cast<PropertyAttributes>(result->Int32Value());
3175     }
3176   } else if (!interceptor->getter()->IsUndefined()) {
3177     v8::NamedPropertyGetter getter =
3178         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
3179     LOG(isolate,
3180         ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
3181     v8::Handle<v8::Value> result;
3182     {
3183       // Leaving JavaScript.
3184       VMState state(isolate, EXTERNAL);
3185       result = getter(v8::Utils::ToLocal(name_handle), info);
3186     }
3187     if (!result.IsEmpty()) return DONT_ENUM;
3188   }
3189   return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
3190                                                             *name_handle,
3191                                                             continue_search);
3192 }
3193
3194
3195 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
3196       JSReceiver* receiver,
3197       String* key) {
3198   uint32_t index = 0;
3199   if (IsJSObject() && key->AsArrayIndex(&index)) {
3200     return JSObject::cast(this)->HasElementWithReceiver(receiver, index)
3201         ? NONE : ABSENT;
3202   }
3203   // Named property.
3204   LookupResult result(GetIsolate());
3205   Lookup(key, &result);
3206   return GetPropertyAttribute(receiver, &result, key, true);
3207 }
3208
3209
3210 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver,
3211                                                     LookupResult* result,
3212                                                     String* name,
3213                                                     bool continue_search) {
3214   // Check access rights if needed.
3215   if (IsAccessCheckNeeded()) {
3216     JSObject* this_obj = JSObject::cast(this);
3217     Heap* heap = GetHeap();
3218     if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
3219       return this_obj->GetPropertyAttributeWithFailedAccessCheck(
3220           receiver, result, name, continue_search);
3221     }
3222   }
3223   if (result->IsProperty()) {
3224     switch (result->type()) {
3225       case NORMAL:  // fall through
3226       case FIELD:
3227       case CONSTANT_FUNCTION:
3228       case CALLBACKS:
3229         return result->GetAttributes();
3230       case HANDLER: {
3231         return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler(
3232             receiver, name);
3233       }
3234       case INTERCEPTOR:
3235         return result->holder()->GetPropertyAttributeWithInterceptor(
3236             JSObject::cast(receiver), name, continue_search);
3237       default:
3238         UNREACHABLE();
3239     }
3240   }
3241   return ABSENT;
3242 }
3243
3244
3245 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
3246   // Check whether the name is an array index.
3247   uint32_t index = 0;
3248   if (IsJSObject() && name->AsArrayIndex(&index)) {
3249     if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
3250     return ABSENT;
3251   }
3252   // Named property.
3253   LookupResult result(GetIsolate());
3254   LocalLookup(name, &result);
3255   return GetPropertyAttribute(this, &result, name, false);
3256 }
3257
3258
3259 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
3260                                      PropertyNormalizationMode mode) {
3261   Isolate* isolate = obj->GetIsolate();
3262   Map* fast = obj->map();
3263   int index = fast->Hash() % kEntries;
3264   Object* result = get(index);
3265   if (result->IsMap() &&
3266       Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
3267 #ifdef DEBUG
3268     if (FLAG_verify_heap) {
3269       Map::cast(result)->SharedMapVerify();
3270     }
3271     if (FLAG_enable_slow_asserts) {
3272       // The cached map should match newly created normalized map bit-by-bit.
3273       Object* fresh;
3274       { MaybeObject* maybe_fresh =
3275             fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
3276         if (maybe_fresh->ToObject(&fresh)) {
3277           ASSERT(memcmp(Map::cast(fresh)->address(),
3278                         Map::cast(result)->address(),
3279                         Map::kSize) == 0);
3280         }
3281       }
3282     }
3283 #endif
3284     return result;
3285   }
3286
3287   { MaybeObject* maybe_result =
3288         fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
3289     if (!maybe_result->ToObject(&result)) return maybe_result;
3290   }
3291   set(index, result);
3292   isolate->counters()->normalized_maps()->Increment();
3293
3294   return result;
3295 }
3296
3297
3298 void NormalizedMapCache::Clear() {
3299   int entries = length();
3300   for (int i = 0; i != entries; i++) {
3301     set_undefined(i);
3302   }
3303 }
3304
3305
3306 void JSObject::UpdateMapCodeCache(Handle<JSObject> object,
3307                                   Handle<String> name,
3308                                   Handle<Code> code) {
3309   Isolate* isolate = object->GetIsolate();
3310   CALL_HEAP_FUNCTION_VOID(isolate,
3311                           object->UpdateMapCodeCache(*name, *code));
3312 }
3313
3314
3315 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
3316   if (map()->is_shared()) {
3317     // Fast case maps are never marked as shared.
3318     ASSERT(!HasFastProperties());
3319     // Replace the map with an identical copy that can be safely modified.
3320     Object* obj;
3321     { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES,
3322                                                      UNIQUE_NORMALIZED_MAP);
3323       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3324     }
3325     GetIsolate()->counters()->normalized_maps()->Increment();
3326
3327     set_map(Map::cast(obj));
3328   }
3329   return map()->UpdateCodeCache(name, code);
3330 }
3331
3332
3333 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
3334                                            int expected_additional_properties) {
3335   if (!HasFastProperties()) return this;
3336
3337   // The global object is always normalized.
3338   ASSERT(!IsGlobalObject());
3339   // JSGlobalProxy must never be normalized
3340   ASSERT(!IsJSGlobalProxy());
3341
3342   Map* map_of_this = map();
3343
3344   // Allocate new content.
3345   int property_count = map_of_this->NumberOfDescribedProperties();
3346   if (expected_additional_properties > 0) {
3347     property_count += expected_additional_properties;
3348   } else {
3349     property_count += 2;  // Make space for two more properties.
3350   }
3351   Object* obj;
3352   { MaybeObject* maybe_obj =
3353         StringDictionary::Allocate(property_count);
3354     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3355   }
3356   StringDictionary* dictionary = StringDictionary::cast(obj);
3357
3358   DescriptorArray* descs = map_of_this->instance_descriptors();
3359   for (int i = 0; i < descs->number_of_descriptors(); i++) {
3360     PropertyDetails details(descs->GetDetails(i));
3361     switch (details.type()) {
3362       case CONSTANT_FUNCTION: {
3363         PropertyDetails d =
3364             PropertyDetails(details.attributes(), NORMAL, details.index());
3365         Object* value = descs->GetConstantFunction(i);
3366         Object* result;
3367         { MaybeObject* maybe_result =
3368               dictionary->Add(descs->GetKey(i), value, d);
3369           if (!maybe_result->ToObject(&result)) return maybe_result;
3370         }
3371         dictionary = StringDictionary::cast(result);
3372         break;
3373       }
3374       case FIELD: {
3375         PropertyDetails d =
3376             PropertyDetails(details.attributes(), NORMAL, details.index());
3377         Object* value = FastPropertyAt(descs->GetFieldIndex(i));
3378         Object* result;
3379         { MaybeObject* maybe_result =
3380               dictionary->Add(descs->GetKey(i), value, d);
3381           if (!maybe_result->ToObject(&result)) return maybe_result;
3382         }
3383         dictionary = StringDictionary::cast(result);
3384         break;
3385       }
3386       case CALLBACKS: {
3387         PropertyDetails d =
3388             PropertyDetails(details.attributes(), CALLBACKS, details.index());
3389         Object* value = descs->GetCallbacksObject(i);
3390         Object* result;
3391         { MaybeObject* maybe_result =
3392               dictionary->Add(descs->GetKey(i), value, d);
3393           if (!maybe_result->ToObject(&result)) return maybe_result;
3394         }
3395         dictionary = StringDictionary::cast(result);
3396         break;
3397       }
3398       case MAP_TRANSITION:
3399       case CONSTANT_TRANSITION:
3400       case NULL_DESCRIPTOR:
3401       case INTERCEPTOR:
3402       case ELEMENTS_TRANSITION:
3403         break;
3404       default:
3405         UNREACHABLE();
3406     }
3407   }
3408
3409   Heap* current_heap = GetHeap();
3410
3411   // Copy the next enumeration index from instance descriptor.
3412   int index = map_of_this->instance_descriptors()->NextEnumerationIndex();
3413   dictionary->SetNextEnumerationIndex(index);
3414
3415   { MaybeObject* maybe_obj =
3416         current_heap->isolate()->context()->global_context()->
3417         normalized_map_cache()->Get(this, mode);
3418     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3419   }
3420   Map* new_map = Map::cast(obj);
3421
3422   // We have now successfully allocated all the necessary objects.
3423   // Changes can now be made with the guarantee that all of them take effect.
3424
3425   // Resize the object in the heap if necessary.
3426   int new_instance_size = new_map->instance_size();
3427   int instance_size_delta = map_of_this->instance_size() - new_instance_size;
3428   ASSERT(instance_size_delta >= 0);
3429   current_heap->CreateFillerObjectAt(this->address() + new_instance_size,
3430                                      instance_size_delta);
3431   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
3432     MemoryChunk::IncrementLiveBytes(this->address(), -instance_size_delta);
3433   }
3434
3435
3436   set_map(new_map);
3437   new_map->clear_instance_descriptors();
3438
3439   set_properties(dictionary);
3440
3441   current_heap->isolate()->counters()->props_to_dictionary()->Increment();
3442
3443 #ifdef DEBUG
3444   if (FLAG_trace_normalization) {
3445     PrintF("Object properties have been normalized:\n");
3446     Print();
3447   }
3448 #endif
3449   return this;
3450 }
3451
3452
3453 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
3454   if (HasFastProperties()) return this;
3455   ASSERT(!IsGlobalObject());
3456   return property_dictionary()->
3457       TransformPropertiesToFastFor(this, unused_property_fields);
3458 }
3459
3460
3461 MaybeObject* JSObject::NormalizeElements() {
3462   ASSERT(!HasExternalArrayElements());
3463
3464   // Find the backing store.
3465   FixedArrayBase* array = FixedArrayBase::cast(elements());
3466   Map* old_map = array->map();
3467   bool is_arguments =
3468       (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
3469   if (is_arguments) {
3470     array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
3471   }
3472   if (array->IsDictionary()) return array;
3473
3474   ASSERT(HasFastElements() ||
3475          HasFastSmiOnlyElements() ||
3476          HasFastDoubleElements() ||
3477          HasFastArgumentsElements());
3478   // Compute the effective length and allocate a new backing store.
3479   int length = IsJSArray()
3480       ? Smi::cast(JSArray::cast(this)->length())->value()
3481       : array->length();
3482   int old_capacity = 0;
3483   int used_elements = 0;
3484   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
3485   NumberDictionary* dictionary = NULL;
3486   { Object* object;
3487     MaybeObject* maybe = NumberDictionary::Allocate(used_elements);
3488     if (!maybe->ToObject(&object)) return maybe;
3489     dictionary = NumberDictionary::cast(object);
3490   }
3491
3492   // Copy the elements to the new backing store.
3493   bool has_double_elements = array->IsFixedDoubleArray();
3494   for (int i = 0; i < length; i++) {
3495     Object* value = NULL;
3496     if (has_double_elements) {
3497       FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
3498       if (double_array->is_the_hole(i)) {
3499         value = GetIsolate()->heap()->the_hole_value();
3500       } else {
3501         // Objects must be allocated in the old object space, since the
3502         // overall number of HeapNumbers needed for the conversion might
3503         // exceed the capacity of new space, and we would fail repeatedly
3504         // trying to convert the FixedDoubleArray.
3505         MaybeObject* maybe_value_object =
3506             GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3507         if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3508       }
3509     } else {
3510       ASSERT(old_map->has_fast_elements() ||
3511              old_map->has_fast_smi_only_elements());
3512       value = FixedArray::cast(array)->get(i);
3513     }
3514     PropertyDetails details = PropertyDetails(NONE, NORMAL);
3515     if (!value->IsTheHole()) {
3516       Object* result;
3517       MaybeObject* maybe_result =
3518           dictionary->AddNumberEntry(i, value, details);
3519       if (!maybe_result->ToObject(&result)) return maybe_result;
3520       dictionary = NumberDictionary::cast(result);
3521     }
3522   }
3523
3524   // Switch to using the dictionary as the backing storage for elements.
3525   if (is_arguments) {
3526     FixedArray::cast(elements())->set(1, dictionary);
3527   } else {
3528     // Set the new map first to satify the elements type assert in
3529     // set_elements().
3530     Object* new_map;
3531     MaybeObject* maybe = GetElementsTransitionMap(DICTIONARY_ELEMENTS);
3532     if (!maybe->ToObject(&new_map)) return maybe;
3533     set_map(Map::cast(new_map));
3534     set_elements(dictionary);
3535   }
3536
3537   old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
3538       Increment();
3539
3540 #ifdef DEBUG
3541   if (FLAG_trace_normalization) {
3542     PrintF("Object elements have been normalized:\n");
3543     Print();
3544   }
3545 #endif
3546
3547   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
3548   return dictionary;
3549 }
3550
3551
3552 Smi* JSReceiver::GenerateIdentityHash() {
3553   Isolate* isolate = GetIsolate();
3554
3555   int hash_value;
3556   int attempts = 0;
3557   do {
3558     // Generate a random 32-bit hash value but limit range to fit
3559     // within a smi.
3560     hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue;
3561     attempts++;
3562   } while (hash_value == 0 && attempts < 30);
3563   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
3564
3565   return Smi::FromInt(hash_value);
3566 }
3567
3568
3569 MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) {
3570   MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3571                                          hash);
3572   if (maybe->IsFailure()) return maybe;
3573   return this;
3574 }
3575
3576
3577 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) {
3578   Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol());
3579   if (stored_value->IsSmi()) return stored_value;
3580
3581   // Do not generate permanent identity hash code if not requested.
3582   if (flag == OMIT_CREATION) return GetHeap()->undefined_value();
3583
3584   Smi* hash = GenerateIdentityHash();
3585   MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3586                                           hash);
3587   if (result->IsFailure()) return result;
3588   if (result->ToObjectUnchecked()->IsUndefined()) {
3589     // Trying to get hash of detached proxy.
3590     return Smi::FromInt(0);
3591   }
3592   return hash;
3593 }
3594
3595
3596 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) {
3597   Object* hash = this->hash();
3598   if (!hash->IsSmi() && flag == ALLOW_CREATION) {
3599     hash = GenerateIdentityHash();
3600     set_hash(hash);
3601   }
3602   return hash;
3603 }
3604
3605
3606 Object* JSObject::GetHiddenProperty(String* key) {
3607   if (IsJSGlobalProxy()) {
3608     // For a proxy, use the prototype as target object.
3609     Object* proxy_parent = GetPrototype();
3610     // If the proxy is detached, return undefined.
3611     if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3612     ASSERT(proxy_parent->IsJSGlobalObject());
3613     return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
3614   }
3615   ASSERT(!IsJSGlobalProxy());
3616   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3617   ASSERT(!hidden_lookup->IsFailure());  // No failure when passing false as arg.
3618   if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) {
3619     return GetHeap()->undefined_value();
3620   }
3621   StringDictionary* dictionary =
3622       StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3623   int entry = dictionary->FindEntry(key);
3624   if (entry == StringDictionary::kNotFound) return GetHeap()->undefined_value();
3625   return dictionary->ValueAt(entry);
3626 }
3627
3628
3629 MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
3630   if (IsJSGlobalProxy()) {
3631     // For a proxy, use the prototype as target object.
3632     Object* proxy_parent = GetPrototype();
3633     // If the proxy is detached, return undefined.
3634     if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3635     ASSERT(proxy_parent->IsJSGlobalObject());
3636     return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value);
3637   }
3638   ASSERT(!IsJSGlobalProxy());
3639   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(true);
3640   StringDictionary* dictionary;
3641   if (!hidden_lookup->To<StringDictionary>(&dictionary)) return hidden_lookup;
3642
3643   // If it was found, check if the key is already in the dictionary.
3644   int entry = dictionary->FindEntry(key);
3645   if (entry != StringDictionary::kNotFound) {
3646     // If key was found, just update the value.
3647     dictionary->ValueAtPut(entry, value);
3648     return this;
3649   }
3650   // Key was not already in the dictionary, so add the entry.
3651   MaybeObject* insert_result = dictionary->Add(key,
3652                                                value,
3653                                                PropertyDetails(NONE, NORMAL));
3654   StringDictionary* new_dict;
3655   if (!insert_result->To<StringDictionary>(&new_dict)) return insert_result;
3656   if (new_dict != dictionary) {
3657     // If adding the key expanded the dictionary (i.e., Add returned a new
3658     // dictionary), store it back to the object.
3659     MaybeObject* store_result = SetHiddenPropertiesDictionary(new_dict);
3660     if (store_result->IsFailure()) return store_result;
3661   }
3662   // Return this to mark success.
3663   return this;
3664 }
3665
3666
3667 void JSObject::DeleteHiddenProperty(String* key) {
3668   if (IsJSGlobalProxy()) {
3669     // For a proxy, use the prototype as target object.
3670     Object* proxy_parent = GetPrototype();
3671     // If the proxy is detached, return immediately.
3672     if (proxy_parent->IsNull()) return;
3673     ASSERT(proxy_parent->IsJSGlobalObject());
3674     JSObject::cast(proxy_parent)->DeleteHiddenProperty(key);
3675     return;
3676   }
3677   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3678   ASSERT(!hidden_lookup->IsFailure());  // No failure when passing false as arg.
3679   if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) return;
3680   StringDictionary* dictionary =
3681       StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3682   int entry = dictionary->FindEntry(key);
3683   if (entry == StringDictionary::kNotFound) {
3684     // Key wasn't in dictionary. Deletion is a success.
3685     return;
3686   }
3687   // Key was in the dictionary. Remove it.
3688   dictionary->DeleteProperty(entry, JSReceiver::FORCE_DELETION);
3689 }
3690
3691
3692 bool JSObject::HasHiddenProperties() {
3693   return GetPropertyAttributePostInterceptor(this,
3694                                              GetHeap()->hidden_symbol(),
3695                                              false) != ABSENT;
3696 }
3697
3698
3699 MaybeObject* JSObject::GetHiddenPropertiesDictionary(bool create_if_absent) {
3700   ASSERT(!IsJSGlobalProxy());
3701   if (HasFastProperties()) {
3702     // If the object has fast properties, check whether the first slot
3703     // in the descriptor array matches the hidden symbol. Since the
3704     // hidden symbols hash code is zero (and no other string has hash
3705     // code zero) it will always occupy the first entry if present.
3706     DescriptorArray* descriptors = this->map()->instance_descriptors();
3707     if ((descriptors->number_of_descriptors() > 0) &&
3708         (descriptors->GetKey(0) == GetHeap()->hidden_symbol()) &&
3709         descriptors->IsProperty(0)) {
3710       ASSERT(descriptors->GetType(0) == FIELD);
3711       Object* hidden_store =
3712           this->FastPropertyAt(descriptors->GetFieldIndex(0));
3713       return StringDictionary::cast(hidden_store);
3714     }
3715   } else {
3716     PropertyAttributes attributes;
3717     // You can't install a getter on a property indexed by the hidden symbol,
3718     // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3719     // object.
3720     Object* lookup =
3721         GetLocalPropertyPostInterceptor(this,
3722                                         GetHeap()->hidden_symbol(),
3723                                         &attributes)->ToObjectUnchecked();
3724     if (!lookup->IsUndefined()) {
3725       return StringDictionary::cast(lookup);
3726     }
3727   }
3728   if (!create_if_absent) return GetHeap()->undefined_value();
3729   const int kInitialSize = 5;
3730   MaybeObject* dict_alloc = StringDictionary::Allocate(kInitialSize);
3731   StringDictionary* dictionary;
3732   if (!dict_alloc->To<StringDictionary>(&dictionary)) return dict_alloc;
3733   MaybeObject* store_result =
3734       SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3735                                  dictionary,
3736                                  DONT_ENUM,
3737                                  kNonStrictMode);
3738   if (store_result->IsFailure()) return store_result;
3739   return dictionary;
3740 }
3741
3742
3743 MaybeObject* JSObject::SetHiddenPropertiesDictionary(
3744     StringDictionary* dictionary) {
3745   ASSERT(!IsJSGlobalProxy());
3746   ASSERT(HasHiddenProperties());
3747   if (HasFastProperties()) {
3748     // If the object has fast properties, check whether the first slot
3749     // in the descriptor array matches the hidden symbol. Since the
3750     // hidden symbols hash code is zero (and no other string has hash
3751     // code zero) it will always occupy the first entry if present.
3752     DescriptorArray* descriptors = this->map()->instance_descriptors();
3753     if ((descriptors->number_of_descriptors() > 0) &&
3754         (descriptors->GetKey(0) == GetHeap()->hidden_symbol()) &&
3755         descriptors->IsProperty(0)) {
3756       ASSERT(descriptors->GetType(0) == FIELD);
3757       this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary);
3758       return this;
3759     }
3760   }
3761   MaybeObject* store_result =
3762       SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3763                                  dictionary,
3764                                  DONT_ENUM,
3765                                  kNonStrictMode);
3766   if (store_result->IsFailure()) return store_result;
3767   return this;
3768 }
3769
3770
3771 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
3772                                                      DeleteMode mode) {
3773   // Check local property, ignore interceptor.
3774   LookupResult result(GetIsolate());
3775   LocalLookupRealNamedProperty(name, &result);
3776   if (!result.IsProperty()) return GetHeap()->true_value();
3777
3778   // Normalize object if needed.
3779   Object* obj;
3780   { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3781     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3782   }
3783
3784   return DeleteNormalizedProperty(name, mode);
3785 }
3786
3787
3788 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) {
3789   Isolate* isolate = GetIsolate();
3790   HandleScope scope(isolate);
3791   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
3792   Handle<String> name_handle(name);
3793   Handle<JSObject> this_handle(this);
3794   if (!interceptor->deleter()->IsUndefined()) {
3795     v8::NamedPropertyDeleter deleter =
3796         v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
3797     LOG(isolate,
3798         ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
3799     CustomArguments args(isolate, interceptor->data(), this, this);
3800     v8::AccessorInfo info(args.end());
3801     v8::Handle<v8::Boolean> result;
3802     {
3803       // Leaving JavaScript.
3804       VMState state(isolate, EXTERNAL);
3805       result = deleter(v8::Utils::ToLocal(name_handle), info);
3806     }
3807     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3808     if (!result.IsEmpty()) {
3809       ASSERT(result->IsBoolean());
3810       return *v8::Utils::OpenHandle(*result);
3811     }
3812   }
3813   MaybeObject* raw_result =
3814       this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
3815   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3816   return raw_result;
3817 }
3818
3819
3820 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
3821   Isolate* isolate = GetIsolate();
3822   Heap* heap = isolate->heap();
3823   // Make sure that the top context does not change when doing
3824   // callbacks or interceptor calls.
3825   AssertNoContextChange ncc;
3826   HandleScope scope(isolate);
3827   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
3828   if (interceptor->deleter()->IsUndefined()) return heap->false_value();
3829   v8::IndexedPropertyDeleter deleter =
3830       v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
3831   Handle<JSObject> this_handle(this);
3832   LOG(isolate,
3833       ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
3834   CustomArguments args(isolate, interceptor->data(), this, this);
3835   v8::AccessorInfo info(args.end());
3836   v8::Handle<v8::Boolean> result;
3837   {
3838     // Leaving JavaScript.
3839     VMState state(isolate, EXTERNAL);
3840     result = deleter(index, info);
3841   }
3842   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3843   if (!result.IsEmpty()) {
3844     ASSERT(result->IsBoolean());
3845     return *v8::Utils::OpenHandle(*result);
3846   }
3847   MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete(
3848       *this_handle,
3849       index,
3850       NORMAL_DELETION);
3851   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3852   return raw_result;
3853 }
3854
3855
3856 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
3857   Isolate* isolate = GetIsolate();
3858   // Check access rights if needed.
3859   if (IsAccessCheckNeeded() &&
3860       !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
3861     isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
3862     return isolate->heap()->false_value();
3863   }
3864
3865   if (IsJSGlobalProxy()) {
3866     Object* proto = GetPrototype();
3867     if (proto->IsNull()) return isolate->heap()->false_value();
3868     ASSERT(proto->IsJSGlobalObject());
3869     return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
3870   }
3871
3872   if (HasIndexedInterceptor()) {
3873     // Skip interceptor if forcing deletion.
3874     if (mode != FORCE_DELETION) {
3875       return DeleteElementWithInterceptor(index);
3876     }
3877     mode = JSReceiver::FORCE_DELETION;
3878   }
3879
3880   return GetElementsAccessor()->Delete(this, index, mode);
3881 }
3882
3883
3884 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
3885   if (IsJSProxy()) {
3886     return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
3887   }
3888   return JSObject::cast(this)->DeleteProperty(name, mode);
3889 }
3890
3891
3892 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
3893   if (IsJSProxy()) {
3894     return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
3895   }
3896   return JSObject::cast(this)->DeleteElement(index, mode);
3897 }
3898
3899
3900 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
3901   Isolate* isolate = GetIsolate();
3902   // ECMA-262, 3rd, 8.6.2.5
3903   ASSERT(name->IsString());
3904
3905   // Check access rights if needed.
3906   if (IsAccessCheckNeeded() &&
3907       !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
3908     isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
3909     return isolate->heap()->false_value();
3910   }
3911
3912   if (IsJSGlobalProxy()) {
3913     Object* proto = GetPrototype();
3914     if (proto->IsNull()) return isolate->heap()->false_value();
3915     ASSERT(proto->IsJSGlobalObject());
3916     return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
3917   }
3918
3919   uint32_t index = 0;
3920   if (name->AsArrayIndex(&index)) {
3921     return DeleteElement(index, mode);
3922   } else {
3923     LookupResult result(isolate);
3924     LocalLookup(name, &result);
3925     if (!result.IsProperty()) return isolate->heap()->true_value();
3926     // Ignore attributes if forcing a deletion.
3927     if (result.IsDontDelete() && mode != FORCE_DELETION) {
3928       if (mode == STRICT_DELETION) {
3929         // Deleting a non-configurable property in strict mode.
3930         HandleScope scope(isolate);
3931         Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
3932         return isolate->Throw(*isolate->factory()->NewTypeError(
3933             "strict_delete_property", HandleVector(args, 2)));
3934       }
3935       return isolate->heap()->false_value();
3936     }
3937     // Check for interceptor.
3938     if (result.type() == INTERCEPTOR) {
3939       // Skip interceptor if forcing a deletion.
3940       if (mode == FORCE_DELETION) {
3941         return DeletePropertyPostInterceptor(name, mode);
3942       }
3943       return DeletePropertyWithInterceptor(name);
3944     }
3945     // Normalize object if needed.
3946     Object* obj;
3947     { MaybeObject* maybe_obj =
3948           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3949       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3950     }
3951     // Make sure the properties are normalized before removing the entry.
3952     return DeleteNormalizedProperty(name, mode);
3953   }
3954 }
3955
3956
3957 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
3958                                             ElementsKind kind,
3959                                             Object* object) {
3960   ASSERT(kind == FAST_ELEMENTS ||
3961          kind == DICTIONARY_ELEMENTS);
3962   if (kind == FAST_ELEMENTS) {
3963     int length = IsJSArray()
3964         ? Smi::cast(JSArray::cast(this)->length())->value()
3965         : elements->length();
3966     for (int i = 0; i < length; ++i) {
3967       Object* element = elements->get(i);
3968       if (!element->IsTheHole() && element == object) return true;
3969     }
3970   } else {
3971     Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object);
3972     if (!key->IsUndefined()) return true;
3973   }
3974   return false;
3975 }
3976
3977
3978 // Check whether this object references another object.
3979 bool JSObject::ReferencesObject(Object* obj) {
3980   Map* map_of_this = map();
3981   Heap* heap = GetHeap();
3982   AssertNoAllocation no_alloc;
3983
3984   // Is the object the constructor for this object?
3985   if (map_of_this->constructor() == obj) {
3986     return true;
3987   }
3988
3989   // Is the object the prototype for this object?
3990   if (map_of_this->prototype() == obj) {
3991     return true;
3992   }
3993
3994   // Check if the object is among the named properties.
3995   Object* key = SlowReverseLookup(obj);
3996   if (!key->IsUndefined()) {
3997     return true;
3998   }
3999
4000   // Check if the object is among the indexed properties.
4001   ElementsKind kind = GetElementsKind();
4002   switch (kind) {
4003     case EXTERNAL_PIXEL_ELEMENTS:
4004     case EXTERNAL_BYTE_ELEMENTS:
4005     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4006     case EXTERNAL_SHORT_ELEMENTS:
4007     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4008     case EXTERNAL_INT_ELEMENTS:
4009     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4010     case EXTERNAL_FLOAT_ELEMENTS:
4011     case EXTERNAL_DOUBLE_ELEMENTS:
4012     case FAST_DOUBLE_ELEMENTS:
4013       // Raw pixels and external arrays do not reference other
4014       // objects.
4015       break;
4016     case FAST_SMI_ONLY_ELEMENTS:
4017       break;
4018     case FAST_ELEMENTS:
4019     case DICTIONARY_ELEMENTS: {
4020       FixedArray* elements = FixedArray::cast(this->elements());
4021       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
4022       break;
4023     }
4024     case NON_STRICT_ARGUMENTS_ELEMENTS: {
4025       FixedArray* parameter_map = FixedArray::cast(elements());
4026       // Check the mapped parameters.
4027       int length = parameter_map->length();
4028       for (int i = 2; i < length; ++i) {
4029         Object* value = parameter_map->get(i);
4030         if (!value->IsTheHole() && value == obj) return true;
4031       }
4032       // Check the arguments.
4033       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4034       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
4035       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
4036       break;
4037     }
4038   }
4039
4040   // For functions check the context.
4041   if (IsJSFunction()) {
4042     // Get the constructor function for arguments array.
4043     JSObject* arguments_boilerplate =
4044         heap->isolate()->context()->global_context()->
4045             arguments_boilerplate();
4046     JSFunction* arguments_function =
4047         JSFunction::cast(arguments_boilerplate->map()->constructor());
4048
4049     // Get the context and don't check if it is the global context.
4050     JSFunction* f = JSFunction::cast(this);
4051     Context* context = f->context();
4052     if (context->IsGlobalContext()) {
4053       return false;
4054     }
4055
4056     // Check the non-special context slots.
4057     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
4058       // Only check JS objects.
4059       if (context->get(i)->IsJSObject()) {
4060         JSObject* ctxobj = JSObject::cast(context->get(i));
4061         // If it is an arguments array check the content.
4062         if (ctxobj->map()->constructor() == arguments_function) {
4063           if (ctxobj->ReferencesObject(obj)) {
4064             return true;
4065           }
4066         } else if (ctxobj == obj) {
4067           return true;
4068         }
4069       }
4070     }
4071
4072     // Check the context extension (if any) if it can have references.
4073     if (context->has_extension() && !context->IsCatchContext()) {
4074       return JSObject::cast(context->extension())->ReferencesObject(obj);
4075     }
4076   }
4077
4078   // No references to object.
4079   return false;
4080 }
4081
4082
4083 MaybeObject* JSObject::PreventExtensions() {
4084   Isolate* isolate = GetIsolate();
4085   if (IsAccessCheckNeeded() &&
4086       !isolate->MayNamedAccess(this,
4087                                isolate->heap()->undefined_value(),
4088                                v8::ACCESS_KEYS)) {
4089     isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
4090     return isolate->heap()->false_value();
4091   }
4092
4093   if (IsJSGlobalProxy()) {
4094     Object* proto = GetPrototype();
4095     if (proto->IsNull()) return this;
4096     ASSERT(proto->IsJSGlobalObject());
4097     return JSObject::cast(proto)->PreventExtensions();
4098   }
4099
4100   // It's not possible to seal objects with external array elements
4101   if (HasExternalArrayElements()) {
4102     HandleScope scope(isolate);
4103     Handle<Object> object(this);
4104     Handle<Object> error  =
4105         isolate->factory()->NewTypeError(
4106             "cant_prevent_ext_external_array_elements",
4107             HandleVector(&object, 1));
4108     return isolate->Throw(*error);
4109   }
4110
4111   // If there are fast elements we normalize.
4112   NumberDictionary* dictionary = NULL;
4113   { MaybeObject* maybe = NormalizeElements();
4114     if (!maybe->To<NumberDictionary>(&dictionary)) return maybe;
4115   }
4116   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
4117   // Make sure that we never go back to fast case.
4118   dictionary->set_requires_slow_elements();
4119
4120   // Do a map transition, other objects with this map may still
4121   // be extensible.
4122   Map* new_map;
4123   { MaybeObject* maybe = map()->CopyDropTransitions();
4124     if (!maybe->To<Map>(&new_map)) return maybe;
4125   }
4126   new_map->set_is_extensible(false);
4127   set_map(new_map);
4128   ASSERT(!map()->is_extensible());
4129   return new_map;
4130 }
4131
4132
4133 // Tests for the fast common case for property enumeration:
4134 // - This object and all prototypes has an enum cache (which means that
4135 //   it is no proxy, has no interceptors and needs no access checks).
4136 // - This object has no elements.
4137 // - No prototype has enumerable properties/elements.
4138 bool JSReceiver::IsSimpleEnum() {
4139   Heap* heap = GetHeap();
4140   for (Object* o = this;
4141        o != heap->null_value();
4142        o = JSObject::cast(o)->GetPrototype()) {
4143     if (!o->IsJSObject()) return false;
4144     JSObject* curr = JSObject::cast(o);
4145     if (!curr->map()->instance_descriptors()->HasEnumCache()) return false;
4146     ASSERT(!curr->HasNamedInterceptor());
4147     ASSERT(!curr->HasIndexedInterceptor());
4148     ASSERT(!curr->IsAccessCheckNeeded());
4149     if (curr->NumberOfEnumElements() > 0) return false;
4150     if (curr != this) {
4151       FixedArray* curr_fixed_array =
4152           FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache());
4153       if (curr_fixed_array->length() > 0) return false;
4154     }
4155   }
4156   return true;
4157 }
4158
4159
4160 int Map::NumberOfDescribedProperties() {
4161   int result = 0;
4162   DescriptorArray* descs = instance_descriptors();
4163   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4164     if (descs->IsProperty(i)) result++;
4165   }
4166   return result;
4167 }
4168
4169
4170 int Map::PropertyIndexFor(String* name) {
4171   DescriptorArray* descs = instance_descriptors();
4172   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4173     if (name->Equals(descs->GetKey(i)) && !descs->IsNullDescriptor(i)) {
4174       return descs->GetFieldIndex(i);
4175     }
4176   }
4177   return -1;
4178 }
4179
4180
4181 int Map::NextFreePropertyIndex() {
4182   int max_index = -1;
4183   DescriptorArray* descs = instance_descriptors();
4184   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4185     if (descs->GetType(i) == FIELD) {
4186       int current_index = descs->GetFieldIndex(i);
4187       if (current_index > max_index) max_index = current_index;
4188     }
4189   }
4190   return max_index + 1;
4191 }
4192
4193
4194 AccessorDescriptor* Map::FindAccessor(String* name) {
4195   DescriptorArray* descs = instance_descriptors();
4196   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4197     if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
4198       return descs->GetCallbacks(i);
4199     }
4200   }
4201   return NULL;
4202 }
4203
4204
4205 void JSReceiver::LocalLookup(String* name, LookupResult* result, 
4206                              bool skip_fallback_interceptor) {
4207   ASSERT(name->IsString());
4208
4209   Heap* heap = GetHeap();
4210
4211   if (IsJSGlobalProxy()) {
4212     Object* proto = GetPrototype();
4213     if (proto->IsNull()) return result->NotFound();
4214     ASSERT(proto->IsJSGlobalObject());
4215     return JSReceiver::cast(proto)->LocalLookup(name, result);
4216   }
4217
4218   if (IsJSProxy()) {
4219     result->HandlerResult(JSProxy::cast(this));
4220     return;
4221   }
4222
4223   // Do not use inline caching if the object is a non-global object
4224   // that requires access checks.
4225   if (IsAccessCheckNeeded()) {
4226     result->DisallowCaching();
4227   }
4228
4229   JSObject* js_object = JSObject::cast(this);
4230
4231   // Check __proto__ before interceptor.
4232   if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) {
4233     result->ConstantResult(js_object);
4234     return;
4235   }
4236
4237   // Check for lookup interceptor except when bootstrapping.
4238   bool wouldIntercept = js_object->HasNamedInterceptor() && 
4239                         !heap->isolate()->bootstrapper()->IsActive();
4240   if (wouldIntercept && !map()->named_interceptor_is_fallback()) {
4241     result->InterceptorResult(js_object);
4242     return;
4243   }
4244
4245   js_object->LocalLookupRealNamedProperty(name, result);
4246
4247   if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() &&
4248       map()->named_interceptor_is_fallback()) {
4249     result->InterceptorResult(js_object);
4250     return;
4251   }
4252 }
4253
4254
4255 void JSReceiver::Lookup(String* name, LookupResult* result, 
4256                         bool skip_fallback_interceptor) {
4257   // Ecma-262 3rd 8.6.2.4
4258   Heap* heap = GetHeap();
4259   for (Object* current = this;
4260        current != heap->null_value();
4261        current = JSObject::cast(current)->GetPrototype()) {
4262     JSReceiver::cast(current)->LocalLookup(name, result, skip_fallback_interceptor);
4263     if (result->IsProperty()) return;
4264   }
4265   result->NotFound();
4266 }
4267
4268
4269 // Search object and it's prototype chain for callback properties.
4270 void JSObject::LookupCallback(String* name, LookupResult* result) {
4271   Heap* heap = GetHeap();
4272   for (Object* current = this;
4273        current != heap->null_value() && current->IsJSObject();
4274        current = JSObject::cast(current)->GetPrototype()) {
4275     JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4276     if (result->IsProperty() && result->type() == CALLBACKS) return;
4277   }
4278   result->NotFound();
4279 }
4280
4281
4282 // Search for a getter or setter in an elements dictionary and update its
4283 // attributes.  Returns either undefined if the element is read-only, or the
4284 // getter/setter pair (fixed array) if there is an existing one, or the hole
4285 // value if the element does not exist or is a normal non-getter/setter data
4286 // element.
4287 static Object* UpdateGetterSetterInDictionary(NumberDictionary* dictionary,
4288                                               uint32_t index,
4289                                               PropertyAttributes attributes,
4290                                               Heap* heap) {
4291   int entry = dictionary->FindEntry(index);
4292   if (entry != NumberDictionary::kNotFound) {
4293     Object* result = dictionary->ValueAt(entry);
4294     PropertyDetails details = dictionary->DetailsAt(entry);
4295     if (details.IsReadOnly()) return heap->undefined_value();
4296     if (details.type() == CALLBACKS && result->IsFixedArray()) {
4297       if (details.attributes() != attributes) {
4298         dictionary->DetailsAtPut(entry,
4299                                  PropertyDetails(attributes, CALLBACKS, index));
4300       }
4301       return result;
4302     }
4303   }
4304   return heap->the_hole_value();
4305 }
4306
4307
4308 MaybeObject* JSObject::DefineGetterSetter(String* name,
4309                                           PropertyAttributes attributes) {
4310   Heap* heap = GetHeap();
4311   // Make sure that the top context does not change when doing callbacks or
4312   // interceptor calls.
4313   AssertNoContextChange ncc;
4314
4315   // Try to flatten before operating on the string.
4316   name->TryFlatten();
4317
4318   if (!CanSetCallback(name)) {
4319     return heap->undefined_value();
4320   }
4321
4322   uint32_t index = 0;
4323   bool is_element = name->AsArrayIndex(&index);
4324
4325   if (is_element) {
4326     switch (GetElementsKind()) {
4327       case FAST_SMI_ONLY_ELEMENTS:
4328       case FAST_ELEMENTS:
4329       case FAST_DOUBLE_ELEMENTS:
4330         break;
4331       case EXTERNAL_PIXEL_ELEMENTS:
4332       case EXTERNAL_BYTE_ELEMENTS:
4333       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4334       case EXTERNAL_SHORT_ELEMENTS:
4335       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4336       case EXTERNAL_INT_ELEMENTS:
4337       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4338       case EXTERNAL_FLOAT_ELEMENTS:
4339       case EXTERNAL_DOUBLE_ELEMENTS:
4340         // Ignore getters and setters on pixel and external array
4341         // elements.
4342         return heap->undefined_value();
4343       case DICTIONARY_ELEMENTS: {
4344         Object* probe = UpdateGetterSetterInDictionary(element_dictionary(),
4345                                                        index,
4346                                                        attributes,
4347                                                        heap);
4348         if (!probe->IsTheHole()) return probe;
4349         // Otherwise allow to override it.
4350         break;
4351       }
4352       case NON_STRICT_ARGUMENTS_ELEMENTS: {
4353         // Ascertain whether we have read-only properties or an existing
4354         // getter/setter pair in an arguments elements dictionary backing
4355         // store.
4356         FixedArray* parameter_map = FixedArray::cast(elements());
4357         uint32_t length = parameter_map->length();
4358         Object* probe =
4359             index < (length - 2) ? parameter_map->get(index + 2) : NULL;
4360         if (probe == NULL || probe->IsTheHole()) {
4361           FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4362           if (arguments->IsDictionary()) {
4363             NumberDictionary* dictionary = NumberDictionary::cast(arguments);
4364             probe = UpdateGetterSetterInDictionary(dictionary,
4365                                                    index,
4366                                                    attributes,
4367                                                    heap);
4368             if (!probe->IsTheHole()) return probe;
4369           }
4370         }
4371         break;
4372       }
4373     }
4374   } else {
4375     // Lookup the name.
4376     LookupResult result(heap->isolate());
4377     LocalLookup(name, &result);
4378     if (result.IsProperty()) {
4379       if (result.IsReadOnly()) return heap->undefined_value();
4380       if (result.type() == CALLBACKS) {
4381         Object* obj = result.GetCallbackObject();
4382         // Need to preserve old getters/setters.
4383         if (obj->IsFixedArray()) {
4384           // Use set to update attributes.
4385           return SetPropertyCallback(name, obj, attributes);
4386         }
4387       }
4388     }
4389   }
4390
4391   // Allocate the fixed array to hold getter and setter.
4392   Object* structure;
4393   { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED);
4394     if (!maybe_structure->ToObject(&structure)) return maybe_structure;
4395   }
4396
4397   if (is_element) {
4398     return SetElementCallback(index, structure, attributes);
4399   } else {
4400     return SetPropertyCallback(name, structure, attributes);
4401   }
4402 }
4403
4404
4405 bool JSObject::CanSetCallback(String* name) {
4406   ASSERT(!IsAccessCheckNeeded() ||
4407          GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4408
4409   // Check if there is an API defined callback object which prohibits
4410   // callback overwriting in this object or it's prototype chain.
4411   // This mechanism is needed for instance in a browser setting, where
4412   // certain accessors such as window.location should not be allowed
4413   // to be overwritten because allowing overwriting could potentially
4414   // cause security problems.
4415   LookupResult callback_result(GetIsolate());
4416   LookupCallback(name, &callback_result);
4417   if (callback_result.IsProperty()) {
4418     Object* obj = callback_result.GetCallbackObject();
4419     if (obj->IsAccessorInfo() &&
4420         AccessorInfo::cast(obj)->prohibits_overwriting()) {
4421       return false;
4422     }
4423   }
4424
4425   return true;
4426 }
4427
4428
4429 MaybeObject* JSObject::SetElementCallback(uint32_t index,
4430                                           Object* structure,
4431                                           PropertyAttributes attributes) {
4432   PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4433
4434   // Normalize elements to make this operation simple.
4435   NumberDictionary* dictionary = NULL;
4436   { Object* result;
4437     MaybeObject* maybe = NormalizeElements();
4438     if (!maybe->ToObject(&result)) return maybe;
4439     dictionary = NumberDictionary::cast(result);
4440   }
4441   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
4442
4443   // Update the dictionary with the new CALLBACKS property.
4444   { Object* result;
4445     MaybeObject* maybe = dictionary->Set(index, structure, details);
4446     if (!maybe->ToObject(&result)) return maybe;
4447     dictionary = NumberDictionary::cast(result);
4448   }
4449
4450   dictionary->set_requires_slow_elements();
4451   // Update the dictionary backing store on the object.
4452   if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
4453     // Also delete any parameter alias.
4454     //
4455     // TODO(kmillikin): when deleting the last parameter alias we could
4456     // switch to a direct backing store without the parameter map.  This
4457     // would allow GC of the context.
4458     FixedArray* parameter_map = FixedArray::cast(elements());
4459     uint32_t length = parameter_map->length();
4460     if (index < length - 2) {
4461       parameter_map->set(index + 2, GetHeap()->the_hole_value());
4462     }
4463     parameter_map->set(1, dictionary);
4464   } else {
4465     set_elements(dictionary);
4466   }
4467
4468   return structure;
4469 }
4470
4471
4472 MaybeObject* JSObject::SetPropertyCallback(String* name,
4473                                            Object* structure,
4474                                            PropertyAttributes attributes) {
4475   PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4476
4477   bool convert_back_to_fast = HasFastProperties() &&
4478       (map()->instance_descriptors()->number_of_descriptors()
4479           < DescriptorArray::kMaxNumberOfDescriptors);
4480
4481   // Normalize object to make this operation simple.
4482   Object* ok;
4483   { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4484     if (!maybe_ok->ToObject(&ok)) return maybe_ok;
4485   }
4486
4487   // For the global object allocate a new map to invalidate the global inline
4488   // caches which have a global property cell reference directly in the code.
4489   if (IsGlobalObject()) {
4490     Object* new_map;
4491     { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
4492       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
4493     }
4494     set_map(Map::cast(new_map));
4495     // When running crankshaft, changing the map is not enough. We
4496     // need to deoptimize all functions that rely on this global
4497     // object.
4498     Deoptimizer::DeoptimizeGlobalObject(this);
4499   }
4500
4501   // Update the dictionary with the new CALLBACKS property.
4502   Object* result;
4503   { MaybeObject* maybe_result = SetNormalizedProperty(name, structure, details);
4504     if (!maybe_result->ToObject(&result)) return maybe_result;
4505   }
4506
4507   if (convert_back_to_fast) {
4508     { MaybeObject* maybe_ok = TransformToFastProperties(0);
4509       if (!maybe_ok->ToObject(&ok)) return maybe_ok;
4510     }
4511   }
4512   return result;
4513 }
4514
4515 MaybeObject* JSObject::DefineAccessor(String* name,
4516                                       bool is_getter,
4517                                       Object* fun,
4518                                       PropertyAttributes attributes) {
4519   ASSERT(fun->IsSpecFunction() || fun->IsUndefined());
4520   Isolate* isolate = GetIsolate();
4521   // Check access rights if needed.
4522   if (IsAccessCheckNeeded() &&
4523       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4524     isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4525     return isolate->heap()->undefined_value();
4526   }
4527
4528   if (IsJSGlobalProxy()) {
4529     Object* proto = GetPrototype();
4530     if (proto->IsNull()) return this;
4531     ASSERT(proto->IsJSGlobalObject());
4532     return JSObject::cast(proto)->DefineAccessor(name, is_getter,
4533                                                  fun, attributes);
4534   }
4535
4536   Object* array;
4537   { MaybeObject* maybe_array = DefineGetterSetter(name, attributes);
4538     if (!maybe_array->ToObject(&array)) return maybe_array;
4539   }
4540   if (array->IsUndefined()) return array;
4541   FixedArray::cast(array)->set(is_getter ? 0 : 1, fun);
4542   return this;
4543 }
4544
4545
4546 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
4547   Isolate* isolate = GetIsolate();
4548   String* name = String::cast(info->name());
4549   // Check access rights if needed.
4550   if (IsAccessCheckNeeded() &&
4551       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4552     isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4553     return isolate->heap()->undefined_value();
4554   }
4555
4556   if (IsJSGlobalProxy()) {
4557     Object* proto = GetPrototype();
4558     if (proto->IsNull()) return this;
4559     ASSERT(proto->IsJSGlobalObject());
4560     return JSObject::cast(proto)->DefineAccessor(info);
4561   }
4562
4563   // Make sure that the top context does not change when doing callbacks or
4564   // interceptor calls.
4565   AssertNoContextChange ncc;
4566
4567   // Try to flatten before operating on the string.
4568   name->TryFlatten();
4569
4570   if (!CanSetCallback(name)) {
4571     return isolate->heap()->undefined_value();
4572   }
4573
4574   uint32_t index = 0;
4575   bool is_element = name->AsArrayIndex(&index);
4576
4577   if (is_element) {
4578     if (IsJSArray()) return isolate->heap()->undefined_value();
4579
4580     // Accessors overwrite previous callbacks (cf. with getters/setters).
4581     switch (GetElementsKind()) {
4582       case FAST_SMI_ONLY_ELEMENTS:
4583       case FAST_ELEMENTS:
4584       case FAST_DOUBLE_ELEMENTS:
4585         break;
4586       case EXTERNAL_PIXEL_ELEMENTS:
4587       case EXTERNAL_BYTE_ELEMENTS:
4588       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4589       case EXTERNAL_SHORT_ELEMENTS:
4590       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4591       case EXTERNAL_INT_ELEMENTS:
4592       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4593       case EXTERNAL_FLOAT_ELEMENTS:
4594       case EXTERNAL_DOUBLE_ELEMENTS:
4595         // Ignore getters and setters on pixel and external array
4596         // elements.
4597         return isolate->heap()->undefined_value();
4598       case DICTIONARY_ELEMENTS:
4599         break;
4600       case NON_STRICT_ARGUMENTS_ELEMENTS:
4601         UNIMPLEMENTED();
4602         break;
4603     }
4604
4605     Object* ok;
4606     { MaybeObject* maybe_ok =
4607           SetElementCallback(index, info, info->property_attributes());
4608       if (!maybe_ok->ToObject(&ok)) return maybe_ok;
4609     }
4610   } else {
4611     // Lookup the name.
4612     LookupResult result(isolate);
4613     LocalLookup(name, &result);
4614     // ES5 forbids turning a property into an accessor if it's not
4615     // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
4616     if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) {
4617       return isolate->heap()->undefined_value();
4618     }
4619     Object* ok;
4620     { MaybeObject* maybe_ok =
4621           SetPropertyCallback(name, info, info->property_attributes());
4622       if (!maybe_ok->ToObject(&ok)) return maybe_ok;
4623     }
4624   }
4625
4626   return this;
4627 }
4628
4629
4630 Object* JSObject::LookupAccessor(String* name, bool is_getter) {
4631   Heap* heap = GetHeap();
4632
4633   // Make sure that the top context does not change when doing callbacks or
4634   // interceptor calls.
4635   AssertNoContextChange ncc;
4636
4637   // Check access rights if needed.
4638   if (IsAccessCheckNeeded() &&
4639       !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
4640     heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
4641     return heap->undefined_value();
4642   }
4643
4644   // Make the lookup and include prototypes.
4645   int accessor_index = is_getter ? kGetterIndex : kSetterIndex;
4646   uint32_t index = 0;
4647   if (name->AsArrayIndex(&index)) {
4648     for (Object* obj = this;
4649          obj != heap->null_value();
4650          obj = JSObject::cast(obj)->GetPrototype()) {
4651       JSObject* js_object = JSObject::cast(obj);
4652       if (js_object->HasDictionaryElements()) {
4653         NumberDictionary* dictionary = js_object->element_dictionary();
4654         int entry = dictionary->FindEntry(index);
4655         if (entry != NumberDictionary::kNotFound) {
4656           Object* element = dictionary->ValueAt(entry);
4657           PropertyDetails details = dictionary->DetailsAt(entry);
4658           if (details.type() == CALLBACKS) {
4659             if (element->IsFixedArray()) {
4660               return FixedArray::cast(element)->get(accessor_index);
4661             }
4662           }
4663         }
4664       }
4665     }
4666   } else {
4667     for (Object* obj = this;
4668          obj != heap->null_value();
4669          obj = JSObject::cast(obj)->GetPrototype()) {
4670       LookupResult result(heap->isolate());
4671       JSObject::cast(obj)->LocalLookup(name, &result);
4672       if (result.IsProperty()) {
4673         if (result.IsReadOnly()) return heap->undefined_value();
4674         if (result.type() == CALLBACKS) {
4675           Object* obj = result.GetCallbackObject();
4676           if (obj->IsFixedArray()) {
4677             return FixedArray::cast(obj)->get(accessor_index);
4678           }
4679         }
4680       }
4681     }
4682   }
4683   return heap->undefined_value();
4684 }
4685
4686
4687 Object* JSObject::SlowReverseLookup(Object* value) {
4688   if (HasFastProperties()) {
4689     DescriptorArray* descs = map()->instance_descriptors();
4690     for (int i = 0; i < descs->number_of_descriptors(); i++) {
4691       if (descs->GetType(i) == FIELD) {
4692         if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
4693           return descs->GetKey(i);
4694         }
4695       } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
4696         if (descs->GetConstantFunction(i) == value) {
4697           return descs->GetKey(i);
4698         }
4699       }
4700     }
4701     return GetHeap()->undefined_value();
4702   } else {
4703     return property_dictionary()->SlowReverseLookup(value);
4704   }
4705 }
4706
4707
4708 MaybeObject* Map::CopyDropDescriptors() {
4709   Heap* heap = GetHeap();
4710   Object* result;
4711   { MaybeObject* maybe_result =
4712         heap->AllocateMap(instance_type(), instance_size());
4713     if (!maybe_result->ToObject(&result)) return maybe_result;
4714   }
4715   Map::cast(result)->set_prototype(prototype());
4716   Map::cast(result)->set_constructor(constructor());
4717   // Don't copy descriptors, so map transitions always remain a forest.
4718   // If we retained the same descriptors we would have two maps
4719   // pointing to the same transition which is bad because the garbage
4720   // collector relies on being able to reverse pointers from transitions
4721   // to maps.  If properties need to be retained use CopyDropTransitions.
4722   Map::cast(result)->clear_instance_descriptors();
4723   // Please note instance_type and instance_size are set when allocated.
4724   Map::cast(result)->set_inobject_properties(inobject_properties());
4725   Map::cast(result)->set_unused_property_fields(unused_property_fields());
4726
4727   // If the map has pre-allocated properties always start out with a descriptor
4728   // array describing these properties.
4729   if (pre_allocated_property_fields() > 0) {
4730     ASSERT(constructor()->IsJSFunction());
4731     JSFunction* ctor = JSFunction::cast(constructor());
4732     Object* descriptors;
4733     { MaybeObject* maybe_descriptors =
4734           ctor->initial_map()->instance_descriptors()->RemoveTransitions();
4735       if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
4736     }
4737     Map::cast(result)->set_instance_descriptors(
4738         DescriptorArray::cast(descriptors));
4739     Map::cast(result)->set_pre_allocated_property_fields(
4740         pre_allocated_property_fields());
4741   }
4742   Map::cast(result)->set_bit_field(bit_field());
4743   Map::cast(result)->set_bit_field2(bit_field2());
4744   Map::cast(result)->set_bit_field3(bit_field3());
4745   Map::cast(result)->set_is_shared(false);
4746   Map::cast(result)->ClearCodeCache(heap);
4747   return result;
4748 }
4749
4750
4751 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
4752                                  NormalizedMapSharingMode sharing) {
4753   int new_instance_size = instance_size();
4754   if (mode == CLEAR_INOBJECT_PROPERTIES) {
4755     new_instance_size -= inobject_properties() * kPointerSize;
4756   }
4757
4758   Object* result;
4759   { MaybeObject* maybe_result =
4760         GetHeap()->AllocateMap(instance_type(), new_instance_size);
4761     if (!maybe_result->ToObject(&result)) return maybe_result;
4762   }
4763
4764   if (mode != CLEAR_INOBJECT_PROPERTIES) {
4765     Map::cast(result)->set_inobject_properties(inobject_properties());
4766   }
4767
4768   Map::cast(result)->set_prototype(prototype());
4769   Map::cast(result)->set_constructor(constructor());
4770
4771   Map::cast(result)->set_bit_field(bit_field());
4772   Map::cast(result)->set_bit_field2(bit_field2());
4773   Map::cast(result)->set_bit_field3(bit_field3());
4774
4775   Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
4776
4777 #ifdef DEBUG
4778   if (FLAG_verify_heap && Map::cast(result)->is_shared()) {
4779     Map::cast(result)->SharedMapVerify();
4780   }
4781 #endif
4782
4783   return result;
4784 }
4785
4786
4787 MaybeObject* Map::CopyDropTransitions() {
4788   Object* new_map;
4789   { MaybeObject* maybe_new_map = CopyDropDescriptors();
4790     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
4791   }
4792   Object* descriptors;
4793   { MaybeObject* maybe_descriptors =
4794         instance_descriptors()->RemoveTransitions();
4795     if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
4796   }
4797   cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
4798   return new_map;
4799 }
4800
4801 void Map::UpdateCodeCache(Handle<Map> map,
4802                           Handle<String> name,
4803                           Handle<Code> code) {
4804   Isolate* isolate = map->GetIsolate();
4805   CALL_HEAP_FUNCTION_VOID(isolate,
4806                           map->UpdateCodeCache(*name, *code));
4807 }
4808
4809 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
4810   // Allocate the code cache if not present.
4811   if (code_cache()->IsFixedArray()) {
4812     Object* result;
4813     { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
4814       if (!maybe_result->ToObject(&result)) return maybe_result;
4815     }
4816     set_code_cache(result);
4817   }
4818
4819   // Update the code cache.
4820   return CodeCache::cast(code_cache())->Update(name, code);
4821 }
4822
4823
4824 Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
4825   // Do a lookup if a code cache exists.
4826   if (!code_cache()->IsFixedArray()) {
4827     return CodeCache::cast(code_cache())->Lookup(name, flags);
4828   } else {
4829     return GetHeap()->undefined_value();
4830   }
4831 }
4832
4833
4834 int Map::IndexInCodeCache(Object* name, Code* code) {
4835   // Get the internal index if a code cache exists.
4836   if (!code_cache()->IsFixedArray()) {
4837     return CodeCache::cast(code_cache())->GetIndex(name, code);
4838   }
4839   return -1;
4840 }
4841
4842
4843 void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
4844   // No GC is supposed to happen between a call to IndexInCodeCache and
4845   // RemoveFromCodeCache so the code cache must be there.
4846   ASSERT(!code_cache()->IsFixedArray());
4847   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
4848 }
4849
4850
4851 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
4852   // Traverse the transition tree without using a stack.  We do this by
4853   // reversing the pointers in the maps and descriptor arrays.
4854   Map* current = this;
4855   Map* meta_map = GetHeap()->meta_map();
4856   Object** map_or_index_field = NULL;
4857   while (current != meta_map) {
4858     DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
4859         *RawField(current, Map::kInstanceDescriptorsOrBitField3Offset));
4860     if (!d->IsEmpty()) {
4861       FixedArray* contents = reinterpret_cast<FixedArray*>(
4862           d->get(DescriptorArray::kContentArrayIndex));
4863       map_or_index_field = RawField(contents, HeapObject::kMapOffset);
4864       Object* map_or_index = *map_or_index_field;
4865       bool map_done = true;  // Controls a nested continue statement.
4866       for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0;
4867            i < contents->length();
4868            i += 2) {
4869         PropertyDetails details(Smi::cast(contents->get(i + 1)));
4870         if (details.IsTransition()) {
4871           // Found a map in the transition array.  We record our progress in
4872           // the transition array by recording the current map in the map field
4873           // of the next map and recording the index in the transition array in
4874           // the map field of the array.
4875           Map* next = Map::cast(contents->get(i));
4876           next->set_map_unsafe(current);
4877           *map_or_index_field = Smi::FromInt(i + 2);
4878           current = next;
4879           map_done = false;
4880           break;
4881         }
4882       }
4883       if (!map_done) continue;
4884     } else {
4885       map_or_index_field = NULL;
4886     }
4887     // That was the regular transitions, now for the prototype transitions.
4888     FixedArray* prototype_transitions =
4889         current->unchecked_prototype_transitions();
4890     Object** proto_map_or_index_field =
4891         RawField(prototype_transitions, HeapObject::kMapOffset);
4892     Object* map_or_index = *proto_map_or_index_field;
4893     const int start = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
4894     int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : start;
4895     if (i < prototype_transitions->length()) {
4896       // Found a map in the prototype transition array.  Record progress in
4897       // an analogous way to the regular transitions array above.
4898       Object* perhaps_map = prototype_transitions->get(i);
4899       if (perhaps_map->IsMap()) {
4900         Map* next = Map::cast(perhaps_map);
4901         next->set_map_unsafe(current);
4902         *proto_map_or_index_field =
4903             Smi::FromInt(i + kProtoTransitionElementsPerEntry);
4904         current = next;
4905         continue;
4906       }
4907     }
4908     *proto_map_or_index_field = GetHeap()->fixed_array_map();
4909     if (map_or_index_field != NULL) {
4910       *map_or_index_field = GetHeap()->fixed_array_map();
4911     }
4912
4913     // The callback expects a map to have a real map as its map, so we save
4914     // the map field, which is being used to track the traversal and put the
4915     // correct map (the meta_map) in place while we do the callback.
4916     Map* prev = current->map();
4917     current->set_map_unsafe(meta_map);
4918     callback(current, data);
4919     current = prev;
4920   }
4921 }
4922
4923
4924 MaybeObject* CodeCache::Update(String* name, Code* code) {
4925   // The number of monomorphic stubs for normal load/store/call IC's can grow to
4926   // a large number and therefore they need to go into a hash table. They are
4927   // used to load global properties from cells.
4928   if (code->type() == NORMAL) {
4929     // Make sure that a hash table is allocated for the normal load code cache.
4930     if (normal_type_cache()->IsUndefined()) {
4931       Object* result;
4932       { MaybeObject* maybe_result =
4933             CodeCacheHashTable::Allocate(CodeCacheHashTable::kInitialSize);
4934         if (!maybe_result->ToObject(&result)) return maybe_result;
4935       }
4936       set_normal_type_cache(result);
4937     }
4938     return UpdateNormalTypeCache(name, code);
4939   } else {
4940     ASSERT(default_cache()->IsFixedArray());
4941     return UpdateDefaultCache(name, code);
4942   }
4943 }
4944
4945
4946 MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) {
4947   // When updating the default code cache we disregard the type encoded in the
4948   // flags. This allows call constant stubs to overwrite call field
4949   // stubs, etc.
4950   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
4951
4952   // First check whether we can update existing code cache without
4953   // extending it.
4954   FixedArray* cache = default_cache();
4955   int length = cache->length();
4956   int deleted_index = -1;
4957   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
4958     Object* key = cache->get(i);
4959     if (key->IsNull()) {
4960       if (deleted_index < 0) deleted_index = i;
4961       continue;
4962     }
4963     if (key->IsUndefined()) {
4964       if (deleted_index >= 0) i = deleted_index;
4965       cache->set(i + kCodeCacheEntryNameOffset, name);
4966       cache->set(i + kCodeCacheEntryCodeOffset, code);
4967       return this;
4968     }
4969     if (name->Equals(String::cast(key))) {
4970       Code::Flags found =
4971           Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
4972       if (Code::RemoveTypeFromFlags(found) == flags) {
4973         cache->set(i + kCodeCacheEntryCodeOffset, code);
4974         return this;
4975       }
4976     }
4977   }
4978
4979   // Reached the end of the code cache.  If there were deleted
4980   // elements, reuse the space for the first of them.
4981   if (deleted_index >= 0) {
4982     cache->set(deleted_index + kCodeCacheEntryNameOffset, name);
4983     cache->set(deleted_index + kCodeCacheEntryCodeOffset, code);
4984     return this;
4985   }
4986
4987   // Extend the code cache with some new entries (at least one). Must be a
4988   // multiple of the entry size.
4989   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
4990   new_length = new_length - new_length % kCodeCacheEntrySize;
4991   ASSERT((new_length % kCodeCacheEntrySize) == 0);
4992   Object* result;
4993   { MaybeObject* maybe_result = cache->CopySize(new_length);
4994     if (!maybe_result->ToObject(&result)) return maybe_result;
4995   }
4996
4997   // Add the (name, code) pair to the new cache.
4998   cache = FixedArray::cast(result);
4999   cache->set(length + kCodeCacheEntryNameOffset, name);
5000   cache->set(length + kCodeCacheEntryCodeOffset, code);
5001   set_default_cache(cache);
5002   return this;
5003 }
5004
5005
5006 MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) {
5007   // Adding a new entry can cause a new cache to be allocated.
5008   CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5009   Object* new_cache;
5010   { MaybeObject* maybe_new_cache = cache->Put(name, code);
5011     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5012   }
5013   set_normal_type_cache(new_cache);
5014   return this;
5015 }
5016
5017
5018 Object* CodeCache::Lookup(String* name, Code::Flags flags) {
5019   if (Code::ExtractTypeFromFlags(flags) == NORMAL) {
5020     return LookupNormalTypeCache(name, flags);
5021   } else {
5022     return LookupDefaultCache(name, flags);
5023   }
5024 }
5025
5026
5027 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) {
5028   FixedArray* cache = default_cache();
5029   int length = cache->length();
5030   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
5031     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
5032     // Skip deleted elements.
5033     if (key->IsNull()) continue;
5034     if (key->IsUndefined()) return key;
5035     if (name->Equals(String::cast(key))) {
5036       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
5037       if (code->flags() == flags) {
5038         return code;
5039       }
5040     }
5041   }
5042   return GetHeap()->undefined_value();
5043 }
5044
5045
5046 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) {
5047   if (!normal_type_cache()->IsUndefined()) {
5048     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5049     return cache->Lookup(name, flags);
5050   } else {
5051     return GetHeap()->undefined_value();
5052   }
5053 }
5054
5055
5056 int CodeCache::GetIndex(Object* name, Code* code) {
5057   if (code->type() == NORMAL) {
5058     if (normal_type_cache()->IsUndefined()) return -1;
5059     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5060     return cache->GetIndex(String::cast(name), code->flags());
5061   }
5062
5063   FixedArray* array = default_cache();
5064   int len = array->length();
5065   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
5066     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
5067   }
5068   return -1;
5069 }
5070
5071
5072 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
5073   if (code->type() == NORMAL) {
5074     ASSERT(!normal_type_cache()->IsUndefined());
5075     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5076     ASSERT(cache->GetIndex(String::cast(name), code->flags()) == index);
5077     cache->RemoveByIndex(index);
5078   } else {
5079     FixedArray* array = default_cache();
5080     ASSERT(array->length() >= index && array->get(index)->IsCode());
5081     // Use null instead of undefined for deleted elements to distinguish
5082     // deleted elements from unused elements.  This distinction is used
5083     // when looking up in the cache and when updating the cache.
5084     ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
5085     array->set_null(index - 1);  // Name.
5086     array->set_null(index);  // Code.
5087   }
5088 }
5089
5090
5091 // The key in the code cache hash table consists of the property name and the
5092 // code object. The actual match is on the name and the code flags. If a key
5093 // is created using the flags and not a code object it can only be used for
5094 // lookup not to create a new entry.
5095 class CodeCacheHashTableKey : public HashTableKey {
5096  public:
5097   CodeCacheHashTableKey(String* name, Code::Flags flags)
5098       : name_(name), flags_(flags), code_(NULL) { }
5099
5100   CodeCacheHashTableKey(String* name, Code* code)
5101       : name_(name),
5102         flags_(code->flags()),
5103         code_(code) { }
5104
5105
5106   bool IsMatch(Object* other) {
5107     if (!other->IsFixedArray()) return false;
5108     FixedArray* pair = FixedArray::cast(other);
5109     String* name = String::cast(pair->get(0));
5110     Code::Flags flags = Code::cast(pair->get(1))->flags();
5111     if (flags != flags_) {
5112       return false;
5113     }
5114     return name_->Equals(name);
5115   }
5116
5117   static uint32_t NameFlagsHashHelper(String* name, Code::Flags flags) {
5118     return name->Hash() ^ flags;
5119   }
5120
5121   uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); }
5122
5123   uint32_t HashForObject(Object* obj) {
5124     FixedArray* pair = FixedArray::cast(obj);
5125     String* name = String::cast(pair->get(0));
5126     Code* code = Code::cast(pair->get(1));
5127     return NameFlagsHashHelper(name, code->flags());
5128   }
5129
5130   MUST_USE_RESULT MaybeObject* AsObject() {
5131     ASSERT(code_ != NULL);
5132     Object* obj;
5133     { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2);
5134       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5135     }
5136     FixedArray* pair = FixedArray::cast(obj);
5137     pair->set(0, name_);
5138     pair->set(1, code_);
5139     return pair;
5140   }
5141
5142  private:
5143   String* name_;
5144   Code::Flags flags_;
5145   // TODO(jkummerow): We should be able to get by without this.
5146   Code* code_;
5147 };
5148
5149
5150 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) {
5151   CodeCacheHashTableKey key(name, flags);
5152   int entry = FindEntry(&key);
5153   if (entry == kNotFound) return GetHeap()->undefined_value();
5154   return get(EntryToIndex(entry) + 1);
5155 }
5156
5157
5158 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) {
5159   CodeCacheHashTableKey key(name, code);
5160   Object* obj;
5161   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5162     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5163   }
5164
5165   // Don't use |this|, as the table might have grown.
5166   CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
5167
5168   int entry = cache->FindInsertionEntry(key.Hash());
5169   Object* k;
5170   { MaybeObject* maybe_k = key.AsObject();
5171     if (!maybe_k->ToObject(&k)) return maybe_k;
5172   }
5173
5174   cache->set(EntryToIndex(entry), k);
5175   cache->set(EntryToIndex(entry) + 1, code);
5176   cache->ElementAdded();
5177   return cache;
5178 }
5179
5180
5181 int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) {
5182   CodeCacheHashTableKey key(name, flags);
5183   int entry = FindEntry(&key);
5184   return (entry == kNotFound) ? -1 : entry;
5185 }
5186
5187
5188 void CodeCacheHashTable::RemoveByIndex(int index) {
5189   ASSERT(index >= 0);
5190   Heap* heap = GetHeap();
5191   set(EntryToIndex(index), heap->null_value());
5192   set(EntryToIndex(index) + 1, heap->null_value());
5193   ElementRemoved();
5194 }
5195
5196
5197 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache,
5198                                   MapHandleList* maps,
5199                                   Code::Flags flags,
5200                                   Handle<Code> code) {
5201   Isolate* isolate = cache->GetIsolate();
5202   CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code));
5203 }
5204
5205
5206 MaybeObject* PolymorphicCodeCache::Update(MapHandleList* maps,
5207                                           Code::Flags flags,
5208                                           Code* code) {
5209   // Initialize cache if necessary.
5210   if (cache()->IsUndefined()) {
5211     Object* result;
5212     { MaybeObject* maybe_result =
5213           PolymorphicCodeCacheHashTable::Allocate(
5214               PolymorphicCodeCacheHashTable::kInitialSize);
5215       if (!maybe_result->ToObject(&result)) return maybe_result;
5216     }
5217     set_cache(result);
5218   } else {
5219     // This entry shouldn't be contained in the cache yet.
5220     ASSERT(PolymorphicCodeCacheHashTable::cast(cache())
5221                ->Lookup(maps, flags)->IsUndefined());
5222   }
5223   PolymorphicCodeCacheHashTable* hash_table =
5224       PolymorphicCodeCacheHashTable::cast(cache());
5225   Object* new_cache;
5226   { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
5227     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5228   }
5229   set_cache(new_cache);
5230   return this;
5231 }
5232
5233
5234 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
5235                                             Code::Flags flags) {
5236   if (!cache()->IsUndefined()) {
5237     PolymorphicCodeCacheHashTable* hash_table =
5238         PolymorphicCodeCacheHashTable::cast(cache());
5239     return Handle<Object>(hash_table->Lookup(maps, flags));
5240   } else {
5241     return GetIsolate()->factory()->undefined_value();
5242   }
5243 }
5244
5245
5246 // Despite their name, object of this class are not stored in the actual
5247 // hash table; instead they're temporarily used for lookups. It is therefore
5248 // safe to have a weak (non-owning) pointer to a MapList as a member field.
5249 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
5250  public:
5251   // Callers must ensure that |maps| outlives the newly constructed object.
5252   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
5253       : maps_(maps),
5254         code_flags_(code_flags) {}
5255
5256   bool IsMatch(Object* other) {
5257     MapHandleList other_maps(kDefaultListAllocationSize);
5258     int other_flags;
5259     FromObject(other, &other_flags, &other_maps);
5260     if (code_flags_ != other_flags) return false;
5261     if (maps_->length() != other_maps.length()) return false;
5262     // Compare just the hashes first because it's faster.
5263     int this_hash = MapsHashHelper(maps_, code_flags_);
5264     int other_hash = MapsHashHelper(&other_maps, other_flags);
5265     if (this_hash != other_hash) return false;
5266
5267     // Full comparison: for each map in maps_, look for an equivalent map in
5268     // other_maps. This implementation is slow, but probably good enough for
5269     // now because the lists are short (<= 4 elements currently).
5270     for (int i = 0; i < maps_->length(); ++i) {
5271       bool match_found = false;
5272       for (int j = 0; j < other_maps.length(); ++j) {
5273         if (maps_->at(i)->EquivalentTo(*other_maps.at(j))) {
5274           match_found = true;
5275           break;
5276         }
5277       }
5278       if (!match_found) return false;
5279     }
5280     return true;
5281   }
5282
5283   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
5284     uint32_t hash = code_flags;
5285     for (int i = 0; i < maps->length(); ++i) {
5286       hash ^= maps->at(i)->Hash();
5287     }
5288     return hash;
5289   }
5290
5291   uint32_t Hash() {
5292     return MapsHashHelper(maps_, code_flags_);
5293   }
5294
5295   uint32_t HashForObject(Object* obj) {
5296     MapHandleList other_maps(kDefaultListAllocationSize);
5297     int other_flags;
5298     FromObject(obj, &other_flags, &other_maps);
5299     return MapsHashHelper(&other_maps, other_flags);
5300   }
5301
5302   MUST_USE_RESULT MaybeObject* AsObject() {
5303     Object* obj;
5304     // The maps in |maps_| must be copied to a newly allocated FixedArray,
5305     // both because the referenced MapList is short-lived, and because C++
5306     // objects can't be stored in the heap anyway.
5307     { MaybeObject* maybe_obj =
5308         HEAP->AllocateUninitializedFixedArray(maps_->length() + 1);
5309       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5310     }
5311     FixedArray* list = FixedArray::cast(obj);
5312     list->set(0, Smi::FromInt(code_flags_));
5313     for (int i = 0; i < maps_->length(); ++i) {
5314       list->set(i + 1, *maps_->at(i));
5315     }
5316     return list;
5317   }
5318
5319  private:
5320   static MapHandleList* FromObject(Object* obj,
5321                                    int* code_flags,
5322                                    MapHandleList* maps) {
5323     FixedArray* list = FixedArray::cast(obj);
5324     maps->Rewind(0);
5325     *code_flags = Smi::cast(list->get(0))->value();
5326     for (int i = 1; i < list->length(); ++i) {
5327       maps->Add(Handle<Map>(Map::cast(list->get(i))));
5328     }
5329     return maps;
5330   }
5331
5332   MapHandleList* maps_;  // weak.
5333   int code_flags_;
5334   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
5335 };
5336
5337
5338 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
5339                                               int code_flags) {
5340   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5341   int entry = FindEntry(&key);
5342   if (entry == kNotFound) return GetHeap()->undefined_value();
5343   return get(EntryToIndex(entry) + 1);
5344 }
5345
5346
5347 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps,
5348                                                 int code_flags,
5349                                                 Code* code) {
5350   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5351   Object* obj;
5352   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5353     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5354   }
5355   PolymorphicCodeCacheHashTable* cache =
5356       reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
5357   int entry = cache->FindInsertionEntry(key.Hash());
5358   { MaybeObject* maybe_obj = key.AsObject();
5359     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5360   }
5361   cache->set(EntryToIndex(entry), obj);
5362   cache->set(EntryToIndex(entry) + 1, code);
5363   cache->ElementAdded();
5364   return cache;
5365 }
5366
5367
5368 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
5369   ElementsAccessor* accessor = array->GetElementsAccessor();
5370   MaybeObject* maybe_result =
5371       accessor->AddElementsToFixedArray(array->elements(), this, array, array);
5372   FixedArray* result;
5373   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
5374 #ifdef DEBUG
5375   if (FLAG_enable_slow_asserts) {
5376     for (int i = 0; i < result->length(); i++) {
5377       Object* current = result->get(i);
5378       ASSERT(current->IsNumber() || current->IsString());
5379     }
5380   }
5381 #endif
5382   return result;
5383 }
5384
5385
5386 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
5387   ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
5388   MaybeObject* maybe_result =
5389       accessor->AddElementsToFixedArray(other, this, NULL, NULL);
5390   FixedArray* result;
5391   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
5392 #ifdef DEBUG
5393   if (FLAG_enable_slow_asserts) {
5394     for (int i = 0; i < result->length(); i++) {
5395       Object* current = result->get(i);
5396       ASSERT(current->IsNumber() || current->IsString());
5397     }
5398   }
5399 #endif
5400   return result;
5401 }
5402
5403
5404 MaybeObject* FixedArray::CopySize(int new_length) {
5405   Heap* heap = GetHeap();
5406   if (new_length == 0) return heap->empty_fixed_array();
5407   Object* obj;
5408   { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length);
5409     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5410   }
5411   FixedArray* result = FixedArray::cast(obj);
5412   // Copy the content
5413   AssertNoAllocation no_gc;
5414   int len = length();
5415   if (new_length < len) len = new_length;
5416   result->set_map(map());
5417   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
5418   for (int i = 0; i < len; i++) {
5419     result->set(i, get(i), mode);
5420   }
5421   return result;
5422 }
5423
5424
5425 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
5426   AssertNoAllocation no_gc;
5427   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
5428   for (int index = 0; index < len; index++) {
5429     dest->set(dest_pos+index, get(pos+index), mode);
5430   }
5431 }
5432
5433
5434 #ifdef DEBUG
5435 bool FixedArray::IsEqualTo(FixedArray* other) {
5436   if (length() != other->length()) return false;
5437   for (int i = 0 ; i < length(); ++i) {
5438     if (get(i) != other->get(i)) return false;
5439   }
5440   return true;
5441 }
5442 #endif
5443
5444
5445 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
5446   Heap* heap = Isolate::Current()->heap();
5447   if (number_of_descriptors == 0) {
5448     return heap->empty_descriptor_array();
5449   }
5450   // Allocate the array of keys.
5451   Object* array;
5452   { MaybeObject* maybe_array =
5453         heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
5454     if (!maybe_array->ToObject(&array)) return maybe_array;
5455   }
5456   // Do not use DescriptorArray::cast on incomplete object.
5457   FixedArray* result = FixedArray::cast(array);
5458
5459   // Allocate the content array and set it in the descriptor array.
5460   { MaybeObject* maybe_array =
5461         heap->AllocateFixedArray(number_of_descriptors << 1);
5462     if (!maybe_array->ToObject(&array)) return maybe_array;
5463   }
5464   result->set(kBitField3StorageIndex, Smi::FromInt(0));
5465   result->set(kContentArrayIndex, array);
5466   result->set(kEnumerationIndexIndex,
5467               Smi::FromInt(PropertyDetails::kInitialIndex));
5468   return result;
5469 }
5470
5471
5472 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
5473                                    FixedArray* new_cache) {
5474   ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
5475   if (HasEnumCache()) {
5476     FixedArray::cast(get(kEnumerationIndexIndex))->
5477       set(kEnumCacheBridgeCacheIndex, new_cache);
5478   } else {
5479     if (IsEmpty()) return;  // Do nothing for empty descriptor array.
5480     FixedArray::cast(bridge_storage)->
5481       set(kEnumCacheBridgeCacheIndex, new_cache);
5482     NoWriteBarrierSet(FixedArray::cast(bridge_storage),
5483                       kEnumCacheBridgeEnumIndex,
5484                       get(kEnumerationIndexIndex));
5485     set(kEnumerationIndexIndex, bridge_storage);
5486   }
5487 }
5488
5489
5490 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor,
5491                                          TransitionFlag transition_flag) {
5492   // Transitions are only kept when inserting another transition.
5493   // This precondition is not required by this function's implementation, but
5494   // is currently required by the semantics of maps, so we check it.
5495   // Conversely, we filter after replacing, so replacing a transition and
5496   // removing all other transitions is not supported.
5497   bool remove_transitions = transition_flag == REMOVE_TRANSITIONS;
5498   ASSERT(remove_transitions == !descriptor->GetDetails().IsTransition());
5499   ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR);
5500
5501   // Ensure the key is a symbol.
5502   Object* result;
5503   { MaybeObject* maybe_result = descriptor->KeyToSymbol();
5504     if (!maybe_result->ToObject(&result)) return maybe_result;
5505   }
5506
5507   int transitions = 0;
5508   int null_descriptors = 0;
5509   if (remove_transitions) {
5510     for (int i = 0; i < number_of_descriptors(); i++) {
5511       if (IsTransition(i)) transitions++;
5512       if (IsNullDescriptor(i)) null_descriptors++;
5513     }
5514   } else {
5515     for (int i = 0; i < number_of_descriptors(); i++) {
5516       if (IsNullDescriptor(i)) null_descriptors++;
5517     }
5518   }
5519   int new_size = number_of_descriptors() - transitions - null_descriptors;
5520
5521   // If key is in descriptor, we replace it in-place when filtering.
5522   // Count a null descriptor for key as inserted, not replaced.
5523   int index = Search(descriptor->GetKey());
5524   const bool inserting = (index == kNotFound);
5525   const bool replacing = !inserting;
5526   bool keep_enumeration_index = false;
5527   if (inserting) {
5528     ++new_size;
5529   }
5530   if (replacing) {
5531     // We are replacing an existing descriptor.  We keep the enumeration
5532     // index of a visible property.
5533     PropertyType t = PropertyDetails(GetDetails(index)).type();
5534     if (t == CONSTANT_FUNCTION ||
5535         t == FIELD ||
5536         t == CALLBACKS ||
5537         t == INTERCEPTOR) {
5538       keep_enumeration_index = true;
5539     } else if (remove_transitions) {
5540      // Replaced descriptor has been counted as removed if it is
5541      // a transition that will be replaced.  Adjust count in this case.
5542       ++new_size;
5543     }
5544   }
5545
5546   DescriptorArray* new_descriptors;
5547   { MaybeObject* maybe_result = Allocate(new_size);
5548     if (!maybe_result->To<DescriptorArray>(&new_descriptors)) {
5549       return maybe_result;
5550     }
5551   }
5552
5553   DescriptorArray::WhitenessWitness witness(new_descriptors);
5554
5555   // Set the enumeration index in the descriptors and set the enumeration index
5556   // in the result.
5557   int enumeration_index = NextEnumerationIndex();
5558   if (!descriptor->GetDetails().IsTransition()) {
5559     if (keep_enumeration_index) {
5560       descriptor->SetEnumerationIndex(
5561           PropertyDetails(GetDetails(index)).index());
5562     } else {
5563       descriptor->SetEnumerationIndex(enumeration_index);
5564       ++enumeration_index;
5565     }
5566   }
5567   new_descriptors->SetNextEnumerationIndex(enumeration_index);
5568
5569   // Copy the descriptors, filtering out transitions and null descriptors,
5570   // and inserting or replacing a descriptor.
5571   uint32_t descriptor_hash = descriptor->GetKey()->Hash();
5572   int from_index = 0;
5573   int to_index = 0;
5574
5575   for (; from_index < number_of_descriptors(); from_index++) {
5576     String* key = GetKey(from_index);
5577     if (key->Hash() > descriptor_hash || key == descriptor->GetKey()) {
5578       break;
5579     }
5580     if (IsNullDescriptor(from_index)) continue;
5581     if (remove_transitions && IsTransition(from_index)) continue;
5582     new_descriptors->CopyFrom(to_index++, this, from_index, witness);
5583   }
5584
5585   new_descriptors->Set(to_index++, descriptor, witness);
5586   if (replacing) from_index++;
5587
5588   for (; from_index < number_of_descriptors(); from_index++) {
5589     if (IsNullDescriptor(from_index)) continue;
5590     if (remove_transitions && IsTransition(from_index)) continue;
5591     new_descriptors->CopyFrom(to_index++, this, from_index, witness);
5592   }
5593
5594   ASSERT(to_index == new_descriptors->number_of_descriptors());
5595   SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5596
5597   return new_descriptors;
5598 }
5599
5600
5601 MaybeObject* DescriptorArray::RemoveTransitions() {
5602   // Remove all transitions and null descriptors. Return a copy of the array
5603   // with all transitions removed, or a Failure object if the new array could
5604   // not be allocated.
5605
5606   // Compute the size of the map transition entries to be removed.
5607   int num_removed = 0;
5608   for (int i = 0; i < number_of_descriptors(); i++) {
5609     if (!IsProperty(i)) num_removed++;
5610   }
5611
5612   // Allocate the new descriptor array.
5613   DescriptorArray* new_descriptors;
5614   { MaybeObject* maybe_result = Allocate(number_of_descriptors() - num_removed);
5615     if (!maybe_result->To<DescriptorArray>(&new_descriptors)) {
5616       return maybe_result;
5617     }
5618   }
5619
5620   DescriptorArray::WhitenessWitness witness(new_descriptors);
5621
5622   // Copy the content.
5623   int next_descriptor = 0;
5624   for (int i = 0; i < number_of_descriptors(); i++) {
5625     if (IsProperty(i)) {
5626       new_descriptors->CopyFrom(next_descriptor++, this, i, witness);
5627     }
5628   }
5629   ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
5630
5631   return new_descriptors;
5632 }
5633
5634
5635 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
5636   // In-place heap sort.
5637   int len = number_of_descriptors();
5638
5639   // Bottom-up max-heap construction.
5640   // Index of the last node with children
5641   const int max_parent_index = (len / 2) - 1;
5642   for (int i = max_parent_index; i >= 0; --i) {
5643     int parent_index = i;
5644     const uint32_t parent_hash = GetKey(i)->Hash();
5645     while (parent_index <= max_parent_index) {
5646       int child_index = 2 * parent_index + 1;
5647       uint32_t child_hash = GetKey(child_index)->Hash();
5648       if (child_index + 1 < len) {
5649         uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
5650         if (right_child_hash > child_hash) {
5651           child_index++;
5652           child_hash = right_child_hash;
5653         }
5654       }
5655       if (child_hash <= parent_hash) break;
5656       NoWriteBarrierSwapDescriptors(parent_index, child_index);
5657       // Now element at child_index could be < its children.
5658       parent_index = child_index;  // parent_hash remains correct.
5659     }
5660   }
5661
5662   // Extract elements and create sorted array.
5663   for (int i = len - 1; i > 0; --i) {
5664     // Put max element at the back of the array.
5665     NoWriteBarrierSwapDescriptors(0, i);
5666     // Shift down the new top element.
5667     int parent_index = 0;
5668     const uint32_t parent_hash = GetKey(parent_index)->Hash();
5669     const int max_parent_index = (i / 2) - 1;
5670     while (parent_index <= max_parent_index) {
5671       int child_index = parent_index * 2 + 1;
5672       uint32_t child_hash = GetKey(child_index)->Hash();
5673       if (child_index + 1 < i) {
5674         uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
5675         if (right_child_hash > child_hash) {
5676           child_index++;
5677           child_hash = right_child_hash;
5678         }
5679       }
5680       if (child_hash <= parent_hash) break;
5681       NoWriteBarrierSwapDescriptors(parent_index, child_index);
5682       parent_index = child_index;
5683     }
5684   }
5685 }
5686
5687
5688 void DescriptorArray::Sort(const WhitenessWitness& witness) {
5689   SortUnchecked(witness);
5690   SLOW_ASSERT(IsSortedNoDuplicates());
5691 }
5692
5693
5694 int DescriptorArray::BinarySearch(String* name, int low, int high) {
5695   uint32_t hash = name->Hash();
5696
5697   while (low <= high) {
5698     int mid = (low + high) / 2;
5699     String* mid_name = GetKey(mid);
5700     uint32_t mid_hash = mid_name->Hash();
5701
5702     if (mid_hash > hash) {
5703       high = mid - 1;
5704       continue;
5705     }
5706     if (mid_hash < hash) {
5707       low = mid + 1;
5708       continue;
5709     }
5710     // Found an element with the same hash-code.
5711     ASSERT(hash == mid_hash);
5712     // There might be more, so we find the first one and
5713     // check them all to see if we have a match.
5714     if (name == mid_name  && !is_null_descriptor(mid)) return mid;
5715     while ((mid > low) && (GetKey(mid - 1)->Hash() == hash)) mid--;
5716     for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) {
5717       if (GetKey(mid)->Equals(name) && !is_null_descriptor(mid)) return mid;
5718     }
5719     break;
5720   }
5721   return kNotFound;
5722 }
5723
5724
5725 int DescriptorArray::LinearSearch(String* name, int len) {
5726   uint32_t hash = name->Hash();
5727   for (int number = 0; number < len; number++) {
5728     String* entry = GetKey(number);
5729     if ((entry->Hash() == hash) &&
5730         name->Equals(entry) &&
5731         !is_null_descriptor(number)) {
5732       return number;
5733     }
5734   }
5735   return kNotFound;
5736 }
5737
5738
5739 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count,
5740                                                PretenureFlag pretenure) {
5741   ASSERT(deopt_entry_count > 0);
5742   return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count),
5743                                   pretenure);
5744 }
5745
5746
5747 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points,
5748                                                 PretenureFlag pretenure) {
5749   if (number_of_deopt_points == 0) return HEAP->empty_fixed_array();
5750   return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points),
5751                                   pretenure);
5752 }
5753
5754
5755 #ifdef DEBUG
5756 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
5757   if (IsEmpty()) return other->IsEmpty();
5758   if (other->IsEmpty()) return false;
5759   if (length() != other->length()) return false;
5760   for (int i = 0; i < length(); ++i) {
5761     if (get(i) != other->get(i) && i != kContentArrayIndex) return false;
5762   }
5763   return GetContentArray()->IsEqualTo(other->GetContentArray());
5764 }
5765 #endif
5766
5767
5768 bool String::LooksValid() {
5769   if (!Isolate::Current()->heap()->Contains(this)) return false;
5770   return true;
5771 }
5772
5773
5774 String::FlatContent String::GetFlatContent() {
5775   int length = this->length();
5776   StringShape shape(this);
5777   String* string = this;
5778   int offset = 0;
5779   if (shape.representation_tag() == kConsStringTag) {
5780     ConsString* cons = ConsString::cast(string);
5781     if (cons->second()->length() != 0) {
5782       return FlatContent();
5783     }
5784     string = cons->first();
5785     shape = StringShape(string);
5786   }
5787   if (shape.representation_tag() == kSlicedStringTag) {
5788     SlicedString* slice = SlicedString::cast(string);
5789     offset = slice->offset();
5790     string = slice->parent();
5791     shape = StringShape(string);
5792     ASSERT(shape.representation_tag() != kConsStringTag &&
5793            shape.representation_tag() != kSlicedStringTag);
5794   }
5795   if (shape.encoding_tag() == kAsciiStringTag) {
5796     const char* start;
5797     if (shape.representation_tag() == kSeqStringTag) {
5798       start = SeqAsciiString::cast(string)->GetChars();
5799     } else {
5800       start = ExternalAsciiString::cast(string)->resource()->data();
5801     }
5802     return FlatContent(Vector<const char>(start + offset, length));
5803   } else {
5804     ASSERT(shape.encoding_tag() == kTwoByteStringTag);
5805     const uc16* start;
5806     if (shape.representation_tag() == kSeqStringTag) {
5807       start = SeqTwoByteString::cast(string)->GetChars();
5808     } else {
5809       start = ExternalTwoByteString::cast(string)->resource()->data();
5810     }
5811     return FlatContent(Vector<const uc16>(start + offset, length));
5812   }
5813 }
5814
5815
5816 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
5817                                           RobustnessFlag robust_flag,
5818                                           int offset,
5819                                           int length,
5820                                           int* length_return) {
5821   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
5822     return SmartArrayPointer<char>(NULL);
5823   }
5824   Heap* heap = GetHeap();
5825
5826   // Negative length means the to the end of the string.
5827   if (length < 0) length = kMaxInt - offset;
5828
5829   // Compute the size of the UTF-8 string. Start at the specified offset.
5830   Access<StringInputBuffer> buffer(
5831       heap->isolate()->objects_string_input_buffer());
5832   buffer->Reset(offset, this);
5833   int character_position = offset;
5834   int utf8_bytes = 0;
5835   while (buffer->has_more()) {
5836     uint16_t character = buffer->GetNext();
5837     if (character_position < offset + length) {
5838       utf8_bytes += unibrow::Utf8::Length(character);
5839     }
5840     character_position++;
5841   }
5842
5843   if (length_return) {
5844     *length_return = utf8_bytes;
5845   }
5846
5847   char* result = NewArray<char>(utf8_bytes + 1);
5848
5849   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
5850   buffer->Rewind();
5851   buffer->Seek(offset);
5852   character_position = offset;
5853   int utf8_byte_position = 0;
5854   while (buffer->has_more()) {
5855     uint16_t character = buffer->GetNext();
5856     if (character_position < offset + length) {
5857       if (allow_nulls == DISALLOW_NULLS && character == 0) {
5858         character = ' ';
5859       }
5860       utf8_byte_position +=
5861           unibrow::Utf8::Encode(result + utf8_byte_position, character);
5862     }
5863     character_position++;
5864   }
5865   result[utf8_byte_position] = 0;
5866   return SmartArrayPointer<char>(result);
5867 }
5868
5869
5870 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
5871                                           RobustnessFlag robust_flag,
5872                                           int* length_return) {
5873   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
5874 }
5875
5876
5877 const uc16* String::GetTwoByteData() {
5878   return GetTwoByteData(0);
5879 }
5880
5881
5882 const uc16* String::GetTwoByteData(unsigned start) {
5883   ASSERT(!IsAsciiRepresentationUnderneath());
5884   switch (StringShape(this).representation_tag()) {
5885     case kSeqStringTag:
5886       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
5887     case kExternalStringTag:
5888       return ExternalTwoByteString::cast(this)->
5889         ExternalTwoByteStringGetData(start);
5890     case kSlicedStringTag: {
5891       SlicedString* slice = SlicedString::cast(this);
5892       return slice->parent()->GetTwoByteData(start + slice->offset());
5893     }
5894     case kConsStringTag:
5895       UNREACHABLE();
5896       return NULL;
5897   }
5898   UNREACHABLE();
5899   return NULL;
5900 }
5901
5902
5903 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
5904   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
5905     return SmartArrayPointer<uc16>();
5906   }
5907   Heap* heap = GetHeap();
5908
5909   Access<StringInputBuffer> buffer(
5910       heap->isolate()->objects_string_input_buffer());
5911   buffer->Reset(this);
5912
5913   uc16* result = NewArray<uc16>(length() + 1);
5914
5915   int i = 0;
5916   while (buffer->has_more()) {
5917     uint16_t character = buffer->GetNext();
5918     result[i++] = character;
5919   }
5920   result[i] = 0;
5921   return SmartArrayPointer<uc16>(result);
5922 }
5923
5924
5925 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
5926   return reinterpret_cast<uc16*>(
5927       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
5928 }
5929
5930
5931 void SeqTwoByteString::SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
5932                                                            unsigned* offset_ptr,
5933                                                            unsigned max_chars) {
5934   unsigned chars_read = 0;
5935   unsigned offset = *offset_ptr;
5936   while (chars_read < max_chars) {
5937     uint16_t c = *reinterpret_cast<uint16_t*>(
5938         reinterpret_cast<char*>(this) -
5939             kHeapObjectTag + kHeaderSize + offset * kShortSize);
5940     if (c <= kMaxAsciiCharCode) {
5941       // Fast case for ASCII characters.   Cursor is an input output argument.
5942       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
5943                                                           rbb->util_buffer,
5944                                                           rbb->capacity,
5945                                                           rbb->cursor)) {
5946         break;
5947       }
5948     } else {
5949       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
5950                                                              rbb->util_buffer,
5951                                                              rbb->capacity,
5952                                                              rbb->cursor)) {
5953         break;
5954       }
5955     }
5956     offset++;
5957     chars_read++;
5958   }
5959   *offset_ptr = offset;
5960   rbb->remaining += chars_read;
5961 }
5962
5963
5964 const unibrow::byte* SeqAsciiString::SeqAsciiStringReadBlock(
5965     unsigned* remaining,
5966     unsigned* offset_ptr,
5967     unsigned max_chars) {
5968   const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
5969       kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
5970   *remaining = max_chars;
5971   *offset_ptr += max_chars;
5972   return b;
5973 }
5974
5975
5976 // This will iterate unless the block of string data spans two 'halves' of
5977 // a ConsString, in which case it will recurse.  Since the block of string
5978 // data to be read has a maximum size this limits the maximum recursion
5979 // depth to something sane.  Since C++ does not have tail call recursion
5980 // elimination, the iteration must be explicit. Since this is not an
5981 // -IntoBuffer method it can delegate to one of the efficient
5982 // *AsciiStringReadBlock routines.
5983 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
5984                                                      unsigned* offset_ptr,
5985                                                      unsigned max_chars) {
5986   ConsString* current = this;
5987   unsigned offset = *offset_ptr;
5988   int offset_correction = 0;
5989
5990   while (true) {
5991     String* left = current->first();
5992     unsigned left_length = (unsigned)left->length();
5993     if (left_length > offset &&
5994         (max_chars <= left_length - offset ||
5995          (rbb->capacity <= left_length - offset &&
5996           (max_chars = left_length - offset, true)))) {  // comma operator!
5997       // Left hand side only - iterate unless we have reached the bottom of
5998       // the cons tree.  The assignment on the left of the comma operator is
5999       // in order to make use of the fact that the -IntoBuffer routines can
6000       // produce at most 'capacity' characters.  This enables us to postpone
6001       // the point where we switch to the -IntoBuffer routines (below) in order
6002       // to maximize the chances of delegating a big chunk of work to the
6003       // efficient *AsciiStringReadBlock routines.
6004       if (StringShape(left).IsCons()) {
6005         current = ConsString::cast(left);
6006         continue;
6007       } else {
6008         const unibrow::byte* answer =
6009             String::ReadBlock(left, rbb, &offset, max_chars);
6010         *offset_ptr = offset + offset_correction;
6011         return answer;
6012       }
6013     } else if (left_length <= offset) {
6014       // Right hand side only - iterate unless we have reached the bottom of
6015       // the cons tree.
6016       String* right = current->second();
6017       offset -= left_length;
6018       offset_correction += left_length;
6019       if (StringShape(right).IsCons()) {
6020         current = ConsString::cast(right);
6021         continue;
6022       } else {
6023         const unibrow::byte* answer =
6024             String::ReadBlock(right, rbb, &offset, max_chars);
6025         *offset_ptr = offset + offset_correction;
6026         return answer;
6027       }
6028     } else {
6029       // The block to be read spans two sides of the ConsString, so we call the
6030       // -IntoBuffer version, which will recurse.  The -IntoBuffer methods
6031       // are able to assemble data from several part strings because they use
6032       // the util_buffer to store their data and never return direct pointers
6033       // to their storage.  We don't try to read more than the buffer capacity
6034       // here or we can get too much recursion.
6035       ASSERT(rbb->remaining == 0);
6036       ASSERT(rbb->cursor == 0);
6037       current->ConsStringReadBlockIntoBuffer(
6038           rbb,
6039           &offset,
6040           max_chars > rbb->capacity ? rbb->capacity : max_chars);
6041       *offset_ptr = offset + offset_correction;
6042       return rbb->util_buffer;
6043     }
6044   }
6045 }
6046
6047
6048 uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
6049   ASSERT(index >= 0 && index < length());
6050   return resource()->data()[index];
6051 }
6052
6053
6054 const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock(
6055       unsigned* remaining,
6056       unsigned* offset_ptr,
6057       unsigned max_chars) {
6058   // Cast const char* to unibrow::byte* (signedness difference).
6059   const unibrow::byte* b =
6060       reinterpret_cast<const unibrow::byte*>(resource()->data()) + *offset_ptr;
6061   *remaining = max_chars;
6062   *offset_ptr += max_chars;
6063   return b;
6064 }
6065
6066
6067 const uc16* ExternalTwoByteString::ExternalTwoByteStringGetData(
6068       unsigned start) {
6069   return resource()->data() + start;
6070 }
6071
6072
6073 uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
6074   ASSERT(index >= 0 && index < length());
6075   return resource()->data()[index];
6076 }
6077
6078
6079 void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer(
6080       ReadBlockBuffer* rbb,
6081       unsigned* offset_ptr,
6082       unsigned max_chars) {
6083   unsigned chars_read = 0;
6084   unsigned offset = *offset_ptr;
6085   const uint16_t* data = resource()->data();
6086   while (chars_read < max_chars) {
6087     uint16_t c = data[offset];
6088     if (c <= kMaxAsciiCharCode) {
6089       // Fast case for ASCII characters. Cursor is an input output argument.
6090       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
6091                                                           rbb->util_buffer,
6092                                                           rbb->capacity,
6093                                                           rbb->cursor))
6094         break;
6095     } else {
6096       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
6097                                                              rbb->util_buffer,
6098                                                              rbb->capacity,
6099                                                              rbb->cursor))
6100         break;
6101     }
6102     offset++;
6103     chars_read++;
6104   }
6105   *offset_ptr = offset;
6106   rbb->remaining += chars_read;
6107 }
6108
6109
6110 void SeqAsciiString::SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
6111                                                  unsigned* offset_ptr,
6112                                                  unsigned max_chars) {
6113   unsigned capacity = rbb->capacity - rbb->cursor;
6114   if (max_chars > capacity) max_chars = capacity;
6115   memcpy(rbb->util_buffer + rbb->cursor,
6116          reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
6117              *offset_ptr * kCharSize,
6118          max_chars);
6119   rbb->remaining += max_chars;
6120   *offset_ptr += max_chars;
6121   rbb->cursor += max_chars;
6122 }
6123
6124
6125 void ExternalAsciiString::ExternalAsciiStringReadBlockIntoBuffer(
6126       ReadBlockBuffer* rbb,
6127       unsigned* offset_ptr,
6128       unsigned max_chars) {
6129   unsigned capacity = rbb->capacity - rbb->cursor;
6130   if (max_chars > capacity) max_chars = capacity;
6131   memcpy(rbb->util_buffer + rbb->cursor,
6132          resource()->data() + *offset_ptr,
6133          max_chars);
6134   rbb->remaining += max_chars;
6135   *offset_ptr += max_chars;
6136   rbb->cursor += max_chars;
6137 }
6138
6139
6140 // This method determines the type of string involved and then copies
6141 // a whole chunk of characters into a buffer, or returns a pointer to a buffer
6142 // where they can be found.  The pointer is not necessarily valid across a GC
6143 // (see AsciiStringReadBlock).
6144 const unibrow::byte* String::ReadBlock(String* input,
6145                                        ReadBlockBuffer* rbb,
6146                                        unsigned* offset_ptr,
6147                                        unsigned max_chars) {
6148   ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
6149   if (max_chars == 0) {
6150     rbb->remaining = 0;
6151     return NULL;
6152   }
6153   switch (StringShape(input).representation_tag()) {
6154     case kSeqStringTag:
6155       if (input->IsAsciiRepresentation()) {
6156         SeqAsciiString* str = SeqAsciiString::cast(input);
6157         return str->SeqAsciiStringReadBlock(&rbb->remaining,
6158                                             offset_ptr,
6159                                             max_chars);
6160       } else {
6161         SeqTwoByteString* str = SeqTwoByteString::cast(input);
6162         str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
6163                                                  offset_ptr,
6164                                                  max_chars);
6165         return rbb->util_buffer;
6166       }
6167     case kConsStringTag:
6168       return ConsString::cast(input)->ConsStringReadBlock(rbb,
6169                                                           offset_ptr,
6170                                                           max_chars);
6171     case kExternalStringTag:
6172       if (input->IsAsciiRepresentation()) {
6173         return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
6174             &rbb->remaining,
6175             offset_ptr,
6176             max_chars);
6177       } else {
6178         ExternalTwoByteString::cast(input)->
6179             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6180                                                      offset_ptr,
6181                                                      max_chars);
6182         return rbb->util_buffer;
6183       }
6184     case kSlicedStringTag:
6185       return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
6186                                                               offset_ptr,
6187                                                               max_chars);
6188     default:
6189       break;
6190   }
6191
6192   UNREACHABLE();
6193   return 0;
6194 }
6195
6196
6197 // This method determines the type of string involved and then gets the UTF8
6198 // length of the string.  It doesn't flatten the string and has log(n) recursion
6199 // for a string of length n.
6200 int String::Utf8Length(String* input, int from, int to) {
6201   if (from == to) return 0;
6202   int total = 0;
6203   while (true) {
6204     if (input->IsAsciiRepresentation()) return total + to - from;
6205     switch (StringShape(input).representation_tag()) {
6206       case kConsStringTag: {
6207         ConsString* str = ConsString::cast(input);
6208         String* first = str->first();
6209         String* second = str->second();
6210         int first_length = first->length();
6211         if (first_length - from < to - first_length) {
6212           if (first_length > from) {
6213             // Left hand side is shorter.
6214             total += Utf8Length(first, from, first_length);
6215             input = second;
6216             from = 0;
6217             to -= first_length;
6218           } else {
6219             // We only need the right hand side.
6220             input = second;
6221             from -= first_length;
6222             to -= first_length;
6223           }
6224         } else {
6225           if (first_length <= to) {
6226             // Right hand side is shorter.
6227             total += Utf8Length(second, 0, to - first_length);
6228             input = first;
6229             to = first_length;
6230           } else {
6231             // We only need the left hand side.
6232             input = first;
6233           }
6234         }
6235         continue;
6236       }
6237       case kExternalStringTag:
6238       case kSeqStringTag: {
6239         Vector<const uc16> vector = input->GetFlatContent().ToUC16Vector();
6240         const uc16* p = vector.start();
6241         for (int i = from; i < to; i++) {
6242           total += unibrow::Utf8::Length(p[i]);
6243         }
6244         return total;
6245       }
6246       case kSlicedStringTag: {
6247         SlicedString* str = SlicedString::cast(input);
6248         int offset = str->offset();
6249         input = str->parent();
6250         from += offset;
6251         to += offset;
6252         continue;
6253       }
6254       default:
6255         break;
6256     }
6257     UNREACHABLE();
6258     return 0;
6259   }
6260   return 0;
6261 }
6262
6263
6264 void Relocatable::PostGarbageCollectionProcessing() {
6265   Isolate* isolate = Isolate::Current();
6266   Relocatable* current = isolate->relocatable_top();
6267   while (current != NULL) {
6268     current->PostGarbageCollection();
6269     current = current->prev_;
6270   }
6271 }
6272
6273
6274 // Reserve space for statics needing saving and restoring.
6275 int Relocatable::ArchiveSpacePerThread() {
6276   return sizeof(Isolate::Current()->relocatable_top());
6277 }
6278
6279
6280 // Archive statics that are thread local.
6281 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
6282   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
6283   isolate->set_relocatable_top(NULL);
6284   return to + ArchiveSpacePerThread();
6285 }
6286
6287
6288 // Restore statics that are thread local.
6289 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
6290   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
6291   return from + ArchiveSpacePerThread();
6292 }
6293
6294
6295 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
6296   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
6297   Iterate(v, top);
6298   return thread_storage + ArchiveSpacePerThread();
6299 }
6300
6301
6302 void Relocatable::Iterate(ObjectVisitor* v) {
6303   Isolate* isolate = Isolate::Current();
6304   Iterate(v, isolate->relocatable_top());
6305 }
6306
6307
6308 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
6309   Relocatable* current = top;
6310   while (current != NULL) {
6311     current->IterateInstance(v);
6312     current = current->prev_;
6313   }
6314 }
6315
6316
6317 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
6318     : Relocatable(isolate),
6319       str_(str.location()),
6320       length_(str->length()) {
6321   PostGarbageCollection();
6322 }
6323
6324
6325 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
6326     : Relocatable(isolate),
6327       str_(0),
6328       is_ascii_(true),
6329       length_(input.length()),
6330       start_(input.start()) { }
6331
6332
6333 void FlatStringReader::PostGarbageCollection() {
6334   if (str_ == NULL) return;
6335   Handle<String> str(str_);
6336   ASSERT(str->IsFlat());
6337   String::FlatContent content = str->GetFlatContent();
6338   ASSERT(content.IsFlat());
6339   is_ascii_ = content.IsAscii();
6340   if (is_ascii_) {
6341     start_ = content.ToAsciiVector().start();
6342   } else {
6343     start_ = content.ToUC16Vector().start();
6344   }
6345 }
6346
6347
6348 void StringInputBuffer::Seek(unsigned pos) {
6349   Reset(pos, input_);
6350 }
6351
6352
6353 void SafeStringInputBuffer::Seek(unsigned pos) {
6354   Reset(pos, input_);
6355 }
6356
6357
6358 // This method determines the type of string involved and then copies
6359 // a whole chunk of characters into a buffer.  It can be used with strings
6360 // that have been glued together to form a ConsString and which must cooperate
6361 // to fill up a buffer.
6362 void String::ReadBlockIntoBuffer(String* input,
6363                                  ReadBlockBuffer* rbb,
6364                                  unsigned* offset_ptr,
6365                                  unsigned max_chars) {
6366   ASSERT(*offset_ptr <= (unsigned)input->length());
6367   if (max_chars == 0) return;
6368
6369   switch (StringShape(input).representation_tag()) {
6370     case kSeqStringTag:
6371       if (input->IsAsciiRepresentation()) {
6372         SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
6373                                                                  offset_ptr,
6374                                                                  max_chars);
6375         return;
6376       } else {
6377         SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
6378                                                                      offset_ptr,
6379                                                                      max_chars);
6380         return;
6381       }
6382     case kConsStringTag:
6383       ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
6384                                                              offset_ptr,
6385                                                              max_chars);
6386       return;
6387     case kExternalStringTag:
6388       if (input->IsAsciiRepresentation()) {
6389         ExternalAsciiString::cast(input)->
6390             ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
6391       } else {
6392         ExternalTwoByteString::cast(input)->
6393             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6394                                                      offset_ptr,
6395                                                      max_chars);
6396        }
6397        return;
6398     case kSlicedStringTag:
6399       SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
6400                                                                  offset_ptr,
6401                                                                  max_chars);
6402       return;
6403     default:
6404       break;
6405   }
6406
6407   UNREACHABLE();
6408   return;
6409 }
6410
6411
6412 const unibrow::byte* String::ReadBlock(String* input,
6413                                        unibrow::byte* util_buffer,
6414                                        unsigned capacity,
6415                                        unsigned* remaining,
6416                                        unsigned* offset_ptr) {
6417   ASSERT(*offset_ptr <= (unsigned)input->length());
6418   unsigned chars = input->length() - *offset_ptr;
6419   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6420   const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
6421   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6422   *remaining = rbb.remaining;
6423   return answer;
6424 }
6425
6426
6427 const unibrow::byte* String::ReadBlock(String** raw_input,
6428                                        unibrow::byte* util_buffer,
6429                                        unsigned capacity,
6430                                        unsigned* remaining,
6431                                        unsigned* offset_ptr) {
6432   Handle<String> input(raw_input);
6433   ASSERT(*offset_ptr <= (unsigned)input->length());
6434   unsigned chars = input->length() - *offset_ptr;
6435   if (chars > capacity) chars = capacity;
6436   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6437   ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
6438   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6439   *remaining = rbb.remaining;
6440   return rbb.util_buffer;
6441 }
6442
6443
6444 // This will iterate unless the block of string data spans two 'halves' of
6445 // a ConsString, in which case it will recurse.  Since the block of string
6446 // data to be read has a maximum size this limits the maximum recursion
6447 // depth to something sane.  Since C++ does not have tail call recursion
6448 // elimination, the iteration must be explicit.
6449 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
6450                                                unsigned* offset_ptr,
6451                                                unsigned max_chars) {
6452   ConsString* current = this;
6453   unsigned offset = *offset_ptr;
6454   int offset_correction = 0;
6455
6456   while (true) {
6457     String* left = current->first();
6458     unsigned left_length = (unsigned)left->length();
6459     if (left_length > offset &&
6460       max_chars <= left_length - offset) {
6461       // Left hand side only - iterate unless we have reached the bottom of
6462       // the cons tree.
6463       if (StringShape(left).IsCons()) {
6464         current = ConsString::cast(left);
6465         continue;
6466       } else {
6467         String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
6468         *offset_ptr = offset + offset_correction;
6469         return;
6470       }
6471     } else if (left_length <= offset) {
6472       // Right hand side only - iterate unless we have reached the bottom of
6473       // the cons tree.
6474       offset -= left_length;
6475       offset_correction += left_length;
6476       String* right = current->second();
6477       if (StringShape(right).IsCons()) {
6478         current = ConsString::cast(right);
6479         continue;
6480       } else {
6481         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6482         *offset_ptr = offset + offset_correction;
6483         return;
6484       }
6485     } else {
6486       // The block to be read spans two sides of the ConsString, so we recurse.
6487       // First recurse on the left.
6488       max_chars -= left_length - offset;
6489       String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
6490       // We may have reached the max or there may not have been enough space
6491       // in the buffer for the characters in the left hand side.
6492       if (offset == left_length) {
6493         // Recurse on the right.
6494         String* right = String::cast(current->second());
6495         offset -= left_length;
6496         offset_correction += left_length;
6497         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6498       }
6499       *offset_ptr = offset + offset_correction;
6500       return;
6501     }
6502   }
6503 }
6504
6505
6506 uint16_t ConsString::ConsStringGet(int index) {
6507   ASSERT(index >= 0 && index < this->length());
6508
6509   // Check for a flattened cons string
6510   if (second()->length() == 0) {
6511     String* left = first();
6512     return left->Get(index);
6513   }
6514
6515   String* string = String::cast(this);
6516
6517   while (true) {
6518     if (StringShape(string).IsCons()) {
6519       ConsString* cons_string = ConsString::cast(string);
6520       String* left = cons_string->first();
6521       if (left->length() > index) {
6522         string = left;
6523       } else {
6524         index -= left->length();
6525         string = cons_string->second();
6526       }
6527     } else {
6528       return string->Get(index);
6529     }
6530   }
6531
6532   UNREACHABLE();
6533   return 0;
6534 }
6535
6536
6537 uint16_t SlicedString::SlicedStringGet(int index) {
6538   return parent()->Get(offset() + index);
6539 }
6540
6541
6542 const unibrow::byte* SlicedString::SlicedStringReadBlock(
6543     ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6544   unsigned offset = this->offset();
6545   *offset_ptr += offset;
6546   const unibrow::byte* answer = String::ReadBlock(String::cast(parent()),
6547                                                   buffer, offset_ptr, chars);
6548   *offset_ptr -= offset;
6549   return answer;
6550 }
6551
6552
6553 void SlicedString::SlicedStringReadBlockIntoBuffer(
6554     ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6555   unsigned offset = this->offset();
6556   *offset_ptr += offset;
6557   String::ReadBlockIntoBuffer(String::cast(parent()),
6558                               buffer, offset_ptr, chars);
6559   *offset_ptr -= offset;
6560 }
6561
6562 template <typename sinkchar>
6563 void String::WriteToFlat(String* src,
6564                          sinkchar* sink,
6565                          int f,
6566                          int t) {
6567   String* source = src;
6568   int from = f;
6569   int to = t;
6570   while (true) {
6571     ASSERT(0 <= from && from <= to && to <= source->length());
6572     switch (StringShape(source).full_representation_tag()) {
6573       case kAsciiStringTag | kExternalStringTag: {
6574         CopyChars(sink,
6575                   ExternalAsciiString::cast(source)->resource()->data() + from,
6576                   to - from);
6577         return;
6578       }
6579       case kTwoByteStringTag | kExternalStringTag: {
6580         const uc16* data =
6581             ExternalTwoByteString::cast(source)->resource()->data();
6582         CopyChars(sink,
6583                   data + from,
6584                   to - from);
6585         return;
6586       }
6587       case kAsciiStringTag | kSeqStringTag: {
6588         CopyChars(sink,
6589                   SeqAsciiString::cast(source)->GetChars() + from,
6590                   to - from);
6591         return;
6592       }
6593       case kTwoByteStringTag | kSeqStringTag: {
6594         CopyChars(sink,
6595                   SeqTwoByteString::cast(source)->GetChars() + from,
6596                   to - from);
6597         return;
6598       }
6599       case kAsciiStringTag | kConsStringTag:
6600       case kTwoByteStringTag | kConsStringTag: {
6601         ConsString* cons_string = ConsString::cast(source);
6602         String* first = cons_string->first();
6603         int boundary = first->length();
6604         if (to - boundary >= boundary - from) {
6605           // Right hand side is longer.  Recurse over left.
6606           if (from < boundary) {
6607             WriteToFlat(first, sink, from, boundary);
6608             sink += boundary - from;
6609             from = 0;
6610           } else {
6611             from -= boundary;
6612           }
6613           to -= boundary;
6614           source = cons_string->second();
6615         } else {
6616           // Left hand side is longer.  Recurse over right.
6617           if (to > boundary) {
6618             String* second = cons_string->second();
6619             WriteToFlat(second,
6620                         sink + boundary - from,
6621                         0,
6622                         to - boundary);
6623             to = boundary;
6624           }
6625           source = first;
6626         }
6627         break;
6628       }
6629       case kAsciiStringTag | kSlicedStringTag:
6630       case kTwoByteStringTag | kSlicedStringTag: {
6631         SlicedString* slice = SlicedString::cast(source);
6632         unsigned offset = slice->offset();
6633         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
6634         return;
6635       }
6636     }
6637   }
6638 }
6639
6640
6641 template <typename IteratorA, typename IteratorB>
6642 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
6643   // General slow case check.  We know that the ia and ib iterators
6644   // have the same length.
6645   while (ia->has_more()) {
6646     uc32 ca = ia->GetNext();
6647     uc32 cb = ib->GetNext();
6648     if (ca != cb)
6649       return false;
6650   }
6651   return true;
6652 }
6653
6654
6655 // Compares the contents of two strings by reading and comparing
6656 // int-sized blocks of characters.
6657 template <typename Char>
6658 static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
6659   int length = a.length();
6660   ASSERT_EQ(length, b.length());
6661   const Char* pa = a.start();
6662   const Char* pb = b.start();
6663   int i = 0;
6664 #ifndef V8_HOST_CAN_READ_UNALIGNED
6665   // If this architecture isn't comfortable reading unaligned ints
6666   // then we have to check that the strings are aligned before
6667   // comparing them blockwise.
6668   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
6669   uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
6670   uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
6671   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
6672 #endif
6673     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
6674     int endpoint = length - kStepSize;
6675     // Compare blocks until we reach near the end of the string.
6676     for (; i <= endpoint; i += kStepSize) {
6677       uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
6678       uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
6679       if (wa != wb) {
6680         return false;
6681       }
6682     }
6683 #ifndef V8_HOST_CAN_READ_UNALIGNED
6684   }
6685 #endif
6686   // Compare the remaining characters that didn't fit into a block.
6687   for (; i < length; i++) {
6688     if (a[i] != b[i]) {
6689       return false;
6690     }
6691   }
6692   return true;
6693 }
6694
6695
6696 template <typename IteratorA>
6697 static inline bool CompareStringContentsPartial(Isolate* isolate,
6698                                                 IteratorA* ia,
6699                                                 String* b) {
6700   String::FlatContent content = b->GetFlatContent();
6701   if (content.IsFlat()) {
6702     if (content.IsAscii()) {
6703       VectorIterator<char> ib(content.ToAsciiVector());
6704       return CompareStringContents(ia, &ib);
6705     } else {
6706       VectorIterator<uc16> ib(content.ToUC16Vector());
6707       return CompareStringContents(ia, &ib);
6708     }
6709   } else {
6710     isolate->objects_string_compare_buffer_b()->Reset(0, b);
6711     return CompareStringContents(ia,
6712                                  isolate->objects_string_compare_buffer_b());
6713   }
6714 }
6715
6716
6717 bool String::SlowEqualsExternal(uc16 *string, int length) {
6718   int len = this->length();
6719   if (len != length) return false;
6720   if (len == 0) return true;
6721
6722   // We know the strings are both non-empty. Compare the first chars
6723   // before we try to flatten the strings.
6724   if (this->Get(0) != string[0]) return false;
6725
6726   String* lhs = this->TryFlattenGetString();
6727
6728   if (lhs->IsFlat()) {
6729     String::FlatContent lhs_content = lhs->GetFlatContent();
6730     if (lhs->IsAsciiRepresentation()) {
6731       Vector<const char> vec1 = lhs_content.ToAsciiVector();
6732       VectorIterator<char> buf1(vec1);
6733       VectorIterator<uc16> ib(string, length);
6734       return CompareStringContents(&buf1, &ib);
6735     } else {
6736       Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
6737       Vector<const uc16> vec2(string, length);
6738       return CompareRawStringContents(vec1, vec2);
6739     }
6740   } else {
6741     Isolate* isolate = GetIsolate();
6742     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
6743     VectorIterator<uc16> ib(string, length);
6744     return CompareStringContents(isolate->objects_string_compare_buffer_a(), &ib);
6745   }
6746 }
6747
6748
6749 bool String::SlowEqualsExternal(char *string, int length)
6750 {
6751   int len = this->length();
6752   if (len != length) return false;
6753   if (len == 0) return true;
6754
6755   // We know the strings are both non-empty. Compare the first chars
6756   // before we try to flatten the strings.
6757   if (this->Get(0) != string[0]) return false;
6758
6759   String* lhs = this->TryFlattenGetString();
6760
6761   if (StringShape(lhs).IsSequentialAscii()) {
6762       const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
6763       return CompareRawStringContents(Vector<const char>(str1, len),
6764                                       Vector<const char>(string, len));
6765   }
6766
6767   if (lhs->IsFlat()) {
6768     String::FlatContent lhs_content = lhs->GetFlatContent();
6769     Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
6770     VectorIterator<const uc16> buf1(vec1);
6771     VectorIterator<char> buf2(string, length);
6772     return CompareStringContents(&buf1, &buf2);
6773   } else {
6774     Isolate* isolate = GetIsolate();
6775     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
6776     VectorIterator<char> ib(string, length);
6777     return CompareStringContents(isolate->objects_string_compare_buffer_a(), &ib);
6778   }
6779 }
6780
6781
6782 bool String::SlowEquals(String* other) {
6783   // Fast check: negative check with lengths.
6784   int len = length();
6785   if (len != other->length()) return false;
6786   if (len == 0) return true;
6787
6788   // Fast check: if hash code is computed for both strings
6789   // a fast negative check can be performed.
6790   if (HasHashCode() && other->HasHashCode()) {
6791     if (Hash() != other->Hash()) return false;
6792   }
6793
6794   // We know the strings are both non-empty. Compare the first chars
6795   // before we try to flatten the strings.
6796   if (this->Get(0) != other->Get(0)) return false;
6797
6798   String* lhs = this->TryFlattenGetString();
6799   String* rhs = other->TryFlattenGetString();
6800
6801   if (StringShape(lhs).IsSequentialAscii() &&
6802       StringShape(rhs).IsSequentialAscii()) {
6803     const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
6804     const char* str2 = SeqAsciiString::cast(rhs)->GetChars();
6805     return CompareRawStringContents(Vector<const char>(str1, len),
6806                                     Vector<const char>(str2, len));
6807   }
6808
6809   Isolate* isolate = GetIsolate();
6810   String::FlatContent lhs_content = lhs->GetFlatContent();
6811   String::FlatContent rhs_content = rhs->GetFlatContent();
6812   if (lhs_content.IsFlat()) {
6813     if (lhs_content.IsAscii()) {
6814       Vector<const char> vec1 = lhs_content.ToAsciiVector();
6815       if (rhs_content.IsFlat()) {
6816         if (rhs_content.IsAscii()) {
6817           Vector<const char> vec2 = rhs_content.ToAsciiVector();
6818           return CompareRawStringContents(vec1, vec2);
6819         } else {
6820           VectorIterator<char> buf1(vec1);
6821           VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
6822           return CompareStringContents(&buf1, &ib);
6823         }
6824       } else {
6825         VectorIterator<char> buf1(vec1);
6826         isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
6827         return CompareStringContents(&buf1,
6828             isolate->objects_string_compare_buffer_b());
6829       }
6830     } else {
6831       Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
6832       if (rhs_content.IsFlat()) {
6833         if (rhs_content.IsAscii()) {
6834           VectorIterator<uc16> buf1(vec1);
6835           VectorIterator<char> ib(rhs_content.ToAsciiVector());
6836           return CompareStringContents(&buf1, &ib);
6837         } else {
6838           Vector<const uc16> vec2(rhs_content.ToUC16Vector());
6839           return CompareRawStringContents(vec1, vec2);
6840         }
6841       } else {
6842         VectorIterator<uc16> buf1(vec1);
6843         isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
6844         return CompareStringContents(&buf1,
6845             isolate->objects_string_compare_buffer_b());
6846       }
6847     }
6848   } else {
6849     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
6850     return CompareStringContentsPartial(isolate,
6851         isolate->objects_string_compare_buffer_a(), rhs);
6852   }
6853 }
6854
6855
6856 bool String::MarkAsUndetectable() {
6857   if (StringShape(this).IsSymbol()) return false;
6858
6859   Map* map = this->map();
6860   Heap* heap = GetHeap();
6861   if (map == heap->string_map()) {
6862     this->set_map(heap->undetectable_string_map());
6863     return true;
6864   } else if (map == heap->ascii_string_map()) {
6865     this->set_map(heap->undetectable_ascii_string_map());
6866     return true;
6867   }
6868   // Rest cannot be marked as undetectable
6869   return false;
6870 }
6871
6872
6873 bool String::IsEqualTo(Vector<const char> str) {
6874   Isolate* isolate = GetIsolate();
6875   int slen = length();
6876   Access<UnicodeCache::Utf8Decoder>
6877       decoder(isolate->unicode_cache()->utf8_decoder());
6878   decoder->Reset(str.start(), str.length());
6879   int i;
6880   for (i = 0; i < slen && decoder->has_more(); i++) {
6881     uc32 r = decoder->GetNext();
6882     if (Get(i) != r) return false;
6883   }
6884   return i == slen && !decoder->has_more();
6885 }
6886
6887
6888 bool String::IsAsciiEqualTo(Vector<const char> str) {
6889   int slen = length();
6890   if (str.length() != slen) return false;
6891   FlatContent content = GetFlatContent();
6892   if (content.IsAscii()) {
6893     return CompareChars(content.ToAsciiVector().start(),
6894                         str.start(), slen) == 0;
6895   }
6896   for (int i = 0; i < slen; i++) {
6897     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
6898   }
6899   return true;
6900 }
6901
6902
6903 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
6904   int slen = length();
6905   if (str.length() != slen) return false;
6906   FlatContent content = GetFlatContent();
6907   if (content.IsTwoByte()) {
6908     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
6909   }
6910   for (int i = 0; i < slen; i++) {
6911     if (Get(i) != str[i]) return false;
6912   }
6913   return true;
6914 }
6915
6916
6917 uint32_t String::ComputeAndSetHash() {
6918   // Should only be called if hash code has not yet been computed.
6919   ASSERT(!HasHashCode());
6920
6921   const int len = length();
6922
6923   // Compute the hash code.
6924   uint32_t field = 0;
6925   if (StringShape(this).IsSequentialAscii()) {
6926     field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(), len);
6927   } else if (StringShape(this).IsSequentialTwoByte()) {
6928     field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(), len);
6929   } else {
6930     StringInputBuffer buffer(this);
6931     field = ComputeHashField(&buffer, len);
6932   }
6933
6934   // Store the hash code in the object.
6935   set_hash_field(field);
6936
6937   // Check the hash code is there.
6938   ASSERT(HasHashCode());
6939   uint32_t result = field >> kHashShift;
6940   ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
6941   return result;
6942 }
6943
6944
6945 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
6946                                uint32_t* index,
6947                                int length) {
6948   if (length == 0 || length > kMaxArrayIndexSize) return false;
6949   uc32 ch = buffer->GetNext();
6950
6951   // If the string begins with a '0' character, it must only consist
6952   // of it to be a legal array index.
6953   if (ch == '0') {
6954     *index = 0;
6955     return length == 1;
6956   }
6957
6958   // Convert string to uint32 array index; character by character.
6959   int d = ch - '0';
6960   if (d < 0 || d > 9) return false;
6961   uint32_t result = d;
6962   while (buffer->has_more()) {
6963     d = buffer->GetNext() - '0';
6964     if (d < 0 || d > 9) return false;
6965     // Check that the new result is below the 32 bit limit.
6966     if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
6967     result = (result * 10) + d;
6968   }
6969
6970   *index = result;
6971   return true;
6972 }
6973
6974
6975 bool String::SlowAsArrayIndex(uint32_t* index) {
6976   if (length() <= kMaxCachedArrayIndexLength) {
6977     Hash();  // force computation of hash code
6978     uint32_t field = hash_field();
6979     if ((field & kIsNotArrayIndexMask) != 0) return false;
6980     // Isolate the array index form the full hash field.
6981     *index = (kArrayIndexHashMask & field) >> kHashShift;
6982     return true;
6983   } else {
6984     StringInputBuffer buffer(this);
6985     return ComputeArrayIndex(&buffer, index, length());
6986   }
6987 }
6988
6989
6990 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
6991   // For array indexes mix the length into the hash as an array index could
6992   // be zero.
6993   ASSERT(length > 0);
6994   ASSERT(length <= String::kMaxArrayIndexSize);
6995   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
6996          (1 << String::kArrayIndexValueBits));
6997
6998   value <<= String::kHashShift;
6999   value |= length << String::kArrayIndexHashLengthShift;
7000
7001   ASSERT((value & String::kIsNotArrayIndexMask) == 0);
7002   ASSERT((length > String::kMaxCachedArrayIndexLength) ||
7003          (value & String::kContainsCachedArrayIndexMask) == 0);
7004   return value;
7005 }
7006
7007
7008 uint32_t StringHasher::GetHashField() {
7009   ASSERT(is_valid());
7010   if (length_ <= String::kMaxHashCalcLength) {
7011     if (is_array_index()) {
7012       return MakeArrayIndexHash(array_index(), length_);
7013     }
7014     return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask;
7015   } else {
7016     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
7017   }
7018 }
7019
7020
7021 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer,
7022                                   int length) {
7023   StringHasher hasher(length);
7024
7025   // Very long strings have a trivial hash that doesn't inspect the
7026   // string contents.
7027   if (hasher.has_trivial_hash()) {
7028     return hasher.GetHashField();
7029   }
7030
7031   // Do the iterative array index computation as long as there is a
7032   // chance this is an array index.
7033   while (buffer->has_more() && hasher.is_array_index()) {
7034     hasher.AddCharacter(buffer->GetNext());
7035   }
7036
7037   // Process the remaining characters without updating the array
7038   // index.
7039   while (buffer->has_more()) {
7040     hasher.AddCharacterNoIndex(buffer->GetNext());
7041   }
7042
7043   return hasher.GetHashField();
7044 }
7045
7046
7047 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
7048   Heap* heap = GetHeap();
7049   if (start == 0 && end == length()) return this;
7050   MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
7051   return result;
7052 }
7053
7054
7055 void String::PrintOn(FILE* file) {
7056   int length = this->length();
7057   for (int i = 0; i < length; i++) {
7058     fprintf(file, "%c", Get(i));
7059   }
7060 }
7061
7062
7063 void Map::CreateOneBackPointer(Map* target) {
7064 #ifdef DEBUG
7065   // Verify target.
7066   Object* source_prototype = prototype();
7067   Object* target_prototype = target->prototype();
7068   ASSERT(source_prototype->IsJSReceiver() ||
7069          source_prototype->IsMap() ||
7070          source_prototype->IsNull());
7071   ASSERT(target_prototype->IsJSReceiver() ||
7072          target_prototype->IsNull());
7073   ASSERT(source_prototype->IsMap() ||
7074          source_prototype == target_prototype);
7075 #endif
7076   // Point target back to source.  set_prototype() will not let us set
7077   // the prototype to a map, as we do here.
7078   *RawField(target, kPrototypeOffset) = this;
7079 }
7080
7081
7082 void Map::CreateBackPointers() {
7083   DescriptorArray* descriptors = instance_descriptors();
7084   for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
7085     if (descriptors->GetType(i) == MAP_TRANSITION ||
7086         descriptors->GetType(i) == ELEMENTS_TRANSITION ||
7087         descriptors->GetType(i) == CONSTANT_TRANSITION) {
7088       Object* object = reinterpret_cast<Object*>(descriptors->GetValue(i));
7089       if (object->IsMap()) {
7090         CreateOneBackPointer(reinterpret_cast<Map*>(object));
7091       } else {
7092         ASSERT(object->IsFixedArray());
7093         ASSERT(descriptors->GetType(i) == ELEMENTS_TRANSITION);
7094         FixedArray* array = reinterpret_cast<FixedArray*>(object);
7095         for (int i = 0; i < array->length(); ++i) {
7096           Map* target = reinterpret_cast<Map*>(array->get(i));
7097           if (!target->IsUndefined()) {
7098             CreateOneBackPointer(target);
7099           }
7100         }
7101       }
7102     }
7103   }
7104 }
7105
7106
7107 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
7108   // Live DescriptorArray objects will be marked, so we must use
7109   // low-level accessors to get and modify their data.
7110   DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
7111       *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset));
7112   if (d->IsEmpty()) return;
7113   Smi* NullDescriptorDetails =
7114     PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
7115   FixedArray* contents = reinterpret_cast<FixedArray*>(
7116       d->get(DescriptorArray::kContentArrayIndex));
7117   ASSERT(contents->length() >= 2);
7118   for (int i = 0; i < contents->length(); i += 2) {
7119     // If the pair (value, details) is a map transition,
7120     // check if the target is live.  If not, null the descriptor.
7121     // Also drop the back pointer for that map transition, so that this
7122     // map is not reached again by following a back pointer from a
7123     // non-live object.
7124     PropertyDetails details(Smi::cast(contents->get(i + 1)));
7125     if (details.type() == MAP_TRANSITION ||
7126         details.type() == ELEMENTS_TRANSITION ||
7127         details.type() == CONSTANT_TRANSITION) {
7128       Object* object = reinterpret_cast<Object*>(contents->get(i));
7129       if (object->IsMap()) {
7130         Map* target = reinterpret_cast<Map*>(object);
7131         ASSERT(target->IsHeapObject());
7132         MarkBit map_mark = Marking::MarkBitFrom(target);
7133         if (!map_mark.Get()) {
7134           ASSERT(target->IsMap());
7135           contents->set_unchecked(i + 1, NullDescriptorDetails);
7136           contents->set_null_unchecked(heap, i);
7137           ASSERT(target->prototype() == this ||
7138                  target->prototype() == real_prototype);
7139           // Getter prototype() is read-only, set_prototype() has side effects.
7140           *RawField(target, Map::kPrototypeOffset) = real_prototype;
7141         }
7142       } else {
7143         ASSERT(object->IsFixedArray());
7144         ASSERT(details.type() == ELEMENTS_TRANSITION);
7145         FixedArray* array = reinterpret_cast<FixedArray*>(object);
7146         bool reachable_map_found = false;
7147         for (int j = 0; j < array->length(); ++j) {
7148           Map* target = reinterpret_cast<Map*>(array->get(j));
7149           ASSERT(target->IsHeapObject());
7150           MarkBit map_mark = Marking::MarkBitFrom(target);
7151           if (!map_mark.Get()) {
7152             ASSERT(target->IsMap());
7153             array->set_undefined(j);
7154             ASSERT(target->prototype() == this ||
7155                    target->prototype() == real_prototype);
7156             // Getter prototype() is read-only, set_prototype() has side
7157             // effects.
7158             *RawField(target, Map::kPrototypeOffset) = real_prototype;
7159           } else if (target->IsMap()) {
7160             reachable_map_found = true;
7161           }
7162         }
7163         // If no map was found, make sure the FixedArray also gets collected.
7164         if (!reachable_map_found) {
7165           contents->set_unchecked(i + 1, NullDescriptorDetails);
7166           contents->set_null_unchecked(heap, i);
7167         }
7168       }
7169     }
7170   }
7171 }
7172
7173
7174 int Map::Hash() {
7175   // For performance reasons we only hash the 3 most variable fields of a map:
7176   // constructor, prototype and bit_field2.
7177
7178   // Shift away the tag.
7179   int hash = (static_cast<uint32_t>(
7180         reinterpret_cast<uintptr_t>(constructor())) >> 2);
7181
7182   // XOR-ing the prototype and constructor directly yields too many zero bits
7183   // when the two pointers are close (which is fairly common).
7184   // To avoid this we shift the prototype 4 bits relatively to the constructor.
7185   hash ^= (static_cast<uint32_t>(
7186         reinterpret_cast<uintptr_t>(prototype())) << 2);
7187
7188   return hash ^ (hash >> 16) ^ bit_field2();
7189 }
7190
7191
7192 bool Map::EquivalentToForNormalization(Map* other,
7193                                        PropertyNormalizationMode mode) {
7194   return
7195     constructor() == other->constructor() &&
7196     prototype() == other->prototype() &&
7197     inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
7198                               0 :
7199                               other->inobject_properties()) &&
7200     instance_type() == other->instance_type() &&
7201     bit_field() == other->bit_field() &&
7202     bit_field2() == other->bit_field2() &&
7203     (bit_field3() & ~(1<<Map::kIsShared)) ==
7204         (other->bit_field3() & ~(1<<Map::kIsShared));
7205 }
7206
7207
7208 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
7209   // Iterate over all fields in the body but take care in dealing with
7210   // the code entry.
7211   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
7212   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
7213   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
7214 }
7215
7216
7217 void JSFunction::MarkForLazyRecompilation() {
7218   ASSERT(is_compiled() && !IsOptimized());
7219   ASSERT(shared()->allows_lazy_compilation() ||
7220          code()->optimizable());
7221   Builtins* builtins = GetIsolate()->builtins();
7222   ReplaceCode(builtins->builtin(Builtins::kLazyRecompile));
7223 }
7224
7225
7226 bool SharedFunctionInfo::EnsureCompiled(Handle<SharedFunctionInfo> shared,
7227                                         ClearExceptionFlag flag) {
7228   return shared->is_compiled() || CompileLazy(shared, flag);
7229 }
7230
7231
7232 static bool CompileLazyHelper(CompilationInfo* info,
7233                               ClearExceptionFlag flag) {
7234   // Compile the source information to a code object.
7235   ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
7236   ASSERT(!info->isolate()->has_pending_exception());
7237   bool result = Compiler::CompileLazy(info);
7238   ASSERT(result != Isolate::Current()->has_pending_exception());
7239   if (!result && flag == CLEAR_EXCEPTION) {
7240     info->isolate()->clear_pending_exception();
7241   }
7242   return result;
7243 }
7244
7245
7246 bool SharedFunctionInfo::CompileLazy(Handle<SharedFunctionInfo> shared,
7247                                      ClearExceptionFlag flag) {
7248   CompilationInfo info(shared);
7249   return CompileLazyHelper(&info, flag);
7250 }
7251
7252
7253 bool JSFunction::CompileLazy(Handle<JSFunction> function,
7254                              ClearExceptionFlag flag) {
7255   bool result = true;
7256   if (function->shared()->is_compiled()) {
7257     function->ReplaceCode(function->shared()->code());
7258     function->shared()->set_code_age(0);
7259   } else {
7260     CompilationInfo info(function);
7261     result = CompileLazyHelper(&info, flag);
7262     ASSERT(!result || function->is_compiled());
7263   }
7264   return result;
7265 }
7266
7267
7268 bool JSFunction::CompileOptimized(Handle<JSFunction> function,
7269                                   int osr_ast_id,
7270                                   ClearExceptionFlag flag) {
7271   CompilationInfo info(function);
7272   info.SetOptimizing(osr_ast_id);
7273   return CompileLazyHelper(&info, flag);
7274 }
7275
7276
7277 bool JSFunction::IsInlineable() {
7278   if (IsBuiltin()) return false;
7279   SharedFunctionInfo* shared_info = shared();
7280   // Check that the function has a script associated with it.
7281   if (!shared_info->script()->IsScript()) return false;
7282   if (shared_info->optimization_disabled()) return false;
7283   Code* code = shared_info->code();
7284   if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
7285   // If we never ran this (unlikely) then lets try to optimize it.
7286   if (code->kind() != Code::FUNCTION) return true;
7287   return code->optimizable();
7288 }
7289
7290
7291 Object* JSFunction::SetInstancePrototype(Object* value) {
7292   ASSERT(value->IsJSObject());
7293   Heap* heap = GetHeap();
7294   if (has_initial_map()) {
7295     initial_map()->set_prototype(value);
7296   } else {
7297     // Put the value in the initial map field until an initial map is
7298     // needed.  At that point, a new initial map is created and the
7299     // prototype is put into the initial map where it belongs.
7300     set_prototype_or_initial_map(value);
7301   }
7302   heap->ClearInstanceofCache();
7303   return value;
7304 }
7305
7306
7307 MaybeObject* JSFunction::SetPrototype(Object* value) {
7308   ASSERT(should_have_prototype());
7309   Object* construct_prototype = value;
7310
7311   // If the value is not a JSObject, store the value in the map's
7312   // constructor field so it can be accessed.  Also, set the prototype
7313   // used for constructing objects to the original object prototype.
7314   // See ECMA-262 13.2.2.
7315   if (!value->IsJSObject()) {
7316     // Copy the map so this does not affect unrelated functions.
7317     // Remove map transitions because they point to maps with a
7318     // different prototype.
7319     Object* new_object;
7320     { MaybeObject* maybe_new_map = map()->CopyDropTransitions();
7321       if (!maybe_new_map->ToObject(&new_object)) return maybe_new_map;
7322     }
7323     Map* new_map = Map::cast(new_object);
7324     Heap* heap = new_map->GetHeap();
7325     set_map(new_map);
7326     new_map->set_constructor(value);
7327     new_map->set_non_instance_prototype(true);
7328     construct_prototype =
7329         heap->isolate()->context()->global_context()->
7330             initial_object_prototype();
7331   } else {
7332     map()->set_non_instance_prototype(false);
7333   }
7334
7335   return SetInstancePrototype(construct_prototype);
7336 }
7337
7338
7339 Object* JSFunction::RemovePrototype() {
7340   Context* global_context = context()->global_context();
7341   Map* no_prototype_map = shared()->strict_mode()
7342       ? global_context->strict_mode_function_without_prototype_map()
7343       : global_context->function_without_prototype_map();
7344
7345   if (map() == no_prototype_map) {
7346     // Be idempotent.
7347     return this;
7348   }
7349
7350   ASSERT(!shared()->strict_mode() ||
7351          map() == global_context->strict_mode_function_map());
7352   ASSERT(shared()->strict_mode() || map() == global_context->function_map());
7353
7354   set_map(no_prototype_map);
7355   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
7356   return this;
7357 }
7358
7359
7360 Object* JSFunction::SetInstanceClassName(String* name) {
7361   shared()->set_instance_class_name(name);
7362   return this;
7363 }
7364
7365
7366 void JSFunction::PrintName(FILE* out) {
7367   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
7368   PrintF(out, "%s", *name);
7369 }
7370
7371
7372 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) {
7373   return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex));
7374 }
7375
7376
7377 MaybeObject* Oddball::Initialize(const char* to_string,
7378                                  Object* to_number,
7379                                  byte kind) {
7380   Object* symbol;
7381   { MaybeObject* maybe_symbol =
7382         Isolate::Current()->heap()->LookupAsciiSymbol(to_string);
7383     if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol;
7384   }
7385   set_to_string(String::cast(symbol));
7386   set_to_number(to_number);
7387   set_kind(kind);
7388   return this;
7389 }
7390
7391
7392 String* SharedFunctionInfo::DebugName() {
7393   Object* n = name();
7394   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
7395   return String::cast(n);
7396 }
7397
7398
7399 bool SharedFunctionInfo::HasSourceCode() {
7400   return !script()->IsUndefined() &&
7401          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
7402 }
7403
7404
7405 Object* SharedFunctionInfo::GetSourceCode() {
7406   Isolate* isolate = GetIsolate();
7407   if (!HasSourceCode()) return isolate->heap()->undefined_value();
7408   HandleScope scope(isolate);
7409   Object* source = Script::cast(script())->source();
7410   return *SubString(Handle<String>(String::cast(source), isolate),
7411                     start_position(), end_position());
7412 }
7413
7414
7415 int SharedFunctionInfo::SourceSize() {
7416   return end_position() - start_position();
7417 }
7418
7419
7420 int SharedFunctionInfo::CalculateInstanceSize() {
7421   int instance_size =
7422       JSObject::kHeaderSize +
7423       expected_nof_properties() * kPointerSize;
7424   if (instance_size > JSObject::kMaxInstanceSize) {
7425     instance_size = JSObject::kMaxInstanceSize;
7426   }
7427   return instance_size;
7428 }
7429
7430
7431 int SharedFunctionInfo::CalculateInObjectProperties() {
7432   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
7433 }
7434
7435
7436 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
7437   // Check the basic conditions for generating inline constructor code.
7438   if (!FLAG_inline_new
7439       || !has_only_simple_this_property_assignments()
7440       || this_property_assignments_count() == 0) {
7441     return false;
7442   }
7443
7444   // If the prototype is null inline constructors cause no problems.
7445   if (!prototype->IsJSObject()) {
7446     ASSERT(prototype->IsNull());
7447     return true;
7448   }
7449
7450   Heap* heap = GetHeap();
7451
7452   // Traverse the proposed prototype chain looking for setters for properties of
7453   // the same names as are set by the inline constructor.
7454   for (Object* obj = prototype;
7455        obj != heap->null_value();
7456        obj = obj->GetPrototype()) {
7457     JSObject* js_object = JSObject::cast(obj);
7458     for (int i = 0; i < this_property_assignments_count(); i++) {
7459       LookupResult result(heap->isolate());
7460       String* name = GetThisPropertyAssignmentName(i);
7461       js_object->LocalLookupRealNamedProperty(name, &result);
7462       if (result.IsProperty() && result.type() == CALLBACKS) {
7463         return false;
7464       }
7465     }
7466   }
7467
7468   return true;
7469 }
7470
7471
7472 void SharedFunctionInfo::ForbidInlineConstructor() {
7473   set_compiler_hints(BooleanBit::set(compiler_hints(),
7474                                      kHasOnlySimpleThisPropertyAssignments,
7475                                      false));
7476 }
7477
7478
7479 void SharedFunctionInfo::SetThisPropertyAssignmentsInfo(
7480     bool only_simple_this_property_assignments,
7481     FixedArray* assignments) {
7482   set_compiler_hints(BooleanBit::set(compiler_hints(),
7483                                      kHasOnlySimpleThisPropertyAssignments,
7484                                      only_simple_this_property_assignments));
7485   set_this_property_assignments(assignments);
7486   set_this_property_assignments_count(assignments->length() / 3);
7487 }
7488
7489
7490 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() {
7491   Heap* heap = GetHeap();
7492   set_compiler_hints(BooleanBit::set(compiler_hints(),
7493                                      kHasOnlySimpleThisPropertyAssignments,
7494                                      false));
7495   set_this_property_assignments(heap->undefined_value());
7496   set_this_property_assignments_count(0);
7497 }
7498
7499
7500 String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) {
7501   Object* obj = this_property_assignments();
7502   ASSERT(obj->IsFixedArray());
7503   ASSERT(index < this_property_assignments_count());
7504   obj = FixedArray::cast(obj)->get(index * 3);
7505   ASSERT(obj->IsString());
7506   return String::cast(obj);
7507 }
7508
7509
7510 bool SharedFunctionInfo::IsThisPropertyAssignmentArgument(int index) {
7511   Object* obj = this_property_assignments();
7512   ASSERT(obj->IsFixedArray());
7513   ASSERT(index < this_property_assignments_count());
7514   obj = FixedArray::cast(obj)->get(index * 3 + 1);
7515   return Smi::cast(obj)->value() != -1;
7516 }
7517
7518
7519 int SharedFunctionInfo::GetThisPropertyAssignmentArgument(int index) {
7520   ASSERT(IsThisPropertyAssignmentArgument(index));
7521   Object* obj =
7522       FixedArray::cast(this_property_assignments())->get(index * 3 + 1);
7523   return Smi::cast(obj)->value();
7524 }
7525
7526
7527 Object* SharedFunctionInfo::GetThisPropertyAssignmentConstant(int index) {
7528   ASSERT(!IsThisPropertyAssignmentArgument(index));
7529   Object* obj =
7530       FixedArray::cast(this_property_assignments())->get(index * 3 + 2);
7531   return obj;
7532 }
7533
7534
7535 // Support function for printing the source code to a StringStream
7536 // without any allocation in the heap.
7537 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
7538                                          int max_length) {
7539   // For some native functions there is no source.
7540   if (!HasSourceCode()) {
7541     accumulator->Add("<No Source>");
7542     return;
7543   }
7544
7545   // Get the source for the script which this function came from.
7546   // Don't use String::cast because we don't want more assertion errors while
7547   // we are already creating a stack dump.
7548   String* script_source =
7549       reinterpret_cast<String*>(Script::cast(script())->source());
7550
7551   if (!script_source->LooksValid()) {
7552     accumulator->Add("<Invalid Source>");
7553     return;
7554   }
7555
7556   if (!is_toplevel()) {
7557     accumulator->Add("function ");
7558     Object* name = this->name();
7559     if (name->IsString() && String::cast(name)->length() > 0) {
7560       accumulator->PrintName(name);
7561     }
7562   }
7563
7564   int len = end_position() - start_position();
7565   if (len <= max_length || max_length < 0) {
7566     accumulator->Put(script_source, start_position(), end_position());
7567   } else {
7568     accumulator->Put(script_source,
7569                      start_position(),
7570                      start_position() + max_length);
7571     accumulator->Add("...\n");
7572   }
7573 }
7574
7575
7576 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
7577   if (code->instruction_size() != recompiled->instruction_size()) return false;
7578   ByteArray* code_relocation = code->relocation_info();
7579   ByteArray* recompiled_relocation = recompiled->relocation_info();
7580   int length = code_relocation->length();
7581   if (length != recompiled_relocation->length()) return false;
7582   int compare = memcmp(code_relocation->GetDataStartAddress(),
7583                        recompiled_relocation->GetDataStartAddress(),
7584                        length);
7585   return compare == 0;
7586 }
7587
7588
7589 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
7590   ASSERT(!has_deoptimization_support());
7591   AssertNoAllocation no_allocation;
7592   Code* code = this->code();
7593   if (IsCodeEquivalent(code, recompiled)) {
7594     // Copy the deoptimization data from the recompiled code.
7595     code->set_deoptimization_data(recompiled->deoptimization_data());
7596     code->set_has_deoptimization_support(true);
7597   } else {
7598     // TODO(3025757): In case the recompiled isn't equivalent to the
7599     // old code, we have to replace it. We should try to avoid this
7600     // altogether because it flushes valuable type feedback by
7601     // effectively resetting all IC state.
7602     set_code(recompiled);
7603   }
7604   ASSERT(has_deoptimization_support());
7605 }
7606
7607
7608 void SharedFunctionInfo::DisableOptimization(JSFunction* function) {
7609   // Disable optimization for the shared function info and mark the
7610   // code as non-optimizable. The marker on the shared function info
7611   // is there because we flush non-optimized code thereby loosing the
7612   // non-optimizable information for the code. When the code is
7613   // regenerated and set on the shared function info it is marked as
7614   // non-optimizable if optimization is disabled for the shared
7615   // function info.
7616   set_optimization_disabled(true);
7617   // Code should be the lazy compilation stub or else unoptimized.  If the
7618   // latter, disable optimization for the code too.
7619   ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
7620   if (code()->kind() == Code::FUNCTION) {
7621     code()->set_optimizable(false);
7622   }
7623   if (FLAG_trace_opt) {
7624     PrintF("[disabled optimization for: ");
7625     function->PrintName();
7626     PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
7627   }
7628 }
7629
7630
7631 bool SharedFunctionInfo::VerifyBailoutId(int id) {
7632   // TODO(srdjan): debugging ARM crashes in hydrogen. OK to disable while
7633   // we are always bailing out on ARM.
7634
7635   ASSERT(id != AstNode::kNoNumber);
7636   Code* unoptimized = code();
7637   DeoptimizationOutputData* data =
7638       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
7639   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
7640   USE(ignore);
7641   return true;  // Return true if there was no ASSERT.
7642 }
7643
7644
7645 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) {
7646   ASSERT(!IsInobjectSlackTrackingInProgress());
7647
7648   if (!FLAG_clever_optimizations) return;
7649
7650   // Only initiate the tracking the first time.
7651   if (live_objects_may_exist()) return;
7652   set_live_objects_may_exist(true);
7653
7654   // No tracking during the snapshot construction phase.
7655   if (Serializer::enabled()) return;
7656
7657   if (map->unused_property_fields() == 0) return;
7658
7659   // Nonzero counter is a leftover from the previous attempt interrupted
7660   // by GC, keep it.
7661   if (construction_count() == 0) {
7662     set_construction_count(kGenerousAllocationCount);
7663   }
7664   set_initial_map(map);
7665   Builtins* builtins = map->GetHeap()->isolate()->builtins();
7666   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
7667             construct_stub());
7668   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
7669 }
7670
7671
7672 // Called from GC, hence reinterpret_cast and unchecked accessors.
7673 void SharedFunctionInfo::DetachInitialMap() {
7674   Map* map = reinterpret_cast<Map*>(initial_map());
7675
7676   // Make the map remember to restore the link if it survives the GC.
7677   map->set_bit_field3(
7678       map->bit_field3() | (1 << Map::kAttachedToSharedFunctionInfo));
7679
7680   // Undo state changes made by StartInobjectTracking (except the
7681   // construction_count). This way if the initial map does not survive the GC
7682   // then StartInobjectTracking will be called again the next time the
7683   // constructor is called. The countdown will continue and (possibly after
7684   // several more GCs) CompleteInobjectSlackTracking will eventually be called.
7685   Heap* heap = map->GetHeap();
7686   set_initial_map(heap->raw_unchecked_undefined_value());
7687   Builtins* builtins = heap->isolate()->builtins();
7688   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
7689             *RawField(this, kConstructStubOffset));
7690   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
7691   // It is safe to clear the flag: it will be set again if the map is live.
7692   set_live_objects_may_exist(false);
7693 }
7694
7695
7696 // Called from GC, hence reinterpret_cast and unchecked accessors.
7697 void SharedFunctionInfo::AttachInitialMap(Map* map) {
7698   map->set_bit_field3(
7699       map->bit_field3() & ~(1 << Map::kAttachedToSharedFunctionInfo));
7700
7701   // Resume inobject slack tracking.
7702   set_initial_map(map);
7703   Builtins* builtins = map->GetHeap()->isolate()->builtins();
7704   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
7705             *RawField(this, kConstructStubOffset));
7706   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
7707   // The map survived the gc, so there may be objects referencing it.
7708   set_live_objects_may_exist(true);
7709 }
7710
7711
7712 static void GetMinInobjectSlack(Map* map, void* data) {
7713   int slack = map->unused_property_fields();
7714   if (*reinterpret_cast<int*>(data) > slack) {
7715     *reinterpret_cast<int*>(data) = slack;
7716   }
7717 }
7718
7719
7720 static void ShrinkInstanceSize(Map* map, void* data) {
7721   int slack = *reinterpret_cast<int*>(data);
7722   map->set_inobject_properties(map->inobject_properties() - slack);
7723   map->set_unused_property_fields(map->unused_property_fields() - slack);
7724   map->set_instance_size(map->instance_size() - slack * kPointerSize);
7725
7726   // Visitor id might depend on the instance size, recalculate it.
7727   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
7728 }
7729
7730
7731 void SharedFunctionInfo::CompleteInobjectSlackTracking() {
7732   ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
7733   Map* map = Map::cast(initial_map());
7734
7735   Heap* heap = map->GetHeap();
7736   set_initial_map(heap->undefined_value());
7737   Builtins* builtins = heap->isolate()->builtins();
7738   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
7739             construct_stub());
7740   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
7741
7742   int slack = map->unused_property_fields();
7743   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
7744   if (slack != 0) {
7745     // Resize the initial map and all maps in its transition tree.
7746     map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
7747
7748     // Give the correct expected_nof_properties to initial maps created later.
7749     ASSERT(expected_nof_properties() >= slack);
7750     set_expected_nof_properties(expected_nof_properties() - slack);
7751   }
7752 }
7753
7754
7755 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
7756   ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
7757   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
7758   Object* old_target = target;
7759   VisitPointer(&target);
7760   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
7761 }
7762
7763
7764 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
7765   Object* code = Code::GetObjectFromEntryAddress(entry_address);
7766   Object* old_code = code;
7767   VisitPointer(&code);
7768   if (code != old_code) {
7769     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
7770   }
7771 }
7772
7773
7774 void ObjectVisitor::VisitGlobalPropertyCell(RelocInfo* rinfo) {
7775   ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
7776   Object* cell = rinfo->target_cell();
7777   Object* old_cell = cell;
7778   VisitPointer(&cell);
7779   if (cell != old_cell) {
7780     rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
7781   }
7782 }
7783
7784
7785 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
7786   ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
7787           rinfo->IsPatchedReturnSequence()) ||
7788          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
7789           rinfo->IsPatchedDebugBreakSlotSequence()));
7790   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
7791   Object* old_target = target;
7792   VisitPointer(&target);
7793   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
7794 }
7795
7796
7797 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
7798   ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
7799   VisitPointer(rinfo->target_object_address());
7800 }
7801
7802
7803 void Code::InvalidateRelocation() {
7804   set_relocation_info(GetHeap()->empty_byte_array());
7805 }
7806
7807
7808 void Code::Relocate(intptr_t delta) {
7809   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
7810     it.rinfo()->apply(delta);
7811   }
7812   CPU::FlushICache(instruction_start(), instruction_size());
7813 }
7814
7815
7816 void Code::CopyFrom(const CodeDesc& desc) {
7817   ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
7818
7819   // copy code
7820   memmove(instruction_start(), desc.buffer, desc.instr_size);
7821
7822   // copy reloc info
7823   memmove(relocation_start(),
7824           desc.buffer + desc.buffer_size - desc.reloc_size,
7825           desc.reloc_size);
7826
7827   // unbox handles and relocate
7828   intptr_t delta = instruction_start() - desc.buffer;
7829   int mode_mask = RelocInfo::kCodeTargetMask |
7830                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
7831                   RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
7832                   RelocInfo::kApplyMask;
7833   Assembler* origin = desc.origin;  // Needed to find target_object on X64.
7834   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
7835     RelocInfo::Mode mode = it.rinfo()->rmode();
7836     if (mode == RelocInfo::EMBEDDED_OBJECT) {
7837       Handle<Object> p = it.rinfo()->target_object_handle(origin);
7838       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
7839     } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
7840       Handle<JSGlobalPropertyCell> cell  = it.rinfo()->target_cell_handle();
7841       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
7842     } else if (RelocInfo::IsCodeTarget(mode)) {
7843       // rewrite code handles in inline cache targets to direct
7844       // pointers to the first instruction in the code object
7845       Handle<Object> p = it.rinfo()->target_object_handle(origin);
7846       Code* code = Code::cast(*p);
7847       it.rinfo()->set_target_address(code->instruction_start(),
7848                                      SKIP_WRITE_BARRIER);
7849     } else {
7850       it.rinfo()->apply(delta);
7851     }
7852   }
7853   CPU::FlushICache(instruction_start(), instruction_size());
7854 }
7855
7856
7857 // Locate the source position which is closest to the address in the code. This
7858 // is using the source position information embedded in the relocation info.
7859 // The position returned is relative to the beginning of the script where the
7860 // source for this function is found.
7861 int Code::SourcePosition(Address pc) {
7862   int distance = kMaxInt;
7863   int position = RelocInfo::kNoPosition;  // Initially no position found.
7864   // Run through all the relocation info to find the best matching source
7865   // position. All the code needs to be considered as the sequence of the
7866   // instructions in the code does not necessarily follow the same order as the
7867   // source.
7868   RelocIterator it(this, RelocInfo::kPositionMask);
7869   while (!it.done()) {
7870     // Only look at positions after the current pc.
7871     if (it.rinfo()->pc() < pc) {
7872       // Get position and distance.
7873
7874       int dist = static_cast<int>(pc - it.rinfo()->pc());
7875       int pos = static_cast<int>(it.rinfo()->data());
7876       // If this position is closer than the current candidate or if it has the
7877       // same distance as the current candidate and the position is higher then
7878       // this position is the new candidate.
7879       if ((dist < distance) ||
7880           (dist == distance && pos > position)) {
7881         position = pos;
7882         distance = dist;
7883       }
7884     }
7885     it.next();
7886   }
7887   return position;
7888 }
7889
7890
7891 // Same as Code::SourcePosition above except it only looks for statement
7892 // positions.
7893 int Code::SourceStatementPosition(Address pc) {
7894   // First find the position as close as possible using all position
7895   // information.
7896   int position = SourcePosition(pc);
7897   // Now find the closest statement position before the position.
7898   int statement_position = 0;
7899   RelocIterator it(this, RelocInfo::kPositionMask);
7900   while (!it.done()) {
7901     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
7902       int p = static_cast<int>(it.rinfo()->data());
7903       if (statement_position < p && p <= position) {
7904         statement_position = p;
7905       }
7906     }
7907     it.next();
7908   }
7909   return statement_position;
7910 }
7911
7912
7913 SafepointEntry Code::GetSafepointEntry(Address pc) {
7914   SafepointTable table(this);
7915   return table.FindEntry(pc);
7916 }
7917
7918
7919 void Code::SetNoStackCheckTable() {
7920   // Indicate the absence of a stack-check table by a table start after the
7921   // end of the instructions.  Table start must be aligned, so round up.
7922   set_stack_check_table_offset(RoundUp(instruction_size(), kIntSize));
7923 }
7924
7925
7926 Map* Code::FindFirstMap() {
7927   ASSERT(is_inline_cache_stub());
7928   AssertNoAllocation no_allocation;
7929   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
7930   for (RelocIterator it(this, mask); !it.done(); it.next()) {
7931     RelocInfo* info = it.rinfo();
7932     Object* object = info->target_object();
7933     if (object->IsMap()) return Map::cast(object);
7934   }
7935   return NULL;
7936 }
7937
7938
7939 #ifdef ENABLE_DISASSEMBLER
7940
7941 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
7942   disasm::NameConverter converter;
7943   int deopt_count = DeoptCount();
7944   PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
7945   if (0 == deopt_count) return;
7946
7947   PrintF(out, "%6s  %6s  %6s  %12s\n", "index", "ast id", "argc",
7948          FLAG_print_code_verbose ? "commands" : "");
7949   for (int i = 0; i < deopt_count; i++) {
7950     PrintF(out, "%6d  %6d  %6d",
7951            i, AstId(i)->value(), ArgumentsStackHeight(i)->value());
7952
7953     if (!FLAG_print_code_verbose) {
7954       PrintF(out, "\n");
7955       continue;
7956     }
7957     // Print details of the frame translation.
7958     int translation_index = TranslationIndex(i)->value();
7959     TranslationIterator iterator(TranslationByteArray(), translation_index);
7960     Translation::Opcode opcode =
7961         static_cast<Translation::Opcode>(iterator.Next());
7962     ASSERT(Translation::BEGIN == opcode);
7963     int frame_count = iterator.Next();
7964     PrintF(out, "  %s {count=%d}\n", Translation::StringFor(opcode),
7965            frame_count);
7966
7967     while (iterator.HasNext() &&
7968            Translation::BEGIN !=
7969            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
7970       PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
7971
7972       switch (opcode) {
7973         case Translation::BEGIN:
7974           UNREACHABLE();
7975           break;
7976
7977         case Translation::FRAME: {
7978           int ast_id = iterator.Next();
7979           int function_id = iterator.Next();
7980           JSFunction* function =
7981               JSFunction::cast(LiteralArray()->get(function_id));
7982           unsigned height = iterator.Next();
7983           PrintF(out, "{ast_id=%d, function=", ast_id);
7984           function->PrintName(out);
7985           PrintF(out, ", height=%u}", height);
7986           break;
7987         }
7988
7989         case Translation::DUPLICATE:
7990           break;
7991
7992         case Translation::REGISTER: {
7993           int reg_code = iterator.Next();
7994             PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
7995           break;
7996         }
7997
7998         case Translation::INT32_REGISTER: {
7999           int reg_code = iterator.Next();
8000           PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
8001           break;
8002         }
8003
8004         case Translation::DOUBLE_REGISTER: {
8005           int reg_code = iterator.Next();
8006           PrintF(out, "{input=%s}",
8007                  DoubleRegister::AllocationIndexToString(reg_code));
8008           break;
8009         }
8010
8011         case Translation::STACK_SLOT: {
8012           int input_slot_index = iterator.Next();
8013           PrintF(out, "{input=%d}", input_slot_index);
8014           break;
8015         }
8016
8017         case Translation::INT32_STACK_SLOT: {
8018           int input_slot_index = iterator.Next();
8019           PrintF(out, "{input=%d}", input_slot_index);
8020           break;
8021         }
8022
8023         case Translation::DOUBLE_STACK_SLOT: {
8024           int input_slot_index = iterator.Next();
8025           PrintF(out, "{input=%d}", input_slot_index);
8026           break;
8027         }
8028
8029         case Translation::LITERAL: {
8030           unsigned literal_index = iterator.Next();
8031           PrintF(out, "{literal_id=%u}", literal_index);
8032           break;
8033         }
8034
8035         case Translation::ARGUMENTS_OBJECT:
8036           break;
8037       }
8038       PrintF(out, "\n");
8039     }
8040   }
8041 }
8042
8043
8044 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
8045   PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
8046          this->DeoptPoints());
8047   if (this->DeoptPoints() == 0) return;
8048
8049   PrintF("%6s  %8s  %s\n", "ast id", "pc", "state");
8050   for (int i = 0; i < this->DeoptPoints(); i++) {
8051     int pc_and_state = this->PcAndState(i)->value();
8052     PrintF("%6d  %8d  %s\n",
8053            this->AstId(i)->value(),
8054            FullCodeGenerator::PcField::decode(pc_and_state),
8055            FullCodeGenerator::State2String(
8056                FullCodeGenerator::StateField::decode(pc_and_state)));
8057   }
8058 }
8059
8060
8061 // Identify kind of code.
8062 const char* Code::Kind2String(Kind kind) {
8063   switch (kind) {
8064     case FUNCTION: return "FUNCTION";
8065     case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION";
8066     case STUB: return "STUB";
8067     case BUILTIN: return "BUILTIN";
8068     case LOAD_IC: return "LOAD_IC";
8069     case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
8070     case STORE_IC: return "STORE_IC";
8071     case KEYED_STORE_IC: return "KEYED_STORE_IC";
8072     case CALL_IC: return "CALL_IC";
8073     case KEYED_CALL_IC: return "KEYED_CALL_IC";
8074     case UNARY_OP_IC: return "UNARY_OP_IC";
8075     case BINARY_OP_IC: return "BINARY_OP_IC";
8076     case COMPARE_IC: return "COMPARE_IC";
8077     case TO_BOOLEAN_IC: return "TO_BOOLEAN_IC";
8078   }
8079   UNREACHABLE();
8080   return NULL;
8081 }
8082
8083
8084 const char* Code::ICState2String(InlineCacheState state) {
8085   switch (state) {
8086     case UNINITIALIZED: return "UNINITIALIZED";
8087     case PREMONOMORPHIC: return "PREMONOMORPHIC";
8088     case MONOMORPHIC: return "MONOMORPHIC";
8089     case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
8090     case MEGAMORPHIC: return "MEGAMORPHIC";
8091     case DEBUG_BREAK: return "DEBUG_BREAK";
8092     case DEBUG_PREPARE_STEP_IN: return "DEBUG_PREPARE_STEP_IN";
8093   }
8094   UNREACHABLE();
8095   return NULL;
8096 }
8097
8098
8099 const char* Code::PropertyType2String(PropertyType type) {
8100   switch (type) {
8101     case NORMAL: return "NORMAL";
8102     case FIELD: return "FIELD";
8103     case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
8104     case CALLBACKS: return "CALLBACKS";
8105     case HANDLER: return "HANDLER";
8106     case INTERCEPTOR: return "INTERCEPTOR";
8107     case MAP_TRANSITION: return "MAP_TRANSITION";
8108     case ELEMENTS_TRANSITION: return "ELEMENTS_TRANSITION";
8109     case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
8110     case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
8111   }
8112   UNREACHABLE();
8113   return NULL;
8114 }
8115
8116
8117 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
8118   const char* name = NULL;
8119   switch (kind) {
8120     case CALL_IC:
8121       if (extra == STRING_INDEX_OUT_OF_BOUNDS) {
8122         name = "STRING_INDEX_OUT_OF_BOUNDS";
8123       }
8124       break;
8125     case STORE_IC:
8126     case KEYED_STORE_IC:
8127       if (extra == kStrictMode) {
8128         name = "STRICT";
8129       }
8130       break;
8131     default:
8132       break;
8133   }
8134   if (name != NULL) {
8135     PrintF(out, "extra_ic_state = %s\n", name);
8136   } else {
8137     PrintF(out, "extra_ic_state = %d\n", extra);
8138   }
8139 }
8140
8141
8142 void Code::Disassemble(const char* name, FILE* out) {
8143   PrintF(out, "kind = %s\n", Kind2String(kind()));
8144   if (is_inline_cache_stub()) {
8145     PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
8146     PrintExtraICState(out, kind(), extra_ic_state());
8147     if (ic_state() == MONOMORPHIC) {
8148       PrintF(out, "type = %s\n", PropertyType2String(type()));
8149     }
8150     if (is_call_stub() || is_keyed_call_stub()) {
8151       PrintF(out, "argc = %d\n", arguments_count());
8152     }
8153   }
8154   if ((name != NULL) && (name[0] != '\0')) {
8155     PrintF(out, "name = %s\n", name);
8156   }
8157   if (kind() == OPTIMIZED_FUNCTION) {
8158     PrintF(out, "stack_slots = %d\n", stack_slots());
8159   }
8160
8161   PrintF(out, "Instructions (size = %d)\n", instruction_size());
8162   Disassembler::Decode(out, this);
8163   PrintF(out, "\n");
8164
8165   if (kind() == FUNCTION) {
8166     DeoptimizationOutputData* data =
8167         DeoptimizationOutputData::cast(this->deoptimization_data());
8168     data->DeoptimizationOutputDataPrint(out);
8169   } else if (kind() == OPTIMIZED_FUNCTION) {
8170     DeoptimizationInputData* data =
8171         DeoptimizationInputData::cast(this->deoptimization_data());
8172     data->DeoptimizationInputDataPrint(out);
8173   }
8174   PrintF("\n");
8175
8176   if (kind() == OPTIMIZED_FUNCTION) {
8177     SafepointTable table(this);
8178     PrintF(out, "Safepoints (size = %u)\n", table.size());
8179     for (unsigned i = 0; i < table.length(); i++) {
8180       unsigned pc_offset = table.GetPcOffset(i);
8181       PrintF(out, "%p  %4d  ", (instruction_start() + pc_offset), pc_offset);
8182       table.PrintEntry(i);
8183       PrintF(out, " (sp -> fp)");
8184       SafepointEntry entry = table.GetEntry(i);
8185       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
8186         PrintF(out, "  %6d", entry.deoptimization_index());
8187       } else {
8188         PrintF(out, "  <none>");
8189       }
8190       if (entry.argument_count() > 0) {
8191         PrintF(out, " argc: %d", entry.argument_count());
8192       }
8193       PrintF(out, "\n");
8194     }
8195     PrintF(out, "\n");
8196   } else if (kind() == FUNCTION) {
8197     unsigned offset = stack_check_table_offset();
8198     // If there is no stack check table, the "table start" will at or after
8199     // (due to alignment) the end of the instruction stream.
8200     if (static_cast<int>(offset) < instruction_size()) {
8201       unsigned* address =
8202           reinterpret_cast<unsigned*>(instruction_start() + offset);
8203       unsigned length = address[0];
8204       PrintF(out, "Stack checks (size = %u)\n", length);
8205       PrintF(out, "ast_id  pc_offset\n");
8206       for (unsigned i = 0; i < length; ++i) {
8207         unsigned index = (2 * i) + 1;
8208         PrintF(out, "%6u  %9u\n", address[index], address[index + 1]);
8209       }
8210       PrintF(out, "\n");
8211     }
8212   }
8213
8214   PrintF("RelocInfo (size = %d)\n", relocation_size());
8215   for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
8216   PrintF(out, "\n");
8217 }
8218 #endif  // ENABLE_DISASSEMBLER
8219
8220
8221 static void CopyFastElementsToFast(FixedArray* source,
8222                                    FixedArray* destination,
8223                                    WriteBarrierMode mode) {
8224   uint32_t count = static_cast<uint32_t>(source->length());
8225   for (uint32_t i = 0; i < count; ++i) {
8226     destination->set(i, source->get(i), mode);
8227   }
8228 }
8229
8230
8231 static void CopySlowElementsToFast(NumberDictionary* source,
8232                                    FixedArray* destination,
8233                                    WriteBarrierMode mode) {
8234   for (int i = 0; i < source->Capacity(); ++i) {
8235     Object* key = source->KeyAt(i);
8236     if (key->IsNumber()) {
8237       uint32_t entry = static_cast<uint32_t>(key->Number());
8238       destination->set(entry, source->ValueAt(i), mode);
8239     }
8240   }
8241 }
8242
8243
8244 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
8245     int capacity,
8246     int length,
8247     SetFastElementsCapacityMode set_capacity_mode) {
8248   Heap* heap = GetHeap();
8249   // We should never end in here with a pixel or external array.
8250   ASSERT(!HasExternalArrayElements());
8251
8252   // Allocate a new fast elements backing store.
8253   FixedArray* new_elements = NULL;
8254   { Object* object;
8255     MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
8256     if (!maybe->ToObject(&object)) return maybe;
8257     new_elements = FixedArray::cast(object);
8258   }
8259
8260   // Find the new map to use for this object if there is a map change.
8261   Map* new_map = NULL;
8262   if (elements()->map() != heap->non_strict_arguments_elements_map()) {
8263     Object* object;
8264     bool has_fast_smi_only_elements =
8265         (set_capacity_mode == kAllowSmiOnlyElements) &&
8266         (elements()->map()->has_fast_smi_only_elements() ||
8267          elements() == heap->empty_fixed_array());
8268     ElementsKind elements_kind = has_fast_smi_only_elements
8269         ? FAST_SMI_ONLY_ELEMENTS
8270         : FAST_ELEMENTS;
8271     MaybeObject* maybe = GetElementsTransitionMap(elements_kind);
8272     if (!maybe->ToObject(&object)) return maybe;
8273     new_map = Map::cast(object);
8274   }
8275
8276   FixedArrayBase* old_elements_raw = elements();
8277   ElementsKind elements_kind = GetElementsKind();
8278   switch (elements_kind) {
8279     case FAST_SMI_ONLY_ELEMENTS:
8280     case FAST_ELEMENTS: {
8281       AssertNoAllocation no_gc;
8282       WriteBarrierMode mode(new_elements->GetWriteBarrierMode(no_gc));
8283       CopyFastElementsToFast(FixedArray::cast(old_elements_raw),
8284                              new_elements, mode);
8285       set_map(new_map);
8286       set_elements(new_elements);
8287       break;
8288     }
8289     case DICTIONARY_ELEMENTS: {
8290       AssertNoAllocation no_gc;
8291       WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
8292       CopySlowElementsToFast(NumberDictionary::cast(old_elements_raw),
8293                              new_elements,
8294                              mode);
8295       set_map(new_map);
8296       set_elements(new_elements);
8297       break;
8298     }
8299     case NON_STRICT_ARGUMENTS_ELEMENTS: {
8300       AssertNoAllocation no_gc;
8301       WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
8302       // The object's map and the parameter map are unchanged, the unaliased
8303       // arguments are copied to the new backing store.
8304       FixedArray* parameter_map = FixedArray::cast(old_elements_raw);
8305       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
8306       if (arguments->IsDictionary()) {
8307         CopySlowElementsToFast(NumberDictionary::cast(arguments),
8308                                new_elements,
8309                                mode);
8310       } else {
8311         CopyFastElementsToFast(arguments, new_elements, mode);
8312       }
8313       parameter_map->set(1, new_elements);
8314       break;
8315     }
8316     case FAST_DOUBLE_ELEMENTS: {
8317       FixedDoubleArray* old_elements = FixedDoubleArray::cast(old_elements_raw);
8318       uint32_t old_length = static_cast<uint32_t>(old_elements->length());
8319       // Fill out the new array with this content and array holes.
8320       for (uint32_t i = 0; i < old_length; i++) {
8321         if (!old_elements->is_the_hole(i)) {
8322           Object* obj;
8323           // Objects must be allocated in the old object space, since the
8324           // overall number of HeapNumbers needed for the conversion might
8325           // exceed the capacity of new space, and we would fail repeatedly
8326           // trying to convert the FixedDoubleArray.
8327           MaybeObject* maybe_value_object =
8328               GetHeap()->AllocateHeapNumber(old_elements->get_scalar(i),
8329                                             TENURED);
8330           if (!maybe_value_object->ToObject(&obj)) return maybe_value_object;
8331           // Force write barrier. It's not worth trying to exploit
8332           // elems->GetWriteBarrierMode(), since it requires an
8333           // AssertNoAllocation stack object that would have to be positioned
8334           // after the HeapNumber allocation anyway.
8335           new_elements->set(i, obj, UPDATE_WRITE_BARRIER);
8336         }
8337       }
8338       set_map(new_map);
8339       set_elements(new_elements);
8340       break;
8341     }
8342     case EXTERNAL_BYTE_ELEMENTS:
8343     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8344     case EXTERNAL_SHORT_ELEMENTS:
8345     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8346     case EXTERNAL_INT_ELEMENTS:
8347     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8348     case EXTERNAL_FLOAT_ELEMENTS:
8349     case EXTERNAL_DOUBLE_ELEMENTS:
8350     case EXTERNAL_PIXEL_ELEMENTS:
8351       UNREACHABLE();
8352       break;
8353   }
8354
8355   if (FLAG_trace_elements_transitions) {
8356     PrintElementsTransition(stdout, elements_kind, old_elements_raw,
8357                             FAST_ELEMENTS, new_elements);
8358   }
8359
8360   // Update the length if necessary.
8361   if (IsJSArray()) {
8362     JSArray::cast(this)->set_length(Smi::FromInt(length));
8363   }
8364
8365   return new_elements;
8366 }
8367
8368
8369 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
8370     int capacity,
8371     int length) {
8372   Heap* heap = GetHeap();
8373   // We should never end in here with a pixel or external array.
8374   ASSERT(!HasExternalArrayElements());
8375
8376   Object* obj;
8377   { MaybeObject* maybe_obj =
8378         heap->AllocateUninitializedFixedDoubleArray(capacity);
8379     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8380   }
8381   FixedDoubleArray* elems = FixedDoubleArray::cast(obj);
8382
8383   { MaybeObject* maybe_obj =
8384         GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS);
8385     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8386   }
8387   Map* new_map = Map::cast(obj);
8388
8389   FixedArrayBase* old_elements = elements();
8390   ElementsKind elements_kind(GetElementsKind());
8391   AssertNoAllocation no_gc;
8392   switch (elements_kind) {
8393     case FAST_SMI_ONLY_ELEMENTS:
8394     case FAST_ELEMENTS: {
8395       elems->Initialize(FixedArray::cast(old_elements));
8396       break;
8397     }
8398     case FAST_DOUBLE_ELEMENTS: {
8399       elems->Initialize(FixedDoubleArray::cast(old_elements));
8400       break;
8401     }
8402     case DICTIONARY_ELEMENTS: {
8403       elems->Initialize(NumberDictionary::cast(old_elements));
8404       break;
8405     }
8406     default:
8407       UNREACHABLE();
8408       break;
8409   }
8410
8411   if (FLAG_trace_elements_transitions) {
8412     PrintElementsTransition(stdout, elements_kind, old_elements,
8413                             FAST_DOUBLE_ELEMENTS, elems);
8414   }
8415
8416   ASSERT(new_map->has_fast_double_elements());
8417   set_map(new_map);
8418   ASSERT(elems->IsFixedDoubleArray());
8419   set_elements(elems);
8420
8421   if (IsJSArray()) {
8422     JSArray::cast(this)->set_length(Smi::FromInt(length));
8423   }
8424
8425   return this;
8426 }
8427
8428
8429 MaybeObject* JSObject::SetSlowElements(Object* len) {
8430   // We should never end in here with a pixel or external array.
8431   ASSERT(!HasExternalArrayElements());
8432
8433   uint32_t new_length = static_cast<uint32_t>(len->Number());
8434
8435   FixedArrayBase* old_elements = elements();
8436   ElementsKind elements_kind = GetElementsKind();
8437   switch (elements_kind) {
8438     case FAST_SMI_ONLY_ELEMENTS:
8439     case FAST_ELEMENTS:
8440     case FAST_DOUBLE_ELEMENTS: {
8441       // Make sure we never try to shrink dense arrays into sparse arrays.
8442       ASSERT(static_cast<uint32_t>(old_elements->length()) <= new_length);
8443       MaybeObject* result = NormalizeElements();
8444       if (result->IsFailure()) return result;
8445
8446       // Update length for JSArrays.
8447       if (IsJSArray()) JSArray::cast(this)->set_length(len);
8448       break;
8449     }
8450     case DICTIONARY_ELEMENTS: {
8451       if (IsJSArray()) {
8452         uint32_t old_length =
8453             static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
8454         element_dictionary()->RemoveNumberEntries(new_length, old_length),
8455         JSArray::cast(this)->set_length(len);
8456       }
8457       break;
8458     }
8459     case NON_STRICT_ARGUMENTS_ELEMENTS:
8460       UNIMPLEMENTED();
8461       break;
8462     case EXTERNAL_BYTE_ELEMENTS:
8463     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8464     case EXTERNAL_SHORT_ELEMENTS:
8465     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8466     case EXTERNAL_INT_ELEMENTS:
8467     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8468     case EXTERNAL_FLOAT_ELEMENTS:
8469     case EXTERNAL_DOUBLE_ELEMENTS:
8470     case EXTERNAL_PIXEL_ELEMENTS:
8471       UNREACHABLE();
8472       break;
8473   }
8474
8475   if (FLAG_trace_elements_transitions) {
8476     PrintElementsTransition(stdout, elements_kind, old_elements,
8477                             DICTIONARY_ELEMENTS, elements());
8478   }
8479
8480   return this;
8481 }
8482
8483
8484 MaybeObject* JSArray::Initialize(int capacity) {
8485   Heap* heap = GetHeap();
8486   ASSERT(capacity >= 0);
8487   set_length(Smi::FromInt(0));
8488   FixedArray* new_elements;
8489   if (capacity == 0) {
8490     new_elements = heap->empty_fixed_array();
8491   } else {
8492     Object* obj;
8493     { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
8494       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8495     }
8496     new_elements = FixedArray::cast(obj);
8497   }
8498   set_elements(new_elements);
8499   return this;
8500 }
8501
8502
8503 void JSArray::Expand(int required_size) {
8504   Handle<JSArray> self(this);
8505   Handle<FixedArray> old_backing(FixedArray::cast(elements()));
8506   int old_size = old_backing->length();
8507   int new_size = required_size > old_size ? required_size : old_size;
8508   Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size);
8509   // Can't use this any more now because we may have had a GC!
8510   for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i));
8511   GetIsolate()->factory()->SetContent(self, new_backing);
8512 }
8513
8514
8515 static Failure* ArrayLengthRangeError(Heap* heap) {
8516   HandleScope scope(heap->isolate());
8517   return heap->isolate()->Throw(
8518       *FACTORY->NewRangeError("invalid_array_length",
8519           HandleVector<Object>(NULL, 0)));
8520 }
8521
8522
8523 MaybeObject* JSObject::SetElementsLength(Object* len) {
8524   // We should never end in here with a pixel or external array.
8525   ASSERT(AllowsSetElementsLength());
8526
8527   MaybeObject* maybe_smi_length = len->ToSmi();
8528   Object* smi_length = Smi::FromInt(0);
8529   if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
8530     const int value = Smi::cast(smi_length)->value();
8531     if (value < 0) return ArrayLengthRangeError(GetHeap());
8532     ElementsKind elements_kind = GetElementsKind();
8533     switch (elements_kind) {
8534       case FAST_SMI_ONLY_ELEMENTS:
8535       case FAST_ELEMENTS:
8536       case FAST_DOUBLE_ELEMENTS: {
8537         int old_capacity = FixedArrayBase::cast(elements())->length();
8538         if (value <= old_capacity) {
8539           if (IsJSArray()) {
8540             Object* obj;
8541             if (elements_kind == FAST_ELEMENTS ||
8542                 elements_kind == FAST_SMI_ONLY_ELEMENTS) {
8543               MaybeObject* maybe_obj = EnsureWritableFastElements();
8544               if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8545             }
8546             if (2 * value <= old_capacity) {
8547               // If more than half the elements won't be used, trim the array.
8548               if (value == 0) {
8549                 initialize_elements();
8550               } else {
8551                 Address filler_start;
8552                 int filler_size;
8553                 if (elements_kind == FAST_ELEMENTS ||
8554                     elements_kind == FAST_SMI_ONLY_ELEMENTS) {
8555                   FixedArray* fast_elements = FixedArray::cast(elements());
8556                   fast_elements->set_length(value);
8557                   filler_start = fast_elements->address() +
8558                       FixedArray::OffsetOfElementAt(value);
8559                   filler_size = (old_capacity - value) * kPointerSize;
8560                 } else {
8561                   ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
8562                   FixedDoubleArray* fast_double_elements =
8563                       FixedDoubleArray::cast(elements());
8564                   fast_double_elements->set_length(value);
8565                   filler_start = fast_double_elements->address() +
8566                       FixedDoubleArray::OffsetOfElementAt(value);
8567                   filler_size = (old_capacity - value) * kDoubleSize;
8568                 }
8569                 GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
8570               }
8571             } else {
8572               // Otherwise, fill the unused tail with holes.
8573               int old_length = FastD2I(JSArray::cast(this)->length()->Number());
8574               if (elements_kind == FAST_ELEMENTS ||
8575                   elements_kind == FAST_SMI_ONLY_ELEMENTS) {
8576                 FixedArray* fast_elements = FixedArray::cast(elements());
8577                 for (int i = value; i < old_length; i++) {
8578                   fast_elements->set_the_hole(i);
8579                 }
8580               } else {
8581                 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS);
8582                 FixedDoubleArray* fast_double_elements =
8583                     FixedDoubleArray::cast(elements());
8584                 for (int i = value; i < old_length; i++) {
8585                   fast_double_elements->set_the_hole(i);
8586                 }
8587               }
8588             }
8589             JSArray::cast(this)->set_length(Smi::cast(smi_length));
8590           }
8591           return this;
8592         }
8593         int min = NewElementsCapacity(old_capacity);
8594         int new_capacity = value > min ? value : min;
8595         if (!ShouldConvertToSlowElements(new_capacity)) {
8596           MaybeObject* result;
8597           if (elements_kind == FAST_ELEMENTS ||
8598               elements_kind == FAST_SMI_ONLY_ELEMENTS) {
8599             SetFastElementsCapacityMode set_capacity_mode =
8600                 elements_kind == FAST_SMI_ONLY_ELEMENTS
8601                     ? kAllowSmiOnlyElements
8602                     : kDontAllowSmiOnlyElements;
8603             result = SetFastElementsCapacityAndLength(new_capacity,
8604                                                       value,
8605                                                       set_capacity_mode);
8606           }  else {
8607             ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS);
8608             result = SetFastDoubleElementsCapacityAndLength(new_capacity,
8609                                                             value);
8610           }
8611           if (result->IsFailure()) return result;
8612           return this;
8613         }
8614         break;
8615       }
8616       case DICTIONARY_ELEMENTS: {
8617         if (IsJSArray()) {
8618           if (value == 0) {
8619             // If the length of a slow array is reset to zero, we clear
8620             // the array and flush backing storage. This has the added
8621             // benefit that the array returns to fast mode.
8622             Object* obj;
8623             { MaybeObject* maybe_obj = ResetElements();
8624               if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8625             }
8626           } else {
8627             // Remove deleted elements.
8628             uint32_t old_length =
8629             static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
8630             element_dictionary()->RemoveNumberEntries(value, old_length);
8631           }
8632           JSArray::cast(this)->set_length(Smi::cast(smi_length));
8633         }
8634         return this;
8635       }
8636       case NON_STRICT_ARGUMENTS_ELEMENTS:
8637       case EXTERNAL_BYTE_ELEMENTS:
8638       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8639       case EXTERNAL_SHORT_ELEMENTS:
8640       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8641       case EXTERNAL_INT_ELEMENTS:
8642       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8643       case EXTERNAL_FLOAT_ELEMENTS:
8644       case EXTERNAL_DOUBLE_ELEMENTS:
8645       case EXTERNAL_PIXEL_ELEMENTS:
8646         UNREACHABLE();
8647         break;
8648     }
8649   }
8650
8651   // General slow case.
8652   if (len->IsNumber()) {
8653     uint32_t length;
8654     if (len->ToArrayIndex(&length)) {
8655       return SetSlowElements(len);
8656     } else {
8657       return ArrayLengthRangeError(GetHeap());
8658     }
8659   }
8660
8661   // len is not a number so make the array size one and
8662   // set only element to len.
8663   Object* obj;
8664   MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1);
8665   if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8666   FixedArray::cast(obj)->set(0, len);
8667
8668   maybe_obj = EnsureCanContainElements(&len, 1);
8669   if (maybe_obj->IsFailure()) return maybe_obj;
8670
8671   if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1));
8672   set_elements(FixedArray::cast(obj));
8673   return this;
8674 }
8675
8676
8677 Object* Map::GetPrototypeTransition(Object* prototype) {
8678   FixedArray* cache = prototype_transitions();
8679   int number_of_transitions = NumberOfProtoTransitions();
8680   const int proto_offset =
8681       kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
8682   const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
8683   const int step = kProtoTransitionElementsPerEntry;
8684   for (int i = 0; i < number_of_transitions; i++) {
8685     if (cache->get(proto_offset + i * step) == prototype) {
8686       Object* map = cache->get(map_offset + i * step);
8687       ASSERT(map->IsMap());
8688       return map;
8689     }
8690   }
8691   return NULL;
8692 }
8693
8694
8695 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
8696   ASSERT(map->IsMap());
8697   ASSERT(HeapObject::cast(prototype)->map()->IsMap());
8698   // Don't cache prototype transition if this map is shared.
8699   if (is_shared() || !FLAG_cache_prototype_transitions) return this;
8700
8701   FixedArray* cache = prototype_transitions();
8702
8703   const int step = kProtoTransitionElementsPerEntry;
8704   const int header = kProtoTransitionHeaderSize;
8705
8706   int capacity = (cache->length() - header) / step;
8707
8708   int transitions = NumberOfProtoTransitions() + 1;
8709
8710   if (transitions > capacity) {
8711     if (capacity > kMaxCachedPrototypeTransitions) return this;
8712
8713     FixedArray* new_cache;
8714     // Grow array by factor 2 over and above what we need.
8715     { MaybeObject* maybe_cache =
8716           GetHeap()->AllocateFixedArray(transitions * 2 * step + header);
8717       if (!maybe_cache->To<FixedArray>(&new_cache)) return maybe_cache;
8718     }
8719
8720     for (int i = 0; i < capacity * step; i++) {
8721       new_cache->set(i + header, cache->get(i + header));
8722     }
8723     cache = new_cache;
8724     set_prototype_transitions(cache);
8725   }
8726
8727   int last = transitions - 1;
8728
8729   cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype);
8730   cache->set(header + last * step + kProtoTransitionMapOffset, map);
8731   SetNumberOfProtoTransitions(transitions);
8732
8733   return cache;
8734 }
8735
8736
8737 MaybeObject* JSReceiver::SetPrototype(Object* value,
8738                                       bool skip_hidden_prototypes) {
8739 #ifdef DEBUG
8740   int size = Size();
8741 #endif
8742
8743   Heap* heap = GetHeap();
8744   // Silently ignore the change if value is not a JSObject or null.
8745   // SpiderMonkey behaves this way.
8746   if (!value->IsJSReceiver() && !value->IsNull()) return value;
8747
8748   // From 8.6.2 Object Internal Methods
8749   // ...
8750   // In addition, if [[Extensible]] is false the value of the [[Class]] and
8751   // [[Prototype]] internal properties of the object may not be modified.
8752   // ...
8753   // Implementation specific extensions that modify [[Class]], [[Prototype]]
8754   // or [[Extensible]] must not violate the invariants defined in the preceding
8755   // paragraph.
8756   if (!this->map()->is_extensible()) {
8757     HandleScope scope(heap->isolate());
8758     Handle<Object> handle(this, heap->isolate());
8759     return heap->isolate()->Throw(
8760         *FACTORY->NewTypeError("non_extensible_proto",
8761                                HandleVector<Object>(&handle, 1)));
8762   }
8763
8764   // Before we can set the prototype we need to be sure
8765   // prototype cycles are prevented.
8766   // It is sufficient to validate that the receiver is not in the new prototype
8767   // chain.
8768   for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
8769     if (JSReceiver::cast(pt) == this) {
8770       // Cycle detected.
8771       HandleScope scope(heap->isolate());
8772       return heap->isolate()->Throw(
8773           *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
8774     }
8775   }
8776
8777   JSReceiver* real_receiver = this;
8778
8779   if (skip_hidden_prototypes) {
8780     // Find the first object in the chain whose prototype object is not
8781     // hidden and set the new prototype on that object.
8782     Object* current_proto = real_receiver->GetPrototype();
8783     while (current_proto->IsJSObject() &&
8784           JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) {
8785       real_receiver = JSReceiver::cast(current_proto);
8786       current_proto = current_proto->GetPrototype();
8787     }
8788   }
8789
8790   // Set the new prototype of the object.
8791   Map* map = real_receiver->map();
8792
8793   // Nothing to do if prototype is already set.
8794   if (map->prototype() == value) return value;
8795
8796   Object* new_map = map->GetPrototypeTransition(value);
8797   if (new_map == NULL) {
8798     { MaybeObject* maybe_new_map = map->CopyDropTransitions();
8799       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
8800     }
8801
8802     { MaybeObject* maybe_new_cache =
8803           map->PutPrototypeTransition(value, Map::cast(new_map));
8804       if (maybe_new_cache->IsFailure()) return maybe_new_cache;
8805     }
8806
8807     Map::cast(new_map)->set_prototype(value);
8808   }
8809   ASSERT(Map::cast(new_map)->prototype() == value);
8810   real_receiver->set_map(Map::cast(new_map));
8811
8812   heap->ClearInstanceofCache();
8813   ASSERT(size == Size());
8814   return value;
8815 }
8816
8817
8818 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args,
8819                                                 uint32_t first_arg,
8820                                                 uint32_t arg_count) {
8821   return EnsureCanContainElements(args->arguments() - first_arg, arg_count);
8822 }
8823
8824
8825 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) {
8826   switch (GetElementsKind()) {
8827     case FAST_SMI_ONLY_ELEMENTS:
8828     case FAST_ELEMENTS: {
8829       uint32_t length = IsJSArray() ?
8830           static_cast<uint32_t>
8831               (Smi::cast(JSArray::cast(this)->length())->value()) :
8832           static_cast<uint32_t>(FixedArray::cast(elements())->length());
8833       if ((index < length) &&
8834           !FixedArray::cast(elements())->get(index)->IsTheHole()) {
8835         return true;
8836       }
8837       break;
8838     }
8839     case FAST_DOUBLE_ELEMENTS: {
8840       uint32_t length = IsJSArray() ?
8841           static_cast<uint32_t>
8842               (Smi::cast(JSArray::cast(this)->length())->value()) :
8843           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
8844       if ((index < length) &&
8845           !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
8846         return true;
8847       }
8848       break;
8849     }
8850     case EXTERNAL_PIXEL_ELEMENTS: {
8851       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
8852       if (index < static_cast<uint32_t>(pixels->length())) {
8853         return true;
8854       }
8855       break;
8856     }
8857     case EXTERNAL_BYTE_ELEMENTS:
8858     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8859     case EXTERNAL_SHORT_ELEMENTS:
8860     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8861     case EXTERNAL_INT_ELEMENTS:
8862     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8863     case EXTERNAL_FLOAT_ELEMENTS:
8864     case EXTERNAL_DOUBLE_ELEMENTS: {
8865       ExternalArray* array = ExternalArray::cast(elements());
8866       if (index < static_cast<uint32_t>(array->length())) {
8867         return true;
8868       }
8869       break;
8870     }
8871     case DICTIONARY_ELEMENTS: {
8872       if (element_dictionary()->FindEntry(index)
8873           != NumberDictionary::kNotFound) {
8874         return true;
8875       }
8876       break;
8877     }
8878     case NON_STRICT_ARGUMENTS_ELEMENTS:
8879       UNREACHABLE();
8880       break;
8881   }
8882
8883   // Handle [] on String objects.
8884   if (this->IsStringObjectWithCharacterAt(index)) return true;
8885
8886   Object* pt = GetPrototype();
8887   if (pt->IsNull()) return false;
8888   if (pt->IsJSProxy()) {
8889     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
8890     return JSProxy::cast(pt)->GetElementAttributeWithHandler(
8891         receiver, index) != ABSENT;
8892   }
8893   return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
8894 }
8895
8896
8897 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) {
8898   Isolate* isolate = GetIsolate();
8899   // Make sure that the top context does not change when doing
8900   // callbacks or interceptor calls.
8901   AssertNoContextChange ncc;
8902   HandleScope scope(isolate);
8903   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
8904   Handle<JSReceiver> receiver_handle(receiver);
8905   Handle<JSObject> holder_handle(this);
8906   CustomArguments args(isolate, interceptor->data(), receiver, this);
8907   v8::AccessorInfo info(args.end());
8908   if (!interceptor->query()->IsUndefined()) {
8909     v8::IndexedPropertyQuery query =
8910         v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
8911     LOG(isolate,
8912         ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
8913     v8::Handle<v8::Integer> result;
8914     {
8915       // Leaving JavaScript.
8916       VMState state(isolate, EXTERNAL);
8917       result = query(index, info);
8918     }
8919     if (!result.IsEmpty()) {
8920       ASSERT(result->IsInt32());
8921       return true;  // absence of property is signaled by empty handle.
8922     }
8923   } else if (!interceptor->getter()->IsUndefined()) {
8924     v8::IndexedPropertyGetter getter =
8925         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
8926     LOG(isolate,
8927         ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
8928     v8::Handle<v8::Value> result;
8929     {
8930       // Leaving JavaScript.
8931       VMState state(isolate, EXTERNAL);
8932       result = getter(index, info);
8933     }
8934     if (!result.IsEmpty()) return true;
8935   }
8936   return holder_handle->HasElementPostInterceptor(*receiver_handle, index);
8937 }
8938
8939
8940 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) {
8941   // Check access rights if needed.
8942   if (IsAccessCheckNeeded()) {
8943     Heap* heap = GetHeap();
8944     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
8945       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
8946       return UNDEFINED_ELEMENT;
8947     }
8948   }
8949
8950   if (IsJSGlobalProxy()) {
8951     Object* proto = GetPrototype();
8952     if (proto->IsNull()) return UNDEFINED_ELEMENT;
8953     ASSERT(proto->IsJSGlobalObject());
8954     return JSObject::cast(proto)->HasLocalElement(index);
8955   }
8956
8957   // Check for lookup interceptor
8958   if (HasIndexedInterceptor()) {
8959     return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
8960                                                   : UNDEFINED_ELEMENT;
8961   }
8962
8963   // Handle [] on String objects.
8964   if (this->IsStringObjectWithCharacterAt(index)) {
8965     return STRING_CHARACTER_ELEMENT;
8966   }
8967
8968   switch (GetElementsKind()) {
8969     case FAST_SMI_ONLY_ELEMENTS:
8970     case FAST_ELEMENTS: {
8971       uint32_t length = IsJSArray() ?
8972           static_cast<uint32_t>
8973               (Smi::cast(JSArray::cast(this)->length())->value()) :
8974           static_cast<uint32_t>(FixedArray::cast(elements())->length());
8975       if ((index < length) &&
8976           !FixedArray::cast(elements())->get(index)->IsTheHole()) {
8977         return FAST_ELEMENT;
8978       }
8979       break;
8980     }
8981     case FAST_DOUBLE_ELEMENTS: {
8982       uint32_t length = IsJSArray() ?
8983           static_cast<uint32_t>
8984               (Smi::cast(JSArray::cast(this)->length())->value()) :
8985           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
8986       if ((index < length) &&
8987           !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
8988         return FAST_ELEMENT;
8989       }
8990       break;
8991     }
8992     case EXTERNAL_PIXEL_ELEMENTS: {
8993       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
8994       if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT;
8995       break;
8996     }
8997     case EXTERNAL_BYTE_ELEMENTS:
8998     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8999     case EXTERNAL_SHORT_ELEMENTS:
9000     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9001     case EXTERNAL_INT_ELEMENTS:
9002     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9003     case EXTERNAL_FLOAT_ELEMENTS:
9004     case EXTERNAL_DOUBLE_ELEMENTS: {
9005       ExternalArray* array = ExternalArray::cast(elements());
9006       if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
9007       break;
9008     }
9009     case DICTIONARY_ELEMENTS: {
9010       if (element_dictionary()->FindEntry(index) !=
9011           NumberDictionary::kNotFound) {
9012         return DICTIONARY_ELEMENT;
9013       }
9014       break;
9015     }
9016     case NON_STRICT_ARGUMENTS_ELEMENTS: {
9017       // Aliased parameters and non-aliased elements in a fast backing store
9018       // behave as FAST_ELEMENT.  Non-aliased elements in a dictionary
9019       // backing store behave as DICTIONARY_ELEMENT.
9020       FixedArray* parameter_map = FixedArray::cast(elements());
9021       uint32_t length = parameter_map->length();
9022       Object* probe =
9023           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
9024       if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
9025       // If not aliased, check the arguments.
9026       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9027       if (arguments->IsDictionary()) {
9028         NumberDictionary* dictionary = NumberDictionary::cast(arguments);
9029         if (dictionary->FindEntry(index) != NumberDictionary::kNotFound) {
9030           return DICTIONARY_ELEMENT;
9031         }
9032       } else {
9033         length = arguments->length();
9034         probe = (index < length) ? arguments->get(index) : NULL;
9035         if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
9036       }
9037       break;
9038     }
9039   }
9040
9041   return UNDEFINED_ELEMENT;
9042 }
9043
9044
9045 bool JSObject::HasElementInElements(FixedArray* elements,
9046                                     ElementsKind kind,
9047                                     uint32_t index) {
9048   ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS);
9049   if (kind == FAST_ELEMENTS) {
9050     int length = IsJSArray()
9051         ? Smi::cast(JSArray::cast(this)->length())->value()
9052         : elements->length();
9053     if (index < static_cast<uint32_t>(length) &&
9054         !elements->get(index)->IsTheHole()) {
9055       return true;
9056     }
9057   } else {
9058     if (NumberDictionary::cast(elements)->FindEntry(index) !=
9059         NumberDictionary::kNotFound) {
9060       return true;
9061     }
9062   }
9063   return false;
9064 }
9065
9066
9067 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
9068   // Check access rights if needed.
9069   if (IsAccessCheckNeeded()) {
9070     Heap* heap = GetHeap();
9071     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
9072       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
9073       return false;
9074     }
9075   }
9076
9077   // Check for lookup interceptor
9078   if (HasIndexedInterceptor()) {
9079     return HasElementWithInterceptor(receiver, index);
9080   }
9081
9082   ElementsKind kind = GetElementsKind();
9083   switch (kind) {
9084     case FAST_SMI_ONLY_ELEMENTS:
9085     case FAST_ELEMENTS: {
9086       uint32_t length = IsJSArray() ?
9087           static_cast<uint32_t>
9088               (Smi::cast(JSArray::cast(this)->length())->value()) :
9089           static_cast<uint32_t>(FixedArray::cast(elements())->length());
9090       if ((index < length) &&
9091           !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
9092       break;
9093     }
9094     case FAST_DOUBLE_ELEMENTS: {
9095       uint32_t length = IsJSArray() ?
9096           static_cast<uint32_t>
9097               (Smi::cast(JSArray::cast(this)->length())->value()) :
9098           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
9099       if ((index < length) &&
9100           !FixedDoubleArray::cast(elements())->is_the_hole(index)) return true;
9101       break;
9102     }
9103     case EXTERNAL_PIXEL_ELEMENTS: {
9104       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9105       if (index < static_cast<uint32_t>(pixels->length())) {
9106         return true;
9107       }
9108       break;
9109     }
9110     case EXTERNAL_BYTE_ELEMENTS:
9111     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9112     case EXTERNAL_SHORT_ELEMENTS:
9113     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9114     case EXTERNAL_INT_ELEMENTS:
9115     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9116     case EXTERNAL_FLOAT_ELEMENTS:
9117     case EXTERNAL_DOUBLE_ELEMENTS: {
9118       ExternalArray* array = ExternalArray::cast(elements());
9119       if (index < static_cast<uint32_t>(array->length())) {
9120         return true;
9121       }
9122       break;
9123     }
9124     case DICTIONARY_ELEMENTS: {
9125       if (element_dictionary()->FindEntry(index)
9126           != NumberDictionary::kNotFound) {
9127         return true;
9128       }
9129       break;
9130     }
9131     case NON_STRICT_ARGUMENTS_ELEMENTS: {
9132       FixedArray* parameter_map = FixedArray::cast(elements());
9133       uint32_t length = parameter_map->length();
9134       Object* probe =
9135           (index < length - 2) ? parameter_map->get(index + 2) : NULL;
9136       if (probe != NULL && !probe->IsTheHole()) return true;
9137
9138       // Not a mapped parameter, check the arguments.
9139       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9140       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
9141       if (HasElementInElements(arguments, kind, index)) return true;
9142       break;
9143     }
9144   }
9145
9146   // Handle [] on String objects.
9147   if (this->IsStringObjectWithCharacterAt(index)) return true;
9148
9149   Object* pt = GetPrototype();
9150   if (pt->IsNull()) return false;
9151   if (pt->IsJSProxy()) {
9152     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
9153     return JSProxy::cast(pt)->GetElementAttributeWithHandler(
9154         receiver, index) != ABSENT;
9155   }
9156   return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
9157 }
9158
9159
9160 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
9161                                                  Object* value,
9162                                                  StrictModeFlag strict_mode,
9163                                                  bool check_prototype) {
9164   Isolate* isolate = GetIsolate();
9165   // Make sure that the top context does not change when doing
9166   // callbacks or interceptor calls.
9167   AssertNoContextChange ncc;
9168   HandleScope scope(isolate);
9169   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
9170   Handle<JSObject> this_handle(this);
9171   Handle<Object> value_handle(value, isolate);
9172   if (!interceptor->setter()->IsUndefined()) {
9173     v8::IndexedPropertySetter setter =
9174         v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
9175     LOG(isolate,
9176         ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
9177     CustomArguments args(isolate, interceptor->data(), this, this);
9178     v8::AccessorInfo info(args.end());
9179     v8::Handle<v8::Value> result;
9180     {
9181       // Leaving JavaScript.
9182       VMState state(isolate, EXTERNAL);
9183       result = setter(index, v8::Utils::ToLocal(value_handle), info);
9184     }
9185     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9186     if (!result.IsEmpty()) return *value_handle;
9187   }
9188   MaybeObject* raw_result =
9189       this_handle->SetElementWithoutInterceptor(index,
9190                                                 *value_handle,
9191                                                 strict_mode,
9192                                                 check_prototype);
9193   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9194   return raw_result;
9195 }
9196
9197
9198 MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
9199                                               Object* structure,
9200                                               uint32_t index,
9201                                               Object* holder) {
9202   Isolate* isolate = GetIsolate();
9203   ASSERT(!structure->IsForeign());
9204
9205   // api style callbacks.
9206   if (structure->IsAccessorInfo()) {
9207     Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9208     Object* fun_obj = data->getter();
9209     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
9210     HandleScope scope(isolate);
9211     Handle<JSObject> self(JSObject::cast(receiver));
9212     Handle<JSObject> holder_handle(JSObject::cast(holder));
9213     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9214     Handle<String> key = isolate->factory()->NumberToString(number);
9215     LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
9216     CustomArguments args(isolate, data->data(), *self, *holder_handle);
9217     v8::AccessorInfo info(args.end());
9218     v8::Handle<v8::Value> result;
9219     {
9220       // Leaving JavaScript.
9221       VMState state(isolate, EXTERNAL);
9222       result = call_fun(v8::Utils::ToLocal(key), info);
9223     }
9224     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9225     if (result.IsEmpty()) return isolate->heap()->undefined_value();
9226     return *v8::Utils::OpenHandle(*result);
9227   }
9228
9229   // __defineGetter__ callback
9230   if (structure->IsFixedArray()) {
9231     Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
9232     if (getter->IsSpecFunction()) {
9233       // TODO(rossberg): nicer would be to cast to some JSCallable here...
9234       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
9235     }
9236     // Getter is not a function.
9237     return isolate->heap()->undefined_value();
9238   }
9239
9240   UNREACHABLE();
9241   return NULL;
9242 }
9243
9244
9245 MaybeObject* JSObject::SetElementWithCallback(Object* structure,
9246                                               uint32_t index,
9247                                               Object* value,
9248                                               JSObject* holder,
9249                                               StrictModeFlag strict_mode) {
9250   Isolate* isolate = GetIsolate();
9251   HandleScope scope(isolate);
9252
9253   // We should never get here to initialize a const with the hole
9254   // value since a const declaration would conflict with the setter.
9255   ASSERT(!value->IsTheHole());
9256   Handle<Object> value_handle(value, isolate);
9257
9258   // To accommodate both the old and the new api we switch on the
9259   // data structure used to store the callbacks.  Eventually foreign
9260   // callbacks should be phased out.
9261   ASSERT(!structure->IsForeign());
9262
9263   if (structure->IsAccessorInfo()) {
9264     // api style callbacks
9265     Handle<JSObject> self(this);
9266     Handle<JSObject> holder_handle(JSObject::cast(holder));
9267     Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9268     Object* call_obj = data->setter();
9269     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
9270     if (call_fun == NULL) return value;
9271     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9272     Handle<String> key(isolate->factory()->NumberToString(number));
9273     LOG(isolate, ApiNamedPropertyAccess("store", *self, *key));
9274     CustomArguments args(isolate, data->data(), *self, *holder_handle);
9275     v8::AccessorInfo info(args.end());
9276     {
9277       // Leaving JavaScript.
9278       VMState state(isolate, EXTERNAL);
9279       call_fun(v8::Utils::ToLocal(key),
9280                v8::Utils::ToLocal(value_handle),
9281                info);
9282     }
9283     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9284     return *value_handle;
9285   }
9286
9287   if (structure->IsFixedArray()) {
9288     Handle<Object> setter(FixedArray::cast(structure)->get(kSetterIndex));
9289     if (setter->IsSpecFunction()) {
9290       // TODO(rossberg): nicer would be to cast to some JSCallable here...
9291       return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
9292     } else {
9293       if (strict_mode == kNonStrictMode) {
9294         return value;
9295       }
9296       Handle<Object> holder_handle(holder, isolate);
9297       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
9298       Handle<Object> args[2] = { key, holder_handle };
9299       return isolate->Throw(
9300           *isolate->factory()->NewTypeError("no_setter_in_callback",
9301                                             HandleVector(args, 2)));
9302     }
9303   }
9304
9305   UNREACHABLE();
9306   return NULL;
9307 }
9308
9309
9310 bool JSObject::HasFastArgumentsElements() {
9311   Heap* heap = GetHeap();
9312   if (!elements()->IsFixedArray()) return false;
9313   FixedArray* elements = FixedArray::cast(this->elements());
9314   if (elements->map() != heap->non_strict_arguments_elements_map()) {
9315     return false;
9316   }
9317   FixedArray* arguments = FixedArray::cast(elements->get(1));
9318   return !arguments->IsDictionary();
9319 }
9320
9321
9322 bool JSObject::HasDictionaryArgumentsElements() {
9323   Heap* heap = GetHeap();
9324   if (!elements()->IsFixedArray()) return false;
9325   FixedArray* elements = FixedArray::cast(this->elements());
9326   if (elements->map() != heap->non_strict_arguments_elements_map()) {
9327     return false;
9328   }
9329   FixedArray* arguments = FixedArray::cast(elements->get(1));
9330   return arguments->IsDictionary();
9331 }
9332
9333
9334 // Adding n elements in fast case is O(n*n).
9335 // Note: revisit design to have dual undefined values to capture absent
9336 // elements.
9337 MaybeObject* JSObject::SetFastElement(uint32_t index,
9338                                       Object* value,
9339                                       StrictModeFlag strict_mode,
9340                                       bool check_prototype) {
9341   ASSERT(HasFastTypeElements() ||
9342          HasFastArgumentsElements());
9343
9344   FixedArray* backing_store = FixedArray::cast(elements());
9345   if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
9346     backing_store = FixedArray::cast(backing_store->get(1));
9347   } else {
9348     Object* writable;
9349     MaybeObject* maybe = EnsureWritableFastElements();
9350     if (!maybe->ToObject(&writable)) return maybe;
9351     backing_store = FixedArray::cast(writable);
9352   }
9353   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
9354
9355   if (check_prototype &&
9356       (index >= capacity || backing_store->get(index)->IsTheHole())) {
9357     bool found;
9358     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9359                                                                    value,
9360                                                                    &found,
9361                                                                    strict_mode);
9362     if (found) return result;
9363   }
9364
9365   uint32_t new_capacity = capacity;
9366   // Check if the length property of this object needs to be updated.
9367   uint32_t array_length = 0;
9368   bool must_update_array_length = false;
9369   if (IsJSArray()) {
9370     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9371     if (index >= array_length) {
9372       must_update_array_length = true;
9373       array_length = index + 1;
9374     }
9375   }
9376   // Check if the capacity of the backing store needs to be increased, or if
9377   // a transition to slow elements is necessary.
9378   if (index >= capacity) {
9379     bool convert_to_slow = true;
9380     if ((index - capacity) < kMaxGap) {
9381       new_capacity = NewElementsCapacity(index + 1);
9382       ASSERT(new_capacity > index);
9383       if (!ShouldConvertToSlowElements(new_capacity)) {
9384         convert_to_slow = false;
9385       }
9386     }
9387     if (convert_to_slow) {
9388       MaybeObject* result = NormalizeElements();
9389       if (result->IsFailure()) return result;
9390       return SetDictionaryElement(index, value, strict_mode, check_prototype);
9391     }
9392   }
9393   // Convert to fast double elements if appropriate.
9394   if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) {
9395     MaybeObject* maybe =
9396         SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
9397     if (maybe->IsFailure()) return maybe;
9398     FixedDoubleArray::cast(elements())->set(index, value->Number());
9399     return value;
9400   }
9401   // Change elements kind from SMI_ONLY to generic FAST if necessary.
9402   if (HasFastSmiOnlyElements() && !value->IsSmi()) {
9403     MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS);
9404     Map* new_map;
9405     if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
9406     set_map(new_map);
9407     if (FLAG_trace_elements_transitions) {
9408       PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
9409                               FAST_ELEMENTS, elements());
9410     }
9411   }
9412   // Increase backing store capacity if that's been decided previously.
9413   if (new_capacity != capacity) {
9414     Object* new_elements;
9415     SetFastElementsCapacityMode set_capacity_mode =
9416         value->IsSmi() && HasFastSmiOnlyElements()
9417             ? kAllowSmiOnlyElements
9418             : kDontAllowSmiOnlyElements;
9419     MaybeObject* maybe =
9420         SetFastElementsCapacityAndLength(new_capacity,
9421                                          array_length,
9422                                          set_capacity_mode);
9423     if (!maybe->ToObject(&new_elements)) return maybe;
9424     FixedArray::cast(new_elements)->set(index, value);
9425     return value;
9426   }
9427   // Finally, set the new element and length.
9428   ASSERT(elements()->IsFixedArray());
9429   backing_store->set(index, value);
9430   if (must_update_array_length) {
9431     JSArray::cast(this)->set_length(Smi::FromInt(array_length));
9432   }
9433   return value;
9434 }
9435
9436
9437 MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
9438                                             Object* value,
9439                                             StrictModeFlag strict_mode,
9440                                             bool check_prototype) {
9441   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
9442   Isolate* isolate = GetIsolate();
9443   Heap* heap = isolate->heap();
9444
9445   // Insert element in the dictionary.
9446   FixedArray* elements = FixedArray::cast(this->elements());
9447   bool is_arguments =
9448       (elements->map() == heap->non_strict_arguments_elements_map());
9449   NumberDictionary* dictionary = NULL;
9450   if (is_arguments) {
9451     dictionary = NumberDictionary::cast(elements->get(1));
9452   } else {
9453     dictionary = NumberDictionary::cast(elements);
9454   }
9455
9456   int entry = dictionary->FindEntry(index);
9457   if (entry != NumberDictionary::kNotFound) {
9458     Object* element = dictionary->ValueAt(entry);
9459     PropertyDetails details = dictionary->DetailsAt(entry);
9460     if (details.type() == CALLBACKS) {
9461       return SetElementWithCallback(element, index, value, this, strict_mode);
9462     } else {
9463       dictionary->UpdateMaxNumberKey(index);
9464       // If put fails in strict mode, throw an exception.
9465       if (!dictionary->ValueAtPut(entry, value) && strict_mode == kStrictMode) {
9466         Handle<Object> holder(this);
9467         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9468         Handle<Object> args[2] = { number, holder };
9469         Handle<Object> error =
9470             isolate->factory()->NewTypeError("strict_read_only_property",
9471                                              HandleVector(args, 2));
9472         return isolate->Throw(*error);
9473       }
9474     }
9475   } else {
9476     // Index not already used. Look for an accessor in the prototype chain.
9477     if (check_prototype) {
9478       bool found;
9479       MaybeObject* result =
9480           SetElementWithCallbackSetterInPrototypes(
9481               index, value, &found, strict_mode);
9482       if (found) return result;
9483     }
9484     // When we set the is_extensible flag to false we always force the
9485     // element into dictionary mode (and force them to stay there).
9486     if (!map()->is_extensible()) {
9487       if (strict_mode == kNonStrictMode) {
9488         return isolate->heap()->undefined_value();
9489       } else {
9490         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9491         Handle<String> name = isolate->factory()->NumberToString(number);
9492         Handle<Object> args[1] = { name };
9493         Handle<Object> error =
9494             isolate->factory()->NewTypeError("object_not_extensible",
9495                                              HandleVector(args, 1));
9496         return isolate->Throw(*error);
9497       }
9498     }
9499     FixedArrayBase* new_dictionary;
9500     MaybeObject* maybe = dictionary->AtNumberPut(index, value);
9501     if (!maybe->To<FixedArrayBase>(&new_dictionary)) return maybe;
9502     if (dictionary != NumberDictionary::cast(new_dictionary)) {
9503       if (is_arguments) {
9504         elements->set(1, new_dictionary);
9505       } else {
9506         set_elements(new_dictionary);
9507       }
9508       dictionary = NumberDictionary::cast(new_dictionary);
9509     }
9510   }
9511
9512   // Update the array length if this JSObject is an array.
9513   if (IsJSArray()) {
9514     MaybeObject* result =
9515         JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
9516     if (result->IsFailure()) return result;
9517   }
9518
9519   // Attempt to put this object back in fast case.
9520   if (ShouldConvertToFastElements()) {
9521     uint32_t new_length = 0;
9522     if (IsJSArray()) {
9523       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
9524     } else {
9525       new_length = dictionary->max_number_key() + 1;
9526     }
9527     MaybeObject* result = CanConvertToFastDoubleElements()
9528         ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
9529         : SetFastElementsCapacityAndLength(new_length,
9530                                            new_length,
9531                                            kDontAllowSmiOnlyElements);
9532     if (result->IsFailure()) return result;
9533 #ifdef DEBUG
9534     if (FLAG_trace_normalization) {
9535       PrintF("Object elements are fast case again:\n");
9536       Print();
9537     }
9538 #endif
9539   }
9540   return value;
9541 }
9542
9543
9544 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
9545     uint32_t index,
9546     Object* value,
9547     StrictModeFlag strict_mode,
9548     bool check_prototype) {
9549   ASSERT(HasFastDoubleElements());
9550
9551   FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9552   uint32_t elms_length = static_cast<uint32_t>(elms->length());
9553
9554   // If storing to an element that isn't in the array, pass the store request
9555   // up the prototype chain before storing in the receiver's elements.
9556   if (check_prototype &&
9557       (index >= elms_length || elms->is_the_hole(index))) {
9558     bool found;
9559     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9560                                                                    value,
9561                                                                    &found,
9562                                                                    strict_mode);
9563     if (found) return result;
9564   }
9565
9566   // If the value object is not a heap number, switch to fast elements and try
9567   // again.
9568   bool value_is_smi = value->IsSmi();
9569   if (!value->IsNumber()) {
9570     Object* obj;
9571     uint32_t length = elms_length;
9572     if (IsJSArray()) {
9573       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9574     }
9575     MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
9576         elms_length,
9577         length,
9578         kDontAllowSmiOnlyElements);
9579     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9580     return SetFastElement(index,
9581                           value,
9582                           strict_mode,
9583                           check_prototype);
9584   }
9585
9586   double double_value = value_is_smi
9587       ? static_cast<double>(Smi::cast(value)->value())
9588       : HeapNumber::cast(value)->value();
9589
9590   // Check whether there is extra space in the fixed array.
9591   if (index < elms_length) {
9592     elms->set(index, double_value);
9593     if (IsJSArray()) {
9594       // Update the length of the array if needed.
9595       uint32_t array_length = 0;
9596       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9597       if (index >= array_length) {
9598         JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
9599       }
9600     }
9601     return value;
9602   }
9603
9604   // Allow gap in fast case.
9605   if ((index - elms_length) < kMaxGap) {
9606     // Try allocating extra space.
9607     int new_capacity = NewElementsCapacity(index+1);
9608     if (!ShouldConvertToSlowElements(new_capacity)) {
9609       ASSERT(static_cast<uint32_t>(new_capacity) > index);
9610       Object* obj;
9611       { MaybeObject* maybe_obj =
9612             SetFastDoubleElementsCapacityAndLength(new_capacity,
9613                                                    index + 1);
9614         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9615       }
9616       FixedDoubleArray::cast(elements())->set(index, double_value);
9617       return value;
9618     }
9619   }
9620
9621   // Otherwise default to slow case.
9622   ASSERT(HasFastDoubleElements());
9623   ASSERT(map()->has_fast_double_elements());
9624   ASSERT(elements()->IsFixedDoubleArray());
9625   Object* obj;
9626   { MaybeObject* maybe_obj = NormalizeElements();
9627     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9628   }
9629   ASSERT(HasDictionaryElements());
9630   return SetElement(index, value, strict_mode, check_prototype);
9631 }
9632
9633
9634 MaybeObject* JSReceiver::SetElement(uint32_t index,
9635                                     Object* value,
9636                                     StrictModeFlag strict_mode,
9637                                     bool check_proto) {
9638   return IsJSProxy()
9639       ? JSProxy::cast(this)->SetElementWithHandler(index, value, strict_mode)
9640       : JSObject::cast(this)->SetElement(index, value, strict_mode, check_proto)
9641   ;
9642 }
9643
9644
9645 MaybeObject* JSObject::SetElement(uint32_t index,
9646                                   Object* value,
9647                                   StrictModeFlag strict_mode,
9648                                   bool check_prototype) {
9649   // Check access rights if needed.
9650   if (IsAccessCheckNeeded()) {
9651     Heap* heap = GetHeap();
9652     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
9653       HandleScope scope(heap->isolate());
9654       Handle<Object> value_handle(value);
9655       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
9656       return *value_handle;
9657     }
9658   }
9659
9660   if (IsJSGlobalProxy()) {
9661     Object* proto = GetPrototype();
9662     if (proto->IsNull()) return value;
9663     ASSERT(proto->IsJSGlobalObject());
9664     return JSObject::cast(proto)->SetElement(index,
9665                                              value,
9666                                              strict_mode,
9667                                              check_prototype);
9668   }
9669
9670   // Check for lookup interceptor
9671   if (HasIndexedInterceptor()) {
9672     return SetElementWithInterceptor(index,
9673                                      value,
9674                                      strict_mode,
9675                                      check_prototype);
9676   }
9677
9678   return SetElementWithoutInterceptor(index,
9679                                       value,
9680                                       strict_mode,
9681                                       check_prototype);
9682 }
9683
9684
9685 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
9686                                                     Object* value,
9687                                                     StrictModeFlag strict_mode,
9688                                                     bool check_prototype) {
9689   Isolate* isolate = GetIsolate();
9690   switch (GetElementsKind()) {
9691     case FAST_SMI_ONLY_ELEMENTS:
9692     case FAST_ELEMENTS:
9693       return SetFastElement(index, value, strict_mode, check_prototype);
9694     case FAST_DOUBLE_ELEMENTS:
9695       return SetFastDoubleElement(index, value, strict_mode, check_prototype);
9696     case EXTERNAL_PIXEL_ELEMENTS: {
9697       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9698       return pixels->SetValue(index, value);
9699     }
9700     case EXTERNAL_BYTE_ELEMENTS: {
9701       ExternalByteArray* array = ExternalByteArray::cast(elements());
9702       return array->SetValue(index, value);
9703     }
9704     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
9705       ExternalUnsignedByteArray* array =
9706           ExternalUnsignedByteArray::cast(elements());
9707       return array->SetValue(index, value);
9708     }
9709     case EXTERNAL_SHORT_ELEMENTS: {
9710       ExternalShortArray* array = ExternalShortArray::cast(elements());
9711       return array->SetValue(index, value);
9712     }
9713     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
9714       ExternalUnsignedShortArray* array =
9715           ExternalUnsignedShortArray::cast(elements());
9716       return array->SetValue(index, value);
9717     }
9718     case EXTERNAL_INT_ELEMENTS: {
9719       ExternalIntArray* array = ExternalIntArray::cast(elements());
9720       return array->SetValue(index, value);
9721     }
9722     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
9723       ExternalUnsignedIntArray* array =
9724           ExternalUnsignedIntArray::cast(elements());
9725       return array->SetValue(index, value);
9726     }
9727     case EXTERNAL_FLOAT_ELEMENTS: {
9728       ExternalFloatArray* array = ExternalFloatArray::cast(elements());
9729       return array->SetValue(index, value);
9730     }
9731     case EXTERNAL_DOUBLE_ELEMENTS: {
9732       ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
9733       return array->SetValue(index, value);
9734     }
9735     case DICTIONARY_ELEMENTS:
9736       return SetDictionaryElement(index, value, strict_mode, check_prototype);
9737     case NON_STRICT_ARGUMENTS_ELEMENTS: {
9738       FixedArray* parameter_map = FixedArray::cast(elements());
9739       uint32_t length = parameter_map->length();
9740       Object* probe =
9741           (index < length - 2) ? parameter_map->get(index + 2) : NULL;
9742       if (probe != NULL && !probe->IsTheHole()) {
9743         Context* context = Context::cast(parameter_map->get(0));
9744         int context_index = Smi::cast(probe)->value();
9745         ASSERT(!context->get(context_index)->IsTheHole());
9746         context->set(context_index, value);
9747         return value;
9748       } else {
9749         // Object is not mapped, defer to the arguments.
9750         FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9751         if (arguments->IsDictionary()) {
9752           return SetDictionaryElement(index, value, strict_mode,
9753                                       check_prototype);
9754         } else {
9755           return SetFastElement(index, value, strict_mode, check_prototype);
9756         }
9757       }
9758     }
9759   }
9760   // All possible cases have been handled above. Add a return to avoid the
9761   // complaints from the compiler.
9762   UNREACHABLE();
9763   return isolate->heap()->null_value();
9764 }
9765
9766
9767 MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind(
9768     ElementsKind to_kind) {
9769   ElementsKind from_kind = map()->elements_kind();
9770   FixedArrayBase* elms = FixedArrayBase::cast(elements());
9771   uint32_t capacity = static_cast<uint32_t>(elms->length());
9772   uint32_t length = capacity;
9773   if (IsJSArray()) {
9774     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9775   }
9776   if (from_kind == FAST_SMI_ONLY_ELEMENTS) {
9777     if (to_kind == FAST_DOUBLE_ELEMENTS) {
9778       MaybeObject* maybe_result =
9779           SetFastDoubleElementsCapacityAndLength(capacity, length);
9780       if (maybe_result->IsFailure()) return maybe_result;
9781       return this;
9782     } else if (to_kind == FAST_ELEMENTS) {
9783       MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS);
9784       Map* new_map;
9785       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9786       set_map(new_map);
9787       return this;
9788     }
9789   } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
9790     MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
9791         capacity, length, kDontAllowSmiOnlyElements);
9792     if (maybe_result->IsFailure()) return maybe_result;
9793     return this;
9794   }
9795   // This method should never be called for any other case than the ones
9796   // handled above.
9797   UNREACHABLE();
9798   return GetIsolate()->heap()->null_value();
9799 }
9800
9801
9802 // static
9803 bool Map::IsValidElementsTransition(ElementsKind from_kind,
9804                                     ElementsKind to_kind) {
9805   return
9806       (from_kind == FAST_SMI_ONLY_ELEMENTS &&
9807           (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) ||
9808       (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS);
9809 }
9810
9811
9812 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
9813                                                    Object* value) {
9814   uint32_t old_len = 0;
9815   CHECK(length()->ToArrayIndex(&old_len));
9816   // Check to see if we need to update the length. For now, we make
9817   // sure that the length stays within 32-bits (unsigned).
9818   if (index >= old_len && index != 0xffffffff) {
9819     Object* len;
9820     { MaybeObject* maybe_len =
9821           GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
9822       if (!maybe_len->ToObject(&len)) return maybe_len;
9823     }
9824     set_length(len);
9825   }
9826   return value;
9827 }
9828
9829
9830 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
9831                                                  uint32_t index) {
9832   Isolate* isolate = GetIsolate();
9833   // Make sure that the top context does not change when doing
9834   // callbacks or interceptor calls.
9835   AssertNoContextChange ncc;
9836   HandleScope scope(isolate);
9837   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
9838   Handle<Object> this_handle(receiver, isolate);
9839   Handle<JSObject> holder_handle(this, isolate);
9840   if (!interceptor->getter()->IsUndefined()) {
9841     v8::IndexedPropertyGetter getter =
9842         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
9843     LOG(isolate,
9844         ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
9845     CustomArguments args(isolate, interceptor->data(), receiver, this);
9846     v8::AccessorInfo info(args.end());
9847     v8::Handle<v8::Value> result;
9848     {
9849       // Leaving JavaScript.
9850       VMState state(isolate, EXTERNAL);
9851       result = getter(index, info);
9852     }
9853     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9854     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
9855   }
9856
9857   Heap* heap = holder_handle->GetHeap();
9858   ElementsAccessor* handler = holder_handle->GetElementsAccessor();
9859   MaybeObject* raw_result = handler->Get(holder_handle->elements(),
9860                                          index,
9861                                          *holder_handle,
9862                                          *this_handle);
9863   if (raw_result != heap->the_hole_value()) return raw_result;
9864
9865   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9866
9867   Object* pt = holder_handle->GetPrototype();
9868   if (pt == heap->null_value()) return heap->undefined_value();
9869   return pt->GetElementWithReceiver(*this_handle, index);
9870 }
9871
9872
9873 bool JSObject::HasDenseElements() {
9874   int capacity = 0;
9875   int used = 0;
9876   GetElementsCapacityAndUsage(&capacity, &used);
9877   return (capacity == 0) || (used > (capacity / 2));
9878 }
9879
9880
9881 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
9882   *capacity = 0;
9883   *used = 0;
9884
9885   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
9886   FixedArray* backing_store = NULL;
9887   switch (GetElementsKind()) {
9888     case NON_STRICT_ARGUMENTS_ELEMENTS:
9889       backing_store_base =
9890           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
9891       backing_store = FixedArray::cast(backing_store_base);
9892       if (backing_store->IsDictionary()) {
9893         NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
9894         *capacity = dictionary->Capacity();
9895         *used = dictionary->NumberOfElements();
9896         break;
9897       }
9898       // Fall through.
9899     case FAST_SMI_ONLY_ELEMENTS:
9900     case FAST_ELEMENTS:
9901       backing_store = FixedArray::cast(backing_store_base);
9902       *capacity = backing_store->length();
9903       for (int i = 0; i < *capacity; ++i) {
9904         if (!backing_store->get(i)->IsTheHole()) ++(*used);
9905       }
9906       break;
9907     case DICTIONARY_ELEMENTS: {
9908       NumberDictionary* dictionary =
9909           NumberDictionary::cast(FixedArray::cast(elements()));
9910       *capacity = dictionary->Capacity();
9911       *used = dictionary->NumberOfElements();
9912       break;
9913     }
9914     case FAST_DOUBLE_ELEMENTS: {
9915       FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9916       *capacity = elms->length();
9917       for (int i = 0; i < *capacity; i++) {
9918         if (!elms->is_the_hole(i)) ++(*used);
9919       }
9920       break;
9921     }
9922     case EXTERNAL_BYTE_ELEMENTS:
9923     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9924     case EXTERNAL_SHORT_ELEMENTS:
9925     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9926     case EXTERNAL_INT_ELEMENTS:
9927     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9928     case EXTERNAL_FLOAT_ELEMENTS:
9929     case EXTERNAL_DOUBLE_ELEMENTS:
9930     case EXTERNAL_PIXEL_ELEMENTS:
9931       // External arrays are considered 100% used.
9932       ExternalArray* external_array = ExternalArray::cast(elements());
9933       *capacity = external_array->length();
9934       *used = external_array->length();
9935       break;
9936   }
9937 }
9938
9939
9940 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
9941   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
9942                 kMaxUncheckedFastElementsLength);
9943   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
9944       (new_capacity <= kMaxUncheckedFastElementsLength &&
9945        GetHeap()->InNewSpace(this))) {
9946     return false;
9947   }
9948   // If the fast-case backing storage takes up roughly three times as
9949   // much space (in machine words) as a dictionary backing storage
9950   // would, the object should have slow elements.
9951   int old_capacity = 0;
9952   int used_elements = 0;
9953   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
9954   int dictionary_size = NumberDictionary::ComputeCapacity(used_elements) *
9955       NumberDictionary::kEntrySize;
9956   return 3 * dictionary_size <= new_capacity;
9957 }
9958
9959
9960 bool JSObject::ShouldConvertToFastElements() {
9961   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
9962   // If the elements are sparse, we should not go back to fast case.
9963   if (!HasDenseElements()) return false;
9964   // An object requiring access checks is never allowed to have fast
9965   // elements.  If it had fast elements we would skip security checks.
9966   if (IsAccessCheckNeeded()) return false;
9967
9968   FixedArray* elements = FixedArray::cast(this->elements());
9969   NumberDictionary* dictionary = NULL;
9970   if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
9971     dictionary = NumberDictionary::cast(elements->get(1));
9972   } else {
9973     dictionary = NumberDictionary::cast(elements);
9974   }
9975   // If an element has been added at a very high index in the elements
9976   // dictionary, we cannot go back to fast case.
9977   if (dictionary->requires_slow_elements()) return false;
9978   // If the dictionary backing storage takes up roughly half as much
9979   // space (in machine words) as a fast-case backing storage would,
9980   // the object should have fast elements.
9981   uint32_t array_size = 0;
9982   if (IsJSArray()) {
9983     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
9984   } else {
9985     array_size = dictionary->max_number_key();
9986   }
9987   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
9988       NumberDictionary::kEntrySize;
9989   return 2 * dictionary_size >= array_size;
9990 }
9991
9992
9993 bool JSObject::CanConvertToFastDoubleElements() {
9994   if (FLAG_unbox_double_arrays) {
9995     ASSERT(HasDictionaryElements());
9996     NumberDictionary* dictionary = NumberDictionary::cast(elements());
9997     for (int i = 0; i < dictionary->Capacity(); i++) {
9998       Object* key = dictionary->KeyAt(i);
9999       if (key->IsNumber()) {
10000         if (!dictionary->ValueAt(i)->IsNumber()) return false;
10001       }
10002     }
10003     return true;
10004   } else {
10005     return false;
10006   }
10007 }
10008
10009
10010 // Certain compilers request function template instantiation when they
10011 // see the definition of the other template functions in the
10012 // class. This requires us to have the template functions put
10013 // together, so even though this function belongs in objects-debug.cc,
10014 // we keep it here instead to satisfy certain compilers.
10015 #ifdef OBJECT_PRINT
10016 template<typename Shape, typename Key>
10017 void Dictionary<Shape, Key>::Print(FILE* out) {
10018   int capacity = HashTable<Shape, Key>::Capacity();
10019   for (int i = 0; i < capacity; i++) {
10020     Object* k = HashTable<Shape, Key>::KeyAt(i);
10021     if (HashTable<Shape, Key>::IsKey(k)) {
10022       PrintF(out, " ");
10023       if (k->IsString()) {
10024         String::cast(k)->StringPrint(out);
10025       } else {
10026         k->ShortPrint(out);
10027       }
10028       PrintF(out, ": ");
10029       ValueAt(i)->ShortPrint(out);
10030       PrintF(out, "\n");
10031     }
10032   }
10033 }
10034 #endif
10035
10036
10037 template<typename Shape, typename Key>
10038 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
10039   int pos = 0;
10040   int capacity = HashTable<Shape, Key>::Capacity();
10041   AssertNoAllocation no_gc;
10042   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
10043   for (int i = 0; i < capacity; i++) {
10044     Object* k =  Dictionary<Shape, Key>::KeyAt(i);
10045     if (Dictionary<Shape, Key>::IsKey(k)) {
10046       elements->set(pos++, ValueAt(i), mode);
10047     }
10048   }
10049   ASSERT(pos == elements->length());
10050 }
10051
10052
10053 InterceptorInfo* JSObject::GetNamedInterceptor() {
10054   ASSERT(map()->has_named_interceptor());
10055   JSFunction* constructor = JSFunction::cast(map()->constructor());
10056   ASSERT(constructor->shared()->IsApiFunction());
10057   Object* result =
10058       constructor->shared()->get_api_func_data()->named_property_handler();
10059   return InterceptorInfo::cast(result);
10060 }
10061
10062
10063 InterceptorInfo* JSObject::GetIndexedInterceptor() {
10064   ASSERT(map()->has_indexed_interceptor());
10065   JSFunction* constructor = JSFunction::cast(map()->constructor());
10066   ASSERT(constructor->shared()->IsApiFunction());
10067   Object* result =
10068       constructor->shared()->get_api_func_data()->indexed_property_handler();
10069   return InterceptorInfo::cast(result);
10070 }
10071
10072
10073 MaybeObject* JSObject::GetPropertyPostInterceptor(
10074     JSReceiver* receiver,
10075     String* name,
10076     PropertyAttributes* attributes) {
10077   // Check local property in holder, ignore interceptor.
10078   LookupResult result(GetIsolate());
10079   LocalLookupRealNamedProperty(name, &result);
10080   if (result.IsProperty()) {
10081     return GetProperty(receiver, &result, name, attributes);
10082   }
10083   // Continue searching via the prototype chain.
10084   Object* pt = GetPrototype();
10085   *attributes = ABSENT;
10086   if (pt->IsNull()) return GetHeap()->undefined_value();
10087   return pt->GetPropertyWithReceiver(receiver, name, attributes);
10088 }
10089
10090
10091 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
10092     JSReceiver* receiver,
10093     String* name,
10094     PropertyAttributes* attributes) {
10095   // Check local property in holder, ignore interceptor.
10096   LookupResult result(GetIsolate());
10097   LocalLookupRealNamedProperty(name, &result);
10098   if (result.IsProperty()) {
10099     return GetProperty(receiver, &result, name, attributes);
10100   }
10101   return GetHeap()->undefined_value();
10102 }
10103
10104
10105 MaybeObject* JSObject::GetPropertyWithInterceptor(
10106     JSReceiver* receiver,
10107     String* name,
10108     PropertyAttributes* attributes) {
10109   Isolate* isolate = GetIsolate();
10110   InterceptorInfo* interceptor = GetNamedInterceptor();
10111   HandleScope scope(isolate);
10112   Handle<JSReceiver> receiver_handle(receiver);
10113   Handle<JSObject> holder_handle(this);
10114   Handle<String> name_handle(name);
10115
10116   if (!interceptor->getter()->IsUndefined()) {
10117     v8::NamedPropertyGetter getter =
10118         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
10119     LOG(isolate,
10120         ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
10121     CustomArguments args(isolate, interceptor->data(), receiver, this);
10122     v8::AccessorInfo info(args.end());
10123     v8::Handle<v8::Value> result;
10124     {
10125       // Leaving JavaScript.
10126       VMState state(isolate, EXTERNAL);
10127       result = getter(v8::Utils::ToLocal(name_handle), info);
10128     }
10129     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
10130     if (!result.IsEmpty()) {
10131       *attributes = NONE;
10132       return *v8::Utils::OpenHandle(*result);
10133     }
10134   }
10135
10136   MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
10137       *receiver_handle,
10138       *name_handle,
10139       attributes);
10140   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
10141   return result;
10142 }
10143
10144
10145 bool JSObject::HasRealNamedProperty(String* key) {
10146   // Check access rights if needed.
10147   Isolate* isolate = GetIsolate();
10148   if (IsAccessCheckNeeded()) {
10149     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10150       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10151       return false;
10152     }
10153   }
10154
10155   LookupResult result(isolate);
10156   LocalLookupRealNamedProperty(key, &result);
10157   return result.IsProperty() && (result.type() != INTERCEPTOR);
10158 }
10159
10160
10161 bool JSObject::HasRealElementProperty(uint32_t index) {
10162   // Check access rights if needed.
10163   if (IsAccessCheckNeeded()) {
10164     Heap* heap = GetHeap();
10165     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
10166       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10167       return false;
10168     }
10169   }
10170
10171   // Handle [] on String objects.
10172   if (this->IsStringObjectWithCharacterAt(index)) return true;
10173
10174   switch (GetElementsKind()) {
10175     case FAST_SMI_ONLY_ELEMENTS:
10176     case FAST_ELEMENTS: {
10177       uint32_t length = IsJSArray() ?
10178           static_cast<uint32_t>(
10179               Smi::cast(JSArray::cast(this)->length())->value()) :
10180           static_cast<uint32_t>(FixedArray::cast(elements())->length());
10181       return (index < length) &&
10182           !FixedArray::cast(elements())->get(index)->IsTheHole();
10183     }
10184     case FAST_DOUBLE_ELEMENTS: {
10185       uint32_t length = IsJSArray() ?
10186           static_cast<uint32_t>(
10187               Smi::cast(JSArray::cast(this)->length())->value()) :
10188           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
10189       return (index < length) &&
10190           !FixedDoubleArray::cast(elements())->is_the_hole(index);
10191       break;
10192     }
10193     case EXTERNAL_PIXEL_ELEMENTS: {
10194       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
10195       return index < static_cast<uint32_t>(pixels->length());
10196     }
10197     case EXTERNAL_BYTE_ELEMENTS:
10198     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
10199     case EXTERNAL_SHORT_ELEMENTS:
10200     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
10201     case EXTERNAL_INT_ELEMENTS:
10202     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
10203     case EXTERNAL_FLOAT_ELEMENTS:
10204     case EXTERNAL_DOUBLE_ELEMENTS: {
10205       ExternalArray* array = ExternalArray::cast(elements());
10206       return index < static_cast<uint32_t>(array->length());
10207     }
10208     case DICTIONARY_ELEMENTS: {
10209       return element_dictionary()->FindEntry(index)
10210           != NumberDictionary::kNotFound;
10211     }
10212     case NON_STRICT_ARGUMENTS_ELEMENTS:
10213       UNIMPLEMENTED();
10214       break;
10215   }
10216   // All possibilities have been handled above already.
10217   UNREACHABLE();
10218   return GetHeap()->null_value();
10219 }
10220
10221
10222 bool JSObject::HasRealNamedCallbackProperty(String* key) {
10223   // Check access rights if needed.
10224   Isolate* isolate = GetIsolate();
10225   if (IsAccessCheckNeeded()) {
10226     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10227       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10228       return false;
10229     }
10230   }
10231
10232   LookupResult result(isolate);
10233   LocalLookupRealNamedProperty(key, &result);
10234   return result.IsProperty() && (result.type() == CALLBACKS);
10235 }
10236
10237
10238 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
10239   if (HasFastProperties()) {
10240     DescriptorArray* descs = map()->instance_descriptors();
10241     int result = 0;
10242     for (int i = 0; i < descs->number_of_descriptors(); i++) {
10243       PropertyDetails details(descs->GetDetails(i));
10244       if (details.IsProperty() && (details.attributes() & filter) == 0) {
10245         result++;
10246       }
10247     }
10248     return result;
10249   } else {
10250     return property_dictionary()->NumberOfElementsFilterAttributes(filter);
10251   }
10252 }
10253
10254
10255 int JSObject::NumberOfEnumProperties() {
10256   return NumberOfLocalProperties(static_cast<PropertyAttributes>(DONT_ENUM));
10257 }
10258
10259
10260 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
10261   Object* temp = get(i);
10262   set(i, get(j));
10263   set(j, temp);
10264   if (this != numbers) {
10265     temp = numbers->get(i);
10266     numbers->set(i, numbers->get(j));
10267     numbers->set(j, temp);
10268   }
10269 }
10270
10271
10272 static void InsertionSortPairs(FixedArray* content,
10273                                FixedArray* numbers,
10274                                int len) {
10275   for (int i = 1; i < len; i++) {
10276     int j = i;
10277     while (j > 0 &&
10278            (NumberToUint32(numbers->get(j - 1)) >
10279             NumberToUint32(numbers->get(j)))) {
10280       content->SwapPairs(numbers, j - 1, j);
10281       j--;
10282     }
10283   }
10284 }
10285
10286
10287 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
10288   // In-place heap sort.
10289   ASSERT(content->length() == numbers->length());
10290
10291   // Bottom-up max-heap construction.
10292   for (int i = 1; i < len; ++i) {
10293     int child_index = i;
10294     while (child_index > 0) {
10295       int parent_index = ((child_index + 1) >> 1) - 1;
10296       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10297       uint32_t child_value = NumberToUint32(numbers->get(child_index));
10298       if (parent_value < child_value) {
10299         content->SwapPairs(numbers, parent_index, child_index);
10300       } else {
10301         break;
10302       }
10303       child_index = parent_index;
10304     }
10305   }
10306
10307   // Extract elements and create sorted array.
10308   for (int i = len - 1; i > 0; --i) {
10309     // Put max element at the back of the array.
10310     content->SwapPairs(numbers, 0, i);
10311     // Sift down the new top element.
10312     int parent_index = 0;
10313     while (true) {
10314       int child_index = ((parent_index + 1) << 1) - 1;
10315       if (child_index >= i) break;
10316       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
10317       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
10318       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10319       if (child_index + 1 >= i || child1_value > child2_value) {
10320         if (parent_value > child1_value) break;
10321         content->SwapPairs(numbers, parent_index, child_index);
10322         parent_index = child_index;
10323       } else {
10324         if (parent_value > child2_value) break;
10325         content->SwapPairs(numbers, parent_index, child_index + 1);
10326         parent_index = child_index + 1;
10327       }
10328     }
10329   }
10330 }
10331
10332
10333 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
10334 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
10335   ASSERT(this->length() == numbers->length());
10336   // For small arrays, simply use insertion sort.
10337   if (len <= 10) {
10338     InsertionSortPairs(this, numbers, len);
10339     return;
10340   }
10341   // Check the range of indices.
10342   uint32_t min_index = NumberToUint32(numbers->get(0));
10343   uint32_t max_index = min_index;
10344   uint32_t i;
10345   for (i = 1; i < len; i++) {
10346     if (NumberToUint32(numbers->get(i)) < min_index) {
10347       min_index = NumberToUint32(numbers->get(i));
10348     } else if (NumberToUint32(numbers->get(i)) > max_index) {
10349       max_index = NumberToUint32(numbers->get(i));
10350     }
10351   }
10352   if (max_index - min_index + 1 == len) {
10353     // Indices form a contiguous range, unless there are duplicates.
10354     // Do an in-place linear time sort assuming distinct numbers, but
10355     // avoid hanging in case they are not.
10356     for (i = 0; i < len; i++) {
10357       uint32_t p;
10358       uint32_t j = 0;
10359       // While the current element at i is not at its correct position p,
10360       // swap the elements at these two positions.
10361       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
10362              j++ < len) {
10363         SwapPairs(numbers, i, p);
10364       }
10365     }
10366   } else {
10367     HeapSortPairs(this, numbers, len);
10368     return;
10369   }
10370 }
10371
10372
10373 // Fill in the names of local properties into the supplied storage. The main
10374 // purpose of this function is to provide reflection information for the object
10375 // mirrors.
10376 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
10377   ASSERT(storage->length() >= (NumberOfLocalProperties(NONE) - index));
10378   if (HasFastProperties()) {
10379     DescriptorArray* descs = map()->instance_descriptors();
10380     for (int i = 0; i < descs->number_of_descriptors(); i++) {
10381       if (descs->IsProperty(i)) storage->set(index++, descs->GetKey(i));
10382     }
10383     ASSERT(storage->length() >= index);
10384   } else {
10385     property_dictionary()->CopyKeysTo(storage,
10386                                       index,
10387                                       StringDictionary::UNSORTED);
10388   }
10389 }
10390
10391
10392 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
10393   return GetLocalElementKeys(NULL, filter);
10394 }
10395
10396
10397 int JSObject::NumberOfEnumElements() {
10398   // Fast case for objects with no elements.
10399   if (!IsJSValue() && HasFastElements()) {
10400     uint32_t length = IsJSArray() ?
10401         static_cast<uint32_t>(
10402             Smi::cast(JSArray::cast(this)->length())->value()) :
10403         static_cast<uint32_t>(FixedArray::cast(elements())->length());
10404     if (length == 0) return 0;
10405   }
10406   // Compute the number of enumerable elements.
10407   return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
10408 }
10409
10410
10411 int JSObject::GetLocalElementKeys(FixedArray* storage,
10412                                   PropertyAttributes filter) {
10413   int counter = 0;
10414   switch (GetElementsKind()) {
10415     case FAST_SMI_ONLY_ELEMENTS:
10416     case FAST_ELEMENTS: {
10417       int length = IsJSArray() ?
10418           Smi::cast(JSArray::cast(this)->length())->value() :
10419           FixedArray::cast(elements())->length();
10420       for (int i = 0; i < length; i++) {
10421         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
10422           if (storage != NULL) {
10423             storage->set(counter, Smi::FromInt(i));
10424           }
10425           counter++;
10426         }
10427       }
10428       ASSERT(!storage || storage->length() >= counter);
10429       break;
10430     }
10431     case FAST_DOUBLE_ELEMENTS: {
10432       int length = IsJSArray() ?
10433           Smi::cast(JSArray::cast(this)->length())->value() :
10434           FixedDoubleArray::cast(elements())->length();
10435       for (int i = 0; i < length; i++) {
10436         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
10437           if (storage != NULL) {
10438             storage->set(counter, Smi::FromInt(i));
10439           }
10440           counter++;
10441         }
10442       }
10443       ASSERT(!storage || storage->length() >= counter);
10444       break;
10445     }
10446     case EXTERNAL_PIXEL_ELEMENTS: {
10447       int length = ExternalPixelArray::cast(elements())->length();
10448       while (counter < length) {
10449         if (storage != NULL) {
10450           storage->set(counter, Smi::FromInt(counter));
10451         }
10452         counter++;
10453       }
10454       ASSERT(!storage || storage->length() >= counter);
10455       break;
10456     }
10457     case EXTERNAL_BYTE_ELEMENTS:
10458     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
10459     case EXTERNAL_SHORT_ELEMENTS:
10460     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
10461     case EXTERNAL_INT_ELEMENTS:
10462     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
10463     case EXTERNAL_FLOAT_ELEMENTS:
10464     case EXTERNAL_DOUBLE_ELEMENTS: {
10465       int length = ExternalArray::cast(elements())->length();
10466       while (counter < length) {
10467         if (storage != NULL) {
10468           storage->set(counter, Smi::FromInt(counter));
10469         }
10470         counter++;
10471       }
10472       ASSERT(!storage || storage->length() >= counter);
10473       break;
10474     }
10475     case DICTIONARY_ELEMENTS: {
10476       if (storage != NULL) {
10477         element_dictionary()->CopyKeysTo(storage,
10478                                          filter,
10479                                          NumberDictionary::SORTED);
10480       }
10481       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
10482       break;
10483     }
10484     case NON_STRICT_ARGUMENTS_ELEMENTS: {
10485       FixedArray* parameter_map = FixedArray::cast(elements());
10486       int mapped_length = parameter_map->length() - 2;
10487       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
10488       if (arguments->IsDictionary()) {
10489         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
10490         // will insert in storage starting at index 0.
10491         NumberDictionary* dictionary = NumberDictionary::cast(arguments);
10492         if (storage != NULL) {
10493           dictionary->CopyKeysTo(storage, filter, NumberDictionary::UNSORTED);
10494         }
10495         counter += dictionary->NumberOfElementsFilterAttributes(filter);
10496         for (int i = 0; i < mapped_length; ++i) {
10497           if (!parameter_map->get(i + 2)->IsTheHole()) {
10498             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10499             ++counter;
10500           }
10501         }
10502         if (storage != NULL) storage->SortPairs(storage, counter);
10503
10504       } else {
10505         int backing_length = arguments->length();
10506         int i = 0;
10507         for (; i < mapped_length; ++i) {
10508           if (!parameter_map->get(i + 2)->IsTheHole()) {
10509             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10510             ++counter;
10511           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
10512             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10513             ++counter;
10514           }
10515         }
10516         for (; i < backing_length; ++i) {
10517           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10518           ++counter;
10519         }
10520       }
10521       break;
10522     }
10523   }
10524
10525   if (this->IsJSValue()) {
10526     Object* val = JSValue::cast(this)->value();
10527     if (val->IsString()) {
10528       String* str = String::cast(val);
10529       if (storage) {
10530         for (int i = 0; i < str->length(); i++) {
10531           storage->set(counter + i, Smi::FromInt(i));
10532         }
10533       }
10534       counter += str->length();
10535     }
10536   }
10537   ASSERT(!storage || storage->length() == counter);
10538   return counter;
10539 }
10540
10541
10542 int JSObject::GetEnumElementKeys(FixedArray* storage) {
10543   return GetLocalElementKeys(storage,
10544                              static_cast<PropertyAttributes>(DONT_ENUM));
10545 }
10546
10547
10548 // StringKey simply carries a string object as key.
10549 class StringKey : public HashTableKey {
10550  public:
10551   explicit StringKey(String* string) :
10552       string_(string),
10553       hash_(HashForObject(string)) { }
10554
10555   bool IsMatch(Object* string) {
10556     // We know that all entries in a hash table had their hash keys created.
10557     // Use that knowledge to have fast failure.
10558     if (hash_ != HashForObject(string)) {
10559       return false;
10560     }
10561     return string_->Equals(String::cast(string));
10562   }
10563
10564   uint32_t Hash() { return hash_; }
10565
10566   uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
10567
10568   Object* AsObject() { return string_; }
10569
10570   String* string_;
10571   uint32_t hash_;
10572 };
10573
10574
10575 // StringSharedKeys are used as keys in the eval cache.
10576 class StringSharedKey : public HashTableKey {
10577  public:
10578   StringSharedKey(String* source,
10579                   SharedFunctionInfo* shared,
10580                   StrictModeFlag strict_mode)
10581       : source_(source),
10582         shared_(shared),
10583         strict_mode_(strict_mode) { }
10584
10585   bool IsMatch(Object* other) {
10586     if (!other->IsFixedArray()) return false;
10587     FixedArray* pair = FixedArray::cast(other);
10588     SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
10589     if (shared != shared_) return false;
10590     int strict_unchecked = Smi::cast(pair->get(2))->value();
10591     ASSERT(strict_unchecked == kStrictMode ||
10592            strict_unchecked == kNonStrictMode);
10593     StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
10594     if (strict_mode != strict_mode_) return false;
10595     String* source = String::cast(pair->get(1));
10596     return source->Equals(source_);
10597   }
10598
10599   static uint32_t StringSharedHashHelper(String* source,
10600                                          SharedFunctionInfo* shared,
10601                                          StrictModeFlag strict_mode) {
10602     uint32_t hash = source->Hash();
10603     if (shared->HasSourceCode()) {
10604       // Instead of using the SharedFunctionInfo pointer in the hash
10605       // code computation, we use a combination of the hash of the
10606       // script source code and the start and end positions.  We do
10607       // this to ensure that the cache entries can survive garbage
10608       // collection.
10609       Script* script = Script::cast(shared->script());
10610       hash ^= String::cast(script->source())->Hash();
10611       if (strict_mode == kStrictMode) hash ^= 0x8000;
10612       hash += shared->start_position();
10613     }
10614     return hash;
10615   }
10616
10617   uint32_t Hash() {
10618     return StringSharedHashHelper(source_, shared_, strict_mode_);
10619   }
10620
10621   uint32_t HashForObject(Object* obj) {
10622     FixedArray* pair = FixedArray::cast(obj);
10623     SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
10624     String* source = String::cast(pair->get(1));
10625     int strict_unchecked = Smi::cast(pair->get(2))->value();
10626     ASSERT(strict_unchecked == kStrictMode ||
10627            strict_unchecked == kNonStrictMode);
10628     StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
10629     return StringSharedHashHelper(source, shared, strict_mode);
10630   }
10631
10632   MUST_USE_RESULT MaybeObject* AsObject() {
10633     Object* obj;
10634     { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(3);
10635       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10636     }
10637     FixedArray* pair = FixedArray::cast(obj);
10638     pair->set(0, shared_);
10639     pair->set(1, source_);
10640     pair->set(2, Smi::FromInt(strict_mode_));
10641     return pair;
10642   }
10643
10644  private:
10645   String* source_;
10646   SharedFunctionInfo* shared_;
10647   StrictModeFlag strict_mode_;
10648 };
10649
10650
10651 // RegExpKey carries the source and flags of a regular expression as key.
10652 class RegExpKey : public HashTableKey {
10653  public:
10654   RegExpKey(String* string, JSRegExp::Flags flags)
10655       : string_(string),
10656         flags_(Smi::FromInt(flags.value())) { }
10657
10658   // Rather than storing the key in the hash table, a pointer to the
10659   // stored value is stored where the key should be.  IsMatch then
10660   // compares the search key to the found object, rather than comparing
10661   // a key to a key.
10662   bool IsMatch(Object* obj) {
10663     FixedArray* val = FixedArray::cast(obj);
10664     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
10665         && (flags_ == val->get(JSRegExp::kFlagsIndex));
10666   }
10667
10668   uint32_t Hash() { return RegExpHash(string_, flags_); }
10669
10670   Object* AsObject() {
10671     // Plain hash maps, which is where regexp keys are used, don't
10672     // use this function.
10673     UNREACHABLE();
10674     return NULL;
10675   }
10676
10677   uint32_t HashForObject(Object* obj) {
10678     FixedArray* val = FixedArray::cast(obj);
10679     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
10680                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
10681   }
10682
10683   static uint32_t RegExpHash(String* string, Smi* flags) {
10684     return string->Hash() + flags->value();
10685   }
10686
10687   String* string_;
10688   Smi* flags_;
10689 };
10690
10691 // Utf8SymbolKey carries a vector of chars as key.
10692 class Utf8SymbolKey : public HashTableKey {
10693  public:
10694   explicit Utf8SymbolKey(Vector<const char> string)
10695       : string_(string), hash_field_(0) { }
10696
10697   bool IsMatch(Object* string) {
10698     return String::cast(string)->IsEqualTo(string_);
10699   }
10700
10701   uint32_t Hash() {
10702     if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
10703     unibrow::Utf8InputBuffer<> buffer(string_.start(),
10704                                       static_cast<unsigned>(string_.length()));
10705     chars_ = buffer.Length();
10706     hash_field_ = String::ComputeHashField(&buffer, chars_);
10707     uint32_t result = hash_field_ >> String::kHashShift;
10708     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
10709     return result;
10710   }
10711
10712   uint32_t HashForObject(Object* other) {
10713     return String::cast(other)->Hash();
10714   }
10715
10716   MaybeObject* AsObject() {
10717     if (hash_field_ == 0) Hash();
10718     return Isolate::Current()->heap()->AllocateSymbol(
10719         string_, chars_, hash_field_);
10720   }
10721
10722   Vector<const char> string_;
10723   uint32_t hash_field_;
10724   int chars_;  // Caches the number of characters when computing the hash code.
10725 };
10726
10727
10728 template <typename Char>
10729 class SequentialSymbolKey : public HashTableKey {
10730  public:
10731   explicit SequentialSymbolKey(Vector<const Char> string)
10732       : string_(string), hash_field_(0) { }
10733
10734   uint32_t Hash() {
10735     StringHasher hasher(string_.length());
10736
10737     // Very long strings have a trivial hash that doesn't inspect the
10738     // string contents.
10739     if (hasher.has_trivial_hash()) {
10740       hash_field_ = hasher.GetHashField();
10741     } else {
10742       int i = 0;
10743       // Do the iterative array index computation as long as there is a
10744       // chance this is an array index.
10745       while (i < string_.length() && hasher.is_array_index()) {
10746         hasher.AddCharacter(static_cast<uc32>(string_[i]));
10747         i++;
10748       }
10749
10750       // Process the remaining characters without updating the array
10751       // index.
10752       while (i < string_.length()) {
10753         hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i]));
10754         i++;
10755       }
10756       hash_field_ = hasher.GetHashField();
10757     }
10758
10759     uint32_t result = hash_field_ >> String::kHashShift;
10760     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
10761     return result;
10762   }
10763
10764
10765   uint32_t HashForObject(Object* other) {
10766     return String::cast(other)->Hash();
10767   }
10768
10769   Vector<const Char> string_;
10770   uint32_t hash_field_;
10771 };
10772
10773
10774
10775 class AsciiSymbolKey : public SequentialSymbolKey<char> {
10776  public:
10777   explicit AsciiSymbolKey(Vector<const char> str)
10778       : SequentialSymbolKey<char>(str) { }
10779
10780   bool IsMatch(Object* string) {
10781     return String::cast(string)->IsAsciiEqualTo(string_);
10782   }
10783
10784   MaybeObject* AsObject() {
10785     if (hash_field_ == 0) Hash();
10786     MaybeObject *result = HEAP->AllocateAsciiSymbol(string_, hash_field_);
10787     if (!result->IsFailure() && result->ToObjectUnchecked()->IsSeqString()) {
10788         while (true) {
10789             Atomic32 my_symbol_id = next_symbol_id;
10790             if (my_symbol_id > Smi::kMaxValue)
10791                 break;
10792             if (my_symbol_id == NoBarrier_CompareAndSwap(&next_symbol_id, my_symbol_id, my_symbol_id + 1)) {
10793                 SeqString::cast(result->ToObjectUnchecked())->set_symbol_id(my_symbol_id);
10794                 break;
10795             }
10796         }
10797     }
10798     return result;
10799   }
10800
10801   static Atomic32 next_symbol_id;
10802 };
10803 Atomic32 AsciiSymbolKey::next_symbol_id = 1;
10804
10805
10806 class SubStringAsciiSymbolKey : public HashTableKey {
10807  public:
10808   explicit SubStringAsciiSymbolKey(Handle<SeqAsciiString> string,
10809                                    int from,
10810                                    int length)
10811       : string_(string), from_(from), length_(length) { }
10812
10813   uint32_t Hash() {
10814     ASSERT(length_ >= 0);
10815     ASSERT(from_ + length_ <= string_->length());
10816     StringHasher hasher(length_);
10817
10818     // Very long strings have a trivial hash that doesn't inspect the
10819     // string contents.
10820     if (hasher.has_trivial_hash()) {
10821       hash_field_ = hasher.GetHashField();
10822     } else {
10823       int i = 0;
10824       // Do the iterative array index computation as long as there is a
10825       // chance this is an array index.
10826       while (i < length_ && hasher.is_array_index()) {
10827         hasher.AddCharacter(static_cast<uc32>(
10828             string_->SeqAsciiStringGet(i + from_)));
10829         i++;
10830       }
10831
10832       // Process the remaining characters without updating the array
10833       // index.
10834       while (i < length_) {
10835         hasher.AddCharacterNoIndex(static_cast<uc32>(
10836             string_->SeqAsciiStringGet(i + from_)));
10837         i++;
10838       }
10839       hash_field_ = hasher.GetHashField();
10840     }
10841
10842     uint32_t result = hash_field_ >> String::kHashShift;
10843     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
10844     return result;
10845   }
10846
10847
10848   uint32_t HashForObject(Object* other) {
10849     return String::cast(other)->Hash();
10850   }
10851
10852   bool IsMatch(Object* string) {
10853     Vector<const char> chars(string_->GetChars() + from_, length_);
10854     return String::cast(string)->IsAsciiEqualTo(chars);
10855   }
10856
10857   MaybeObject* AsObject() {
10858     if (hash_field_ == 0) Hash();
10859     Vector<const char> chars(string_->GetChars() + from_, length_);
10860     return HEAP->AllocateAsciiSymbol(chars, hash_field_);
10861   }
10862
10863  private:
10864   Handle<SeqAsciiString> string_;
10865   int from_;
10866   int length_;
10867   uint32_t hash_field_;
10868 };
10869
10870
10871 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
10872  public:
10873   explicit TwoByteSymbolKey(Vector<const uc16> str)
10874       : SequentialSymbolKey<uc16>(str) { }
10875
10876   bool IsMatch(Object* string) {
10877     return String::cast(string)->IsTwoByteEqualTo(string_);
10878   }
10879
10880   MaybeObject* AsObject() {
10881     if (hash_field_ == 0) Hash();
10882     return HEAP->AllocateTwoByteSymbol(string_, hash_field_);
10883   }
10884 };
10885
10886
10887 // SymbolKey carries a string/symbol object as key.
10888 class SymbolKey : public HashTableKey {
10889  public:
10890   explicit SymbolKey(String* string)
10891       : string_(string) { }
10892
10893   bool IsMatch(Object* string) {
10894     return String::cast(string)->Equals(string_);
10895   }
10896
10897   uint32_t Hash() { return string_->Hash(); }
10898
10899   uint32_t HashForObject(Object* other) {
10900     return String::cast(other)->Hash();
10901   }
10902
10903   MaybeObject* AsObject() {
10904     // Attempt to flatten the string, so that symbols will most often
10905     // be flat strings.
10906     string_ = string_->TryFlattenGetString();
10907     Heap* heap = string_->GetHeap();
10908     // Transform string to symbol if possible.
10909     Map* map = heap->SymbolMapForString(string_);
10910     if (map != NULL) {
10911       string_->set_map(map);
10912       ASSERT(string_->IsSymbol());
10913       return string_;
10914     }
10915     // Otherwise allocate a new symbol.
10916     StringInputBuffer buffer(string_);
10917     return heap->AllocateInternalSymbol(&buffer,
10918                                         string_->length(),
10919                                         string_->hash_field());
10920   }
10921
10922   static uint32_t StringHash(Object* obj) {
10923     return String::cast(obj)->Hash();
10924   }
10925
10926   String* string_;
10927 };
10928
10929
10930 template<typename Shape, typename Key>
10931 void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
10932   IteratePointers(v, 0, kElementsStartOffset);
10933 }
10934
10935
10936 template<typename Shape, typename Key>
10937 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
10938   IteratePointers(v,
10939                   kElementsStartOffset,
10940                   kHeaderSize + length() * kPointerSize);
10941 }
10942
10943
10944 template<typename Shape, typename Key>
10945 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for,
10946                                              PretenureFlag pretenure) {
10947   int capacity = ComputeCapacity(at_least_space_for);
10948   if (capacity > HashTable::kMaxCapacity) {
10949     return Failure::OutOfMemoryException();
10950   }
10951
10952   Object* obj;
10953   { MaybeObject* maybe_obj = Isolate::Current()->heap()->
10954         AllocateHashTable(EntryToIndex(capacity), pretenure);
10955     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10956   }
10957   HashTable::cast(obj)->SetNumberOfElements(0);
10958   HashTable::cast(obj)->SetNumberOfDeletedElements(0);
10959   HashTable::cast(obj)->SetCapacity(capacity);
10960   return obj;
10961 }
10962
10963
10964 // Find entry for key otherwise return kNotFound.
10965 int StringDictionary::FindEntry(String* key) {
10966   if (!key->IsSymbol()) {
10967     return HashTable<StringDictionaryShape, String*>::FindEntry(key);
10968   }
10969
10970   // Optimized for symbol key. Knowledge of the key type allows:
10971   // 1. Move the check if the key is a symbol out of the loop.
10972   // 2. Avoid comparing hash codes in symbol to symbol comparision.
10973   // 3. Detect a case when a dictionary key is not a symbol but the key is.
10974   //    In case of positive result the dictionary key may be replaced by
10975   //    the symbol with minimal performance penalty. It gives a chance to
10976   //    perform further lookups in code stubs (and significant performance boost
10977   //    a certain style of code).
10978
10979   // EnsureCapacity will guarantee the hash table is never full.
10980   uint32_t capacity = Capacity();
10981   uint32_t entry = FirstProbe(key->Hash(), capacity);
10982   uint32_t count = 1;
10983
10984   while (true) {
10985     int index = EntryToIndex(entry);
10986     Object* element = get(index);
10987     if (element->IsUndefined()) break;  // Empty entry.
10988     if (key == element) return entry;
10989     if (!element->IsSymbol() &&
10990         !element->IsNull() &&
10991         String::cast(element)->Equals(key)) {
10992       // Replace a non-symbol key by the equivalent symbol for faster further
10993       // lookups.
10994       set(index, key);
10995       return entry;
10996     }
10997     ASSERT(element->IsNull() || !String::cast(element)->Equals(key));
10998     entry = NextProbe(entry, count++, capacity);
10999   }
11000   return kNotFound;
11001 }
11002
11003
11004 template<typename Shape, typename Key>
11005 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
11006   ASSERT(NumberOfElements() < new_table->Capacity());
11007
11008   AssertNoAllocation no_gc;
11009   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
11010
11011   // Copy prefix to new array.
11012   for (int i = kPrefixStartIndex;
11013        i < kPrefixStartIndex + Shape::kPrefixSize;
11014        i++) {
11015     new_table->set(i, get(i), mode);
11016   }
11017
11018   // Rehash the elements.
11019   int capacity = Capacity();
11020   for (int i = 0; i < capacity; i++) {
11021     uint32_t from_index = EntryToIndex(i);
11022     Object* k = get(from_index);
11023     if (IsKey(k)) {
11024       uint32_t hash = Shape::HashForObject(key, k);
11025       uint32_t insertion_index =
11026           EntryToIndex(new_table->FindInsertionEntry(hash));
11027       for (int j = 0; j < Shape::kEntrySize; j++) {
11028         new_table->set(insertion_index + j, get(from_index + j), mode);
11029       }
11030     }
11031   }
11032   new_table->SetNumberOfElements(NumberOfElements());
11033   new_table->SetNumberOfDeletedElements(0);
11034   return new_table;
11035 }
11036
11037
11038 template<typename Shape, typename Key>
11039 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
11040   int capacity = Capacity();
11041   int nof = NumberOfElements() + n;
11042   int nod = NumberOfDeletedElements();
11043   // Return if:
11044   //   50% is still free after adding n elements and
11045   //   at most 50% of the free elements are deleted elements.
11046   if (nod <= (capacity - nof) >> 1) {
11047     int needed_free = nof >> 1;
11048     if (nof + needed_free <= capacity) return this;
11049   }
11050
11051   const int kMinCapacityForPretenure = 256;
11052   bool pretenure =
11053       (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this);
11054   Object* obj;
11055   { MaybeObject* maybe_obj =
11056         Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED);
11057     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11058   }
11059
11060   return Rehash(HashTable::cast(obj), key);
11061 }
11062
11063
11064 template<typename Shape, typename Key>
11065 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
11066   int capacity = Capacity();
11067   int nof = NumberOfElements();
11068
11069   // Shrink to fit the number of elements if only a quarter of the
11070   // capacity is filled with elements.
11071   if (nof > (capacity >> 2)) return this;
11072   // Allocate a new dictionary with room for at least the current
11073   // number of elements. The allocation method will make sure that
11074   // there is extra room in the dictionary for additions. Don't go
11075   // lower than room for 16 elements.
11076   int at_least_room_for = nof;
11077   if (at_least_room_for < 16) return this;
11078
11079   const int kMinCapacityForPretenure = 256;
11080   bool pretenure =
11081       (at_least_room_for > kMinCapacityForPretenure) &&
11082       !GetHeap()->InNewSpace(this);
11083   Object* obj;
11084   { MaybeObject* maybe_obj =
11085         Allocate(at_least_room_for, pretenure ? TENURED : NOT_TENURED);
11086     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11087   }
11088
11089   return Rehash(HashTable::cast(obj), key);
11090 }
11091
11092
11093 template<typename Shape, typename Key>
11094 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
11095   uint32_t capacity = Capacity();
11096   uint32_t entry = FirstProbe(hash, capacity);
11097   uint32_t count = 1;
11098   // EnsureCapacity will guarantee the hash table is never full.
11099   while (true) {
11100     Object* element = KeyAt(entry);
11101     if (element->IsUndefined() || element->IsNull()) break;
11102     entry = NextProbe(entry, count++, capacity);
11103   }
11104   return entry;
11105 }
11106
11107 // Force instantiation of template instances class.
11108 // Please note this list is compiler dependent.
11109
11110 template class HashTable<SymbolTableShape, HashTableKey*>;
11111
11112 template class HashTable<CompilationCacheShape, HashTableKey*>;
11113
11114 template class HashTable<MapCacheShape, HashTableKey*>;
11115
11116 template class HashTable<ObjectHashTableShape<1>, Object*>;
11117
11118 template class HashTable<ObjectHashTableShape<2>, Object*>;
11119
11120 template class Dictionary<StringDictionaryShape, String*>;
11121
11122 template class Dictionary<NumberDictionaryShape, uint32_t>;
11123
11124 #ifndef __INTEL_COMPILER
11125 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate(
11126     int);
11127
11128 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate(
11129     int);
11130
11131 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AtPut(
11132     uint32_t, Object*);
11133
11134 template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup(
11135     Object*);
11136
11137 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
11138     Object*);
11139
11140 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo(
11141     FixedArray*,
11142     PropertyAttributes,
11143     Dictionary<NumberDictionaryShape, uint32_t>::SortMode);
11144
11145 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
11146     int, JSObject::DeleteMode);
11147
11148 template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty(
11149     int, JSObject::DeleteMode);
11150
11151 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink(
11152     String*);
11153
11154 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Shrink(
11155     uint32_t);
11156
11157 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
11158     FixedArray*,
11159     int,
11160     Dictionary<StringDictionaryShape, String*>::SortMode);
11161
11162 template int
11163 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
11164     PropertyAttributes);
11165
11166 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add(
11167     String*, Object*, PropertyDetails);
11168
11169 template MaybeObject*
11170 Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
11171
11172 template int
11173 Dictionary<NumberDictionaryShape, uint32_t>::NumberOfElementsFilterAttributes(
11174     PropertyAttributes);
11175
11176 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Add(
11177     uint32_t, Object*, PropertyDetails);
11178
11179 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::
11180     EnsureCapacity(int, uint32_t);
11181
11182 template MaybeObject* Dictionary<StringDictionaryShape, String*>::
11183     EnsureCapacity(int, String*);
11184
11185 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry(
11186     uint32_t, Object*, PropertyDetails, uint32_t);
11187
11188 template MaybeObject* Dictionary<StringDictionaryShape, String*>::AddEntry(
11189     String*, Object*, PropertyDetails, uint32_t);
11190
11191 template
11192 int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements();
11193
11194 template
11195 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
11196
11197 template
11198 int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
11199 #endif
11200
11201 // Collates undefined and unexisting elements below limit from position
11202 // zero of the elements. The object stays in Dictionary mode.
11203 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
11204   ASSERT(HasDictionaryElements());
11205   // Must stay in dictionary mode, either because of requires_slow_elements,
11206   // or because we are not going to sort (and therefore compact) all of the
11207   // elements.
11208   NumberDictionary* dict = element_dictionary();
11209   HeapNumber* result_double = NULL;
11210   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11211     // Allocate space for result before we start mutating the object.
11212     Object* new_double;
11213     { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0);
11214       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11215     }
11216     result_double = HeapNumber::cast(new_double);
11217   }
11218
11219   Object* obj;
11220   { MaybeObject* maybe_obj =
11221         NumberDictionary::Allocate(dict->NumberOfElements());
11222     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11223   }
11224   NumberDictionary* new_dict = NumberDictionary::cast(obj);
11225
11226   AssertNoAllocation no_alloc;
11227
11228   uint32_t pos = 0;
11229   uint32_t undefs = 0;
11230   int capacity = dict->Capacity();
11231   for (int i = 0; i < capacity; i++) {
11232     Object* k = dict->KeyAt(i);
11233     if (dict->IsKey(k)) {
11234       ASSERT(k->IsNumber());
11235       ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
11236       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
11237       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
11238       Object* value = dict->ValueAt(i);
11239       PropertyDetails details = dict->DetailsAt(i);
11240       if (details.type() == CALLBACKS) {
11241         // Bail out and do the sorting of undefineds and array holes in JS.
11242         return Smi::FromInt(-1);
11243       }
11244       uint32_t key = NumberToUint32(k);
11245       // In the following we assert that adding the entry to the new dictionary
11246       // does not cause GC.  This is the case because we made sure to allocate
11247       // the dictionary big enough above, so it need not grow.
11248       if (key < limit) {
11249         if (value->IsUndefined()) {
11250           undefs++;
11251         } else {
11252           if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11253             // Adding an entry with the key beyond smi-range requires
11254             // allocation. Bailout.
11255             return Smi::FromInt(-1);
11256           }
11257           new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
11258           pos++;
11259         }
11260       } else {
11261         if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
11262           // Adding an entry with the key beyond smi-range requires
11263           // allocation. Bailout.
11264           return Smi::FromInt(-1);
11265         }
11266         new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
11267       }
11268     }
11269   }
11270
11271   uint32_t result = pos;
11272   PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
11273   Heap* heap = GetHeap();
11274   while (undefs > 0) {
11275     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11276       // Adding an entry with the key beyond smi-range requires
11277       // allocation. Bailout.
11278       return Smi::FromInt(-1);
11279     }
11280     new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
11281         ToObjectUnchecked();
11282     pos++;
11283     undefs--;
11284   }
11285
11286   set_elements(new_dict);
11287
11288   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11289     return Smi::FromInt(static_cast<int>(result));
11290   }
11291
11292   ASSERT_NE(NULL, result_double);
11293   result_double->set_value(static_cast<double>(result));
11294   return result_double;
11295 }
11296
11297
11298 // Collects all defined (non-hole) and non-undefined (array) elements at
11299 // the start of the elements array.
11300 // If the object is in dictionary mode, it is converted to fast elements
11301 // mode.
11302 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
11303   Heap* heap = GetHeap();
11304
11305   if (HasDictionaryElements()) {
11306     // Convert to fast elements containing only the existing properties.
11307     // Ordering is irrelevant, since we are going to sort anyway.
11308     NumberDictionary* dict = element_dictionary();
11309     if (IsJSArray() || dict->requires_slow_elements() ||
11310         dict->max_number_key() >= limit) {
11311       return PrepareSlowElementsForSort(limit);
11312     }
11313     // Convert to fast elements.
11314
11315     Object* obj;
11316     { MaybeObject* maybe_obj = GetElementsTransitionMap(FAST_ELEMENTS);
11317       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11318     }
11319     Map* new_map = Map::cast(obj);
11320
11321     PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
11322     Object* new_array;
11323     { MaybeObject* maybe_new_array =
11324           heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
11325       if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
11326     }
11327     FixedArray* fast_elements = FixedArray::cast(new_array);
11328     dict->CopyValuesTo(fast_elements);
11329
11330     set_map(new_map);
11331     set_elements(fast_elements);
11332   } else if (HasExternalArrayElements()) {
11333     // External arrays cannot have holes or undefined elements.
11334     return Smi::FromInt(ExternalArray::cast(elements())->length());
11335   } else if (!HasFastDoubleElements()) {
11336     Object* obj;
11337     { MaybeObject* maybe_obj = EnsureWritableFastElements();
11338       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11339     }
11340   }
11341   ASSERT(HasFastTypeElements() || HasFastDoubleElements());
11342
11343   // Collect holes at the end, undefined before that and the rest at the
11344   // start, and return the number of non-hole, non-undefined values.
11345
11346   FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
11347   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
11348   if (limit > elements_length) {
11349     limit = elements_length ;
11350   }
11351   if (limit == 0) {
11352     return Smi::FromInt(0);
11353   }
11354
11355   HeapNumber* result_double = NULL;
11356   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11357     // Pessimistically allocate space for return value before
11358     // we start mutating the array.
11359     Object* new_double;
11360     { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0);
11361       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11362     }
11363     result_double = HeapNumber::cast(new_double);
11364   }
11365
11366   uint32_t result = 0;
11367   if (elements_base->map() == heap->fixed_double_array_map()) {
11368     FixedDoubleArray* elements = FixedDoubleArray::cast(elements_base);
11369     // Split elements into defined and the_hole, in that order.
11370     unsigned int holes = limit;
11371     // Assume most arrays contain no holes and undefined values, so minimize the
11372     // number of stores of non-undefined, non-the-hole values.
11373     for (unsigned int i = 0; i < holes; i++) {
11374       if (elements->is_the_hole(i)) {
11375         holes--;
11376       } else {
11377         continue;
11378       }
11379       // Position i needs to be filled.
11380       while (holes > i) {
11381         if (elements->is_the_hole(holes)) {
11382           holes--;
11383         } else {
11384           elements->set(i, elements->get_scalar(holes));
11385           break;
11386         }
11387       }
11388     }
11389     result = holes;
11390     while (holes < limit) {
11391       elements->set_the_hole(holes);
11392       holes++;
11393     }
11394   } else {
11395     FixedArray* elements = FixedArray::cast(elements_base);
11396     AssertNoAllocation no_alloc;
11397
11398     // Split elements into defined, undefined and the_hole, in that order.  Only
11399     // count locations for undefined and the hole, and fill them afterwards.
11400     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
11401     unsigned int undefs = limit;
11402     unsigned int holes = limit;
11403     // Assume most arrays contain no holes and undefined values, so minimize the
11404     // number of stores of non-undefined, non-the-hole values.
11405     for (unsigned int i = 0; i < undefs; i++) {
11406       Object* current = elements->get(i);
11407       if (current->IsTheHole()) {
11408         holes--;
11409         undefs--;
11410       } else if (current->IsUndefined()) {
11411         undefs--;
11412       } else {
11413         continue;
11414       }
11415       // Position i needs to be filled.
11416       while (undefs > i) {
11417         current = elements->get(undefs);
11418         if (current->IsTheHole()) {
11419           holes--;
11420           undefs--;
11421         } else if (current->IsUndefined()) {
11422           undefs--;
11423         } else {
11424           elements->set(i, current, write_barrier);
11425           break;
11426         }
11427       }
11428     }
11429     result = undefs;
11430     while (undefs < holes) {
11431       elements->set_undefined(undefs);
11432       undefs++;
11433     }
11434     while (holes < limit) {
11435       elements->set_the_hole(holes);
11436       holes++;
11437     }
11438   }
11439
11440   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11441     return Smi::FromInt(static_cast<int>(result));
11442   }
11443   ASSERT_NE(NULL, result_double);
11444   result_double->set_value(static_cast<double>(result));
11445   return result_double;
11446 }
11447
11448
11449 Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
11450   uint8_t clamped_value = 0;
11451   if (index < static_cast<uint32_t>(length())) {
11452     if (value->IsSmi()) {
11453       int int_value = Smi::cast(value)->value();
11454       if (int_value < 0) {
11455         clamped_value = 0;
11456       } else if (int_value > 255) {
11457         clamped_value = 255;
11458       } else {
11459         clamped_value = static_cast<uint8_t>(int_value);
11460       }
11461     } else if (value->IsHeapNumber()) {
11462       double double_value = HeapNumber::cast(value)->value();
11463       if (!(double_value > 0)) {
11464         // NaN and less than zero clamp to zero.
11465         clamped_value = 0;
11466       } else if (double_value > 255) {
11467         // Greater than 255 clamp to 255.
11468         clamped_value = 255;
11469       } else {
11470         // Other doubles are rounded to the nearest integer.
11471         clamped_value = static_cast<uint8_t>(double_value + 0.5);
11472       }
11473     } else {
11474       // Clamp undefined to zero (default). All other types have been
11475       // converted to a number type further up in the call chain.
11476       ASSERT(value->IsUndefined());
11477     }
11478     set(index, clamped_value);
11479   }
11480   return Smi::FromInt(clamped_value);
11481 }
11482
11483
11484 template<typename ExternalArrayClass, typename ValueType>
11485 static MaybeObject* ExternalArrayIntSetter(Heap* heap,
11486                                            ExternalArrayClass* receiver,
11487                                            uint32_t index,
11488                                            Object* value) {
11489   ValueType cast_value = 0;
11490   if (index < static_cast<uint32_t>(receiver->length())) {
11491     if (value->IsSmi()) {
11492       int int_value = Smi::cast(value)->value();
11493       cast_value = static_cast<ValueType>(int_value);
11494     } else if (value->IsHeapNumber()) {
11495       double double_value = HeapNumber::cast(value)->value();
11496       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
11497     } else {
11498       // Clamp undefined to zero (default). All other types have been
11499       // converted to a number type further up in the call chain.
11500       ASSERT(value->IsUndefined());
11501     }
11502     receiver->set(index, cast_value);
11503   }
11504   return heap->NumberFromInt32(cast_value);
11505 }
11506
11507
11508 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) {
11509   return ExternalArrayIntSetter<ExternalByteArray, int8_t>
11510       (GetHeap(), this, index, value);
11511 }
11512
11513
11514 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index,
11515                                                  Object* value) {
11516   return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
11517       (GetHeap(), this, index, value);
11518 }
11519
11520
11521 MaybeObject* ExternalShortArray::SetValue(uint32_t index,
11522                                           Object* value) {
11523   return ExternalArrayIntSetter<ExternalShortArray, int16_t>
11524       (GetHeap(), this, index, value);
11525 }
11526
11527
11528 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index,
11529                                                   Object* value) {
11530   return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
11531       (GetHeap(), this, index, value);
11532 }
11533
11534
11535 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) {
11536   return ExternalArrayIntSetter<ExternalIntArray, int32_t>
11537       (GetHeap(), this, index, value);
11538 }
11539
11540
11541 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
11542   uint32_t cast_value = 0;
11543   Heap* heap = GetHeap();
11544   if (index < static_cast<uint32_t>(length())) {
11545     if (value->IsSmi()) {
11546       int int_value = Smi::cast(value)->value();
11547       cast_value = static_cast<uint32_t>(int_value);
11548     } else if (value->IsHeapNumber()) {
11549       double double_value = HeapNumber::cast(value)->value();
11550       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
11551     } else {
11552       // Clamp undefined to zero (default). All other types have been
11553       // converted to a number type further up in the call chain.
11554       ASSERT(value->IsUndefined());
11555     }
11556     set(index, cast_value);
11557   }
11558   return heap->NumberFromUint32(cast_value);
11559 }
11560
11561
11562 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
11563   float cast_value = 0;
11564   Heap* heap = GetHeap();
11565   if (index < static_cast<uint32_t>(length())) {
11566     if (value->IsSmi()) {
11567       int int_value = Smi::cast(value)->value();
11568       cast_value = static_cast<float>(int_value);
11569     } else if (value->IsHeapNumber()) {
11570       double double_value = HeapNumber::cast(value)->value();
11571       cast_value = static_cast<float>(double_value);
11572     } else {
11573       // Clamp undefined to zero (default). All other types have been
11574       // converted to a number type further up in the call chain.
11575       ASSERT(value->IsUndefined());
11576     }
11577     set(index, cast_value);
11578   }
11579   return heap->AllocateHeapNumber(cast_value);
11580 }
11581
11582
11583 MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) {
11584   double double_value = 0;
11585   Heap* heap = GetHeap();
11586   if (index < static_cast<uint32_t>(length())) {
11587     if (value->IsSmi()) {
11588       int int_value = Smi::cast(value)->value();
11589       double_value = static_cast<double>(int_value);
11590     } else if (value->IsHeapNumber()) {
11591       double_value = HeapNumber::cast(value)->value();
11592     } else {
11593       // Clamp undefined to zero (default). All other types have been
11594       // converted to a number type further up in the call chain.
11595       ASSERT(value->IsUndefined());
11596     }
11597     set(index, double_value);
11598   }
11599   return heap->AllocateHeapNumber(double_value);
11600 }
11601
11602
11603 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
11604   ASSERT(!HasFastProperties());
11605   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
11606   return JSGlobalPropertyCell::cast(value);
11607 }
11608
11609
11610 Handle<JSGlobalPropertyCell> GlobalObject::EnsurePropertyCell(
11611     Handle<GlobalObject> global,
11612     Handle<String> name) {
11613   Isolate* isolate = global->GetIsolate();
11614   CALL_HEAP_FUNCTION(isolate,
11615                      global->EnsurePropertyCell(*name),
11616                      JSGlobalPropertyCell);
11617 }
11618
11619
11620 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) {
11621   ASSERT(!HasFastProperties());
11622   int entry = property_dictionary()->FindEntry(name);
11623   if (entry == StringDictionary::kNotFound) {
11624     Heap* heap = GetHeap();
11625     Object* cell;
11626     { MaybeObject* maybe_cell =
11627           heap->AllocateJSGlobalPropertyCell(heap->the_hole_value());
11628       if (!maybe_cell->ToObject(&cell)) return maybe_cell;
11629     }
11630     PropertyDetails details(NONE, NORMAL);
11631     details = details.AsDeleted();
11632     Object* dictionary;
11633     { MaybeObject* maybe_dictionary =
11634           property_dictionary()->Add(name, cell, details);
11635       if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
11636     }
11637     set_properties(StringDictionary::cast(dictionary));
11638     return cell;
11639   } else {
11640     Object* value = property_dictionary()->ValueAt(entry);
11641     ASSERT(value->IsJSGlobalPropertyCell());
11642     return value;
11643   }
11644 }
11645
11646
11647 MaybeObject* SymbolTable::LookupString(String* string, Object** s) {
11648   SymbolKey key(string);
11649   return LookupKey(&key, s);
11650 }
11651
11652
11653 // This class is used for looking up two character strings in the symbol table.
11654 // If we don't have a hit we don't want to waste much time so we unroll the
11655 // string hash calculation loop here for speed.  Doesn't work if the two
11656 // characters form a decimal integer, since such strings have a different hash
11657 // algorithm.
11658 class TwoCharHashTableKey : public HashTableKey {
11659  public:
11660   TwoCharHashTableKey(uint32_t c1, uint32_t c2)
11661     : c1_(c1), c2_(c2) {
11662     // Char 1.
11663     uint32_t hash = c1 + (c1 << 10);
11664     hash ^= hash >> 6;
11665     // Char 2.
11666     hash += c2;
11667     hash += hash << 10;
11668     hash ^= hash >> 6;
11669     // GetHash.
11670     hash += hash << 3;
11671     hash ^= hash >> 11;
11672     hash += hash << 15;
11673     if (hash == 0) hash = 27;
11674 #ifdef DEBUG
11675     StringHasher hasher(2);
11676     hasher.AddCharacter(c1);
11677     hasher.AddCharacter(c2);
11678     // If this assert fails then we failed to reproduce the two-character
11679     // version of the string hashing algorithm above.  One reason could be
11680     // that we were passed two digits as characters, since the hash
11681     // algorithm is different in that case.
11682     ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
11683 #endif
11684     hash_ = hash;
11685   }
11686
11687   bool IsMatch(Object* o) {
11688     if (!o->IsString()) return false;
11689     String* other = String::cast(o);
11690     if (other->length() != 2) return false;
11691     if (other->Get(0) != c1_) return false;
11692     return other->Get(1) == c2_;
11693   }
11694
11695   uint32_t Hash() { return hash_; }
11696   uint32_t HashForObject(Object* key) {
11697     if (!key->IsString()) return 0;
11698     return String::cast(key)->Hash();
11699   }
11700
11701   Object* AsObject() {
11702     // The TwoCharHashTableKey is only used for looking in the symbol
11703     // table, not for adding to it.
11704     UNREACHABLE();
11705     return NULL;
11706   }
11707
11708  private:
11709   uint32_t c1_;
11710   uint32_t c2_;
11711   uint32_t hash_;
11712 };
11713
11714
11715 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
11716   SymbolKey key(string);
11717   int entry = FindEntry(&key);
11718   if (entry == kNotFound) {
11719     return false;
11720   } else {
11721     String* result = String::cast(KeyAt(entry));
11722     ASSERT(StringShape(result).IsSymbol());
11723     *symbol = result;
11724     return true;
11725   }
11726 }
11727
11728
11729 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
11730                                                uint32_t c2,
11731                                                String** symbol) {
11732   TwoCharHashTableKey key(c1, c2);
11733   int entry = FindEntry(&key);
11734   if (entry == kNotFound) {
11735     return false;
11736   } else {
11737     String* result = String::cast(KeyAt(entry));
11738     ASSERT(StringShape(result).IsSymbol());
11739     *symbol = result;
11740     return true;
11741   }
11742 }
11743
11744
11745 MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
11746   Utf8SymbolKey key(str);
11747   return LookupKey(&key, s);
11748 }
11749
11750
11751 MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str,
11752                                             Object** s) {
11753   AsciiSymbolKey key(str);
11754   return LookupKey(&key, s);
11755 }
11756
11757
11758 MaybeObject* SymbolTable::LookupSubStringAsciiSymbol(Handle<SeqAsciiString> str,
11759                                                      int from,
11760                                                      int length,
11761                                                      Object** s) {
11762   SubStringAsciiSymbolKey key(str, from, length);
11763   return LookupKey(&key, s);
11764 }
11765
11766
11767 MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
11768                                               Object** s) {
11769   TwoByteSymbolKey key(str);
11770   return LookupKey(&key, s);
11771 }
11772
11773 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
11774   int entry = FindEntry(key);
11775
11776   // Symbol already in table.
11777   if (entry != kNotFound) {
11778     *s = KeyAt(entry);
11779     return this;
11780   }
11781
11782   // Adding new symbol. Grow table if needed.
11783   Object* obj;
11784   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
11785     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11786   }
11787
11788   // Create symbol object.
11789   Object* symbol;
11790   { MaybeObject* maybe_symbol = key->AsObject();
11791     if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol;
11792   }
11793
11794   // If the symbol table grew as part of EnsureCapacity, obj is not
11795   // the current symbol table and therefore we cannot use
11796   // SymbolTable::cast here.
11797   SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
11798
11799   // Add the new symbol and return it along with the symbol table.
11800   entry = table->FindInsertionEntry(key->Hash());
11801   table->set(EntryToIndex(entry), symbol);
11802   table->ElementAdded();
11803   *s = symbol;
11804   return table;
11805 }
11806
11807
11808 Object* CompilationCacheTable::Lookup(String* src) {
11809   StringKey key(src);
11810   int entry = FindEntry(&key);
11811   if (entry == kNotFound) return GetHeap()->undefined_value();
11812   return get(EntryToIndex(entry) + 1);
11813 }
11814
11815
11816 Object* CompilationCacheTable::LookupEval(String* src,
11817                                           Context* context,
11818                                           StrictModeFlag strict_mode) {
11819   StringSharedKey key(src, context->closure()->shared(), strict_mode);
11820   int entry = FindEntry(&key);
11821   if (entry == kNotFound) return GetHeap()->undefined_value();
11822   return get(EntryToIndex(entry) + 1);
11823 }
11824
11825
11826 Object* CompilationCacheTable::LookupRegExp(String* src,
11827                                             JSRegExp::Flags flags) {
11828   RegExpKey key(src, flags);
11829   int entry = FindEntry(&key);
11830   if (entry == kNotFound) return GetHeap()->undefined_value();
11831   return get(EntryToIndex(entry) + 1);
11832 }
11833
11834
11835 MaybeObject* CompilationCacheTable::Put(String* src, Object* value) {
11836   StringKey key(src);
11837   Object* obj;
11838   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11839     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11840   }
11841
11842   CompilationCacheTable* cache =
11843       reinterpret_cast<CompilationCacheTable*>(obj);
11844   int entry = cache->FindInsertionEntry(key.Hash());
11845   cache->set(EntryToIndex(entry), src);
11846   cache->set(EntryToIndex(entry) + 1, value);
11847   cache->ElementAdded();
11848   return cache;
11849 }
11850
11851
11852 MaybeObject* CompilationCacheTable::PutEval(String* src,
11853                                             Context* context,
11854                                             SharedFunctionInfo* value) {
11855   StringSharedKey key(src,
11856                       context->closure()->shared(),
11857                       value->strict_mode_flag());
11858   Object* obj;
11859   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11860     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11861   }
11862
11863   CompilationCacheTable* cache =
11864       reinterpret_cast<CompilationCacheTable*>(obj);
11865   int entry = cache->FindInsertionEntry(key.Hash());
11866
11867   Object* k;
11868   { MaybeObject* maybe_k = key.AsObject();
11869     if (!maybe_k->ToObject(&k)) return maybe_k;
11870   }
11871
11872   cache->set(EntryToIndex(entry), k);
11873   cache->set(EntryToIndex(entry) + 1, value);
11874   cache->ElementAdded();
11875   return cache;
11876 }
11877
11878
11879 MaybeObject* CompilationCacheTable::PutRegExp(String* src,
11880                                               JSRegExp::Flags flags,
11881                                               FixedArray* value) {
11882   RegExpKey key(src, flags);
11883   Object* obj;
11884   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11885     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11886   }
11887
11888   CompilationCacheTable* cache =
11889       reinterpret_cast<CompilationCacheTable*>(obj);
11890   int entry = cache->FindInsertionEntry(key.Hash());
11891   // We store the value in the key slot, and compare the search key
11892   // to the stored value with a custon IsMatch function during lookups.
11893   cache->set(EntryToIndex(entry), value);
11894   cache->set(EntryToIndex(entry) + 1, value);
11895   cache->ElementAdded();
11896   return cache;
11897 }
11898
11899
11900 void CompilationCacheTable::Remove(Object* value) {
11901   Object* null_value = GetHeap()->null_value();
11902   for (int entry = 0, size = Capacity(); entry < size; entry++) {
11903     int entry_index = EntryToIndex(entry);
11904     int value_index = entry_index + 1;
11905     if (get(value_index) == value) {
11906       NoWriteBarrierSet(this, entry_index, null_value);
11907       NoWriteBarrierSet(this, value_index, null_value);
11908       ElementRemoved();
11909     }
11910   }
11911   return;
11912 }
11913
11914
11915 // SymbolsKey used for HashTable where key is array of symbols.
11916 class SymbolsKey : public HashTableKey {
11917  public:
11918   explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
11919
11920   bool IsMatch(Object* symbols) {
11921     FixedArray* o = FixedArray::cast(symbols);
11922     int len = symbols_->length();
11923     if (o->length() != len) return false;
11924     for (int i = 0; i < len; i++) {
11925       if (o->get(i) != symbols_->get(i)) return false;
11926     }
11927     return true;
11928   }
11929
11930   uint32_t Hash() { return HashForObject(symbols_); }
11931
11932   uint32_t HashForObject(Object* obj) {
11933     FixedArray* symbols = FixedArray::cast(obj);
11934     int len = symbols->length();
11935     uint32_t hash = 0;
11936     for (int i = 0; i < len; i++) {
11937       hash ^= String::cast(symbols->get(i))->Hash();
11938     }
11939     return hash;
11940   }
11941
11942   Object* AsObject() { return symbols_; }
11943
11944  private:
11945   FixedArray* symbols_;
11946 };
11947
11948
11949 Object* MapCache::Lookup(FixedArray* array) {
11950   SymbolsKey key(array);
11951   int entry = FindEntry(&key);
11952   if (entry == kNotFound) return GetHeap()->undefined_value();
11953   return get(EntryToIndex(entry) + 1);
11954 }
11955
11956
11957 MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
11958   SymbolsKey key(array);
11959   Object* obj;
11960   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11961     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11962   }
11963
11964   MapCache* cache = reinterpret_cast<MapCache*>(obj);
11965   int entry = cache->FindInsertionEntry(key.Hash());
11966   cache->set(EntryToIndex(entry), array);
11967   cache->set(EntryToIndex(entry) + 1, value);
11968   cache->ElementAdded();
11969   return cache;
11970 }
11971
11972
11973 template<typename Shape, typename Key>
11974 MaybeObject* Dictionary<Shape, Key>::Allocate(int at_least_space_for) {
11975   Object* obj;
11976   { MaybeObject* maybe_obj =
11977         HashTable<Shape, Key>::Allocate(at_least_space_for);
11978     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11979   }
11980   // Initialize the next enumeration index.
11981   Dictionary<Shape, Key>::cast(obj)->
11982       SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
11983   return obj;
11984 }
11985
11986
11987 template<typename Shape, typename Key>
11988 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
11989   Heap* heap = Dictionary<Shape, Key>::GetHeap();
11990   int length = HashTable<Shape, Key>::NumberOfElements();
11991
11992   // Allocate and initialize iteration order array.
11993   Object* obj;
11994   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
11995     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11996   }
11997   FixedArray* iteration_order = FixedArray::cast(obj);
11998   for (int i = 0; i < length; i++) {
11999     iteration_order->set(i, Smi::FromInt(i));
12000   }
12001
12002   // Allocate array with enumeration order.
12003   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12004     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12005   }
12006   FixedArray* enumeration_order = FixedArray::cast(obj);
12007
12008   // Fill the enumeration order array with property details.
12009   int capacity = HashTable<Shape, Key>::Capacity();
12010   int pos = 0;
12011   for (int i = 0; i < capacity; i++) {
12012     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
12013       enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
12014     }
12015   }
12016
12017   // Sort the arrays wrt. enumeration order.
12018   iteration_order->SortPairs(enumeration_order, enumeration_order->length());
12019
12020   // Overwrite the enumeration_order with the enumeration indices.
12021   for (int i = 0; i < length; i++) {
12022     int index = Smi::cast(iteration_order->get(i))->value();
12023     int enum_index = PropertyDetails::kInitialIndex + i;
12024     enumeration_order->set(index, Smi::FromInt(enum_index));
12025   }
12026
12027   // Update the dictionary with new indices.
12028   capacity = HashTable<Shape, Key>::Capacity();
12029   pos = 0;
12030   for (int i = 0; i < capacity; i++) {
12031     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
12032       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
12033       PropertyDetails details = DetailsAt(i);
12034       PropertyDetails new_details =
12035           PropertyDetails(details.attributes(), details.type(), enum_index);
12036       DetailsAtPut(i, new_details);
12037     }
12038   }
12039
12040   // Set the next enumeration index.
12041   SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
12042   return this;
12043 }
12044
12045 template<typename Shape, typename Key>
12046 MaybeObject* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
12047   // Check whether there are enough enumeration indices to add n elements.
12048   if (Shape::kIsEnumerable &&
12049       !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
12050     // If not, we generate new indices for the properties.
12051     Object* result;
12052     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12053       if (!maybe_result->ToObject(&result)) return maybe_result;
12054     }
12055   }
12056   return HashTable<Shape, Key>::EnsureCapacity(n, key);
12057 }
12058
12059
12060 void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
12061   // Do nothing if the interval [from, to) is empty.
12062   if (from >= to) return;
12063
12064   Heap* heap = GetHeap();
12065   int removed_entries = 0;
12066   Object* sentinel = heap->null_value();
12067   int capacity = Capacity();
12068   for (int i = 0; i < capacity; i++) {
12069     Object* key = KeyAt(i);
12070     if (key->IsNumber()) {
12071       uint32_t number = static_cast<uint32_t>(key->Number());
12072       if (from <= number && number < to) {
12073         SetEntry(i, sentinel, sentinel);
12074         removed_entries++;
12075       }
12076     }
12077   }
12078
12079   // Update the number of elements.
12080   ElementsRemoved(removed_entries);
12081 }
12082
12083
12084 template<typename Shape, typename Key>
12085 Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
12086                                                JSReceiver::DeleteMode mode) {
12087   Heap* heap = Dictionary<Shape, Key>::GetHeap();
12088   PropertyDetails details = DetailsAt(entry);
12089   // Ignore attributes if forcing a deletion.
12090   if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
12091     return heap->false_value();
12092   }
12093   SetEntry(entry, heap->null_value(), heap->null_value());
12094   HashTable<Shape, Key>::ElementRemoved();
12095   return heap->true_value();
12096 }
12097
12098
12099 template<typename Shape, typename Key>
12100 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
12101   return HashTable<Shape, Key>::Shrink(key);
12102 }
12103
12104
12105 template<typename Shape, typename Key>
12106 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
12107   int entry = this->FindEntry(key);
12108
12109   // If the entry is present set the value;
12110   if (entry != Dictionary<Shape, Key>::kNotFound) {
12111     ValueAtPut(entry, value);
12112     return this;
12113   }
12114
12115   // Check whether the dictionary should be extended.
12116   Object* obj;
12117   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12118     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12119   }
12120
12121   Object* k;
12122   { MaybeObject* maybe_k = Shape::AsObject(key);
12123     if (!maybe_k->ToObject(&k)) return maybe_k;
12124   }
12125   PropertyDetails details = PropertyDetails(NONE, NORMAL);
12126   return Dictionary<Shape, Key>::cast(obj)->
12127       AddEntry(key, value, details, Shape::Hash(key));
12128 }
12129
12130
12131 template<typename Shape, typename Key>
12132 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
12133                                          Object* value,
12134                                          PropertyDetails details) {
12135   // Valdate key is absent.
12136   SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
12137   // Check whether the dictionary should be extended.
12138   Object* obj;
12139   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12140     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12141   }
12142   return Dictionary<Shape, Key>::cast(obj)->
12143       AddEntry(key, value, details, Shape::Hash(key));
12144 }
12145
12146
12147 // Add a key, value pair to the dictionary.
12148 template<typename Shape, typename Key>
12149 MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key,
12150                                               Object* value,
12151                                               PropertyDetails details,
12152                                               uint32_t hash) {
12153   // Compute the key object.
12154   Object* k;
12155   { MaybeObject* maybe_k = Shape::AsObject(key);
12156     if (!maybe_k->ToObject(&k)) return maybe_k;
12157   }
12158
12159   uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
12160   // Insert element at empty or deleted entry
12161   if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
12162     // Assign an enumeration index to the property and update
12163     // SetNextEnumerationIndex.
12164     int index = NextEnumerationIndex();
12165     details = PropertyDetails(details.attributes(), details.type(), index);
12166     SetNextEnumerationIndex(index + 1);
12167   }
12168   SetEntry(entry, k, value, details);
12169   ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
12170           || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
12171   HashTable<Shape, Key>::ElementAdded();
12172   return this;
12173 }
12174
12175
12176 void NumberDictionary::UpdateMaxNumberKey(uint32_t key) {
12177   // If the dictionary requires slow elements an element has already
12178   // been added at a high index.
12179   if (requires_slow_elements()) return;
12180   // Check if this index is high enough that we should require slow
12181   // elements.
12182   if (key > kRequiresSlowElementsLimit) {
12183     set_requires_slow_elements();
12184     return;
12185   }
12186   // Update max key value.
12187   Object* max_index_object = get(kMaxNumberKeyIndex);
12188   if (!max_index_object->IsSmi() || max_number_key() < key) {
12189     FixedArray::set(kMaxNumberKeyIndex,
12190                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
12191   }
12192 }
12193
12194
12195 MaybeObject* NumberDictionary::AddNumberEntry(uint32_t key,
12196                                               Object* value,
12197                                               PropertyDetails details) {
12198   UpdateMaxNumberKey(key);
12199   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
12200   return Add(key, value, details);
12201 }
12202
12203
12204 MaybeObject* NumberDictionary::AtNumberPut(uint32_t key, Object* value) {
12205   UpdateMaxNumberKey(key);
12206   return AtPut(key, value);
12207 }
12208
12209
12210 MaybeObject* NumberDictionary::Set(uint32_t key,
12211                                    Object* value,
12212                                    PropertyDetails details) {
12213   int entry = FindEntry(key);
12214   if (entry == kNotFound) return AddNumberEntry(key, value, details);
12215   // Preserve enumeration index.
12216   details = PropertyDetails(details.attributes(),
12217                             details.type(),
12218                             DetailsAt(entry).index());
12219   MaybeObject* maybe_object_key = NumberDictionaryShape::AsObject(key);
12220   Object* object_key;
12221   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
12222   SetEntry(entry, object_key, value, details);
12223   return this;
12224 }
12225
12226
12227
12228 template<typename Shape, typename Key>
12229 int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
12230     PropertyAttributes filter) {
12231   int capacity = HashTable<Shape, Key>::Capacity();
12232   int result = 0;
12233   for (int i = 0; i < capacity; i++) {
12234     Object* k = HashTable<Shape, Key>::KeyAt(i);
12235     if (HashTable<Shape, Key>::IsKey(k)) {
12236       PropertyDetails details = DetailsAt(i);
12237       if (details.IsDeleted()) continue;
12238       PropertyAttributes attr = details.attributes();
12239       if ((attr & filter) == 0) result++;
12240     }
12241   }
12242   return result;
12243 }
12244
12245
12246 template<typename Shape, typename Key>
12247 int Dictionary<Shape, Key>::NumberOfEnumElements() {
12248   return NumberOfElementsFilterAttributes(
12249       static_cast<PropertyAttributes>(DONT_ENUM));
12250 }
12251
12252
12253 template<typename Shape, typename Key>
12254 void Dictionary<Shape, Key>::CopyKeysTo(
12255     FixedArray* storage,
12256     PropertyAttributes filter,
12257     typename Dictionary<Shape, Key>::SortMode sort_mode) {
12258   ASSERT(storage->length() >= NumberOfEnumElements());
12259   int capacity = HashTable<Shape, Key>::Capacity();
12260   int index = 0;
12261   for (int i = 0; i < capacity; i++) {
12262      Object* k = HashTable<Shape, Key>::KeyAt(i);
12263      if (HashTable<Shape, Key>::IsKey(k)) {
12264        PropertyDetails details = DetailsAt(i);
12265        if (details.IsDeleted()) continue;
12266        PropertyAttributes attr = details.attributes();
12267        if ((attr & filter) == 0) storage->set(index++, k);
12268      }
12269   }
12270   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12271     storage->SortPairs(storage, index);
12272   }
12273   ASSERT(storage->length() >= index);
12274 }
12275
12276
12277 void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
12278                                       FixedArray* sort_array) {
12279   ASSERT(storage->length() >= NumberOfEnumElements());
12280   int capacity = Capacity();
12281   int index = 0;
12282   for (int i = 0; i < capacity; i++) {
12283      Object* k = KeyAt(i);
12284      if (IsKey(k)) {
12285        PropertyDetails details = DetailsAt(i);
12286        if (details.IsDeleted() || details.IsDontEnum()) continue;
12287        storage->set(index, k);
12288        sort_array->set(index, Smi::FromInt(details.index()));
12289        index++;
12290      }
12291   }
12292   storage->SortPairs(sort_array, sort_array->length());
12293   ASSERT(storage->length() >= index);
12294 }
12295
12296
12297 template<typename Shape, typename Key>
12298 void Dictionary<Shape, Key>::CopyKeysTo(
12299     FixedArray* storage,
12300     int index,
12301     typename Dictionary<Shape, Key>::SortMode sort_mode) {
12302   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
12303       static_cast<PropertyAttributes>(NONE)));
12304   int capacity = HashTable<Shape, Key>::Capacity();
12305   for (int i = 0; i < capacity; i++) {
12306     Object* k = HashTable<Shape, Key>::KeyAt(i);
12307     if (HashTable<Shape, Key>::IsKey(k)) {
12308       PropertyDetails details = DetailsAt(i);
12309       if (details.IsDeleted()) continue;
12310       storage->set(index++, k);
12311     }
12312   }
12313   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12314     storage->SortPairs(storage, index);
12315   }
12316   ASSERT(storage->length() >= index);
12317 }
12318
12319
12320 // Backwards lookup (slow).
12321 template<typename Shape, typename Key>
12322 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
12323   int capacity = HashTable<Shape, Key>::Capacity();
12324   for (int i = 0; i < capacity; i++) {
12325     Object* k =  HashTable<Shape, Key>::KeyAt(i);
12326     if (Dictionary<Shape, Key>::IsKey(k)) {
12327       Object* e = ValueAt(i);
12328       if (e->IsJSGlobalPropertyCell()) {
12329         e = JSGlobalPropertyCell::cast(e)->value();
12330       }
12331       if (e == value) return k;
12332     }
12333   }
12334   Heap* heap = Dictionary<Shape, Key>::GetHeap();
12335   return heap->undefined_value();
12336 }
12337
12338
12339 MaybeObject* StringDictionary::TransformPropertiesToFastFor(
12340     JSObject* obj, int unused_property_fields) {
12341   // Make sure we preserve dictionary representation if there are too many
12342   // descriptors.
12343   if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
12344
12345   // Figure out if it is necessary to generate new enumeration indices.
12346   int max_enumeration_index =
12347       NextEnumerationIndex() +
12348           (DescriptorArray::kMaxNumberOfDescriptors -
12349            NumberOfElements());
12350   if (!PropertyDetails::IsValidIndex(max_enumeration_index)) {
12351     Object* result;
12352     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12353       if (!maybe_result->ToObject(&result)) return maybe_result;
12354     }
12355   }
12356
12357   int instance_descriptor_length = 0;
12358   int number_of_fields = 0;
12359
12360   Heap* heap = GetHeap();
12361
12362   // Compute the length of the instance descriptor.
12363   int capacity = Capacity();
12364   for (int i = 0; i < capacity; i++) {
12365     Object* k = KeyAt(i);
12366     if (IsKey(k)) {
12367       Object* value = ValueAt(i);
12368       PropertyType type = DetailsAt(i).type();
12369       ASSERT(type != FIELD);
12370       instance_descriptor_length++;
12371       if (type == NORMAL &&
12372           (!value->IsJSFunction() || heap->InNewSpace(value))) {
12373         number_of_fields += 1;
12374       }
12375     }
12376   }
12377
12378   // Allocate the instance descriptor.
12379   DescriptorArray* descriptors;
12380   { MaybeObject* maybe_descriptors =
12381         DescriptorArray::Allocate(instance_descriptor_length);
12382     if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) {
12383       return maybe_descriptors;
12384     }
12385   }
12386
12387   DescriptorArray::WhitenessWitness witness(descriptors);
12388
12389   int inobject_props = obj->map()->inobject_properties();
12390   int number_of_allocated_fields =
12391       number_of_fields + unused_property_fields - inobject_props;
12392   if (number_of_allocated_fields < 0) {
12393     // There is enough inobject space for all fields (including unused).
12394     number_of_allocated_fields = 0;
12395     unused_property_fields = inobject_props - number_of_fields;
12396   }
12397
12398   // Allocate the fixed array for the fields.
12399   Object* fields;
12400   { MaybeObject* maybe_fields =
12401         heap->AllocateFixedArray(number_of_allocated_fields);
12402     if (!maybe_fields->ToObject(&fields)) return maybe_fields;
12403   }
12404
12405   // Fill in the instance descriptor and the fields.
12406   int next_descriptor = 0;
12407   int current_offset = 0;
12408   for (int i = 0; i < capacity; i++) {
12409     Object* k = KeyAt(i);
12410     if (IsKey(k)) {
12411       Object* value = ValueAt(i);
12412       // Ensure the key is a symbol before writing into the instance descriptor.
12413       Object* key;
12414       { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
12415         if (!maybe_key->ToObject(&key)) return maybe_key;
12416       }
12417       PropertyDetails details = DetailsAt(i);
12418       PropertyType type = details.type();
12419
12420       if (value->IsJSFunction() && !heap->InNewSpace(value)) {
12421         ConstantFunctionDescriptor d(String::cast(key),
12422                                      JSFunction::cast(value),
12423                                      details.attributes(),
12424                                      details.index());
12425         descriptors->Set(next_descriptor++, &d, witness);
12426       } else if (type == NORMAL) {
12427         if (current_offset < inobject_props) {
12428           obj->InObjectPropertyAtPut(current_offset,
12429                                      value,
12430                                      UPDATE_WRITE_BARRIER);
12431         } else {
12432           int offset = current_offset - inobject_props;
12433           FixedArray::cast(fields)->set(offset, value);
12434         }
12435         FieldDescriptor d(String::cast(key),
12436                           current_offset++,
12437                           details.attributes(),
12438                           details.index());
12439         descriptors->Set(next_descriptor++, &d, witness);
12440       } else if (type == CALLBACKS) {
12441         CallbacksDescriptor d(String::cast(key),
12442                               value,
12443                               details.attributes(),
12444                               details.index());
12445         descriptors->Set(next_descriptor++, &d, witness);
12446       } else {
12447         UNREACHABLE();
12448       }
12449     }
12450   }
12451   ASSERT(current_offset == number_of_fields);
12452
12453   descriptors->Sort(witness);
12454   // Allocate new map.
12455   Object* new_map;
12456   { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
12457     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
12458   }
12459
12460   // Transform the object.
12461   obj->set_map(Map::cast(new_map));
12462   obj->map()->set_instance_descriptors(descriptors);
12463   obj->map()->set_unused_property_fields(unused_property_fields);
12464
12465   obj->set_properties(FixedArray::cast(fields));
12466   ASSERT(obj->IsJSObject());
12467
12468   descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
12469   // Check that it really works.
12470   ASSERT(obj->HasFastProperties());
12471
12472   return obj;
12473 }
12474
12475
12476 bool ObjectHashSet::Contains(Object* key) {
12477   // If the object does not have an identity hash, it was never used as a key.
12478   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12479     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false;
12480   }
12481   return (FindEntry(key) != kNotFound);
12482 }
12483
12484
12485 MaybeObject* ObjectHashSet::Add(Object* key) {
12486   // Make sure the key object has an identity hash code.
12487   int hash;
12488   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
12489     if (maybe_hash->IsFailure()) return maybe_hash;
12490     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
12491   }
12492   int entry = FindEntry(key);
12493
12494   // Check whether key is already present.
12495   if (entry != kNotFound) return this;
12496
12497   // Check whether the hash set should be extended and add entry.
12498   Object* obj;
12499   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12500     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12501   }
12502   ObjectHashSet* table = ObjectHashSet::cast(obj);
12503   entry = table->FindInsertionEntry(hash);
12504   table->set(EntryToIndex(entry), key);
12505   table->ElementAdded();
12506   return table;
12507 }
12508
12509
12510 MaybeObject* ObjectHashSet::Remove(Object* key) {
12511   // If the object does not have an identity hash, it was never used as a key.
12512   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12513     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this;
12514   }
12515   int entry = FindEntry(key);
12516
12517   // Check whether key is actually present.
12518   if (entry == kNotFound) return this;
12519
12520   // Remove entry and try to shrink this hash set.
12521   set_null(EntryToIndex(entry));
12522   ElementRemoved();
12523   return Shrink(key);
12524 }
12525
12526
12527 Object* ObjectHashTable::Lookup(Object* key) {
12528   // If the object does not have an identity hash, it was never used as a key.
12529   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12530     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) {
12531       return GetHeap()->undefined_value();
12532     }
12533   }
12534   int entry = FindEntry(key);
12535   if (entry == kNotFound) return GetHeap()->undefined_value();
12536   return get(EntryToIndex(entry) + 1);
12537 }
12538
12539
12540 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) {
12541   // Make sure the key object has an identity hash code.
12542   int hash;
12543   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
12544     if (maybe_hash->IsFailure()) return maybe_hash;
12545     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
12546   }
12547   int entry = FindEntry(key);
12548
12549   // Check whether to perform removal operation.
12550   if (value->IsUndefined()) {
12551     if (entry == kNotFound) return this;
12552     RemoveEntry(entry);
12553     return Shrink(key);
12554   }
12555
12556   // Key is already in table, just overwrite value.
12557   if (entry != kNotFound) {
12558     set(EntryToIndex(entry) + 1, value);
12559     return this;
12560   }
12561
12562   // Check whether the hash table should be extended.
12563   Object* obj;
12564   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12565     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12566   }
12567   ObjectHashTable* table = ObjectHashTable::cast(obj);
12568   table->AddEntry(table->FindInsertionEntry(hash), key, value);
12569   return table;
12570 }
12571
12572
12573 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
12574   set(EntryToIndex(entry), key);
12575   set(EntryToIndex(entry) + 1, value);
12576   ElementAdded();
12577 }
12578
12579
12580 void ObjectHashTable::RemoveEntry(int entry, Heap* heap) {
12581   set_null(heap, EntryToIndex(entry));
12582   set_null(heap, EntryToIndex(entry) + 1);
12583   ElementRemoved();
12584 }
12585
12586
12587 #ifdef ENABLE_DEBUGGER_SUPPORT
12588 // Check if there is a break point at this code position.
12589 bool DebugInfo::HasBreakPoint(int code_position) {
12590   // Get the break point info object for this code position.
12591   Object* break_point_info = GetBreakPointInfo(code_position);
12592
12593   // If there is no break point info object or no break points in the break
12594   // point info object there is no break point at this code position.
12595   if (break_point_info->IsUndefined()) return false;
12596   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
12597 }
12598
12599
12600 // Get the break point info object for this code position.
12601 Object* DebugInfo::GetBreakPointInfo(int code_position) {
12602   // Find the index of the break point info object for this code position.
12603   int index = GetBreakPointInfoIndex(code_position);
12604
12605   // Return the break point info object if any.
12606   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
12607   return BreakPointInfo::cast(break_points()->get(index));
12608 }
12609
12610
12611 // Clear a break point at the specified code position.
12612 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
12613                                 int code_position,
12614                                 Handle<Object> break_point_object) {
12615   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
12616   if (break_point_info->IsUndefined()) return;
12617   BreakPointInfo::ClearBreakPoint(
12618       Handle<BreakPointInfo>::cast(break_point_info),
12619       break_point_object);
12620 }
12621
12622
12623 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
12624                               int code_position,
12625                               int source_position,
12626                               int statement_position,
12627                               Handle<Object> break_point_object) {
12628   Isolate* isolate = Isolate::Current();
12629   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
12630   if (!break_point_info->IsUndefined()) {
12631     BreakPointInfo::SetBreakPoint(
12632         Handle<BreakPointInfo>::cast(break_point_info),
12633         break_point_object);
12634     return;
12635   }
12636
12637   // Adding a new break point for a code position which did not have any
12638   // break points before. Try to find a free slot.
12639   int index = kNoBreakPointInfo;
12640   for (int i = 0; i < debug_info->break_points()->length(); i++) {
12641     if (debug_info->break_points()->get(i)->IsUndefined()) {
12642       index = i;
12643       break;
12644     }
12645   }
12646   if (index == kNoBreakPointInfo) {
12647     // No free slot - extend break point info array.
12648     Handle<FixedArray> old_break_points =
12649         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
12650     Handle<FixedArray> new_break_points =
12651         isolate->factory()->NewFixedArray(
12652             old_break_points->length() +
12653             Debug::kEstimatedNofBreakPointsInFunction);
12654
12655     debug_info->set_break_points(*new_break_points);
12656     for (int i = 0; i < old_break_points->length(); i++) {
12657       new_break_points->set(i, old_break_points->get(i));
12658     }
12659     index = old_break_points->length();
12660   }
12661   ASSERT(index != kNoBreakPointInfo);
12662
12663   // Allocate new BreakPointInfo object and set the break point.
12664   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
12665       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
12666   new_break_point_info->set_code_position(Smi::FromInt(code_position));
12667   new_break_point_info->set_source_position(Smi::FromInt(source_position));
12668   new_break_point_info->
12669       set_statement_position(Smi::FromInt(statement_position));
12670   new_break_point_info->set_break_point_objects(
12671       isolate->heap()->undefined_value());
12672   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
12673   debug_info->break_points()->set(index, *new_break_point_info);
12674 }
12675
12676
12677 // Get the break point objects for a code position.
12678 Object* DebugInfo::GetBreakPointObjects(int code_position) {
12679   Object* break_point_info = GetBreakPointInfo(code_position);
12680   if (break_point_info->IsUndefined()) {
12681     return GetHeap()->undefined_value();
12682   }
12683   return BreakPointInfo::cast(break_point_info)->break_point_objects();
12684 }
12685
12686
12687 // Get the total number of break points.
12688 int DebugInfo::GetBreakPointCount() {
12689   if (break_points()->IsUndefined()) return 0;
12690   int count = 0;
12691   for (int i = 0; i < break_points()->length(); i++) {
12692     if (!break_points()->get(i)->IsUndefined()) {
12693       BreakPointInfo* break_point_info =
12694           BreakPointInfo::cast(break_points()->get(i));
12695       count += break_point_info->GetBreakPointCount();
12696     }
12697   }
12698   return count;
12699 }
12700
12701
12702 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
12703                                       Handle<Object> break_point_object) {
12704   Heap* heap = debug_info->GetHeap();
12705   if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
12706   for (int i = 0; i < debug_info->break_points()->length(); i++) {
12707     if (!debug_info->break_points()->get(i)->IsUndefined()) {
12708       Handle<BreakPointInfo> break_point_info =
12709           Handle<BreakPointInfo>(BreakPointInfo::cast(
12710               debug_info->break_points()->get(i)));
12711       if (BreakPointInfo::HasBreakPointObject(break_point_info,
12712                                               break_point_object)) {
12713         return *break_point_info;
12714       }
12715     }
12716   }
12717   return heap->undefined_value();
12718 }
12719
12720
12721 // Find the index of the break point info object for the specified code
12722 // position.
12723 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
12724   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
12725   for (int i = 0; i < break_points()->length(); i++) {
12726     if (!break_points()->get(i)->IsUndefined()) {
12727       BreakPointInfo* break_point_info =
12728           BreakPointInfo::cast(break_points()->get(i));
12729       if (break_point_info->code_position()->value() == code_position) {
12730         return i;
12731       }
12732     }
12733   }
12734   return kNoBreakPointInfo;
12735 }
12736
12737
12738 // Remove the specified break point object.
12739 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
12740                                      Handle<Object> break_point_object) {
12741   Isolate* isolate = Isolate::Current();
12742   // If there are no break points just ignore.
12743   if (break_point_info->break_point_objects()->IsUndefined()) return;
12744   // If there is a single break point clear it if it is the same.
12745   if (!break_point_info->break_point_objects()->IsFixedArray()) {
12746     if (break_point_info->break_point_objects() == *break_point_object) {
12747       break_point_info->set_break_point_objects(
12748           isolate->heap()->undefined_value());
12749     }
12750     return;
12751   }
12752   // If there are multiple break points shrink the array
12753   ASSERT(break_point_info->break_point_objects()->IsFixedArray());
12754   Handle<FixedArray> old_array =
12755       Handle<FixedArray>(
12756           FixedArray::cast(break_point_info->break_point_objects()));
12757   Handle<FixedArray> new_array =
12758       isolate->factory()->NewFixedArray(old_array->length() - 1);
12759   int found_count = 0;
12760   for (int i = 0; i < old_array->length(); i++) {
12761     if (old_array->get(i) == *break_point_object) {
12762       ASSERT(found_count == 0);
12763       found_count++;
12764     } else {
12765       new_array->set(i - found_count, old_array->get(i));
12766     }
12767   }
12768   // If the break point was found in the list change it.
12769   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
12770 }
12771
12772
12773 // Add the specified break point object.
12774 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
12775                                    Handle<Object> break_point_object) {
12776   // If there was no break point objects before just set it.
12777   if (break_point_info->break_point_objects()->IsUndefined()) {
12778     break_point_info->set_break_point_objects(*break_point_object);
12779     return;
12780   }
12781   // If the break point object is the same as before just ignore.
12782   if (break_point_info->break_point_objects() == *break_point_object) return;
12783   // If there was one break point object before replace with array.
12784   if (!break_point_info->break_point_objects()->IsFixedArray()) {
12785     Handle<FixedArray> array = FACTORY->NewFixedArray(2);
12786     array->set(0, break_point_info->break_point_objects());
12787     array->set(1, *break_point_object);
12788     break_point_info->set_break_point_objects(*array);
12789     return;
12790   }
12791   // If there was more than one break point before extend array.
12792   Handle<FixedArray> old_array =
12793       Handle<FixedArray>(
12794           FixedArray::cast(break_point_info->break_point_objects()));
12795   Handle<FixedArray> new_array =
12796       FACTORY->NewFixedArray(old_array->length() + 1);
12797   for (int i = 0; i < old_array->length(); i++) {
12798     // If the break point was there before just ignore.
12799     if (old_array->get(i) == *break_point_object) return;
12800     new_array->set(i, old_array->get(i));
12801   }
12802   // Add the new break point.
12803   new_array->set(old_array->length(), *break_point_object);
12804   break_point_info->set_break_point_objects(*new_array);
12805 }
12806
12807
12808 bool BreakPointInfo::HasBreakPointObject(
12809     Handle<BreakPointInfo> break_point_info,
12810     Handle<Object> break_point_object) {
12811   // No break point.
12812   if (break_point_info->break_point_objects()->IsUndefined()) return false;
12813   // Single break point.
12814   if (!break_point_info->break_point_objects()->IsFixedArray()) {
12815     return break_point_info->break_point_objects() == *break_point_object;
12816   }
12817   // Multiple break points.
12818   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
12819   for (int i = 0; i < array->length(); i++) {
12820     if (array->get(i) == *break_point_object) {
12821       return true;
12822     }
12823   }
12824   return false;
12825 }
12826
12827
12828 // Get the number of break points.
12829 int BreakPointInfo::GetBreakPointCount() {
12830   // No break point.
12831   if (break_point_objects()->IsUndefined()) return 0;
12832   // Single break point.
12833   if (!break_point_objects()->IsFixedArray()) return 1;
12834   // Multiple break points.
12835   return FixedArray::cast(break_point_objects())->length();
12836 }
12837 #endif  // ENABLE_DEBUGGER_SUPPORT
12838
12839
12840 } }  // namespace v8::internal