[V8] Add custom object compare callback
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / objects.cc
1 // Copyright 2012 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 "date.h"
37 #include "elements.h"
38 #include "execution.h"
39 #include "full-codegen.h"
40 #include "hydrogen.h"
41 #include "objects-inl.h"
42 #include "objects-visiting.h"
43 #include "objects-visiting-inl.h"
44 #include "macro-assembler.h"
45 #include "mark-compact.h"
46 #include "safepoint-table.h"
47 #include "string-stream.h"
48 #include "utils.h"
49 #include "vm-state-inl.h"
50
51 #ifdef ENABLE_DISASSEMBLER
52 #include "disasm.h"
53 #include "disassembler.h"
54 #endif
55
56 namespace v8 {
57 namespace internal {
58
59 void PrintElementsKind(FILE* out, ElementsKind kind) {
60   ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
61   PrintF(out, "%s", accessor->name());
62 }
63
64
65 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
66                                                   Object* value) {
67   Object* result;
68   { MaybeObject* maybe_result =
69         constructor->GetHeap()->AllocateJSObject(constructor);
70     if (!maybe_result->ToObject(&result)) return maybe_result;
71   }
72   JSValue::cast(result)->set_value(value);
73   return result;
74 }
75
76
77 MaybeObject* Object::ToObject(Context* global_context) {
78   if (IsNumber()) {
79     return CreateJSValue(global_context->number_function(), this);
80   } else if (IsBoolean()) {
81     return CreateJSValue(global_context->boolean_function(), this);
82   } else if (IsString()) {
83     return CreateJSValue(global_context->string_function(), this);
84   }
85   ASSERT(IsJSObject());
86   return this;
87 }
88
89
90 MaybeObject* Object::ToObject() {
91   if (IsJSReceiver()) {
92     return this;
93   } else if (IsNumber()) {
94     Isolate* isolate = Isolate::Current();
95     Context* global_context = isolate->context()->global_context();
96     return CreateJSValue(global_context->number_function(), this);
97   } else if (IsBoolean()) {
98     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
99     Context* global_context = isolate->context()->global_context();
100     return CreateJSValue(global_context->boolean_function(), this);
101   } else if (IsString()) {
102     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
103     Context* global_context = isolate->context()->global_context();
104     return CreateJSValue(global_context->string_function(), this);
105   }
106
107   // Throw a type error.
108   return Failure::InternalError();
109 }
110
111
112 Object* Object::ToBoolean() {
113   if (IsTrue()) return this;
114   if (IsFalse()) return this;
115   if (IsSmi()) {
116     return Isolate::Current()->heap()->ToBoolean(Smi::cast(this)->value() != 0);
117   }
118   HeapObject* heap_object = HeapObject::cast(this);
119   if (heap_object->IsUndefined() || heap_object->IsNull()) {
120     return heap_object->GetHeap()->false_value();
121   }
122   // Undetectable object is false
123   if (heap_object->IsUndetectableObject()) {
124     return heap_object->GetHeap()->false_value();
125   }
126   if (heap_object->IsString()) {
127     return heap_object->GetHeap()->ToBoolean(
128         String::cast(this)->length() != 0);
129   }
130   if (heap_object->IsHeapNumber()) {
131     return HeapNumber::cast(this)->HeapNumberToBoolean();
132   }
133   return heap_object->GetHeap()->true_value();
134 }
135
136
137 void Object::Lookup(String* name, LookupResult* result) {
138   Object* holder = NULL;
139   if (IsJSReceiver()) {
140     holder = this;
141   } else {
142     Context* global_context = Isolate::Current()->context()->global_context();
143     if (IsNumber()) {
144       holder = global_context->number_function()->instance_prototype();
145     } else if (IsString()) {
146       holder = global_context->string_function()->instance_prototype();
147     } else if (IsBoolean()) {
148       holder = global_context->boolean_function()->instance_prototype();
149     }
150   }
151   ASSERT(holder != NULL);  // Cannot handle null or undefined.
152   JSReceiver::cast(holder)->Lookup(name, result);
153 }
154
155
156 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
157                                              String* name,
158                                              PropertyAttributes* attributes) {
159   LookupResult result(name->GetIsolate());
160   Lookup(name, &result);
161   MaybeObject* value = GetProperty(receiver, &result, name, attributes);
162   ASSERT(*attributes <= ABSENT);
163   return value;
164 }
165
166
167 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver,
168                                                Object* structure,
169                                                String* name) {
170   Isolate* isolate = name->GetIsolate();
171   // To accommodate both the old and the new api we switch on the
172   // data structure used to store the callbacks.  Eventually foreign
173   // callbacks should be phased out.
174   if (structure->IsForeign()) {
175     AccessorDescriptor* callback =
176         reinterpret_cast<AccessorDescriptor*>(
177             Foreign::cast(structure)->foreign_address());
178     MaybeObject* value = (callback->getter)(receiver, callback->data);
179     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
180     return value;
181   }
182
183   // api style callbacks.
184   if (structure->IsAccessorInfo()) {
185     AccessorInfo* data = AccessorInfo::cast(structure);
186     Object* fun_obj = data->getter();
187     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
188     HandleScope scope(isolate);
189     JSObject* self = JSObject::cast(receiver);
190     Handle<String> key(name);
191     LOG(isolate, ApiNamedPropertyAccess("load", self, name));
192     CustomArguments args(isolate, data->data(), self, this);
193     v8::AccessorInfo info(args.end());
194     v8::Handle<v8::Value> result;
195     {
196       // Leaving JavaScript.
197       VMState state(isolate, EXTERNAL);
198       result = call_fun(v8::Utils::ToLocal(key), info);
199     }
200     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
201     if (result.IsEmpty()) {
202       return isolate->heap()->undefined_value();
203     }
204     return *v8::Utils::OpenHandle(*result);
205   }
206
207   // __defineGetter__ callback
208   if (structure->IsAccessorPair()) {
209     Object* getter = AccessorPair::cast(structure)->getter();
210     if (getter->IsSpecFunction()) {
211       // TODO(rossberg): nicer would be to cast to some JSCallable here...
212       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
213     }
214     // Getter is not a function.
215     return isolate->heap()->undefined_value();
216   }
217
218   UNREACHABLE();
219   return NULL;
220 }
221
222
223 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
224                                              String* name_raw) {
225   Isolate* isolate = GetIsolate();
226   HandleScope scope(isolate);
227   Handle<Object> receiver(receiver_raw);
228   Handle<Object> name(name_raw);
229
230   Handle<Object> args[] = { receiver, name };
231   Handle<Object> result = CallTrap(
232     "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
233   if (isolate->has_pending_exception()) return Failure::Exception();
234
235   return *result;
236 }
237
238
239 Handle<Object> Object::GetElement(Handle<Object> object, uint32_t index) {
240   Isolate* isolate = object->IsHeapObject()
241       ? Handle<HeapObject>::cast(object)->GetIsolate()
242       : Isolate::Current();
243   CALL_HEAP_FUNCTION(isolate, object->GetElement(index), Object);
244 }
245
246
247 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
248                                             uint32_t index) {
249   String* name;
250   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
251   if (!maybe->To<String>(&name)) return maybe;
252   return GetPropertyWithHandler(receiver, name);
253 }
254
255
256 MaybeObject* JSProxy::SetElementWithHandler(uint32_t index,
257                                             Object* value,
258                                             StrictModeFlag strict_mode) {
259   String* name;
260   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
261   if (!maybe->To<String>(&name)) return maybe;
262   return SetPropertyWithHandler(name, value, NONE, strict_mode);
263 }
264
265
266 bool JSProxy::HasElementWithHandler(uint32_t index) {
267   String* name;
268   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
269   if (!maybe->To<String>(&name)) return maybe;
270   return HasPropertyWithHandler(name);
271 }
272
273
274 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver,
275                                                   JSReceiver* getter) {
276   HandleScope scope;
277   Handle<JSReceiver> fun(getter);
278   Handle<Object> self(receiver);
279 #ifdef ENABLE_DEBUGGER_SUPPORT
280   Debug* debug = fun->GetHeap()->isolate()->debug();
281   // Handle stepping into a getter if step into is active.
282   // TODO(rossberg): should this apply to getters that are function proxies?
283   if (debug->StepInActive() && fun->IsJSFunction()) {
284     debug->HandleStepIn(
285         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
286   }
287 #endif
288
289   bool has_pending_exception;
290   Handle<Object> result =
291       Execution::Call(fun, self, 0, NULL, &has_pending_exception, true);
292   // Check for pending exception and return the result.
293   if (has_pending_exception) return Failure::Exception();
294   return *result;
295 }
296
297
298 // Only deal with CALLBACKS and INTERCEPTOR
299 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck(
300     Object* receiver,
301     LookupResult* result,
302     String* name,
303     PropertyAttributes* attributes) {
304   if (result->IsProperty()) {
305     switch (result->type()) {
306       case CALLBACKS: {
307         // Only allow API accessors.
308         Object* obj = result->GetCallbackObject();
309         if (obj->IsAccessorInfo()) {
310           AccessorInfo* info = AccessorInfo::cast(obj);
311           if (info->all_can_read()) {
312             *attributes = result->GetAttributes();
313             return result->holder()->GetPropertyWithCallback(
314                 receiver, result->GetCallbackObject(), name);
315           }
316         }
317         break;
318       }
319       case NORMAL:
320       case FIELD:
321       case CONSTANT_FUNCTION: {
322         // Search ALL_CAN_READ accessors in prototype chain.
323         LookupResult r(GetIsolate());
324         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
325         if (r.IsProperty()) {
326           return GetPropertyWithFailedAccessCheck(receiver,
327                                                   &r,
328                                                   name,
329                                                   attributes);
330         }
331         break;
332       }
333       case INTERCEPTOR: {
334         // If the object has an interceptor, try real named properties.
335         // No access check in GetPropertyAttributeWithInterceptor.
336         LookupResult r(GetIsolate());
337         result->holder()->LookupRealNamedProperty(name, &r);
338         if (r.IsProperty()) {
339           return GetPropertyWithFailedAccessCheck(receiver,
340                                                   &r,
341                                                   name,
342                                                   attributes);
343         }
344         break;
345       }
346       default:
347         UNREACHABLE();
348     }
349   }
350
351   // No accessible property found.
352   *attributes = ABSENT;
353   Heap* heap = name->GetHeap();
354   heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET);
355   return heap->undefined_value();
356 }
357
358
359 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
360     Object* receiver,
361     LookupResult* result,
362     String* name,
363     bool continue_search) {
364   if (result->IsProperty()) {
365     switch (result->type()) {
366       case CALLBACKS: {
367         // Only allow API accessors.
368         Object* obj = result->GetCallbackObject();
369         if (obj->IsAccessorInfo()) {
370           AccessorInfo* info = AccessorInfo::cast(obj);
371           if (info->all_can_read()) {
372             return result->GetAttributes();
373           }
374         }
375         break;
376       }
377
378       case NORMAL:
379       case FIELD:
380       case CONSTANT_FUNCTION: {
381         if (!continue_search) break;
382         // Search ALL_CAN_READ accessors in prototype chain.
383         LookupResult r(GetIsolate());
384         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
385         if (r.IsProperty()) {
386           return GetPropertyAttributeWithFailedAccessCheck(receiver,
387                                                            &r,
388                                                            name,
389                                                            continue_search);
390         }
391         break;
392       }
393
394       case INTERCEPTOR: {
395         // If the object has an interceptor, try real named properties.
396         // No access check in GetPropertyAttributeWithInterceptor.
397         LookupResult r(GetIsolate());
398         if (continue_search) {
399           result->holder()->LookupRealNamedProperty(name, &r);
400         } else {
401           result->holder()->LocalLookupRealNamedProperty(name, &r);
402         }
403         if (r.IsProperty()) {
404           return GetPropertyAttributeWithFailedAccessCheck(receiver,
405                                                            &r,
406                                                            name,
407                                                            continue_search);
408         }
409         break;
410       }
411
412       default:
413         UNREACHABLE();
414     }
415   }
416
417   GetIsolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
418   return ABSENT;
419 }
420
421
422 Object* JSObject::GetNormalizedProperty(LookupResult* result) {
423   ASSERT(!HasFastProperties());
424   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
425   if (IsGlobalObject()) {
426     value = JSGlobalPropertyCell::cast(value)->value();
427   }
428   ASSERT(!value->IsJSGlobalPropertyCell());
429   return value;
430 }
431
432
433 Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
434   ASSERT(!HasFastProperties());
435   if (IsGlobalObject()) {
436     JSGlobalPropertyCell* cell =
437         JSGlobalPropertyCell::cast(
438             property_dictionary()->ValueAt(result->GetDictionaryEntry()));
439     cell->set_value(value);
440   } else {
441     property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
442   }
443   return value;
444 }
445
446
447 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object,
448                                                Handle<String> key,
449                                                Handle<Object> value,
450                                                PropertyDetails details) {
451   CALL_HEAP_FUNCTION(object->GetIsolate(),
452                      object->SetNormalizedProperty(*key, *value, details),
453                      Object);
454 }
455
456
457 MaybeObject* JSObject::SetNormalizedProperty(String* name,
458                                              Object* value,
459                                              PropertyDetails details) {
460   ASSERT(!HasFastProperties());
461   int entry = property_dictionary()->FindEntry(name);
462   if (entry == StringDictionary::kNotFound) {
463     Object* store_value = value;
464     if (IsGlobalObject()) {
465       Heap* heap = name->GetHeap();
466       MaybeObject* maybe_store_value =
467           heap->AllocateJSGlobalPropertyCell(value);
468       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
469     }
470     Object* dict;
471     { MaybeObject* maybe_dict =
472           property_dictionary()->Add(name, store_value, details);
473       if (!maybe_dict->ToObject(&dict)) return maybe_dict;
474     }
475     set_properties(StringDictionary::cast(dict));
476     return value;
477   }
478   // Preserve enumeration index.
479   details = PropertyDetails(details.attributes(),
480                             details.type(),
481                             property_dictionary()->DetailsAt(entry).index());
482   if (IsGlobalObject()) {
483     JSGlobalPropertyCell* cell =
484         JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
485     cell->set_value(value);
486     // Please note we have to update the property details.
487     property_dictionary()->DetailsAtPut(entry, details);
488   } else {
489     property_dictionary()->SetEntry(entry, name, value, details);
490   }
491   return value;
492 }
493
494
495 MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
496   ASSERT(!HasFastProperties());
497   StringDictionary* dictionary = property_dictionary();
498   int entry = dictionary->FindEntry(name);
499   if (entry != StringDictionary::kNotFound) {
500     // If we have a global object set the cell to the hole.
501     if (IsGlobalObject()) {
502       PropertyDetails details = dictionary->DetailsAt(entry);
503       if (details.IsDontDelete()) {
504         if (mode != FORCE_DELETION) return GetHeap()->false_value();
505         // When forced to delete global properties, we have to make a
506         // map change to invalidate any ICs that think they can load
507         // from the DontDelete cell without checking if it contains
508         // the hole value.
509         Object* new_map;
510         { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
511           if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
512         }
513         set_map(Map::cast(new_map));
514       }
515       JSGlobalPropertyCell* cell =
516           JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
517       cell->set_value(cell->GetHeap()->the_hole_value());
518       dictionary->DetailsAtPut(entry, details.AsDeleted());
519     } else {
520       Object* deleted = dictionary->DeleteProperty(entry, mode);
521       if (deleted == GetHeap()->true_value()) {
522         FixedArray* new_properties = NULL;
523         MaybeObject* maybe_properties = dictionary->Shrink(name);
524         if (!maybe_properties->To(&new_properties)) {
525           return maybe_properties;
526         }
527         set_properties(new_properties);
528       }
529       return deleted;
530     }
531   }
532   return GetHeap()->true_value();
533 }
534
535
536 bool JSObject::IsDirty() {
537   Object* cons_obj = map()->constructor();
538   if (!cons_obj->IsJSFunction())
539     return true;
540   JSFunction* fun = JSFunction::cast(cons_obj);
541   if (!fun->shared()->IsApiFunction())
542     return true;
543   // If the object is fully fast case and has the same map it was
544   // created with then no changes can have been made to it.
545   return map() != fun->initial_map()
546       || !HasFastElements()
547       || !HasFastProperties();
548 }
549
550
551 Handle<Object> Object::GetProperty(Handle<Object> object,
552                                    Handle<Object> receiver,
553                                    LookupResult* result,
554                                    Handle<String> key,
555                                    PropertyAttributes* attributes) {
556   Isolate* isolate = object->IsHeapObject()
557       ? Handle<HeapObject>::cast(object)->GetIsolate()
558       : Isolate::Current();
559   CALL_HEAP_FUNCTION(
560       isolate,
561       object->GetProperty(*receiver, result, *key, attributes),
562       Object);
563 }
564
565
566 MaybeObject* Object::GetProperty(Object* receiver,
567                                  LookupResult* result,
568                                  String* name,
569                                  PropertyAttributes* attributes) {
570   // Make sure that the top context does not change when doing
571   // callbacks or interceptor calls.
572   AssertNoContextChange ncc;
573   Heap* heap = name->GetHeap();
574
575   // Traverse the prototype chain from the current object (this) to
576   // the holder and check for access rights. This avoids traversing the
577   // objects more than once in case of interceptors, because the
578   // holder will always be the interceptor holder and the search may
579   // only continue with a current object just after the interceptor
580   // holder in the prototype chain.
581   // Proxy handlers do not use the proxy's prototype, so we can skip this.
582   if (!result->IsHandler()) {
583     Object* last = result->IsProperty()
584         ? result->holder()
585         : Object::cast(heap->null_value());
586     ASSERT(this != this->GetPrototype());
587     for (Object* current = this; true; current = current->GetPrototype()) {
588       if (current->IsAccessCheckNeeded()) {
589         // Check if we're allowed to read from the current object. Note
590         // that even though we may not actually end up loading the named
591         // property from the current object, we still check that we have
592         // access to it.
593         JSObject* checked = JSObject::cast(current);
594         if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
595           return checked->GetPropertyWithFailedAccessCheck(receiver,
596                                                            result,
597                                                            name,
598                                                            attributes);
599         }
600       }
601       // Stop traversing the chain once we reach the last object in the
602       // chain; either the holder of the result or null in case of an
603       // absent property.
604       if (current == last) break;
605     }
606   }
607
608   if (!result->IsProperty()) {
609     *attributes = ABSENT;
610     return heap->undefined_value();
611   }
612   *attributes = result->GetAttributes();
613   Object* value;
614   switch (result->type()) {
615     case NORMAL:
616       value = result->holder()->GetNormalizedProperty(result);
617       ASSERT(!value->IsTheHole() || result->IsReadOnly());
618       return value->IsTheHole() ? heap->undefined_value() : value;
619     case FIELD:
620       value = result->holder()->FastPropertyAt(result->GetFieldIndex());
621       ASSERT(!value->IsTheHole() || result->IsReadOnly());
622       return value->IsTheHole() ? heap->undefined_value() : value;
623     case CONSTANT_FUNCTION:
624       return result->GetConstantFunction();
625     case CALLBACKS:
626       return result->holder()->GetPropertyWithCallback(
627           receiver, result->GetCallbackObject(), name);
628     case HANDLER:
629       return result->proxy()->GetPropertyWithHandler(receiver, name);
630     case INTERCEPTOR: {
631       JSObject* recvr = JSObject::cast(receiver);
632       return result->holder()->GetPropertyWithInterceptor(
633           recvr, name, attributes);
634     }
635     case MAP_TRANSITION:
636     case ELEMENTS_TRANSITION:
637     case CONSTANT_TRANSITION:
638     case NULL_DESCRIPTOR:
639       break;
640   }
641   UNREACHABLE();
642   return NULL;
643 }
644
645
646 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
647   Heap* heap = IsSmi()
648       ? Isolate::Current()->heap()
649       : HeapObject::cast(this)->GetHeap();
650   Object* holder = this;
651
652   // Iterate up the prototype chain until an element is found or the null
653   // prototype is encountered.
654   for (holder = this;
655        holder != heap->null_value();
656        holder = holder->GetPrototype()) {
657     if (!holder->IsJSObject()) {
658       Isolate* isolate = heap->isolate();
659       Context* global_context = isolate->context()->global_context();
660       if (holder->IsNumber()) {
661         holder = global_context->number_function()->instance_prototype();
662       } else if (holder->IsString()) {
663         holder = global_context->string_function()->instance_prototype();
664       } else if (holder->IsBoolean()) {
665         holder = global_context->boolean_function()->instance_prototype();
666       } else if (holder->IsJSProxy()) {
667         return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
668       } else {
669         // Undefined and null have no indexed properties.
670         ASSERT(holder->IsUndefined() || holder->IsNull());
671         return heap->undefined_value();
672       }
673     }
674
675     // Inline the case for JSObjects. Doing so significantly improves the
676     // performance of fetching elements where checking the prototype chain is
677     // necessary.
678     JSObject* js_object = JSObject::cast(holder);
679
680     // Check access rights if needed.
681     if (js_object->IsAccessCheckNeeded()) {
682       Isolate* isolate = heap->isolate();
683       if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
684         isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
685         return heap->undefined_value();
686       }
687     }
688
689     if (js_object->HasIndexedInterceptor()) {
690       return js_object->GetElementWithInterceptor(receiver, index);
691     }
692
693     if (js_object->elements() != heap->empty_fixed_array()) {
694       MaybeObject* result = js_object->GetElementsAccessor()->Get(
695           receiver, js_object, index);
696       if (result != heap->the_hole_value()) return result;
697     }
698   }
699
700   return heap->undefined_value();
701 }
702
703
704 Object* Object::GetPrototype() {
705   if (IsSmi()) {
706     Heap* heap = Isolate::Current()->heap();
707     Context* context = heap->isolate()->context()->global_context();
708     return context->number_function()->instance_prototype();
709   }
710
711   HeapObject* heap_object = HeapObject::cast(this);
712
713   // The object is either a number, a string, a boolean,
714   // a real JS object, or a Harmony proxy.
715   if (heap_object->IsJSReceiver()) {
716     return heap_object->map()->prototype();
717   }
718   Heap* heap = heap_object->GetHeap();
719   Context* context = heap->isolate()->context()->global_context();
720
721   if (heap_object->IsHeapNumber()) {
722     return context->number_function()->instance_prototype();
723   }
724   if (heap_object->IsString()) {
725     return context->string_function()->instance_prototype();
726   }
727   if (heap_object->IsBoolean()) {
728     return context->boolean_function()->instance_prototype();
729   } else {
730     return heap->null_value();
731   }
732 }
733
734
735 MaybeObject* Object::GetHash(CreationFlag flag) {
736   // The object is either a number, a string, an odd-ball,
737   // a real JS object, or a Harmony proxy.
738   if (IsNumber()) {
739     uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
740     return Smi::FromInt(hash & Smi::kMaxValue);
741   }
742   if (IsString()) {
743     uint32_t hash = String::cast(this)->Hash();
744     return Smi::FromInt(hash);
745   }
746   if (IsOddball()) {
747     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
748     return Smi::FromInt(hash);
749   }
750   if (IsJSReceiver()) {
751     return JSReceiver::cast(this)->GetIdentityHash(flag);
752   }
753
754   UNREACHABLE();
755   return Smi::FromInt(0);
756 }
757
758
759 bool Object::SameValue(Object* other) {
760   if (other == this) return true;
761   if (!IsHeapObject() || !other->IsHeapObject()) return false;
762
763   // The object is either a number, a string, an odd-ball,
764   // a real JS object, or a Harmony proxy.
765   if (IsNumber() && other->IsNumber()) {
766     double this_value = Number();
767     double other_value = other->Number();
768     return (this_value == other_value) ||
769         (isnan(this_value) && isnan(other_value));
770   }
771   if (IsString() && other->IsString()) {
772     return String::cast(this)->Equals(String::cast(other));
773   }
774   return false;
775 }
776
777
778 void Object::ShortPrint(FILE* out) {
779   HeapStringAllocator allocator;
780   StringStream accumulator(&allocator);
781   ShortPrint(&accumulator);
782   accumulator.OutputToFile(out);
783 }
784
785
786 void Object::ShortPrint(StringStream* accumulator) {
787   if (IsSmi()) {
788     Smi::cast(this)->SmiPrint(accumulator);
789   } else if (IsFailure()) {
790     Failure::cast(this)->FailurePrint(accumulator);
791   } else {
792     HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
793   }
794 }
795
796
797 void Smi::SmiPrint(FILE* out) {
798   PrintF(out, "%d", value());
799 }
800
801
802 void Smi::SmiPrint(StringStream* accumulator) {
803   accumulator->Add("%d", value());
804 }
805
806
807 void Failure::FailurePrint(StringStream* accumulator) {
808   accumulator->Add("Failure(%p)", reinterpret_cast<void*>(value()));
809 }
810
811
812 void Failure::FailurePrint(FILE* out) {
813   PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
814 }
815
816
817 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
818 // English?  Returns false for non-ASCII or words that don't start with
819 // a capital letter.  The a/an rule follows pronunciation in English.
820 // We don't use the BBC's overcorrect "an historic occasion" though if
821 // you speak a dialect you may well say "an 'istoric occasion".
822 static bool AnWord(String* str) {
823   if (str->length() == 0) return false;  // A nothing.
824   int c0 = str->Get(0);
825   int c1 = str->length() > 1 ? str->Get(1) : 0;
826   if (c0 == 'U') {
827     if (c1 > 'Z') {
828       return true;  // An Umpire, but a UTF8String, a U.
829     }
830   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
831     return true;    // An Ape, an ABCBook.
832   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
833            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
834             c0 == 'S' || c0 == 'X')) {
835     return true;    // An MP3File, an M.
836   }
837   return false;
838 }
839
840
841 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
842 #ifdef DEBUG
843   // Do not attempt to flatten in debug mode when allocation is not
844   // allowed.  This is to avoid an assertion failure when allocating.
845   // Flattening strings is the only case where we always allow
846   // allocation because no GC is performed if the allocation fails.
847   if (!HEAP->IsAllocationAllowed()) return this;
848 #endif
849
850   Heap* heap = GetHeap();
851   switch (StringShape(this).representation_tag()) {
852     case kConsStringTag: {
853       ConsString* cs = ConsString::cast(this);
854       if (cs->second()->length() == 0) {
855         return cs->first();
856       }
857       // There's little point in putting the flat string in new space if the
858       // cons string is in old space.  It can never get GCed until there is
859       // an old space GC.
860       PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
861       int len = length();
862       Object* object;
863       String* result;
864       if (IsAsciiRepresentation()) {
865         { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure);
866           if (!maybe_object->ToObject(&object)) return maybe_object;
867         }
868         result = String::cast(object);
869         String* first = cs->first();
870         int first_length = first->length();
871         char* dest = SeqAsciiString::cast(result)->GetChars();
872         WriteToFlat(first, dest, 0, first_length);
873         String* second = cs->second();
874         WriteToFlat(second,
875                     dest + first_length,
876                     0,
877                     len - first_length);
878       } else {
879         { MaybeObject* maybe_object =
880               heap->AllocateRawTwoByteString(len, tenure);
881           if (!maybe_object->ToObject(&object)) return maybe_object;
882         }
883         result = String::cast(object);
884         uc16* dest = SeqTwoByteString::cast(result)->GetChars();
885         String* first = cs->first();
886         int first_length = first->length();
887         WriteToFlat(first, dest, 0, first_length);
888         String* second = cs->second();
889         WriteToFlat(second,
890                     dest + first_length,
891                     0,
892                     len - first_length);
893       }
894       cs->set_first(result);
895       cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
896       return result;
897     }
898     default:
899       return this;
900   }
901 }
902
903
904 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
905   // Externalizing twice leaks the external resource, so it's
906   // prohibited by the API.
907   ASSERT(!this->IsExternalString());
908 #ifdef DEBUG
909   if (FLAG_enable_slow_asserts) {
910     // Assert that the resource and the string are equivalent.
911     ASSERT(static_cast<size_t>(this->length()) == resource->length());
912     ScopedVector<uc16> smart_chars(this->length());
913     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
914     ASSERT(memcmp(smart_chars.start(),
915                   resource->data(),
916                   resource->length() * sizeof(smart_chars[0])) == 0);
917   }
918 #endif  // DEBUG
919   Heap* heap = GetHeap();
920   int size = this->Size();  // Byte size of the original string.
921   if (size < ExternalString::kShortSize) {
922     return false;
923   }
924   bool is_ascii = this->IsAsciiRepresentation();
925   bool is_symbol = this->IsSymbol();
926
927   // Morph the object to an external string by adjusting the map and
928   // reinitializing the fields.
929   if (size >= ExternalString::kSize) {
930     this->set_map_no_write_barrier(
931         is_symbol
932             ? (is_ascii ?  heap->external_symbol_with_ascii_data_map()
933                         :  heap->external_symbol_map())
934             : (is_ascii ?  heap->external_string_with_ascii_data_map()
935                         :  heap->external_string_map()));
936   } else {
937     this->set_map_no_write_barrier(
938         is_symbol
939             ? (is_ascii ?  heap->short_external_symbol_with_ascii_data_map()
940                         :  heap->short_external_symbol_map())
941             : (is_ascii ?  heap->short_external_string_with_ascii_data_map()
942                         :  heap->short_external_string_map()));
943   }
944   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
945   self->set_resource(resource);
946   if (is_symbol) self->Hash();  // Force regeneration of the hash value.
947
948   // Fill the remainder of the string with dead wood.
949   int new_size = this->Size();  // Byte size of the external String object.
950   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
951   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
952     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
953                                                new_size - size);
954   }
955   return true;
956 }
957
958
959 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
960 #ifdef DEBUG
961   if (FLAG_enable_slow_asserts) {
962     // Assert that the resource and the string are equivalent.
963     ASSERT(static_cast<size_t>(this->length()) == resource->length());
964     ScopedVector<char> smart_chars(this->length());
965     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
966     ASSERT(memcmp(smart_chars.start(),
967                   resource->data(),
968                   resource->length() * sizeof(smart_chars[0])) == 0);
969   }
970 #endif  // DEBUG
971   Heap* heap = GetHeap();
972   int size = this->Size();  // Byte size of the original string.
973   if (size < ExternalString::kShortSize) {
974     return false;
975   }
976   bool is_symbol = this->IsSymbol();
977
978   // Morph the object to an external string by adjusting the map and
979   // reinitializing the fields.  Use short version if space is limited.
980   if (size >= ExternalString::kSize) {
981     this->set_map_no_write_barrier(
982         is_symbol ? heap->external_ascii_symbol_map()
983                   : heap->external_ascii_string_map());
984   } else {
985     this->set_map_no_write_barrier(
986         is_symbol ? heap->short_external_ascii_symbol_map()
987                   : heap->short_external_ascii_string_map());
988   }
989   ExternalAsciiString* self = ExternalAsciiString::cast(this);
990   self->set_resource(resource);
991   if (is_symbol) self->Hash();  // Force regeneration of the hash value.
992
993   // Fill the remainder of the string with dead wood.
994   int new_size = this->Size();  // Byte size of the external String object.
995   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
996   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
997     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
998                                                new_size - size);
999   }
1000   return true;
1001 }
1002
1003
1004 void String::StringShortPrint(StringStream* accumulator) {
1005   int len = length();
1006   if (len > kMaxShortPrintLength) {
1007     accumulator->Add("<Very long string[%u]>", len);
1008     return;
1009   }
1010
1011   if (!LooksValid()) {
1012     accumulator->Add("<Invalid String>");
1013     return;
1014   }
1015
1016   StringInputBuffer buf(this);
1017
1018   bool truncated = false;
1019   if (len > kMaxShortPrintLength) {
1020     len = kMaxShortPrintLength;
1021     truncated = true;
1022   }
1023   bool ascii = true;
1024   for (int i = 0; i < len; i++) {
1025     int c = buf.GetNext();
1026
1027     if (c < 32 || c >= 127) {
1028       ascii = false;
1029     }
1030   }
1031   buf.Reset(this);
1032   if (ascii) {
1033     accumulator->Add("<String[%u]: ", length());
1034     for (int i = 0; i < len; i++) {
1035       accumulator->Put(buf.GetNext());
1036     }
1037     accumulator->Put('>');
1038   } else {
1039     // Backslash indicates that the string contains control
1040     // characters and that backslashes are therefore escaped.
1041     accumulator->Add("<String[%u]\\: ", length());
1042     for (int i = 0; i < len; i++) {
1043       int c = buf.GetNext();
1044       if (c == '\n') {
1045         accumulator->Add("\\n");
1046       } else if (c == '\r') {
1047         accumulator->Add("\\r");
1048       } else if (c == '\\') {
1049         accumulator->Add("\\\\");
1050       } else if (c < 32 || c > 126) {
1051         accumulator->Add("\\x%02x", c);
1052       } else {
1053         accumulator->Put(c);
1054       }
1055     }
1056     if (truncated) {
1057       accumulator->Put('.');
1058       accumulator->Put('.');
1059       accumulator->Put('.');
1060     }
1061     accumulator->Put('>');
1062   }
1063   return;
1064 }
1065
1066
1067 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1068   switch (map()->instance_type()) {
1069     case JS_ARRAY_TYPE: {
1070       double length = JSArray::cast(this)->length()->Number();
1071       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1072       break;
1073     }
1074     case JS_WEAK_MAP_TYPE: {
1075       accumulator->Add("<JS WeakMap>");
1076       break;
1077     }
1078     case JS_REGEXP_TYPE: {
1079       accumulator->Add("<JS RegExp>");
1080       break;
1081     }
1082     case JS_FUNCTION_TYPE: {
1083       Object* fun_name = JSFunction::cast(this)->shared()->name();
1084       bool printed = false;
1085       if (fun_name->IsString()) {
1086         String* str = String::cast(fun_name);
1087         if (str->length() > 0) {
1088           accumulator->Add("<JS Function ");
1089           accumulator->Put(str);
1090           accumulator->Put('>');
1091           printed = true;
1092         }
1093       }
1094       if (!printed) {
1095         accumulator->Add("<JS Function>");
1096       }
1097       break;
1098     }
1099     // All other JSObjects are rather similar to each other (JSObject,
1100     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1101     default: {
1102       Map* map_of_this = map();
1103       Heap* heap = GetHeap();
1104       Object* constructor = map_of_this->constructor();
1105       bool printed = false;
1106       if (constructor->IsHeapObject() &&
1107           !heap->Contains(HeapObject::cast(constructor))) {
1108         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1109       } else {
1110         bool global_object = IsJSGlobalProxy();
1111         if (constructor->IsJSFunction()) {
1112           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1113             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1114           } else {
1115             Object* constructor_name =
1116                 JSFunction::cast(constructor)->shared()->name();
1117             if (constructor_name->IsString()) {
1118               String* str = String::cast(constructor_name);
1119               if (str->length() > 0) {
1120                 bool vowel = AnWord(str);
1121                 accumulator->Add("<%sa%s ",
1122                        global_object ? "Global Object: " : "",
1123                        vowel ? "n" : "");
1124                 accumulator->Put(str);
1125                 printed = true;
1126               }
1127             }
1128           }
1129         }
1130         if (!printed) {
1131           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1132         }
1133       }
1134       if (IsJSValue()) {
1135         accumulator->Add(" value = ");
1136         JSValue::cast(this)->value()->ShortPrint(accumulator);
1137       }
1138       accumulator->Put('>');
1139       break;
1140     }
1141   }
1142 }
1143
1144
1145 void JSObject::PrintElementsTransition(
1146     FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
1147     ElementsKind to_kind, FixedArrayBase* to_elements) {
1148   if (from_kind != to_kind) {
1149     PrintF(file, "elements transition [");
1150     PrintElementsKind(file, from_kind);
1151     PrintF(file, " -> ");
1152     PrintElementsKind(file, to_kind);
1153     PrintF(file, "] in ");
1154     JavaScriptFrame::PrintTop(file, false, true);
1155     PrintF(file, " for ");
1156     ShortPrint(file);
1157     PrintF(file, " from ");
1158     from_elements->ShortPrint(file);
1159     PrintF(file, " to ");
1160     to_elements->ShortPrint(file);
1161     PrintF(file, "\n");
1162   }
1163 }
1164
1165
1166 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
1167   Heap* heap = GetHeap();
1168   if (!heap->Contains(this)) {
1169     accumulator->Add("!!!INVALID POINTER!!!");
1170     return;
1171   }
1172   if (!heap->Contains(map())) {
1173     accumulator->Add("!!!INVALID MAP!!!");
1174     return;
1175   }
1176
1177   accumulator->Add("%p ", this);
1178
1179   if (IsString()) {
1180     String::cast(this)->StringShortPrint(accumulator);
1181     return;
1182   }
1183   if (IsJSObject()) {
1184     JSObject::cast(this)->JSObjectShortPrint(accumulator);
1185     return;
1186   }
1187   switch (map()->instance_type()) {
1188     case MAP_TYPE:
1189       accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind());
1190       break;
1191     case FIXED_ARRAY_TYPE:
1192       accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
1193       break;
1194     case FIXED_DOUBLE_ARRAY_TYPE:
1195       accumulator->Add("<FixedDoubleArray[%u]>",
1196                        FixedDoubleArray::cast(this)->length());
1197       break;
1198     case BYTE_ARRAY_TYPE:
1199       accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
1200       break;
1201     case FREE_SPACE_TYPE:
1202       accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size());
1203       break;
1204     case EXTERNAL_PIXEL_ARRAY_TYPE:
1205       accumulator->Add("<ExternalPixelArray[%u]>",
1206                        ExternalPixelArray::cast(this)->length());
1207       break;
1208     case EXTERNAL_BYTE_ARRAY_TYPE:
1209       accumulator->Add("<ExternalByteArray[%u]>",
1210                        ExternalByteArray::cast(this)->length());
1211       break;
1212     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1213       accumulator->Add("<ExternalUnsignedByteArray[%u]>",
1214                        ExternalUnsignedByteArray::cast(this)->length());
1215       break;
1216     case EXTERNAL_SHORT_ARRAY_TYPE:
1217       accumulator->Add("<ExternalShortArray[%u]>",
1218                        ExternalShortArray::cast(this)->length());
1219       break;
1220     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1221       accumulator->Add("<ExternalUnsignedShortArray[%u]>",
1222                        ExternalUnsignedShortArray::cast(this)->length());
1223       break;
1224     case EXTERNAL_INT_ARRAY_TYPE:
1225       accumulator->Add("<ExternalIntArray[%u]>",
1226                        ExternalIntArray::cast(this)->length());
1227       break;
1228     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1229       accumulator->Add("<ExternalUnsignedIntArray[%u]>",
1230                        ExternalUnsignedIntArray::cast(this)->length());
1231       break;
1232     case EXTERNAL_FLOAT_ARRAY_TYPE:
1233       accumulator->Add("<ExternalFloatArray[%u]>",
1234                        ExternalFloatArray::cast(this)->length());
1235       break;
1236     case EXTERNAL_DOUBLE_ARRAY_TYPE:
1237       accumulator->Add("<ExternalDoubleArray[%u]>",
1238                        ExternalDoubleArray::cast(this)->length());
1239       break;
1240     case SHARED_FUNCTION_INFO_TYPE:
1241       accumulator->Add("<SharedFunctionInfo>");
1242       break;
1243     case JS_MESSAGE_OBJECT_TYPE:
1244       accumulator->Add("<JSMessageObject>");
1245       break;
1246 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1247   case NAME##_TYPE:                        \
1248     accumulator->Put('<');                 \
1249     accumulator->Add(#Name);               \
1250     accumulator->Put('>');                 \
1251     break;
1252   STRUCT_LIST(MAKE_STRUCT_CASE)
1253 #undef MAKE_STRUCT_CASE
1254     case CODE_TYPE:
1255       accumulator->Add("<Code>");
1256       break;
1257     case ODDBALL_TYPE: {
1258       if (IsUndefined())
1259         accumulator->Add("<undefined>");
1260       else if (IsTheHole())
1261         accumulator->Add("<the hole>");
1262       else if (IsNull())
1263         accumulator->Add("<null>");
1264       else if (IsTrue())
1265         accumulator->Add("<true>");
1266       else if (IsFalse())
1267         accumulator->Add("<false>");
1268       else
1269         accumulator->Add("<Odd Oddball>");
1270       break;
1271     }
1272     case HEAP_NUMBER_TYPE:
1273       accumulator->Add("<Number: ");
1274       HeapNumber::cast(this)->HeapNumberPrint(accumulator);
1275       accumulator->Put('>');
1276       break;
1277     case JS_PROXY_TYPE:
1278       accumulator->Add("<JSProxy>");
1279       break;
1280     case JS_FUNCTION_PROXY_TYPE:
1281       accumulator->Add("<JSFunctionProxy>");
1282       break;
1283     case FOREIGN_TYPE:
1284       accumulator->Add("<Foreign>");
1285       break;
1286     case JS_GLOBAL_PROPERTY_CELL_TYPE:
1287       accumulator->Add("Cell for ");
1288       JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
1289       break;
1290     default:
1291       accumulator->Add("<Other heap object (%d)>", map()->instance_type());
1292       break;
1293   }
1294 }
1295
1296
1297 void HeapObject::Iterate(ObjectVisitor* v) {
1298   // Handle header
1299   IteratePointer(v, kMapOffset);
1300   // Handle object body
1301   Map* m = map();
1302   IterateBody(m->instance_type(), SizeFromMap(m), v);
1303 }
1304
1305
1306 void HeapObject::IterateBody(InstanceType type, int object_size,
1307                              ObjectVisitor* v) {
1308   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1309   // During GC, the map pointer field is encoded.
1310   if (type < FIRST_NONSTRING_TYPE) {
1311     switch (type & kStringRepresentationMask) {
1312       case kSeqStringTag:
1313         break;
1314       case kConsStringTag:
1315         ConsString::BodyDescriptor::IterateBody(this, v);
1316         break;
1317       case kSlicedStringTag:
1318         SlicedString::BodyDescriptor::IterateBody(this, v);
1319         break;
1320       case kExternalStringTag:
1321         if ((type & kStringEncodingMask) == kAsciiStringTag) {
1322           reinterpret_cast<ExternalAsciiString*>(this)->
1323               ExternalAsciiStringIterateBody(v);
1324         } else {
1325           reinterpret_cast<ExternalTwoByteString*>(this)->
1326               ExternalTwoByteStringIterateBody(v);
1327         }
1328         break;
1329     }
1330     return;
1331   }
1332
1333   switch (type) {
1334     case FIXED_ARRAY_TYPE:
1335       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1336       break;
1337     case FIXED_DOUBLE_ARRAY_TYPE:
1338       break;
1339     case JS_OBJECT_TYPE:
1340     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1341     case JS_VALUE_TYPE:
1342     case JS_DATE_TYPE:
1343     case JS_ARRAY_TYPE:
1344     case JS_SET_TYPE:
1345     case JS_MAP_TYPE:
1346     case JS_WEAK_MAP_TYPE:
1347     case JS_REGEXP_TYPE:
1348     case JS_GLOBAL_PROXY_TYPE:
1349     case JS_GLOBAL_OBJECT_TYPE:
1350     case JS_BUILTINS_OBJECT_TYPE:
1351     case JS_MESSAGE_OBJECT_TYPE:
1352       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1353       break;
1354     case JS_FUNCTION_TYPE:
1355       reinterpret_cast<JSFunction*>(this)
1356           ->JSFunctionIterateBody(object_size, v);
1357       break;
1358     case ODDBALL_TYPE:
1359       Oddball::BodyDescriptor::IterateBody(this, v);
1360       break;
1361     case JS_PROXY_TYPE:
1362       JSProxy::BodyDescriptor::IterateBody(this, v);
1363       break;
1364     case JS_FUNCTION_PROXY_TYPE:
1365       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1366       break;
1367     case FOREIGN_TYPE:
1368       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1369       break;
1370     case MAP_TYPE:
1371       Map::BodyDescriptor::IterateBody(this, v);
1372       break;
1373     case CODE_TYPE:
1374       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1375       break;
1376     case JS_GLOBAL_PROPERTY_CELL_TYPE:
1377       JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v);
1378       break;
1379     case HEAP_NUMBER_TYPE:
1380     case FILLER_TYPE:
1381     case BYTE_ARRAY_TYPE:
1382     case FREE_SPACE_TYPE:
1383     case EXTERNAL_PIXEL_ARRAY_TYPE:
1384     case EXTERNAL_BYTE_ARRAY_TYPE:
1385     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1386     case EXTERNAL_SHORT_ARRAY_TYPE:
1387     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1388     case EXTERNAL_INT_ARRAY_TYPE:
1389     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1390     case EXTERNAL_FLOAT_ARRAY_TYPE:
1391     case EXTERNAL_DOUBLE_ARRAY_TYPE:
1392       break;
1393     case SHARED_FUNCTION_INFO_TYPE: {
1394       SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this);
1395       shared->SharedFunctionInfoIterateBody(v);
1396       break;
1397     }
1398
1399 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1400         case NAME##_TYPE:
1401       STRUCT_LIST(MAKE_STRUCT_CASE)
1402 #undef MAKE_STRUCT_CASE
1403       StructBodyDescriptor::IterateBody(this, object_size, v);
1404       break;
1405     default:
1406       PrintF("Unknown type: %d\n", type);
1407       UNREACHABLE();
1408   }
1409 }
1410
1411
1412 Object* HeapNumber::HeapNumberToBoolean() {
1413   // NaN, +0, and -0 should return the false object
1414 #if __BYTE_ORDER == __LITTLE_ENDIAN
1415   union IeeeDoubleLittleEndianArchType u;
1416 #elif __BYTE_ORDER == __BIG_ENDIAN
1417   union IeeeDoubleBigEndianArchType u;
1418 #endif
1419   u.d = value();
1420   if (u.bits.exp == 2047) {
1421     // Detect NaN for IEEE double precision floating point.
1422     if ((u.bits.man_low | u.bits.man_high) != 0)
1423       return GetHeap()->false_value();
1424   }
1425   if (u.bits.exp == 0) {
1426     // Detect +0, and -0 for IEEE double precision floating point.
1427     if ((u.bits.man_low | u.bits.man_high) == 0)
1428       return GetHeap()->false_value();
1429   }
1430   return GetHeap()->true_value();
1431 }
1432
1433
1434 void HeapNumber::HeapNumberPrint(FILE* out) {
1435   PrintF(out, "%.16g", Number());
1436 }
1437
1438
1439 void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
1440   // The Windows version of vsnprintf can allocate when printing a %g string
1441   // into a buffer that may not be big enough.  We don't want random memory
1442   // allocation when producing post-crash stack traces, so we print into a
1443   // buffer that is plenty big enough for any floating point number, then
1444   // print that using vsnprintf (which may truncate but never allocate if
1445   // there is no more space in the buffer).
1446   EmbeddedVector<char, 100> buffer;
1447   OS::SNPrintF(buffer, "%.16g", Number());
1448   accumulator->Add("%s", buffer.start());
1449 }
1450
1451
1452 String* JSReceiver::class_name() {
1453   if (IsJSFunction() && IsJSFunctionProxy()) {
1454     return GetHeap()->function_class_symbol();
1455   }
1456   if (map()->constructor()->IsJSFunction()) {
1457     JSFunction* constructor = JSFunction::cast(map()->constructor());
1458     return String::cast(constructor->shared()->instance_class_name());
1459   }
1460   // If the constructor is not present, return "Object".
1461   return GetHeap()->Object_symbol();
1462 }
1463
1464
1465 String* JSReceiver::constructor_name() {
1466   if (map()->constructor()->IsJSFunction()) {
1467     JSFunction* constructor = JSFunction::cast(map()->constructor());
1468     String* name = String::cast(constructor->shared()->name());
1469     if (name->length() > 0) return name;
1470     String* inferred_name = constructor->shared()->inferred_name();
1471     if (inferred_name->length() > 0) return inferred_name;
1472     Object* proto = GetPrototype();
1473     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1474   }
1475   // TODO(rossberg): what about proxies?
1476   // If the constructor is not present, return "Object".
1477   return GetHeap()->Object_symbol();
1478 }
1479
1480
1481 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
1482                                                String* name,
1483                                                Object* value) {
1484   int index = new_map->PropertyIndexFor(name);
1485   if (map()->unused_property_fields() == 0) {
1486     ASSERT(map()->unused_property_fields() == 0);
1487     int new_unused = new_map->unused_property_fields();
1488     Object* values;
1489     { MaybeObject* maybe_values =
1490           properties()->CopySize(properties()->length() + new_unused + 1);
1491       if (!maybe_values->ToObject(&values)) return maybe_values;
1492     }
1493     set_properties(FixedArray::cast(values));
1494   }
1495   set_map(new_map);
1496   return FastPropertyAtPut(index, value);
1497 }
1498
1499
1500 static bool IsIdentifier(UnicodeCache* cache,
1501                          unibrow::CharacterStream* buffer) {
1502   // Checks whether the buffer contains an identifier (no escape).
1503   if (!buffer->has_more()) return false;
1504   if (!cache->IsIdentifierStart(buffer->GetNext())) {
1505     return false;
1506   }
1507   while (buffer->has_more()) {
1508     if (!cache->IsIdentifierPart(buffer->GetNext())) {
1509       return false;
1510     }
1511   }
1512   return true;
1513 }
1514
1515
1516 MaybeObject* JSObject::AddFastProperty(String* name,
1517                                        Object* value,
1518                                        PropertyAttributes attributes) {
1519   ASSERT(!IsJSGlobalProxy());
1520
1521   // Normalize the object if the name is an actual string (not the
1522   // hidden symbols) and is not a real identifier.
1523   Isolate* isolate = GetHeap()->isolate();
1524   StringInputBuffer buffer(name);
1525   if (!IsIdentifier(isolate->unicode_cache(), &buffer)
1526       && name != isolate->heap()->hidden_symbol()) {
1527     Object* obj;
1528     { MaybeObject* maybe_obj =
1529           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1530       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1531     }
1532     return AddSlowProperty(name, value, attributes);
1533   }
1534
1535   DescriptorArray* old_descriptors = map()->instance_descriptors();
1536   // Compute the new index for new field.
1537   int index = map()->NextFreePropertyIndex();
1538
1539   // Allocate new instance descriptors with (name, index) added
1540   FieldDescriptor new_field(name, index, attributes);
1541   Object* new_descriptors;
1542   { MaybeObject* maybe_new_descriptors =
1543         old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
1544     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1545       return maybe_new_descriptors;
1546     }
1547   }
1548
1549   // Only allow map transition if the object isn't the global object and there
1550   // is not a transition for the name, or there's a transition for the name but
1551   // it's unrelated to properties.
1552   int descriptor_index = old_descriptors->Search(name);
1553
1554   // Element transitions are stored in the descriptor for property "", which is
1555   // not a identifier and should have forced a switch to slow properties above.
1556   ASSERT(descriptor_index == DescriptorArray::kNotFound ||
1557       old_descriptors->GetType(descriptor_index) != ELEMENTS_TRANSITION);
1558   bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound ||
1559       old_descriptors->GetType(descriptor_index) == ELEMENTS_TRANSITION;
1560   bool allow_map_transition =
1561       can_insert_transition &&
1562       (isolate->context()->global_context()->object_function()->map() != map());
1563
1564   ASSERT(index < map()->inobject_properties() ||
1565          (index - map()->inobject_properties()) < properties()->length() ||
1566          map()->unused_property_fields() == 0);
1567   // Allocate a new map for the object.
1568   Object* r;
1569   { MaybeObject* maybe_r = map()->CopyDropDescriptors();
1570     if (!maybe_r->ToObject(&r)) return maybe_r;
1571   }
1572   Map* new_map = Map::cast(r);
1573   if (allow_map_transition) {
1574     // Allocate new instance descriptors for the old map with map transition.
1575     MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
1576     Object* r;
1577     { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
1578       if (!maybe_r->ToObject(&r)) return maybe_r;
1579     }
1580     old_descriptors = DescriptorArray::cast(r);
1581   }
1582
1583   if (map()->unused_property_fields() == 0) {
1584     if (properties()->length() > MaxFastProperties()) {
1585       Object* obj;
1586       { MaybeObject* maybe_obj =
1587             NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1588         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1589       }
1590       return AddSlowProperty(name, value, attributes);
1591     }
1592     // Make room for the new value
1593     Object* values;
1594     { MaybeObject* maybe_values =
1595           properties()->CopySize(properties()->length() + kFieldsAdded);
1596       if (!maybe_values->ToObject(&values)) return maybe_values;
1597     }
1598     set_properties(FixedArray::cast(values));
1599     new_map->set_unused_property_fields(kFieldsAdded - 1);
1600   } else {
1601     new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
1602   }
1603   // We have now allocated all the necessary objects.
1604   // All the changes can be applied at once, so they are atomic.
1605   map()->set_instance_descriptors(old_descriptors);
1606   new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1607   set_map(new_map);
1608   return FastPropertyAtPut(index, value);
1609 }
1610
1611
1612 MaybeObject* JSObject::AddConstantFunctionProperty(
1613     String* name,
1614     JSFunction* function,
1615     PropertyAttributes attributes) {
1616   // Allocate new instance descriptors with (name, function) added
1617   ConstantFunctionDescriptor d(name, function, attributes);
1618   Object* new_descriptors;
1619   { MaybeObject* maybe_new_descriptors =
1620         map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS);
1621     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1622       return maybe_new_descriptors;
1623     }
1624   }
1625
1626   // Allocate a new map for the object.
1627   Object* new_map;
1628   { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
1629     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1630   }
1631
1632   DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
1633   Map::cast(new_map)->set_instance_descriptors(descriptors);
1634   Map* old_map = map();
1635   set_map(Map::cast(new_map));
1636
1637   // If the old map is the global object map (from new Object()),
1638   // then transitions are not added to it, so we are done.
1639   Heap* heap = GetHeap();
1640   if (old_map == heap->isolate()->context()->global_context()->
1641       object_function()->map()) {
1642     return function;
1643   }
1644
1645   // Do not add CONSTANT_TRANSITIONS to global objects
1646   if (IsGlobalObject()) {
1647     return function;
1648   }
1649
1650   // Add a CONSTANT_TRANSITION descriptor to the old map,
1651   // so future assignments to this property on other objects
1652   // of the same type will create a normal field, not a constant function.
1653   // Don't do this for special properties, with non-trival attributes.
1654   if (attributes != NONE) {
1655     return function;
1656   }
1657   ConstTransitionDescriptor mark(name, Map::cast(new_map));
1658   { MaybeObject* maybe_new_descriptors =
1659         old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS);
1660     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1661       // We have accomplished the main goal, so return success.
1662       return function;
1663     }
1664   }
1665   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1666
1667   return function;
1668 }
1669
1670
1671 // Add property in slow mode
1672 MaybeObject* JSObject::AddSlowProperty(String* name,
1673                                        Object* value,
1674                                        PropertyAttributes attributes) {
1675   ASSERT(!HasFastProperties());
1676   StringDictionary* dict = property_dictionary();
1677   Object* store_value = value;
1678   if (IsGlobalObject()) {
1679     // In case name is an orphaned property reuse the cell.
1680     int entry = dict->FindEntry(name);
1681     if (entry != StringDictionary::kNotFound) {
1682       store_value = dict->ValueAt(entry);
1683       JSGlobalPropertyCell::cast(store_value)->set_value(value);
1684       // Assign an enumeration index to the property and update
1685       // SetNextEnumerationIndex.
1686       int index = dict->NextEnumerationIndex();
1687       PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
1688       dict->SetNextEnumerationIndex(index + 1);
1689       dict->SetEntry(entry, name, store_value, details);
1690       return value;
1691     }
1692     Heap* heap = GetHeap();
1693     { MaybeObject* maybe_store_value =
1694           heap->AllocateJSGlobalPropertyCell(value);
1695       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
1696     }
1697     JSGlobalPropertyCell::cast(store_value)->set_value(value);
1698   }
1699   PropertyDetails details = PropertyDetails(attributes, NORMAL);
1700   Object* result;
1701   { MaybeObject* maybe_result = dict->Add(name, store_value, details);
1702     if (!maybe_result->ToObject(&result)) return maybe_result;
1703   }
1704   if (dict != result) set_properties(StringDictionary::cast(result));
1705   return value;
1706 }
1707
1708
1709 MaybeObject* JSObject::AddProperty(String* name,
1710                                    Object* value,
1711                                    PropertyAttributes attributes,
1712                                    StrictModeFlag strict_mode) {
1713   ASSERT(!IsJSGlobalProxy());
1714   Map* map_of_this = map();
1715   Heap* heap = GetHeap();
1716   if (!map_of_this->is_extensible()) {
1717     if (strict_mode == kNonStrictMode) {
1718       return value;
1719     } else {
1720       Handle<Object> args[1] = {Handle<String>(name)};
1721       return heap->isolate()->Throw(
1722           *FACTORY->NewTypeError("object_not_extensible",
1723                                  HandleVector(args, 1)));
1724     }
1725   }
1726   if (HasFastProperties()) {
1727     // Ensure the descriptor array does not get too big.
1728     if (map_of_this->instance_descriptors()->number_of_descriptors() <
1729         DescriptorArray::kMaxNumberOfDescriptors) {
1730       if (value->IsJSFunction()) {
1731         return AddConstantFunctionProperty(name,
1732                                            JSFunction::cast(value),
1733                                            attributes);
1734       } else {
1735         return AddFastProperty(name, value, attributes);
1736       }
1737     } else {
1738       // Normalize the object to prevent very large instance descriptors.
1739       // This eliminates unwanted N^2 allocation and lookup behavior.
1740       Object* obj;
1741       { MaybeObject* maybe_obj =
1742             NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1743         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1744       }
1745     }
1746   }
1747   return AddSlowProperty(name, value, attributes);
1748 }
1749
1750
1751 MaybeObject* JSObject::SetPropertyPostInterceptor(
1752     String* name,
1753     Object* value,
1754     PropertyAttributes attributes,
1755     StrictModeFlag strict_mode) {
1756   // Check local property, ignore interceptor.
1757   LookupResult result(GetIsolate());
1758   LocalLookupRealNamedProperty(name, &result);
1759   if (result.IsFound()) {
1760     // An existing property, a map transition or a null descriptor was
1761     // found.  Use set property to handle all these cases.
1762     return SetProperty(&result, name, value, attributes, strict_mode);
1763   }
1764   bool found = false;
1765   MaybeObject* result_object;
1766   result_object = SetPropertyWithCallbackSetterInPrototypes(name,
1767                                                             value,
1768                                                             attributes,
1769                                                             &found,
1770                                                             strict_mode);
1771   if (found) return result_object;
1772   // Add a new real property.
1773   return AddProperty(name, value, attributes, strict_mode);
1774 }
1775
1776
1777 MaybeObject* JSObject::ReplaceSlowProperty(String* name,
1778                                            Object* value,
1779                                            PropertyAttributes attributes) {
1780   StringDictionary* dictionary = property_dictionary();
1781   int old_index = dictionary->FindEntry(name);
1782   int new_enumeration_index = 0;  // 0 means "Use the next available index."
1783   if (old_index != -1) {
1784     // All calls to ReplaceSlowProperty have had all transitions removed.
1785     ASSERT(!dictionary->ContainsTransition(old_index));
1786     new_enumeration_index = dictionary->DetailsAt(old_index).index();
1787   }
1788
1789   PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
1790   return SetNormalizedProperty(name, value, new_details);
1791 }
1792
1793
1794 MaybeObject* JSObject::ConvertDescriptorToFieldAndMapTransition(
1795     String* name,
1796     Object* new_value,
1797     PropertyAttributes attributes) {
1798   Map* old_map = map();
1799   Object* result;
1800   { MaybeObject* maybe_result =
1801         ConvertDescriptorToField(name, new_value, attributes);
1802     if (!maybe_result->ToObject(&result)) return maybe_result;
1803   }
1804   // If we get to this point we have succeeded - do not return failure
1805   // after this point.  Later stuff is optional.
1806   if (!HasFastProperties()) {
1807     return result;
1808   }
1809   // Do not add transitions to the map of "new Object()".
1810   if (map() == GetIsolate()->context()->global_context()->
1811       object_function()->map()) {
1812     return result;
1813   }
1814
1815   MapTransitionDescriptor transition(name,
1816                                      map(),
1817                                      attributes);
1818   Object* new_descriptors;
1819   { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()->
1820         CopyInsert(&transition, KEEP_TRANSITIONS);
1821     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1822       return result;  // Yes, return _result_.
1823     }
1824   }
1825   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1826   return result;
1827 }
1828
1829
1830 MaybeObject* JSObject::ConvertDescriptorToField(String* name,
1831                                                 Object* new_value,
1832                                                 PropertyAttributes attributes) {
1833   if (map()->unused_property_fields() == 0 &&
1834       properties()->length() > MaxFastProperties()) {
1835     Object* obj;
1836     { MaybeObject* maybe_obj =
1837           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1838       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1839     }
1840     return ReplaceSlowProperty(name, new_value, attributes);
1841   }
1842
1843   int index = map()->NextFreePropertyIndex();
1844   FieldDescriptor new_field(name, index, attributes);
1845   // Make a new DescriptorArray replacing an entry with FieldDescriptor.
1846   Object* descriptors_unchecked;
1847   { MaybeObject* maybe_descriptors_unchecked = map()->instance_descriptors()->
1848                                   CopyInsert(&new_field, REMOVE_TRANSITIONS);
1849     if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
1850       return maybe_descriptors_unchecked;
1851     }
1852   }
1853   DescriptorArray* new_descriptors =
1854       DescriptorArray::cast(descriptors_unchecked);
1855
1856   // Make a new map for the object.
1857   Object* new_map_unchecked;
1858   { MaybeObject* maybe_new_map_unchecked = map()->CopyDropDescriptors();
1859     if (!maybe_new_map_unchecked->ToObject(&new_map_unchecked)) {
1860       return maybe_new_map_unchecked;
1861     }
1862   }
1863   Map* new_map = Map::cast(new_map_unchecked);
1864   new_map->set_instance_descriptors(new_descriptors);
1865
1866   // Make new properties array if necessary.
1867   FixedArray* new_properties = 0;  // Will always be NULL or a valid pointer.
1868   int new_unused_property_fields = map()->unused_property_fields() - 1;
1869   if (map()->unused_property_fields() == 0) {
1870     new_unused_property_fields = kFieldsAdded - 1;
1871     Object* new_properties_object;
1872     { MaybeObject* maybe_new_properties_object =
1873           properties()->CopySize(properties()->length() + kFieldsAdded);
1874       if (!maybe_new_properties_object->ToObject(&new_properties_object)) {
1875         return maybe_new_properties_object;
1876       }
1877     }
1878     new_properties = FixedArray::cast(new_properties_object);
1879   }
1880
1881   // Update pointers to commit changes.
1882   // Object points to the new map.
1883   new_map->set_unused_property_fields(new_unused_property_fields);
1884   set_map(new_map);
1885   if (new_properties) {
1886     set_properties(FixedArray::cast(new_properties));
1887   }
1888   return FastPropertyAtPut(index, new_value);
1889 }
1890
1891
1892
1893 MaybeObject* JSObject::SetPropertyWithInterceptor(
1894     String* name,
1895     Object* value,
1896     PropertyAttributes attributes,
1897     StrictModeFlag strict_mode) {
1898   Isolate* isolate = GetIsolate();
1899   HandleScope scope(isolate);
1900   Handle<JSObject> this_handle(this);
1901   Handle<String> name_handle(name);
1902   Handle<Object> value_handle(value, isolate);
1903   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
1904   if (!interceptor->setter()->IsUndefined()) {
1905     LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name));
1906     CustomArguments args(isolate, interceptor->data(), this, this);
1907     v8::AccessorInfo info(args.end());
1908     v8::NamedPropertySetter setter =
1909         v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
1910     v8::Handle<v8::Value> result;
1911     {
1912       // Leaving JavaScript.
1913       VMState state(isolate, EXTERNAL);
1914       Handle<Object> value_unhole(value->IsTheHole() ?
1915                                   isolate->heap()->undefined_value() :
1916                                   value,
1917                                   isolate);
1918       result = setter(v8::Utils::ToLocal(name_handle),
1919                       v8::Utils::ToLocal(value_unhole),
1920                       info);
1921     }
1922     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1923     if (!result.IsEmpty()) return *value_handle;
1924   }
1925   MaybeObject* raw_result =
1926       this_handle->SetPropertyPostInterceptor(*name_handle,
1927                                               *value_handle,
1928                                               attributes,
1929                                               strict_mode);
1930   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1931   return raw_result;
1932 }
1933
1934
1935 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
1936                                        Handle<String> key,
1937                                        Handle<Object> value,
1938                                        PropertyAttributes attributes,
1939                                        StrictModeFlag strict_mode,
1940                                        bool skip_fallback_interceptor) {
1941   CALL_HEAP_FUNCTION(object->GetIsolate(),
1942                      object->SetProperty(*key, *value, attributes, strict_mode,
1943                                          skip_fallback_interceptor),
1944                      Object);
1945 }
1946
1947
1948 MaybeObject* JSReceiver::SetProperty(String* name,
1949                                      Object* value,
1950                                      PropertyAttributes attributes,
1951                                      StrictModeFlag strict_mode,
1952                                      bool skip_fallback_interceptor) {
1953   LookupResult result(GetIsolate());
1954   LocalLookup(name, &result, skip_fallback_interceptor);
1955   return SetProperty(&result, name, value, attributes, strict_mode);
1956 }
1957
1958
1959 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
1960                                                String* name,
1961                                                Object* value,
1962                                                JSObject* holder,
1963                                                StrictModeFlag strict_mode) {
1964   Isolate* isolate = GetIsolate();
1965   HandleScope scope(isolate);
1966
1967   // We should never get here to initialize a const with the hole
1968   // value since a const declaration would conflict with the setter.
1969   ASSERT(!value->IsTheHole());
1970   Handle<Object> value_handle(value, isolate);
1971
1972   // To accommodate both the old and the new api we switch on the
1973   // data structure used to store the callbacks.  Eventually foreign
1974   // callbacks should be phased out.
1975   if (structure->IsForeign()) {
1976     AccessorDescriptor* callback =
1977         reinterpret_cast<AccessorDescriptor*>(
1978             Foreign::cast(structure)->foreign_address());
1979     MaybeObject* obj = (callback->setter)(this,  value, callback->data);
1980     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1981     if (obj->IsFailure()) return obj;
1982     return *value_handle;
1983   }
1984
1985   if (structure->IsAccessorInfo()) {
1986     // api style callbacks
1987     AccessorInfo* data = AccessorInfo::cast(structure);
1988     Object* call_obj = data->setter();
1989     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
1990     if (call_fun == NULL) return value;
1991     Handle<String> key(name);
1992     LOG(isolate, ApiNamedPropertyAccess("store", this, name));
1993     CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
1994     v8::AccessorInfo info(args.end());
1995     {
1996       // Leaving JavaScript.
1997       VMState state(isolate, EXTERNAL);
1998       call_fun(v8::Utils::ToLocal(key),
1999                v8::Utils::ToLocal(value_handle),
2000                info);
2001     }
2002     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
2003     return *value_handle;
2004   }
2005
2006   if (structure->IsAccessorPair()) {
2007     Object* setter = AccessorPair::cast(structure)->setter();
2008     if (setter->IsSpecFunction()) {
2009       // TODO(rossberg): nicer would be to cast to some JSCallable here...
2010      return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
2011     } else {
2012       if (strict_mode == kNonStrictMode) {
2013         return value;
2014       }
2015       Handle<String> key(name);
2016       Handle<Object> holder_handle(holder, isolate);
2017       Handle<Object> args[2] = { key, holder_handle };
2018       return isolate->Throw(
2019           *isolate->factory()->NewTypeError("no_setter_in_callback",
2020                                             HandleVector(args, 2)));
2021     }
2022   }
2023
2024   UNREACHABLE();
2025   return NULL;
2026 }
2027
2028
2029 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter,
2030                                                       Object* value) {
2031   Isolate* isolate = GetIsolate();
2032   Handle<Object> value_handle(value, isolate);
2033   Handle<JSReceiver> fun(setter, isolate);
2034   Handle<JSReceiver> self(this, isolate);
2035 #ifdef ENABLE_DEBUGGER_SUPPORT
2036   Debug* debug = isolate->debug();
2037   // Handle stepping into a setter if step into is active.
2038   // TODO(rossberg): should this apply to getters that are function proxies?
2039   if (debug->StepInActive() && fun->IsJSFunction()) {
2040     debug->HandleStepIn(
2041         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
2042   }
2043 #endif
2044   bool has_pending_exception;
2045   Handle<Object> argv[] = { value_handle };
2046   Execution::Call(fun, self, ARRAY_SIZE(argv), argv, &has_pending_exception);
2047   // Check for pending exception and return the result.
2048   if (has_pending_exception) return Failure::Exception();
2049   return *value_handle;
2050 }
2051
2052
2053 void JSObject::LookupCallbackSetterInPrototypes(String* name,
2054                                                 LookupResult* result) {
2055   Heap* heap = GetHeap();
2056   for (Object* pt = GetPrototype();
2057        pt != heap->null_value();
2058        pt = pt->GetPrototype()) {
2059     if (pt->IsJSProxy()) {
2060       return result->HandlerResult(JSProxy::cast(pt));
2061     }
2062     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
2063     if (result->IsProperty()) {
2064       if (result->type() == CALLBACKS && !result->IsReadOnly()) return;
2065       // Found non-callback or read-only callback, stop looking.
2066       break;
2067     }
2068   }
2069   result->NotFound();
2070 }
2071
2072
2073 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
2074     uint32_t index,
2075     Object* value,
2076     bool* found,
2077     StrictModeFlag strict_mode) {
2078   Heap* heap = GetHeap();
2079   for (Object* pt = GetPrototype();
2080        pt != heap->null_value();
2081        pt = pt->GetPrototype()) {
2082     if (pt->IsJSProxy()) {
2083       String* name;
2084       MaybeObject* maybe = GetHeap()->Uint32ToString(index);
2085       if (!maybe->To<String>(&name)) {
2086         *found = true;  // Force abort
2087         return maybe;
2088       }
2089       return JSProxy::cast(pt)->SetPropertyWithHandlerIfDefiningSetter(
2090           name, value, NONE, strict_mode, found);
2091     }
2092     if (!JSObject::cast(pt)->HasDictionaryElements()) {
2093       continue;
2094     }
2095     SeededNumberDictionary* dictionary =
2096         JSObject::cast(pt)->element_dictionary();
2097     int entry = dictionary->FindEntry(index);
2098     if (entry != SeededNumberDictionary::kNotFound) {
2099       PropertyDetails details = dictionary->DetailsAt(entry);
2100       if (details.type() == CALLBACKS) {
2101         *found = true;
2102         return SetElementWithCallback(dictionary->ValueAt(entry),
2103                                       index,
2104                                       value,
2105                                       JSObject::cast(pt),
2106                                       strict_mode);
2107       }
2108     }
2109   }
2110   *found = false;
2111   return heap->the_hole_value();
2112 }
2113
2114 MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes(
2115     String* name,
2116     Object* value,
2117     PropertyAttributes attributes,
2118     bool* found,
2119     StrictModeFlag strict_mode) {
2120   Heap* heap = GetHeap();
2121   // We could not find a local property so let's check whether there is an
2122   // accessor that wants to handle the property.
2123   LookupResult accessor_result(heap->isolate());
2124   LookupCallbackSetterInPrototypes(name, &accessor_result);
2125   if (accessor_result.IsFound()) {
2126     *found = true;
2127     if (accessor_result.type() == CALLBACKS) {
2128       return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
2129                                      name,
2130                                      value,
2131                                      accessor_result.holder(),
2132                                      strict_mode);
2133     } else if (accessor_result.type() == HANDLER) {
2134       // There is a proxy in the prototype chain. Invoke its
2135       // getPropertyDescriptor trap.
2136       bool found = false;
2137       // SetPropertyWithHandlerIfDefiningSetter can cause GC,
2138       // make sure to use the handlified references after calling
2139       // the function.
2140       Handle<JSObject> self(this);
2141       Handle<String> hname(name);
2142       Handle<Object> hvalue(value);
2143       MaybeObject* result =
2144           accessor_result.proxy()->SetPropertyWithHandlerIfDefiningSetter(
2145               name, value, attributes, strict_mode, &found);
2146       if (found) return result;
2147       // The proxy does not define the property as an accessor.
2148       // Consequently, it has no effect on setting the receiver.
2149       return self->AddProperty(*hname, *hvalue, attributes, strict_mode);
2150     }
2151   }
2152   *found = false;
2153   return heap->the_hole_value();
2154 }
2155
2156
2157 void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
2158   DescriptorArray* descriptors = map()->instance_descriptors();
2159   int number = descriptors->SearchWithCache(name);
2160   if (number != DescriptorArray::kNotFound) {
2161     result->DescriptorResult(this, descriptors->GetDetails(number), number);
2162   } else {
2163     result->NotFound();
2164   }
2165 }
2166
2167
2168 void Map::LookupInDescriptors(JSObject* holder,
2169                               String* name,
2170                               LookupResult* result) {
2171   DescriptorArray* descriptors = instance_descriptors();
2172   DescriptorLookupCache* cache =
2173       GetHeap()->isolate()->descriptor_lookup_cache();
2174   int number = cache->Lookup(descriptors, name);
2175   if (number == DescriptorLookupCache::kAbsent) {
2176     number = descriptors->Search(name);
2177     cache->Update(descriptors, name, number);
2178   }
2179   if (number != DescriptorArray::kNotFound) {
2180     result->DescriptorResult(holder, descriptors->GetDetails(number), number);
2181   } else {
2182     result->NotFound();
2183   }
2184 }
2185
2186
2187 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
2188   ASSERT(!map.is_null());
2189   for (int i = 0; i < maps->length(); ++i) {
2190     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
2191   }
2192   return false;
2193 }
2194
2195
2196 template <class T>
2197 static Handle<T> MaybeNull(T* p) {
2198   if (p == NULL) return Handle<T>::null();
2199   return Handle<T>(p);
2200 }
2201
2202
2203 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
2204   ElementsKind elms_kind = elements_kind();
2205   if (elms_kind == FAST_DOUBLE_ELEMENTS) {
2206     bool dummy = true;
2207     Handle<Map> fast_map =
2208         MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy));
2209     if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
2210       return fast_map;
2211     }
2212     return Handle<Map>::null();
2213   }
2214   if (elms_kind == FAST_SMI_ONLY_ELEMENTS) {
2215     bool dummy = true;
2216     Handle<Map> double_map =
2217         MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy));
2218     // In the current implementation, if the DOUBLE map doesn't exist, the
2219     // FAST map can't exist either.
2220     if (double_map.is_null()) return Handle<Map>::null();
2221     Handle<Map> fast_map =
2222         MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
2223                                                           &dummy));
2224     if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
2225       return fast_map;
2226     }
2227     if (ContainsMap(candidates, double_map)) return double_map;
2228   }
2229   return Handle<Map>::null();
2230 }
2231
2232 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents,
2233                                                    ElementsKind elements_kind) {
2234   if (descriptor_contents->IsMap()) {
2235     Map* map = Map::cast(descriptor_contents);
2236     if (map->elements_kind() == elements_kind) {
2237       return map;
2238     }
2239     return NULL;
2240   }
2241
2242   FixedArray* map_array = FixedArray::cast(descriptor_contents);
2243   for (int i = 0; i < map_array->length(); ++i) {
2244     Object* current = map_array->get(i);
2245     // Skip undefined slots, they are sentinels for reclaimed maps.
2246     if (!current->IsUndefined()) {
2247       Map* current_map = Map::cast(map_array->get(i));
2248       if (current_map->elements_kind() == elements_kind) {
2249         return current_map;
2250       }
2251     }
2252   }
2253
2254   return NULL;
2255 }
2256
2257
2258 static MaybeObject* AddElementsTransitionMapToDescriptor(
2259     Object* descriptor_contents,
2260     Map* new_map) {
2261   // Nothing was in the descriptor for an ELEMENTS_TRANSITION,
2262   // simply add the map.
2263   if (descriptor_contents == NULL) {
2264     return new_map;
2265   }
2266
2267   // There was already a map in the descriptor, create a 2-element FixedArray
2268   // to contain the existing map plus the new one.
2269   FixedArray* new_array;
2270   Heap* heap = new_map->GetHeap();
2271   if (descriptor_contents->IsMap()) {
2272     // Must tenure, DescriptorArray expects no new-space objects.
2273     MaybeObject* maybe_new_array = heap->AllocateFixedArray(2, TENURED);
2274     if (!maybe_new_array->To<FixedArray>(&new_array)) {
2275       return maybe_new_array;
2276     }
2277     new_array->set(0, descriptor_contents);
2278     new_array->set(1, new_map);
2279     return new_array;
2280   }
2281
2282   // The descriptor already contained a list of maps for different ElementKinds
2283   // of ELEMENTS_TRANSITION, first check the existing array for an undefined
2284   // slot, and if that's not available, create a FixedArray to hold the existing
2285   // maps plus the new one and fill it in.
2286   FixedArray* array = FixedArray::cast(descriptor_contents);
2287   for (int i = 0; i < array->length(); ++i) {
2288     if (array->get(i)->IsUndefined()) {
2289       array->set(i, new_map);
2290       return array;
2291     }
2292   }
2293
2294   // Must tenure, DescriptorArray expects no new-space objects.
2295   MaybeObject* maybe_new_array =
2296       heap->AllocateFixedArray(array->length() + 1, TENURED);
2297   if (!maybe_new_array->To<FixedArray>(&new_array)) {
2298     return maybe_new_array;
2299   }
2300   int i = 0;
2301   while (i < array->length()) {
2302     new_array->set(i, array->get(i));
2303     ++i;
2304   }
2305   new_array->set(i, new_map);
2306   return new_array;
2307 }
2308
2309
2310 String* Map::elements_transition_sentinel_name() {
2311   return GetHeap()->empty_symbol();
2312 }
2313
2314
2315 Object* Map::GetDescriptorContents(String* sentinel_name,
2316                                    bool* safe_to_add_transition) {
2317   // Get the cached index for the descriptors lookup, or find and cache it.
2318   DescriptorArray* descriptors = instance_descriptors();
2319   DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
2320   int index = cache->Lookup(descriptors, sentinel_name);
2321   if (index == DescriptorLookupCache::kAbsent) {
2322     index = descriptors->Search(sentinel_name);
2323     cache->Update(descriptors, sentinel_name, index);
2324   }
2325   // If the transition already exists, return its descriptor.
2326   if (index != DescriptorArray::kNotFound) {
2327     PropertyDetails details(descriptors->GetDetails(index));
2328     if (details.type() == ELEMENTS_TRANSITION) {
2329       return descriptors->GetValue(index);
2330     } else {
2331       if (safe_to_add_transition != NULL) {
2332         *safe_to_add_transition = false;
2333       }
2334     }
2335   }
2336   return NULL;
2337 }
2338
2339
2340 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind,
2341                                       bool* safe_to_add_transition) {
2342   // Special case: indirect SMI->FAST transition (cf. comment in
2343   // AddElementsTransition()).
2344   if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2345       elements_kind == FAST_ELEMENTS) {
2346     Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
2347                                                         safe_to_add_transition);
2348     if (double_map == NULL) return double_map;
2349     return double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
2350                                                    safe_to_add_transition);
2351   }
2352   Object* descriptor_contents = GetDescriptorContents(
2353       elements_transition_sentinel_name(), safe_to_add_transition);
2354   if (descriptor_contents != NULL) {
2355     Map* maybe_transition_map =
2356         GetElementsTransitionMapFromDescriptor(descriptor_contents,
2357                                                elements_kind);
2358     ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap());
2359     return maybe_transition_map;
2360   }
2361   return NULL;
2362 }
2363
2364
2365 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind,
2366                                         Map* transitioned_map) {
2367   // The map transition graph should be a tree, therefore the transition
2368   // from SMI to FAST elements is not done directly, but by going through
2369   // DOUBLE elements first.
2370   if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2371       elements_kind == FAST_ELEMENTS) {
2372     bool safe_to_add = true;
2373     Map* double_map = this->LookupElementsTransitionMap(
2374         FAST_DOUBLE_ELEMENTS, &safe_to_add);
2375     // This method is only called when safe_to_add_transition has been found
2376     // to be true earlier.
2377     ASSERT(safe_to_add);
2378
2379     if (double_map == NULL) {
2380       MaybeObject* maybe_map = this->CopyDropTransitions();
2381       if (!maybe_map->To(&double_map)) return maybe_map;
2382       double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
2383       MaybeObject* maybe_double_transition = this->AddElementsTransition(
2384           FAST_DOUBLE_ELEMENTS, double_map);
2385       if (maybe_double_transition->IsFailure()) return maybe_double_transition;
2386     }
2387     return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map);
2388   }
2389
2390   bool safe_to_add_transition = true;
2391   Object* descriptor_contents = GetDescriptorContents(
2392       elements_transition_sentinel_name(), &safe_to_add_transition);
2393   // This method is only called when safe_to_add_transition has been found
2394   // to be true earlier.
2395   ASSERT(safe_to_add_transition);
2396   MaybeObject* maybe_new_contents =
2397       AddElementsTransitionMapToDescriptor(descriptor_contents,
2398                                            transitioned_map);
2399   Object* new_contents;
2400   if (!maybe_new_contents->ToObject(&new_contents)) {
2401     return maybe_new_contents;
2402   }
2403
2404   ElementsTransitionDescriptor desc(elements_transition_sentinel_name(),
2405                                     new_contents);
2406   Object* new_descriptors;
2407   MaybeObject* maybe_new_descriptors =
2408       instance_descriptors()->CopyInsert(&desc, KEEP_TRANSITIONS);
2409   if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
2410     return maybe_new_descriptors;
2411   }
2412   set_instance_descriptors(DescriptorArray::cast(new_descriptors));
2413   return this;
2414 }
2415
2416
2417 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
2418                                                ElementsKind to_kind) {
2419   Isolate* isolate = object->GetIsolate();
2420   CALL_HEAP_FUNCTION(isolate,
2421                      object->GetElementsTransitionMap(isolate, to_kind),
2422                      Map);
2423 }
2424
2425
2426 MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
2427   Map* current_map = map();
2428   ElementsKind from_kind = current_map->elements_kind();
2429
2430   if (from_kind == to_kind) return current_map;
2431
2432   // Only objects with FastProperties can have DescriptorArrays and can track
2433   // element-related maps. Also don't add descriptors to maps that are shared.
2434   bool safe_to_add_transition = HasFastProperties() &&
2435       !current_map->IsUndefined() &&
2436       !current_map->is_shared();
2437
2438   // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects
2439   // with elements that switch back and forth between dictionary and fast
2440   // element mode.
2441   if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) {
2442     safe_to_add_transition = false;
2443   }
2444
2445   if (safe_to_add_transition) {
2446     // It's only safe to manipulate the descriptor array if it would be
2447     // safe to add a transition.
2448     Map* maybe_transition_map = current_map->LookupElementsTransitionMap(
2449         to_kind, &safe_to_add_transition);
2450     if (maybe_transition_map != NULL) {
2451       return maybe_transition_map;
2452     }
2453   }
2454
2455   Map* new_map = NULL;
2456
2457   // No transition to an existing map for the given ElementsKind. Make a new
2458   // one.
2459   { MaybeObject* maybe_map = current_map->CopyDropTransitions();
2460     if (!maybe_map->To(&new_map)) return maybe_map;
2461   }
2462
2463   new_map->set_elements_kind(to_kind);
2464
2465   // Only remember the map transition if the object's map is NOT equal to the
2466   // global object_function's map and there is not an already existing
2467   // non-matching element transition.
2468   Context* global_context = GetIsolate()->context()->global_context();
2469   bool allow_map_transition = safe_to_add_transition &&
2470       (global_context->object_function()->map() != map());
2471   if (allow_map_transition) {
2472     MaybeObject* maybe_transition =
2473         current_map->AddElementsTransition(to_kind, new_map);
2474     if (maybe_transition->IsFailure()) return maybe_transition;
2475   }
2476   return new_map;
2477 }
2478
2479
2480 void JSObject::LocalLookupRealNamedProperty(String* name,
2481                                             LookupResult* result) {
2482   if (IsJSGlobalProxy()) {
2483     Object* proto = GetPrototype();
2484     if (proto->IsNull()) return result->NotFound();
2485     ASSERT(proto->IsJSGlobalObject());
2486     // A GlobalProxy's prototype should always be a proper JSObject.
2487     return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
2488   }
2489
2490   if (HasFastProperties()) {
2491     LookupInDescriptor(name, result);
2492     if (result->IsFound()) {
2493       // A property, a map transition or a null descriptor was found.
2494       // We return all of these result types because
2495       // LocalLookupRealNamedProperty is used when setting properties
2496       // where map transitions and null descriptors are handled.
2497       ASSERT(result->holder() == this && result->type() != NORMAL);
2498       // Disallow caching for uninitialized constants. These can only
2499       // occur as fields.
2500       if (result->IsReadOnly() && result->type() == FIELD &&
2501           FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
2502         result->DisallowCaching();
2503       }
2504       return;
2505     }
2506   } else {
2507     int entry = property_dictionary()->FindEntry(name);
2508     if (entry != StringDictionary::kNotFound) {
2509       Object* value = property_dictionary()->ValueAt(entry);
2510       if (IsGlobalObject()) {
2511         PropertyDetails d = property_dictionary()->DetailsAt(entry);
2512         if (d.IsDeleted()) {
2513           result->NotFound();
2514           return;
2515         }
2516         value = JSGlobalPropertyCell::cast(value)->value();
2517       }
2518       // Make sure to disallow caching for uninitialized constants
2519       // found in the dictionary-mode objects.
2520       if (value->IsTheHole()) result->DisallowCaching();
2521       result->DictionaryResult(this, entry);
2522       return;
2523     }
2524   }
2525   result->NotFound();
2526 }
2527
2528
2529 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
2530   LocalLookupRealNamedProperty(name, result);
2531   if (result->IsProperty()) return;
2532
2533   LookupRealNamedPropertyInPrototypes(name, result);
2534 }
2535
2536
2537 void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
2538                                                    LookupResult* result) {
2539   Heap* heap = GetHeap();
2540   for (Object* pt = GetPrototype();
2541        pt != heap->null_value();
2542        pt = JSObject::cast(pt)->GetPrototype()) {
2543     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
2544     if (result->IsProperty() && (result->type() != INTERCEPTOR)) return;
2545   }
2546   result->NotFound();
2547 }
2548
2549
2550 // We only need to deal with CALLBACKS and INTERCEPTORS
2551 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
2552     LookupResult* result,
2553     String* name,
2554     Object* value,
2555     bool check_prototype,
2556     StrictModeFlag strict_mode) {
2557   if (check_prototype && !result->IsProperty()) {
2558     LookupCallbackSetterInPrototypes(name, result);
2559   }
2560
2561   if (result->IsProperty()) {
2562     if (!result->IsReadOnly()) {
2563       switch (result->type()) {
2564         case CALLBACKS: {
2565           Object* obj = result->GetCallbackObject();
2566           if (obj->IsAccessorInfo()) {
2567             AccessorInfo* info = AccessorInfo::cast(obj);
2568             if (info->all_can_write()) {
2569               return SetPropertyWithCallback(result->GetCallbackObject(),
2570                                              name,
2571                                              value,
2572                                              result->holder(),
2573                                              strict_mode);
2574             }
2575           }
2576           break;
2577         }
2578         case INTERCEPTOR: {
2579           // Try lookup real named properties. Note that only property can be
2580           // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
2581           LookupResult r(GetIsolate());
2582           LookupRealNamedProperty(name, &r);
2583           if (r.IsProperty()) {
2584             return SetPropertyWithFailedAccessCheck(&r,
2585                                                     name,
2586                                                     value,
2587                                                     check_prototype,
2588                                                     strict_mode);
2589           }
2590           break;
2591         }
2592         default: {
2593           break;
2594         }
2595       }
2596     }
2597   }
2598
2599   Isolate* isolate = GetIsolate();
2600   HandleScope scope(isolate);
2601   Handle<Object> value_handle(value);
2602   isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
2603   return *value_handle;
2604 }
2605
2606
2607 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
2608                                      String* key,
2609                                      Object* value,
2610                                      PropertyAttributes attributes,
2611                                      StrictModeFlag strict_mode) {
2612   if (result->IsFound() && result->type() == HANDLER) {
2613     return result->proxy()->SetPropertyWithHandler(
2614         key, value, attributes, strict_mode);
2615   } else {
2616     return JSObject::cast(this)->SetPropertyForResult(
2617         result, key, value, attributes, strict_mode);
2618   }
2619 }
2620
2621
2622 bool JSProxy::HasPropertyWithHandler(String* name_raw) {
2623   Isolate* isolate = GetIsolate();
2624   HandleScope scope(isolate);
2625   Handle<Object> receiver(this);
2626   Handle<Object> name(name_raw);
2627
2628   Handle<Object> args[] = { name };
2629   Handle<Object> result = CallTrap(
2630     "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
2631   if (isolate->has_pending_exception()) return Failure::Exception();
2632
2633   return result->ToBoolean()->IsTrue();
2634 }
2635
2636
2637 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
2638     String* name_raw,
2639     Object* value_raw,
2640     PropertyAttributes attributes,
2641     StrictModeFlag strict_mode) {
2642   Isolate* isolate = GetIsolate();
2643   HandleScope scope(isolate);
2644   Handle<Object> receiver(this);
2645   Handle<Object> name(name_raw);
2646   Handle<Object> value(value_raw);
2647
2648   Handle<Object> args[] = { receiver, name, value };
2649   CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
2650   if (isolate->has_pending_exception()) return Failure::Exception();
2651
2652   return *value;
2653 }
2654
2655
2656 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandlerIfDefiningSetter(
2657     String* name_raw,
2658     Object* value_raw,
2659     PropertyAttributes attributes,
2660     StrictModeFlag strict_mode,
2661     bool* found) {
2662   *found = true;  // except where defined otherwise...
2663   Isolate* isolate = GetHeap()->isolate();
2664   Handle<JSProxy> proxy(this);
2665   Handle<Object> handler(this->handler());  // Trap might morph proxy.
2666   Handle<String> name(name_raw);
2667   Handle<Object> value(value_raw);
2668   Handle<Object> args[] = { name };
2669   Handle<Object> result = proxy->CallTrap(
2670       "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2671   if (isolate->has_pending_exception()) return Failure::Exception();
2672
2673   if (!result->IsUndefined()) {
2674     // The proxy handler cares about this property.
2675     // Check whether it is virtualized as an accessor.
2676     // Emulate [[GetProperty]] semantics for proxies.
2677     bool has_pending_exception;
2678     Handle<Object> argv[] = { result };
2679     Handle<Object> desc =
2680         Execution::Call(isolate->to_complete_property_descriptor(), result,
2681                         ARRAY_SIZE(argv), argv, &has_pending_exception);
2682     if (has_pending_exception) return Failure::Exception();
2683
2684     Handle<String> conf_name =
2685         isolate->factory()->LookupAsciiSymbol("configurable_");
2686     Handle<Object> configurable(v8::internal::GetProperty(desc, conf_name));
2687     ASSERT(!isolate->has_pending_exception());
2688     if (configurable->IsFalse()) {
2689       Handle<String> trap =
2690           isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2691       Handle<Object> args[] = { handler, trap, name };
2692       Handle<Object> error = isolate->factory()->NewTypeError(
2693           "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2694       return isolate->Throw(*error);
2695     }
2696     ASSERT(configurable->IsTrue());
2697
2698     // Check for AccessorDescriptor.
2699     Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_");
2700     Handle<Object> setter(v8::internal::GetProperty(desc, set_name));
2701     ASSERT(!isolate->has_pending_exception());
2702     if (!setter->IsUndefined()) {
2703       // We have a setter -- invoke it.
2704       // TODO(rossberg): nicer would be to cast to some JSCallable here...
2705       return proxy->SetPropertyWithDefinedSetter(
2706           JSReceiver::cast(*setter), *value);
2707     } else {
2708       Handle<String> get_name = isolate->factory()->LookupAsciiSymbol("get_");
2709       Handle<Object> getter(v8::internal::GetProperty(desc, get_name));
2710       ASSERT(!isolate->has_pending_exception());
2711       if (!getter->IsUndefined()) {
2712         // We have a getter but no setter -- the property may not be
2713         // written. In strict mode, throw an error.
2714         if (strict_mode == kNonStrictMode) return *value;
2715         Handle<Object> args[] = { name, proxy };
2716         Handle<Object> error = isolate->factory()->NewTypeError(
2717             "no_setter_in_callback", HandleVector(args, ARRAY_SIZE(args)));
2718         return isolate->Throw(*error);
2719       }
2720     }
2721     // Fall-through.
2722   }
2723
2724   // The proxy does not define the property as an accessor.
2725   *found = false;
2726   return *value;
2727 }
2728
2729
2730 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
2731     String* name_raw, DeleteMode mode) {
2732   Isolate* isolate = GetIsolate();
2733   HandleScope scope(isolate);
2734   Handle<Object> receiver(this);
2735   Handle<Object> name(name_raw);
2736
2737   Handle<Object> args[] = { name };
2738   Handle<Object> result = CallTrap(
2739     "delete", Handle<Object>(), ARRAY_SIZE(args), args);
2740   if (isolate->has_pending_exception()) return Failure::Exception();
2741
2742   Object* bool_result = result->ToBoolean();
2743   if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
2744     Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
2745     Handle<Object> args[] = { Handle<Object>(handler()), trap_name };
2746     Handle<Object> error = isolate->factory()->NewTypeError(
2747         "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
2748     isolate->Throw(*error);
2749     return Failure::Exception();
2750   }
2751   return bool_result;
2752 }
2753
2754
2755 MUST_USE_RESULT MaybeObject* JSProxy::DeleteElementWithHandler(
2756     uint32_t index,
2757     DeleteMode mode) {
2758   Isolate* isolate = GetIsolate();
2759   HandleScope scope(isolate);
2760   Handle<String> name = isolate->factory()->Uint32ToString(index);
2761   return JSProxy::DeletePropertyWithHandler(*name, mode);
2762 }
2763
2764
2765 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
2766     JSReceiver* receiver_raw,
2767     String* name_raw) {
2768   Isolate* isolate = GetIsolate();
2769   HandleScope scope(isolate);
2770   Handle<JSProxy> proxy(this);
2771   Handle<Object> handler(this->handler());  // Trap might morph proxy.
2772   Handle<JSReceiver> receiver(receiver_raw);
2773   Handle<Object> name(name_raw);
2774
2775   Handle<Object> args[] = { name };
2776   Handle<Object> result = CallTrap(
2777     "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2778   if (isolate->has_pending_exception()) return NONE;
2779
2780   if (result->IsUndefined()) return ABSENT;
2781
2782   bool has_pending_exception;
2783   Handle<Object> argv[] = { result };
2784   Handle<Object> desc =
2785       Execution::Call(isolate->to_complete_property_descriptor(), result,
2786                       ARRAY_SIZE(argv), argv, &has_pending_exception);
2787   if (has_pending_exception) return NONE;
2788
2789   // Convert result to PropertyAttributes.
2790   Handle<String> enum_n = isolate->factory()->LookupAsciiSymbol("enumerable");
2791   Handle<Object> enumerable(v8::internal::GetProperty(desc, enum_n));
2792   if (isolate->has_pending_exception()) return NONE;
2793   Handle<String> conf_n = isolate->factory()->LookupAsciiSymbol("configurable");
2794   Handle<Object> configurable(v8::internal::GetProperty(desc, conf_n));
2795   if (isolate->has_pending_exception()) return NONE;
2796   Handle<String> writ_n = isolate->factory()->LookupAsciiSymbol("writable");
2797   Handle<Object> writable(v8::internal::GetProperty(desc, writ_n));
2798   if (isolate->has_pending_exception()) return NONE;
2799
2800   if (configurable->IsFalse()) {
2801     Handle<String> trap =
2802         isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2803     Handle<Object> args[] = { handler, trap, name };
2804     Handle<Object> error = isolate->factory()->NewTypeError(
2805         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2806     isolate->Throw(*error);
2807     return NONE;
2808   }
2809
2810   int attributes = NONE;
2811   if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM;
2812   if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE;
2813   if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY;
2814   return static_cast<PropertyAttributes>(attributes);
2815 }
2816
2817
2818 MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler(
2819     JSReceiver* receiver,
2820     uint32_t index) {
2821   Isolate* isolate = GetIsolate();
2822   HandleScope scope(isolate);
2823   Handle<String> name = isolate->factory()->Uint32ToString(index);
2824   return GetPropertyAttributeWithHandler(receiver, *name);
2825 }
2826
2827
2828 void JSProxy::Fix() {
2829   Isolate* isolate = GetIsolate();
2830   HandleScope scope(isolate);
2831   Handle<JSProxy> self(this);
2832
2833   // Save identity hash.
2834   MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
2835
2836   if (IsJSFunctionProxy()) {
2837     isolate->factory()->BecomeJSFunction(self);
2838     // Code will be set on the JavaScript side.
2839   } else {
2840     isolate->factory()->BecomeJSObject(self);
2841   }
2842   ASSERT(self->IsJSObject());
2843
2844   // Inherit identity, if it was present.
2845   Object* hash;
2846   if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
2847     Handle<JSObject> new_self(JSObject::cast(*self));
2848     isolate->factory()->SetIdentityHash(new_self, hash);
2849   }
2850 }
2851
2852
2853 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
2854                                                  Handle<Object> derived,
2855                                                  int argc,
2856                                                  Handle<Object> argv[]) {
2857   Isolate* isolate = GetIsolate();
2858   Handle<Object> handler(this->handler());
2859
2860   Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol(name);
2861   Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2862   if (isolate->has_pending_exception()) return trap;
2863
2864   if (trap->IsUndefined()) {
2865     if (derived.is_null()) {
2866       Handle<Object> args[] = { handler, trap_name };
2867       Handle<Object> error = isolate->factory()->NewTypeError(
2868         "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2869       isolate->Throw(*error);
2870       return Handle<Object>();
2871     }
2872     trap = Handle<Object>(derived);
2873   }
2874
2875   bool threw;
2876   return Execution::Call(trap, handler, argc, argv, &threw);
2877 }
2878
2879
2880 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
2881                                             String* name,
2882                                             Object* value,
2883                                             PropertyAttributes attributes,
2884                                             StrictModeFlag strict_mode) {
2885   Heap* heap = GetHeap();
2886   // Make sure that the top context does not change when doing callbacks or
2887   // interceptor calls.
2888   AssertNoContextChange ncc;
2889
2890   // Optimization for 2-byte strings often used as keys in a decompression
2891   // dictionary.  We make these short keys into symbols to avoid constantly
2892   // reallocating them.
2893   if (!name->IsSymbol() && name->length() <= 2) {
2894     Object* symbol_version;
2895     { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
2896       if (maybe_symbol_version->ToObject(&symbol_version)) {
2897         name = String::cast(symbol_version);
2898       }
2899     }
2900   }
2901
2902   // Check access rights if needed.
2903   if (IsAccessCheckNeeded()) {
2904     if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
2905       return SetPropertyWithFailedAccessCheck(
2906           result, name, value, true, strict_mode);
2907     }
2908   }
2909
2910   if (IsJSGlobalProxy()) {
2911     Object* proto = GetPrototype();
2912     if (proto->IsNull()) return value;
2913     ASSERT(proto->IsJSGlobalObject());
2914     return JSObject::cast(proto)->SetPropertyForResult(
2915         result, name, value, attributes, strict_mode);
2916   }
2917
2918   if (!result->IsProperty() && !IsJSContextExtensionObject()) {
2919     bool found = false;
2920     MaybeObject* result_object;
2921     result_object = SetPropertyWithCallbackSetterInPrototypes(name,
2922                                                               value,
2923                                                               attributes,
2924                                                               &found,
2925                                                               strict_mode);
2926     if (found) return result_object;
2927   }
2928
2929   // At this point, no GC should have happened, as this would invalidate
2930   // 'result', which we cannot handlify!
2931
2932   if (!result->IsFound()) {
2933     // Neither properties nor transitions found.
2934     return AddProperty(name, value, attributes, strict_mode);
2935   }
2936   if (result->IsReadOnly() && result->IsProperty()) {
2937     if (strict_mode == kStrictMode) {
2938       Handle<JSObject> self(this);
2939       Handle<String> hname(name);
2940       Handle<Object> args[] = { hname, self };
2941       return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
2942           "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2943     } else {
2944       return value;
2945     }
2946   }
2947   // This is a real property that is not read-only, or it is a
2948   // transition or null descriptor and there are no setters in the prototypes.
2949   switch (result->type()) {
2950     case NORMAL:
2951       return SetNormalizedProperty(result, value);
2952     case FIELD:
2953       return FastPropertyAtPut(result->GetFieldIndex(), value);
2954     case MAP_TRANSITION:
2955       if (attributes == result->GetAttributes()) {
2956         // Only use map transition if the attributes match.
2957         return AddFastPropertyUsingMap(result->GetTransitionMap(),
2958                                        name,
2959                                        value);
2960       }
2961       return ConvertDescriptorToField(name, value, attributes);
2962     case CONSTANT_FUNCTION:
2963       // Only replace the function if necessary.
2964       if (value == result->GetConstantFunction()) return value;
2965       // Preserve the attributes of this existing property.
2966       attributes = result->GetAttributes();
2967       return ConvertDescriptorToField(name, value, attributes);
2968     case CALLBACKS:
2969       return SetPropertyWithCallback(result->GetCallbackObject(),
2970                                      name,
2971                                      value,
2972                                      result->holder(),
2973                                      strict_mode);
2974     case INTERCEPTOR:
2975       return SetPropertyWithInterceptor(name, value, attributes, strict_mode);
2976     case CONSTANT_TRANSITION: {
2977       // If the same constant function is being added we can simply
2978       // transition to the target map.
2979       Map* target_map = result->GetTransitionMap();
2980       DescriptorArray* target_descriptors = target_map->instance_descriptors();
2981       int number = target_descriptors->SearchWithCache(name);
2982       ASSERT(number != DescriptorArray::kNotFound);
2983       ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
2984       JSFunction* function =
2985           JSFunction::cast(target_descriptors->GetValue(number));
2986       if (value == function) {
2987         set_map(target_map);
2988         return value;
2989       }
2990       // Otherwise, replace with a MAP_TRANSITION to a new map with a
2991       // FIELD, even if the value is a constant function.
2992       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2993     }
2994     case NULL_DESCRIPTOR:
2995     case ELEMENTS_TRANSITION:
2996       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2997     case HANDLER:
2998       UNREACHABLE();
2999       return value;
3000   }
3001   UNREACHABLE();  // keep the compiler happy
3002   return value;
3003 }
3004
3005
3006 // Set a real local property, even if it is READ_ONLY.  If the property is not
3007 // present, add it with attributes NONE.  This code is an exact clone of
3008 // SetProperty, with the check for IsReadOnly and the check for a
3009 // callback setter removed.  The two lines looking up the LookupResult
3010 // result are also added.  If one of the functions is changed, the other
3011 // should be.
3012 // Note that this method cannot be used to set the prototype of a function
3013 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
3014 // doesn't handle function prototypes correctly.
3015 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
3016     Handle<JSObject> object,
3017     Handle<String> key,
3018     Handle<Object> value,
3019     PropertyAttributes attributes) {
3020   CALL_HEAP_FUNCTION(
3021     object->GetIsolate(),
3022     object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
3023     Object);
3024 }
3025
3026
3027 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
3028     String* name,
3029     Object* value,
3030     PropertyAttributes attributes) {
3031
3032   // Make sure that the top context does not change when doing callbacks or
3033   // interceptor calls.
3034   AssertNoContextChange ncc;
3035   Isolate* isolate = GetIsolate();
3036   LookupResult result(isolate);
3037   LocalLookup(name, &result);
3038   // Check access rights if needed.
3039   if (IsAccessCheckNeeded()) {
3040     if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
3041       return SetPropertyWithFailedAccessCheck(&result,
3042                                               name,
3043                                               value,
3044                                               false,
3045                                               kNonStrictMode);
3046     }
3047   }
3048
3049   if (IsJSGlobalProxy()) {
3050     Object* proto = GetPrototype();
3051     if (proto->IsNull()) return value;
3052     ASSERT(proto->IsJSGlobalObject());
3053     return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
3054         name,
3055         value,
3056         attributes);
3057   }
3058
3059   // Check for accessor in prototype chain removed here in clone.
3060   if (!result.IsFound()) {
3061     // Neither properties nor transitions found.
3062     return AddProperty(name, value, attributes, kNonStrictMode);
3063   }
3064
3065   PropertyDetails details = PropertyDetails(attributes, NORMAL);
3066
3067   // Check of IsReadOnly removed from here in clone.
3068   switch (result.type()) {
3069     case NORMAL:
3070       return SetNormalizedProperty(name, value, details);
3071     case FIELD:
3072       return FastPropertyAtPut(result.GetFieldIndex(), value);
3073     case MAP_TRANSITION:
3074       if (attributes == result.GetAttributes()) {
3075         // Only use map transition if the attributes match.
3076         return AddFastPropertyUsingMap(result.GetTransitionMap(),
3077                                        name,
3078                                        value);
3079       }
3080       return ConvertDescriptorToField(name, value, attributes);
3081     case CONSTANT_FUNCTION:
3082       // Only replace the function if necessary.
3083       if (value == result.GetConstantFunction()) return value;
3084       // Preserve the attributes of this existing property.
3085       attributes = result.GetAttributes();
3086       return ConvertDescriptorToField(name, value, attributes);
3087     case CALLBACKS:
3088     case INTERCEPTOR:
3089       // Override callback in clone
3090       return ConvertDescriptorToField(name, value, attributes);
3091     case CONSTANT_TRANSITION:
3092       // Replace with a MAP_TRANSITION to a new map with a FIELD, even
3093       // if the value is a function.
3094       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3095     case NULL_DESCRIPTOR:
3096     case ELEMENTS_TRANSITION:
3097       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3098     case HANDLER:
3099       UNREACHABLE();
3100       return value;
3101   }
3102   UNREACHABLE();  // keep the compiler happy
3103   return value;
3104 }
3105
3106
3107 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
3108       JSObject* receiver,
3109       String* name,
3110       bool continue_search) {
3111   // Check local property, ignore interceptor.
3112   LookupResult result(GetIsolate());
3113   LocalLookupRealNamedProperty(name, &result);
3114   if (result.IsProperty()) return result.GetAttributes();
3115
3116   if (continue_search) {
3117     // Continue searching via the prototype chain.
3118     Object* pt = GetPrototype();
3119     if (!pt->IsNull()) {
3120       return JSObject::cast(pt)->
3121         GetPropertyAttributeWithReceiver(receiver, name);
3122     }
3123   }
3124   return ABSENT;
3125 }
3126
3127
3128 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
3129       JSObject* receiver,
3130       String* name,
3131       bool continue_search) {
3132   Isolate* isolate = GetIsolate();
3133
3134   // Make sure that the top context does not change when doing
3135   // callbacks or interceptor calls.
3136   AssertNoContextChange ncc;
3137
3138   HandleScope scope(isolate);
3139   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
3140   Handle<JSObject> receiver_handle(receiver);
3141   Handle<JSObject> holder_handle(this);
3142   Handle<String> name_handle(name);
3143   CustomArguments args(isolate, interceptor->data(), receiver, this);
3144   v8::AccessorInfo info(args.end());
3145   if (!interceptor->query()->IsUndefined()) {
3146     v8::NamedPropertyQuery query =
3147         v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
3148     LOG(isolate,
3149         ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
3150     v8::Handle<v8::Integer> result;
3151     {
3152       // Leaving JavaScript.
3153       VMState state(isolate, EXTERNAL);
3154       result = query(v8::Utils::ToLocal(name_handle), info);
3155     }
3156     if (!result.IsEmpty()) {
3157       ASSERT(result->IsInt32());
3158       return static_cast<PropertyAttributes>(result->Int32Value());
3159     }
3160   } else if (!interceptor->getter()->IsUndefined()) {
3161     v8::NamedPropertyGetter getter =
3162         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
3163     LOG(isolate,
3164         ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
3165     v8::Handle<v8::Value> result;
3166     {
3167       // Leaving JavaScript.
3168       VMState state(isolate, EXTERNAL);
3169       result = getter(v8::Utils::ToLocal(name_handle), info);
3170     }
3171     if (!result.IsEmpty()) return DONT_ENUM;
3172   }
3173   return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
3174                                                             *name_handle,
3175                                                             continue_search);
3176 }
3177
3178
3179 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
3180       JSReceiver* receiver,
3181       String* key) {
3182   uint32_t index = 0;
3183   if (IsJSObject() && key->AsArrayIndex(&index)) {
3184     return JSObject::cast(this)->HasElementWithReceiver(receiver, index)
3185         ? NONE : ABSENT;
3186   }
3187   // Named property.
3188   LookupResult result(GetIsolate());
3189   Lookup(key, &result);
3190   return GetPropertyAttribute(receiver, &result, key, true);
3191 }
3192
3193
3194 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver,
3195                                                     LookupResult* result,
3196                                                     String* name,
3197                                                     bool continue_search) {
3198   // Check access rights if needed.
3199   if (IsAccessCheckNeeded()) {
3200     JSObject* this_obj = JSObject::cast(this);
3201     Heap* heap = GetHeap();
3202     if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
3203       return this_obj->GetPropertyAttributeWithFailedAccessCheck(
3204           receiver, result, name, continue_search);
3205     }
3206   }
3207   if (result->IsProperty()) {
3208     switch (result->type()) {
3209       case NORMAL:  // fall through
3210       case FIELD:
3211       case CONSTANT_FUNCTION:
3212       case CALLBACKS:
3213         return result->GetAttributes();
3214       case HANDLER: {
3215         return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler(
3216             receiver, name);
3217       }
3218       case INTERCEPTOR:
3219         return result->holder()->GetPropertyAttributeWithInterceptor(
3220             JSObject::cast(receiver), name, continue_search);
3221       default:
3222         UNREACHABLE();
3223     }
3224   }
3225   return ABSENT;
3226 }
3227
3228
3229 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
3230   // Check whether the name is an array index.
3231   uint32_t index = 0;
3232   if (IsJSObject() && name->AsArrayIndex(&index)) {
3233     if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
3234     return ABSENT;
3235   }
3236   // Named property.
3237   LookupResult result(GetIsolate());
3238   LocalLookup(name, &result);
3239   return GetPropertyAttribute(this, &result, name, false);
3240 }
3241
3242
3243 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
3244                                      PropertyNormalizationMode mode) {
3245   Isolate* isolate = obj->GetIsolate();
3246   Map* fast = obj->map();
3247   int index = fast->Hash() % kEntries;
3248   Object* result = get(index);
3249   if (result->IsMap() &&
3250       Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
3251 #ifdef DEBUG
3252     if (FLAG_verify_heap) {
3253       Map::cast(result)->SharedMapVerify();
3254     }
3255     if (FLAG_enable_slow_asserts) {
3256       // The cached map should match newly created normalized map bit-by-bit.
3257       Object* fresh;
3258       { MaybeObject* maybe_fresh =
3259             fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
3260         if (maybe_fresh->ToObject(&fresh)) {
3261           ASSERT(memcmp(Map::cast(fresh)->address(),
3262                         Map::cast(result)->address(),
3263                         Map::kSize) == 0);
3264         }
3265       }
3266     }
3267 #endif
3268     return result;
3269   }
3270
3271   { MaybeObject* maybe_result =
3272         fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
3273     if (!maybe_result->ToObject(&result)) return maybe_result;
3274   }
3275   set(index, result);
3276   isolate->counters()->normalized_maps()->Increment();
3277
3278   return result;
3279 }
3280
3281
3282 void NormalizedMapCache::Clear() {
3283   int entries = length();
3284   for (int i = 0; i != entries; i++) {
3285     set_undefined(i);
3286   }
3287 }
3288
3289
3290 void JSObject::UpdateMapCodeCache(Handle<JSObject> object,
3291                                   Handle<String> name,
3292                                   Handle<Code> code) {
3293   Isolate* isolate = object->GetIsolate();
3294   CALL_HEAP_FUNCTION_VOID(isolate,
3295                           object->UpdateMapCodeCache(*name, *code));
3296 }
3297
3298
3299 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
3300   if (map()->is_shared()) {
3301     // Fast case maps are never marked as shared.
3302     ASSERT(!HasFastProperties());
3303     // Replace the map with an identical copy that can be safely modified.
3304     Object* obj;
3305     { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES,
3306                                                      UNIQUE_NORMALIZED_MAP);
3307       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3308     }
3309     GetIsolate()->counters()->normalized_maps()->Increment();
3310
3311     set_map(Map::cast(obj));
3312   }
3313   return map()->UpdateCodeCache(name, code);
3314 }
3315
3316
3317 void JSObject::NormalizeProperties(Handle<JSObject> object,
3318                                    PropertyNormalizationMode mode,
3319                                    int expected_additional_properties) {
3320   CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
3321                           object->NormalizeProperties(
3322                               mode, expected_additional_properties));
3323 }
3324
3325
3326 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
3327                                            int expected_additional_properties) {
3328   if (!HasFastProperties()) return this;
3329
3330   // The global object is always normalized.
3331   ASSERT(!IsGlobalObject());
3332   // JSGlobalProxy must never be normalized
3333   ASSERT(!IsJSGlobalProxy());
3334
3335   Map* map_of_this = map();
3336
3337   // Allocate new content.
3338   int property_count = map_of_this->NumberOfDescribedProperties();
3339   if (expected_additional_properties > 0) {
3340     property_count += expected_additional_properties;
3341   } else {
3342     property_count += 2;  // Make space for two more properties.
3343   }
3344   StringDictionary* dictionary;
3345   { MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
3346     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3347   }
3348
3349   DescriptorArray* descs = map_of_this->instance_descriptors();
3350   for (int i = 0; i < descs->number_of_descriptors(); i++) {
3351     PropertyDetails details(descs->GetDetails(i));
3352     switch (details.type()) {
3353       case CONSTANT_FUNCTION: {
3354         PropertyDetails d =
3355             PropertyDetails(details.attributes(), NORMAL, details.index());
3356         Object* value = descs->GetConstantFunction(i);
3357         MaybeObject* maybe_dictionary =
3358             dictionary->Add(descs->GetKey(i), value, d);
3359         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3360         break;
3361       }
3362       case FIELD: {
3363         PropertyDetails d =
3364             PropertyDetails(details.attributes(), NORMAL, details.index());
3365         Object* value = FastPropertyAt(descs->GetFieldIndex(i));
3366         MaybeObject* maybe_dictionary =
3367             dictionary->Add(descs->GetKey(i), value, d);
3368         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3369         break;
3370       }
3371       case CALLBACKS: {
3372         if (!descs->IsProperty(i)) break;
3373         Object* value = descs->GetCallbacksObject(i);
3374         if (value->IsAccessorPair()) {
3375           MaybeObject* maybe_copy =
3376               AccessorPair::cast(value)->CopyWithoutTransitions();
3377           if (!maybe_copy->To(&value)) return maybe_copy;
3378         }
3379         MaybeObject* maybe_dictionary =
3380             dictionary->Add(descs->GetKey(i), value, details);
3381         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3382         break;
3383       }
3384       case MAP_TRANSITION:
3385       case CONSTANT_TRANSITION:
3386       case NULL_DESCRIPTOR:
3387       case INTERCEPTOR:
3388       case ELEMENTS_TRANSITION:
3389         break;
3390       case HANDLER:
3391       case NORMAL:
3392         UNREACHABLE();
3393         break;
3394     }
3395   }
3396
3397   Heap* current_heap = GetHeap();
3398
3399   // Copy the next enumeration index from instance descriptor.
3400   int index = map_of_this->instance_descriptors()->NextEnumerationIndex();
3401   dictionary->SetNextEnumerationIndex(index);
3402
3403   Map* new_map;
3404   { MaybeObject* maybe_map =
3405         current_heap->isolate()->context()->global_context()->
3406         normalized_map_cache()->Get(this, mode);
3407     if (!maybe_map->To(&new_map)) return maybe_map;
3408   }
3409
3410   // We have now successfully allocated all the necessary objects.
3411   // Changes can now be made with the guarantee that all of them take effect.
3412
3413   // Resize the object in the heap if necessary.
3414   int new_instance_size = new_map->instance_size();
3415   int instance_size_delta = map_of_this->instance_size() - new_instance_size;
3416   ASSERT(instance_size_delta >= 0);
3417   current_heap->CreateFillerObjectAt(this->address() + new_instance_size,
3418                                      instance_size_delta);
3419   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
3420     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
3421                                                -instance_size_delta);
3422   }
3423
3424
3425   set_map(new_map);
3426   new_map->clear_instance_descriptors();
3427
3428   set_properties(dictionary);
3429
3430   current_heap->isolate()->counters()->props_to_dictionary()->Increment();
3431
3432 #ifdef DEBUG
3433   if (FLAG_trace_normalization) {
3434     PrintF("Object properties have been normalized:\n");
3435     Print();
3436   }
3437 #endif
3438   return this;
3439 }
3440
3441
3442 void JSObject::TransformToFastProperties(Handle<JSObject> object,
3443                                          int unused_property_fields) {
3444   CALL_HEAP_FUNCTION_VOID(
3445       object->GetIsolate(),
3446       object->TransformToFastProperties(unused_property_fields));
3447 }
3448
3449
3450 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
3451   if (HasFastProperties()) return this;
3452   ASSERT(!IsGlobalObject());
3453   return property_dictionary()->
3454       TransformPropertiesToFastFor(this, unused_property_fields);
3455 }
3456
3457
3458 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
3459     Handle<JSObject> object) {
3460   CALL_HEAP_FUNCTION(object->GetIsolate(),
3461                      object->NormalizeElements(),
3462                      SeededNumberDictionary);
3463 }
3464
3465
3466 MaybeObject* JSObject::NormalizeElements() {
3467   ASSERT(!HasExternalArrayElements());
3468
3469   // Find the backing store.
3470   FixedArrayBase* array = FixedArrayBase::cast(elements());
3471   Map* old_map = array->map();
3472   bool is_arguments =
3473       (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
3474   if (is_arguments) {
3475     array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
3476   }
3477   if (array->IsDictionary()) return array;
3478
3479   ASSERT(HasFastElements() ||
3480          HasFastSmiOnlyElements() ||
3481          HasFastDoubleElements() ||
3482          HasFastArgumentsElements());
3483   // Compute the effective length and allocate a new backing store.
3484   int length = IsJSArray()
3485       ? Smi::cast(JSArray::cast(this)->length())->value()
3486       : array->length();
3487   int old_capacity = 0;
3488   int used_elements = 0;
3489   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
3490   SeededNumberDictionary* dictionary = NULL;
3491   { Object* object;
3492     MaybeObject* maybe = SeededNumberDictionary::Allocate(used_elements);
3493     if (!maybe->ToObject(&object)) return maybe;
3494     dictionary = SeededNumberDictionary::cast(object);
3495   }
3496
3497   // Copy the elements to the new backing store.
3498   bool has_double_elements = array->IsFixedDoubleArray();
3499   for (int i = 0; i < length; i++) {
3500     Object* value = NULL;
3501     if (has_double_elements) {
3502       FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
3503       if (double_array->is_the_hole(i)) {
3504         value = GetIsolate()->heap()->the_hole_value();
3505       } else {
3506         // Objects must be allocated in the old object space, since the
3507         // overall number of HeapNumbers needed for the conversion might
3508         // exceed the capacity of new space, and we would fail repeatedly
3509         // trying to convert the FixedDoubleArray.
3510         MaybeObject* maybe_value_object =
3511             GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3512         if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3513       }
3514     } else {
3515       ASSERT(old_map->has_fast_elements() ||
3516              old_map->has_fast_smi_only_elements());
3517       value = FixedArray::cast(array)->get(i);
3518     }
3519     PropertyDetails details = PropertyDetails(NONE, NORMAL);
3520     if (!value->IsTheHole()) {
3521       Object* result;
3522       MaybeObject* maybe_result =
3523           dictionary->AddNumberEntry(i, value, details);
3524       if (!maybe_result->ToObject(&result)) return maybe_result;
3525       dictionary = SeededNumberDictionary::cast(result);
3526     }
3527   }
3528
3529   // Switch to using the dictionary as the backing storage for elements.
3530   if (is_arguments) {
3531     FixedArray::cast(elements())->set(1, dictionary);
3532   } else {
3533     // Set the new map first to satify the elements type assert in
3534     // set_elements().
3535     Object* new_map;
3536     MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
3537                                                   DICTIONARY_ELEMENTS);
3538     if (!maybe->ToObject(&new_map)) return maybe;
3539     set_map(Map::cast(new_map));
3540     set_elements(dictionary);
3541   }
3542
3543   old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
3544       Increment();
3545
3546 #ifdef DEBUG
3547   if (FLAG_trace_normalization) {
3548     PrintF("Object elements have been normalized:\n");
3549     Print();
3550   }
3551 #endif
3552
3553   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
3554   return dictionary;
3555 }
3556
3557
3558 Smi* JSReceiver::GenerateIdentityHash() {
3559   Isolate* isolate = GetIsolate();
3560
3561   int hash_value;
3562   int attempts = 0;
3563   do {
3564     // Generate a random 32-bit hash value but limit range to fit
3565     // within a smi.
3566     hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue;
3567     attempts++;
3568   } while (hash_value == 0 && attempts < 30);
3569   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
3570
3571   return Smi::FromInt(hash_value);
3572 }
3573
3574
3575 MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) {
3576   MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3577                                          hash);
3578   if (maybe->IsFailure()) return maybe;
3579   return this;
3580 }
3581
3582
3583 int JSObject::GetIdentityHash(Handle<JSObject> obj) {
3584   CALL_AND_RETRY(obj->GetIsolate(),
3585                  obj->GetIdentityHash(ALLOW_CREATION),
3586                  return Smi::cast(__object__)->value(),
3587                  return 0);
3588 }
3589
3590
3591 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) {
3592   Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol());
3593   if (stored_value->IsSmi()) return stored_value;
3594
3595   // Do not generate permanent identity hash code if not requested.
3596   if (flag == OMIT_CREATION) return GetHeap()->undefined_value();
3597
3598   Smi* hash = GenerateIdentityHash();
3599   MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3600                                           hash);
3601   if (result->IsFailure()) return result;
3602   if (result->ToObjectUnchecked()->IsUndefined()) {
3603     // Trying to get hash of detached proxy.
3604     return Smi::FromInt(0);
3605   }
3606   return hash;
3607 }
3608
3609
3610 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) {
3611   Object* hash = this->hash();
3612   if (!hash->IsSmi() && flag == ALLOW_CREATION) {
3613     hash = GenerateIdentityHash();
3614     set_hash(hash);
3615   }
3616   return hash;
3617 }
3618
3619
3620 Object* JSObject::GetHiddenProperty(String* key) {
3621   if (IsJSGlobalProxy()) {
3622     // For a proxy, use the prototype as target object.
3623     Object* proxy_parent = GetPrototype();
3624     // If the proxy is detached, return undefined.
3625     if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3626     ASSERT(proxy_parent->IsJSGlobalObject());
3627     return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
3628   }
3629   ASSERT(!IsJSGlobalProxy());
3630   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3631   ASSERT(!hidden_lookup->IsFailure());  // No failure when passing false as arg.
3632   if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) {
3633     return GetHeap()->undefined_value();
3634   }
3635   StringDictionary* dictionary =
3636       StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3637   int entry = dictionary->FindEntry(key);
3638   if (entry == StringDictionary::kNotFound) return GetHeap()->undefined_value();
3639   return dictionary->ValueAt(entry);
3640 }
3641
3642
3643 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj,
3644                                  Handle<String> key,
3645                                  Handle<Object> value) {
3646   CALL_HEAP_FUNCTION(obj->GetIsolate(),
3647                      obj->SetHiddenProperty(*key, *value),
3648                      Object);
3649 }
3650
3651
3652 MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
3653   if (IsJSGlobalProxy()) {
3654     // For a proxy, use the prototype as target object.
3655     Object* proxy_parent = GetPrototype();
3656     // If the proxy is detached, return undefined.
3657     if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3658     ASSERT(proxy_parent->IsJSGlobalObject());
3659     return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value);
3660   }
3661   ASSERT(!IsJSGlobalProxy());
3662   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(true);
3663   StringDictionary* dictionary;
3664   if (!hidden_lookup->To<StringDictionary>(&dictionary)) return hidden_lookup;
3665
3666   // If it was found, check if the key is already in the dictionary.
3667   int entry = dictionary->FindEntry(key);
3668   if (entry != StringDictionary::kNotFound) {
3669     // If key was found, just update the value.
3670     dictionary->ValueAtPut(entry, value);
3671     return this;
3672   }
3673   // Key was not already in the dictionary, so add the entry.
3674   MaybeObject* insert_result = dictionary->Add(key,
3675                                                value,
3676                                                PropertyDetails(NONE, NORMAL));
3677   StringDictionary* new_dict;
3678   if (!insert_result->To<StringDictionary>(&new_dict)) return insert_result;
3679   if (new_dict != dictionary) {
3680     // If adding the key expanded the dictionary (i.e., Add returned a new
3681     // dictionary), store it back to the object.
3682     MaybeObject* store_result = SetHiddenPropertiesDictionary(new_dict);
3683     if (store_result->IsFailure()) return store_result;
3684   }
3685   // Return this to mark success.
3686   return this;
3687 }
3688
3689
3690 void JSObject::DeleteHiddenProperty(String* key) {
3691   if (IsJSGlobalProxy()) {
3692     // For a proxy, use the prototype as target object.
3693     Object* proxy_parent = GetPrototype();
3694     // If the proxy is detached, return immediately.
3695     if (proxy_parent->IsNull()) return;
3696     ASSERT(proxy_parent->IsJSGlobalObject());
3697     JSObject::cast(proxy_parent)->DeleteHiddenProperty(key);
3698     return;
3699   }
3700   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3701   ASSERT(!hidden_lookup->IsFailure());  // No failure when passing false as arg.
3702   if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) return;
3703   StringDictionary* dictionary =
3704       StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3705   int entry = dictionary->FindEntry(key);
3706   if (entry == StringDictionary::kNotFound) {
3707     // Key wasn't in dictionary. Deletion is a success.
3708     return;
3709   }
3710   // Key was in the dictionary. Remove it.
3711   dictionary->DeleteProperty(entry, JSReceiver::FORCE_DELETION);
3712 }
3713
3714
3715 bool JSObject::HasHiddenProperties() {
3716   return GetPropertyAttributePostInterceptor(this,
3717                                              GetHeap()->hidden_symbol(),
3718                                              false) != ABSENT;
3719 }
3720
3721
3722 MaybeObject* JSObject::GetHiddenPropertiesDictionary(bool create_if_absent) {
3723   ASSERT(!IsJSGlobalProxy());
3724   if (HasFastProperties()) {
3725     // If the object has fast properties, check whether the first slot
3726     // in the descriptor array matches the hidden symbol. Since the
3727     // hidden symbols hash code is zero (and no other string has hash
3728     // code zero) it will always occupy the first entry if present.
3729     DescriptorArray* descriptors = this->map()->instance_descriptors();
3730     if ((descriptors->number_of_descriptors() > 0) &&
3731         (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
3732       if (descriptors->GetType(0) == FIELD) {
3733         Object* hidden_store =
3734             this->FastPropertyAt(descriptors->GetFieldIndex(0));
3735         return StringDictionary::cast(hidden_store);
3736       } else {
3737         ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR ||
3738                descriptors->GetType(0) == MAP_TRANSITION);
3739       }
3740     }
3741   } else {
3742     PropertyAttributes attributes;
3743     // You can't install a getter on a property indexed by the hidden symbol,
3744     // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3745     // object.
3746     Object* lookup =
3747         GetLocalPropertyPostInterceptor(this,
3748                                         GetHeap()->hidden_symbol(),
3749                                         &attributes)->ToObjectUnchecked();
3750     if (!lookup->IsUndefined()) {
3751       return StringDictionary::cast(lookup);
3752     }
3753   }
3754   if (!create_if_absent) return GetHeap()->undefined_value();
3755   const int kInitialSize = 5;
3756   MaybeObject* dict_alloc = StringDictionary::Allocate(kInitialSize);
3757   StringDictionary* dictionary;
3758   if (!dict_alloc->To<StringDictionary>(&dictionary)) return dict_alloc;
3759   // Using AddProperty or SetPropertyPostInterceptor here could fail, because
3760   // object might be non-extensible.
3761   return HasFastProperties()
3762       ? AddFastProperty(GetHeap()->hidden_symbol(), dictionary, DONT_ENUM)
3763       : AddSlowProperty(GetHeap()->hidden_symbol(), dictionary, DONT_ENUM);
3764 }
3765
3766
3767 MaybeObject* JSObject::SetHiddenPropertiesDictionary(
3768     StringDictionary* dictionary) {
3769   ASSERT(!IsJSGlobalProxy());
3770   ASSERT(HasHiddenProperties());
3771   if (HasFastProperties()) {
3772     // If the object has fast properties, check whether the first slot
3773     // in the descriptor array matches the hidden symbol. Since the
3774     // hidden symbols hash code is zero (and no other string has hash
3775     // code zero) it will always occupy the first entry if present.
3776     DescriptorArray* descriptors = this->map()->instance_descriptors();
3777     if ((descriptors->number_of_descriptors() > 0) &&
3778         (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
3779       if (descriptors->GetType(0) == FIELD) {
3780         this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary);
3781         return this;
3782       } else {
3783         ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR ||
3784                descriptors->GetType(0) == MAP_TRANSITION);
3785       }
3786     }
3787   }
3788   MaybeObject* store_result =
3789       SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3790                                  dictionary,
3791                                  DONT_ENUM,
3792                                  kNonStrictMode);
3793   if (store_result->IsFailure()) return store_result;
3794   return this;
3795 }
3796
3797
3798 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
3799                                                      DeleteMode mode) {
3800   // Check local property, ignore interceptor.
3801   LookupResult result(GetIsolate());
3802   LocalLookupRealNamedProperty(name, &result);
3803   if (!result.IsProperty()) return GetHeap()->true_value();
3804
3805   // Normalize object if needed.
3806   Object* obj;
3807   { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3808     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3809   }
3810
3811   return DeleteNormalizedProperty(name, mode);
3812 }
3813
3814
3815 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) {
3816   Isolate* isolate = GetIsolate();
3817   HandleScope scope(isolate);
3818   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
3819   Handle<String> name_handle(name);
3820   Handle<JSObject> this_handle(this);
3821   if (!interceptor->deleter()->IsUndefined()) {
3822     v8::NamedPropertyDeleter deleter =
3823         v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
3824     LOG(isolate,
3825         ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
3826     CustomArguments args(isolate, interceptor->data(), this, this);
3827     v8::AccessorInfo info(args.end());
3828     v8::Handle<v8::Boolean> result;
3829     {
3830       // Leaving JavaScript.
3831       VMState state(isolate, EXTERNAL);
3832       result = deleter(v8::Utils::ToLocal(name_handle), info);
3833     }
3834     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3835     if (!result.IsEmpty()) {
3836       ASSERT(result->IsBoolean());
3837       return *v8::Utils::OpenHandle(*result);
3838     }
3839   }
3840   MaybeObject* raw_result =
3841       this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
3842   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3843   return raw_result;
3844 }
3845
3846
3847 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
3848   Isolate* isolate = GetIsolate();
3849   Heap* heap = isolate->heap();
3850   // Make sure that the top context does not change when doing
3851   // callbacks or interceptor calls.
3852   AssertNoContextChange ncc;
3853   HandleScope scope(isolate);
3854   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
3855   if (interceptor->deleter()->IsUndefined()) return heap->false_value();
3856   v8::IndexedPropertyDeleter deleter =
3857       v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
3858   Handle<JSObject> this_handle(this);
3859   LOG(isolate,
3860       ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
3861   CustomArguments args(isolate, interceptor->data(), this, this);
3862   v8::AccessorInfo info(args.end());
3863   v8::Handle<v8::Boolean> result;
3864   {
3865     // Leaving JavaScript.
3866     VMState state(isolate, EXTERNAL);
3867     result = deleter(index, info);
3868   }
3869   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3870   if (!result.IsEmpty()) {
3871     ASSERT(result->IsBoolean());
3872     return *v8::Utils::OpenHandle(*result);
3873   }
3874   MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete(
3875       *this_handle,
3876       index,
3877       NORMAL_DELETION);
3878   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3879   return raw_result;
3880 }
3881
3882
3883 Handle<Object> JSObject::DeleteElement(Handle<JSObject> obj,
3884                                        uint32_t index) {
3885   CALL_HEAP_FUNCTION(obj->GetIsolate(),
3886                      obj->DeleteElement(index, JSObject::NORMAL_DELETION),
3887                      Object);
3888 }
3889
3890
3891 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
3892   Isolate* isolate = GetIsolate();
3893   // Check access rights if needed.
3894   if (IsAccessCheckNeeded() &&
3895       !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
3896     isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
3897     return isolate->heap()->false_value();
3898   }
3899
3900   if (IsJSGlobalProxy()) {
3901     Object* proto = GetPrototype();
3902     if (proto->IsNull()) return isolate->heap()->false_value();
3903     ASSERT(proto->IsJSGlobalObject());
3904     return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
3905   }
3906
3907   if (HasIndexedInterceptor()) {
3908     // Skip interceptor if forcing deletion.
3909     if (mode != FORCE_DELETION) {
3910       return DeleteElementWithInterceptor(index);
3911     }
3912     mode = JSReceiver::FORCE_DELETION;
3913   }
3914
3915   return GetElementsAccessor()->Delete(this, index, mode);
3916 }
3917
3918
3919 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj,
3920                               Handle<String> prop) {
3921   CALL_HEAP_FUNCTION(obj->GetIsolate(),
3922                      obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
3923                      Object);
3924 }
3925
3926
3927 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
3928   Isolate* isolate = GetIsolate();
3929   // ECMA-262, 3rd, 8.6.2.5
3930   ASSERT(name->IsString());
3931
3932   // Check access rights if needed.
3933   if (IsAccessCheckNeeded() &&
3934       !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
3935     isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
3936     return isolate->heap()->false_value();
3937   }
3938
3939   if (IsJSGlobalProxy()) {
3940     Object* proto = GetPrototype();
3941     if (proto->IsNull()) return isolate->heap()->false_value();
3942     ASSERT(proto->IsJSGlobalObject());
3943     return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
3944   }
3945
3946   uint32_t index = 0;
3947   if (name->AsArrayIndex(&index)) {
3948     return DeleteElement(index, mode);
3949   } else {
3950     LookupResult result(isolate);
3951     LocalLookup(name, &result);
3952     if (!result.IsProperty()) return isolate->heap()->true_value();
3953     // Ignore attributes if forcing a deletion.
3954     if (result.IsDontDelete() && mode != FORCE_DELETION) {
3955       if (mode == STRICT_DELETION) {
3956         // Deleting a non-configurable property in strict mode.
3957         HandleScope scope(isolate);
3958         Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
3959         return isolate->Throw(*isolate->factory()->NewTypeError(
3960             "strict_delete_property", HandleVector(args, 2)));
3961       }
3962       return isolate->heap()->false_value();
3963     }
3964     // Check for interceptor.
3965     if (result.type() == INTERCEPTOR) {
3966       // Skip interceptor if forcing a deletion.
3967       if (mode == FORCE_DELETION) {
3968         return DeletePropertyPostInterceptor(name, mode);
3969       }
3970       return DeletePropertyWithInterceptor(name);
3971     }
3972     // Normalize object if needed.
3973     Object* obj;
3974     { MaybeObject* maybe_obj =
3975           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3976       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3977     }
3978     // Make sure the properties are normalized before removing the entry.
3979     return DeleteNormalizedProperty(name, mode);
3980   }
3981 }
3982
3983
3984 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
3985   if (IsJSProxy()) {
3986     return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
3987   }
3988   return JSObject::cast(this)->DeleteElement(index, mode);
3989 }
3990
3991
3992 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
3993   if (IsJSProxy()) {
3994     return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
3995   }
3996   return JSObject::cast(this)->DeleteProperty(name, mode);
3997 }
3998
3999
4000 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
4001                                             ElementsKind kind,
4002                                             Object* object) {
4003   ASSERT(kind == FAST_ELEMENTS ||
4004          kind == DICTIONARY_ELEMENTS);
4005   if (kind == FAST_ELEMENTS) {
4006     int length = IsJSArray()
4007         ? Smi::cast(JSArray::cast(this)->length())->value()
4008         : elements->length();
4009     for (int i = 0; i < length; ++i) {
4010       Object* element = elements->get(i);
4011       if (!element->IsTheHole() && element == object) return true;
4012     }
4013   } else {
4014     Object* key =
4015         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
4016     if (!key->IsUndefined()) return true;
4017   }
4018   return false;
4019 }
4020
4021
4022 // Check whether this object references another object.
4023 bool JSObject::ReferencesObject(Object* obj) {
4024   Map* map_of_this = map();
4025   Heap* heap = GetHeap();
4026   AssertNoAllocation no_alloc;
4027
4028   // Is the object the constructor for this object?
4029   if (map_of_this->constructor() == obj) {
4030     return true;
4031   }
4032
4033   // Is the object the prototype for this object?
4034   if (map_of_this->prototype() == obj) {
4035     return true;
4036   }
4037
4038   // Check if the object is among the named properties.
4039   Object* key = SlowReverseLookup(obj);
4040   if (!key->IsUndefined()) {
4041     return true;
4042   }
4043
4044   // Check if the object is among the indexed properties.
4045   ElementsKind kind = GetElementsKind();
4046   switch (kind) {
4047     case EXTERNAL_PIXEL_ELEMENTS:
4048     case EXTERNAL_BYTE_ELEMENTS:
4049     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4050     case EXTERNAL_SHORT_ELEMENTS:
4051     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4052     case EXTERNAL_INT_ELEMENTS:
4053     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4054     case EXTERNAL_FLOAT_ELEMENTS:
4055     case EXTERNAL_DOUBLE_ELEMENTS:
4056     case FAST_DOUBLE_ELEMENTS:
4057       // Raw pixels and external arrays do not reference other
4058       // objects.
4059       break;
4060     case FAST_SMI_ONLY_ELEMENTS:
4061       break;
4062     case FAST_ELEMENTS:
4063     case DICTIONARY_ELEMENTS: {
4064       FixedArray* elements = FixedArray::cast(this->elements());
4065       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
4066       break;
4067     }
4068     case NON_STRICT_ARGUMENTS_ELEMENTS: {
4069       FixedArray* parameter_map = FixedArray::cast(elements());
4070       // Check the mapped parameters.
4071       int length = parameter_map->length();
4072       for (int i = 2; i < length; ++i) {
4073         Object* value = parameter_map->get(i);
4074         if (!value->IsTheHole() && value == obj) return true;
4075       }
4076       // Check the arguments.
4077       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4078       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
4079       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
4080       break;
4081     }
4082   }
4083
4084   // For functions check the context.
4085   if (IsJSFunction()) {
4086     // Get the constructor function for arguments array.
4087     JSObject* arguments_boilerplate =
4088         heap->isolate()->context()->global_context()->
4089             arguments_boilerplate();
4090     JSFunction* arguments_function =
4091         JSFunction::cast(arguments_boilerplate->map()->constructor());
4092
4093     // Get the context and don't check if it is the global context.
4094     JSFunction* f = JSFunction::cast(this);
4095     Context* context = f->context();
4096     if (context->IsGlobalContext()) {
4097       return false;
4098     }
4099
4100     // Check the non-special context slots.
4101     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
4102       // Only check JS objects.
4103       if (context->get(i)->IsJSObject()) {
4104         JSObject* ctxobj = JSObject::cast(context->get(i));
4105         // If it is an arguments array check the content.
4106         if (ctxobj->map()->constructor() == arguments_function) {
4107           if (ctxobj->ReferencesObject(obj)) {
4108             return true;
4109           }
4110         } else if (ctxobj == obj) {
4111           return true;
4112         }
4113       }
4114     }
4115
4116     // Check the context extension (if any) if it can have references.
4117     if (context->has_extension() && !context->IsCatchContext()) {
4118       return JSObject::cast(context->extension())->ReferencesObject(obj);
4119     }
4120   }
4121
4122   // No references to object.
4123   return false;
4124 }
4125
4126
4127 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
4128   CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object);
4129 }
4130
4131
4132 MaybeObject* JSObject::PreventExtensions() {
4133   Isolate* isolate = GetIsolate();
4134   if (IsAccessCheckNeeded() &&
4135       !isolate->MayNamedAccess(this,
4136                                isolate->heap()->undefined_value(),
4137                                v8::ACCESS_KEYS)) {
4138     isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
4139     return isolate->heap()->false_value();
4140   }
4141
4142   if (IsJSGlobalProxy()) {
4143     Object* proto = GetPrototype();
4144     if (proto->IsNull()) return this;
4145     ASSERT(proto->IsJSGlobalObject());
4146     return JSObject::cast(proto)->PreventExtensions();
4147   }
4148
4149   // It's not possible to seal objects with external array elements
4150   if (HasExternalArrayElements()) {
4151     HandleScope scope(isolate);
4152     Handle<Object> object(this);
4153     Handle<Object> error  =
4154         isolate->factory()->NewTypeError(
4155             "cant_prevent_ext_external_array_elements",
4156             HandleVector(&object, 1));
4157     return isolate->Throw(*error);
4158   }
4159
4160   // If there are fast elements we normalize.
4161   SeededNumberDictionary* dictionary = NULL;
4162   { MaybeObject* maybe = NormalizeElements();
4163     if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe;
4164   }
4165   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
4166   // Make sure that we never go back to fast case.
4167   dictionary->set_requires_slow_elements();
4168
4169   // Do a map transition, other objects with this map may still
4170   // be extensible.
4171   Map* new_map;
4172   { MaybeObject* maybe = map()->CopyDropTransitions();
4173     if (!maybe->To<Map>(&new_map)) return maybe;
4174   }
4175   new_map->set_is_extensible(false);
4176   set_map(new_map);
4177   ASSERT(!map()->is_extensible());
4178   return new_map;
4179 }
4180
4181
4182 // Tests for the fast common case for property enumeration:
4183 // - This object and all prototypes has an enum cache (which means that
4184 //   it is no proxy, has no interceptors and needs no access checks).
4185 // - This object has no elements.
4186 // - No prototype has enumerable properties/elements.
4187 bool JSReceiver::IsSimpleEnum() {
4188   Heap* heap = GetHeap();
4189   for (Object* o = this;
4190        o != heap->null_value();
4191        o = JSObject::cast(o)->GetPrototype()) {
4192     if (!o->IsJSObject()) return false;
4193     JSObject* curr = JSObject::cast(o);
4194     if (!curr->map()->instance_descriptors()->HasEnumCache()) return false;
4195     ASSERT(!curr->HasNamedInterceptor());
4196     ASSERT(!curr->HasIndexedInterceptor());
4197     ASSERT(!curr->IsAccessCheckNeeded());
4198     if (curr->NumberOfEnumElements() > 0) return false;
4199     if (curr != this) {
4200       FixedArray* curr_fixed_array =
4201           FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache());
4202       if (curr_fixed_array->length() > 0) return false;
4203     }
4204   }
4205   return true;
4206 }
4207
4208
4209 int Map::NumberOfDescribedProperties(PropertyAttributes filter) {
4210   int result = 0;
4211   DescriptorArray* descs = instance_descriptors();
4212   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4213     PropertyDetails details(descs->GetDetails(i));
4214     if (descs->IsProperty(i) && (details.attributes() & filter) == 0) {
4215       result++;
4216     }
4217   }
4218   return result;
4219 }
4220
4221
4222 int Map::PropertyIndexFor(String* name) {
4223   DescriptorArray* descs = instance_descriptors();
4224   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4225     if (name->Equals(descs->GetKey(i)) && !descs->IsNullDescriptor(i)) {
4226       return descs->GetFieldIndex(i);
4227     }
4228   }
4229   return -1;
4230 }
4231
4232
4233 int Map::NextFreePropertyIndex() {
4234   int max_index = -1;
4235   DescriptorArray* descs = instance_descriptors();
4236   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4237     if (descs->GetType(i) == FIELD) {
4238       int current_index = descs->GetFieldIndex(i);
4239       if (current_index > max_index) max_index = current_index;
4240     }
4241   }
4242   return max_index + 1;
4243 }
4244
4245
4246 AccessorDescriptor* Map::FindAccessor(String* name) {
4247   DescriptorArray* descs = instance_descriptors();
4248   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4249     if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
4250       return descs->GetCallbacks(i);
4251     }
4252   }
4253   return NULL;
4254 }
4255
4256
4257 void JSReceiver::LocalLookup(String* name, LookupResult* result,
4258                              bool skip_fallback_interceptor) {
4259   ASSERT(name->IsString());
4260
4261   Heap* heap = GetHeap();
4262
4263   if (IsJSGlobalProxy()) {
4264     Object* proto = GetPrototype();
4265     if (proto->IsNull()) return result->NotFound();
4266     ASSERT(proto->IsJSGlobalObject());
4267     return JSReceiver::cast(proto)->LocalLookup(name, result);
4268   }
4269
4270   if (IsJSProxy()) {
4271     result->HandlerResult(JSProxy::cast(this));
4272     return;
4273   }
4274
4275   // Do not use inline caching if the object is a non-global object
4276   // that requires access checks.
4277   if (IsAccessCheckNeeded()) {
4278     result->DisallowCaching();
4279   }
4280
4281   JSObject* js_object = JSObject::cast(this);
4282
4283   // Check __proto__ before interceptor.
4284   if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) {
4285     result->ConstantResult(js_object);
4286     return;
4287   }
4288
4289   // Check for lookup interceptor except when bootstrapping.
4290   bool wouldIntercept = js_object->HasNamedInterceptor() &&
4291                         !heap->isolate()->bootstrapper()->IsActive();
4292   if (wouldIntercept && !map()->named_interceptor_is_fallback()) {
4293     result->InterceptorResult(js_object);
4294     return;
4295   }
4296
4297   js_object->LocalLookupRealNamedProperty(name, result);
4298
4299   if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() &&
4300       map()->named_interceptor_is_fallback()) {
4301     result->InterceptorResult(js_object);
4302     return;
4303   }
4304 }
4305
4306
4307 void JSReceiver::Lookup(String* name, LookupResult* result,
4308                         bool skip_fallback_interceptor) {
4309   // Ecma-262 3rd 8.6.2.4
4310   Heap* heap = GetHeap();
4311   for (Object* current = this;
4312        current != heap->null_value();
4313        current = JSObject::cast(current)->GetPrototype()) {
4314     JSReceiver::cast(current)->LocalLookup(name,
4315                                            result,
4316                                            skip_fallback_interceptor);
4317     if (result->IsProperty()) return;
4318   }
4319   result->NotFound();
4320 }
4321
4322
4323 // Search object and it's prototype chain for callback properties.
4324 void JSObject::LookupCallback(String* name, LookupResult* result) {
4325   Heap* heap = GetHeap();
4326   for (Object* current = this;
4327        current != heap->null_value() && current->IsJSObject();
4328        current = JSObject::cast(current)->GetPrototype()) {
4329     JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4330     if (result->IsFound() && result->type() == CALLBACKS) return;
4331   }
4332   result->NotFound();
4333 }
4334
4335
4336 // Try to update an accessor in an elements dictionary. Return true if the
4337 // update succeeded, and false otherwise.
4338 static bool UpdateGetterSetterInDictionary(
4339     SeededNumberDictionary* dictionary,
4340     uint32_t index,
4341     Object* getter,
4342     Object* setter,
4343     PropertyAttributes attributes) {
4344   int entry = dictionary->FindEntry(index);
4345   if (entry != SeededNumberDictionary::kNotFound) {
4346     Object* result = dictionary->ValueAt(entry);
4347     PropertyDetails details = dictionary->DetailsAt(entry);
4348     if (details.type() == CALLBACKS && result->IsAccessorPair()) {
4349       ASSERT(!details.IsDontDelete());
4350       if (details.attributes() != attributes) {
4351         dictionary->DetailsAtPut(entry,
4352                                  PropertyDetails(attributes, CALLBACKS, index));
4353       }
4354       AccessorPair::cast(result)->SetComponents(getter, setter);
4355       return true;
4356     }
4357   }
4358   return false;
4359 }
4360
4361
4362 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
4363                                              Object* getter,
4364                                              Object* setter,
4365                                              PropertyAttributes attributes) {
4366   switch (GetElementsKind()) {
4367     case FAST_SMI_ONLY_ELEMENTS:
4368     case FAST_ELEMENTS:
4369     case FAST_DOUBLE_ELEMENTS:
4370       break;
4371     case EXTERNAL_PIXEL_ELEMENTS:
4372     case EXTERNAL_BYTE_ELEMENTS:
4373     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4374     case EXTERNAL_SHORT_ELEMENTS:
4375     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4376     case EXTERNAL_INT_ELEMENTS:
4377     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4378     case EXTERNAL_FLOAT_ELEMENTS:
4379     case EXTERNAL_DOUBLE_ELEMENTS:
4380       // Ignore getters and setters on pixel and external array elements.
4381       return GetHeap()->undefined_value();
4382     case DICTIONARY_ELEMENTS:
4383       if (UpdateGetterSetterInDictionary(element_dictionary(),
4384                                          index,
4385                                          getter,
4386                                          setter,
4387                                          attributes)) {
4388         return GetHeap()->undefined_value();
4389       }
4390       break;
4391     case NON_STRICT_ARGUMENTS_ELEMENTS: {
4392       // Ascertain whether we have read-only properties or an existing
4393       // getter/setter pair in an arguments elements dictionary backing
4394       // store.
4395       FixedArray* parameter_map = FixedArray::cast(elements());
4396       uint32_t length = parameter_map->length();
4397       Object* probe =
4398           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
4399       if (probe == NULL || probe->IsTheHole()) {
4400         FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4401         if (arguments->IsDictionary()) {
4402           SeededNumberDictionary* dictionary =
4403               SeededNumberDictionary::cast(arguments);
4404           if (UpdateGetterSetterInDictionary(dictionary,
4405                                              index,
4406                                              getter,
4407                                              setter,
4408                                              attributes)) {
4409             return GetHeap()->undefined_value();
4410           }
4411         }
4412       }
4413       break;
4414     }
4415   }
4416
4417   AccessorPair* accessors;
4418   { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair();
4419     if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4420   }
4421   accessors->SetComponents(getter, setter);
4422
4423   return SetElementCallback(index, accessors, attributes);
4424 }
4425
4426
4427 MaybeObject* JSObject::DefinePropertyAccessor(String* name,
4428                                               Object* getter,
4429                                               Object* setter,
4430                                               PropertyAttributes attributes) {
4431   // Lookup the name.
4432   LookupResult result(GetHeap()->isolate());
4433   LocalLookupRealNamedProperty(name, &result);
4434   if (result.IsFound()) {
4435     if (result.type() == CALLBACKS) {
4436       ASSERT(!result.IsDontDelete());
4437       Object* obj = result.GetCallbackObject();
4438       // Need to preserve old getters/setters.
4439       if (obj->IsAccessorPair()) {
4440         AccessorPair* copy;
4441         { MaybeObject* maybe_copy =
4442               AccessorPair::cast(obj)->CopyWithoutTransitions();
4443           if (!maybe_copy->To(&copy)) return maybe_copy;
4444         }
4445         copy->SetComponents(getter, setter);
4446         // Use set to update attributes.
4447         return SetPropertyCallback(name, copy, attributes);
4448       }
4449     }
4450   }
4451
4452   AccessorPair* accessors;
4453   { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair();
4454     if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4455   }
4456   accessors->SetComponents(getter, setter);
4457
4458   return SetPropertyCallback(name, accessors, attributes);
4459 }
4460
4461
4462 bool JSObject::CanSetCallback(String* name) {
4463   ASSERT(!IsAccessCheckNeeded() ||
4464          GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4465
4466   // Check if there is an API defined callback object which prohibits
4467   // callback overwriting in this object or it's prototype chain.
4468   // This mechanism is needed for instance in a browser setting, where
4469   // certain accessors such as window.location should not be allowed
4470   // to be overwritten because allowing overwriting could potentially
4471   // cause security problems.
4472   LookupResult callback_result(GetIsolate());
4473   LookupCallback(name, &callback_result);
4474   if (callback_result.IsProperty()) {
4475     Object* obj = callback_result.GetCallbackObject();
4476     if (obj->IsAccessorInfo() &&
4477         AccessorInfo::cast(obj)->prohibits_overwriting()) {
4478       return false;
4479     }
4480   }
4481
4482   return true;
4483 }
4484
4485
4486 MaybeObject* JSObject::SetElementCallback(uint32_t index,
4487                                           Object* structure,
4488                                           PropertyAttributes attributes) {
4489   PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4490
4491   // Normalize elements to make this operation simple.
4492   SeededNumberDictionary* dictionary;
4493   { MaybeObject* maybe_dictionary = NormalizeElements();
4494     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4495   }
4496   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
4497
4498   // Update the dictionary with the new CALLBACKS property.
4499   { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details);
4500     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4501   }
4502
4503   dictionary->set_requires_slow_elements();
4504   // Update the dictionary backing store on the object.
4505   if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
4506     // Also delete any parameter alias.
4507     //
4508     // TODO(kmillikin): when deleting the last parameter alias we could
4509     // switch to a direct backing store without the parameter map.  This
4510     // would allow GC of the context.
4511     FixedArray* parameter_map = FixedArray::cast(elements());
4512     if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
4513       parameter_map->set(index + 2, GetHeap()->the_hole_value());
4514     }
4515     parameter_map->set(1, dictionary);
4516   } else {
4517     set_elements(dictionary);
4518   }
4519
4520   return GetHeap()->undefined_value();
4521 }
4522
4523
4524 MaybeObject* JSObject::SetPropertyCallback(String* name,
4525                                            Object* structure,
4526                                            PropertyAttributes attributes) {
4527   // Normalize object to make this operation simple.
4528   { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4529     if (maybe_ok->IsFailure()) return maybe_ok;
4530   }
4531
4532   // For the global object allocate a new map to invalidate the global inline
4533   // caches which have a global property cell reference directly in the code.
4534   if (IsGlobalObject()) {
4535     Map* new_map;
4536     { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
4537       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4538     }
4539     set_map(new_map);
4540     // When running crankshaft, changing the map is not enough. We
4541     // need to deoptimize all functions that rely on this global
4542     // object.
4543     Deoptimizer::DeoptimizeGlobalObject(this);
4544   }
4545
4546   // Update the dictionary with the new CALLBACKS property.
4547   PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4548   { MaybeObject* maybe_ok = SetNormalizedProperty(name, structure, details);
4549     if (maybe_ok->IsFailure()) return maybe_ok;
4550   }
4551
4552   return GetHeap()->undefined_value();
4553 }
4554
4555
4556 void JSObject::DefineAccessor(Handle<JSObject> object,
4557                               Handle<String> name,
4558                               Handle<Object> getter,
4559                               Handle<Object> setter,
4560                               PropertyAttributes attributes) {
4561   CALL_HEAP_FUNCTION_VOID(
4562       object->GetIsolate(),
4563       object->DefineAccessor(*name, *getter, *setter, attributes));
4564 }
4565
4566 MaybeObject* JSObject::DefineAccessor(String* name,
4567                                       Object* getter,
4568                                       Object* setter,
4569                                       PropertyAttributes attributes) {
4570   Isolate* isolate = GetIsolate();
4571   // Check access rights if needed.
4572   if (IsAccessCheckNeeded() &&
4573       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4574     isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4575     return isolate->heap()->undefined_value();
4576   }
4577
4578   if (IsJSGlobalProxy()) {
4579     Object* proto = GetPrototype();
4580     if (proto->IsNull()) return this;
4581     ASSERT(proto->IsJSGlobalObject());
4582     return JSObject::cast(proto)->DefineAccessor(
4583         name, getter, setter, attributes);
4584   }
4585
4586   // Make sure that the top context does not change when doing callbacks or
4587   // interceptor calls.
4588   AssertNoContextChange ncc;
4589
4590   // Try to flatten before operating on the string.
4591   name->TryFlatten();
4592
4593   if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
4594
4595   uint32_t index = 0;
4596   return name->AsArrayIndex(&index) ?
4597       DefineElementAccessor(index, getter, setter, attributes) :
4598       DefinePropertyAccessor(name, getter, setter, attributes);
4599 }
4600
4601
4602 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
4603   Isolate* isolate = GetIsolate();
4604   String* name = String::cast(info->name());
4605   // Check access rights if needed.
4606   if (IsAccessCheckNeeded() &&
4607       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4608     isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4609     return isolate->heap()->undefined_value();
4610   }
4611
4612   if (IsJSGlobalProxy()) {
4613     Object* proto = GetPrototype();
4614     if (proto->IsNull()) return this;
4615     ASSERT(proto->IsJSGlobalObject());
4616     return JSObject::cast(proto)->DefineAccessor(info);
4617   }
4618
4619   // Make sure that the top context does not change when doing callbacks or
4620   // interceptor calls.
4621   AssertNoContextChange ncc;
4622
4623   // Try to flatten before operating on the string.
4624   name->TryFlatten();
4625
4626   if (!CanSetCallback(name)) {
4627     return isolate->heap()->undefined_value();
4628   }
4629
4630   uint32_t index = 0;
4631   bool is_element = name->AsArrayIndex(&index);
4632
4633   if (is_element) {
4634     if (IsJSArray()) return isolate->heap()->undefined_value();
4635
4636     // Accessors overwrite previous callbacks (cf. with getters/setters).
4637     switch (GetElementsKind()) {
4638       case FAST_SMI_ONLY_ELEMENTS:
4639       case FAST_ELEMENTS:
4640       case FAST_DOUBLE_ELEMENTS:
4641         break;
4642       case EXTERNAL_PIXEL_ELEMENTS:
4643       case EXTERNAL_BYTE_ELEMENTS:
4644       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4645       case EXTERNAL_SHORT_ELEMENTS:
4646       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4647       case EXTERNAL_INT_ELEMENTS:
4648       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4649       case EXTERNAL_FLOAT_ELEMENTS:
4650       case EXTERNAL_DOUBLE_ELEMENTS:
4651         // Ignore getters and setters on pixel and external array
4652         // elements.
4653         return isolate->heap()->undefined_value();
4654       case DICTIONARY_ELEMENTS:
4655         break;
4656       case NON_STRICT_ARGUMENTS_ELEMENTS:
4657         UNIMPLEMENTED();
4658         break;
4659     }
4660
4661     { MaybeObject* maybe_ok =
4662           SetElementCallback(index, info, info->property_attributes());
4663       if (maybe_ok->IsFailure()) return maybe_ok;
4664     }
4665   } else {
4666     // Lookup the name.
4667     LookupResult result(isolate);
4668     LocalLookup(name, &result);
4669     // ES5 forbids turning a property into an accessor if it's not
4670     // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
4671     if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) {
4672       return isolate->heap()->undefined_value();
4673     }
4674     { MaybeObject* maybe_ok =
4675           SetPropertyCallback(name, info, info->property_attributes());
4676       if (maybe_ok->IsFailure()) return maybe_ok;
4677     }
4678   }
4679
4680   return this;
4681 }
4682
4683
4684 Object* JSObject::LookupAccessor(String* name, AccessorComponent component) {
4685   Heap* heap = GetHeap();
4686
4687   // Make sure that the top context does not change when doing callbacks or
4688   // interceptor calls.
4689   AssertNoContextChange ncc;
4690
4691   // Check access rights if needed.
4692   if (IsAccessCheckNeeded() &&
4693       !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
4694     heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
4695     return heap->undefined_value();
4696   }
4697
4698   // Make the lookup and include prototypes.
4699   uint32_t index = 0;
4700   if (name->AsArrayIndex(&index)) {
4701     for (Object* obj = this;
4702          obj != heap->null_value();
4703          obj = JSObject::cast(obj)->GetPrototype()) {
4704       JSObject* js_object = JSObject::cast(obj);
4705       if (js_object->HasDictionaryElements()) {
4706         SeededNumberDictionary* dictionary = js_object->element_dictionary();
4707         int entry = dictionary->FindEntry(index);
4708         if (entry != SeededNumberDictionary::kNotFound) {
4709           Object* element = dictionary->ValueAt(entry);
4710           if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
4711               element->IsAccessorPair()) {
4712             return AccessorPair::cast(element)->GetComponent(component);
4713           }
4714         }
4715       }
4716     }
4717   } else {
4718     for (Object* obj = this;
4719          obj != heap->null_value();
4720          obj = JSObject::cast(obj)->GetPrototype()) {
4721       LookupResult result(heap->isolate());
4722       JSObject::cast(obj)->LocalLookup(name, &result);
4723       if (result.IsProperty()) {
4724         if (result.IsReadOnly()) return heap->undefined_value();
4725         if (result.type() == CALLBACKS) {
4726           Object* obj = result.GetCallbackObject();
4727           if (obj->IsAccessorPair()) {
4728             return AccessorPair::cast(obj)->GetComponent(component);
4729           }
4730         }
4731       }
4732     }
4733   }
4734   return heap->undefined_value();
4735 }
4736
4737
4738 Object* JSObject::SlowReverseLookup(Object* value) {
4739   if (HasFastProperties()) {
4740     DescriptorArray* descs = map()->instance_descriptors();
4741     for (int i = 0; i < descs->number_of_descriptors(); i++) {
4742       if (descs->GetType(i) == FIELD) {
4743         if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
4744           return descs->GetKey(i);
4745         }
4746       } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
4747         if (descs->GetConstantFunction(i) == value) {
4748           return descs->GetKey(i);
4749         }
4750       }
4751     }
4752     return GetHeap()->undefined_value();
4753   } else {
4754     return property_dictionary()->SlowReverseLookup(value);
4755   }
4756 }
4757
4758
4759 MaybeObject* Map::CopyDropDescriptors() {
4760   Heap* heap = GetHeap();
4761   Object* result;
4762   { MaybeObject* maybe_result =
4763         heap->AllocateMap(instance_type(), instance_size());
4764     if (!maybe_result->ToObject(&result)) return maybe_result;
4765   }
4766   Map::cast(result)->set_prototype(prototype());
4767   Map::cast(result)->set_constructor(constructor());
4768   // Don't copy descriptors, so map transitions always remain a forest.
4769   // If we retained the same descriptors we would have two maps
4770   // pointing to the same transition which is bad because the garbage
4771   // collector relies on being able to reverse pointers from transitions
4772   // to maps.  If properties need to be retained use CopyDropTransitions.
4773   Map::cast(result)->clear_instance_descriptors();
4774   // Please note instance_type and instance_size are set when allocated.
4775   Map::cast(result)->set_inobject_properties(inobject_properties());
4776   Map::cast(result)->set_unused_property_fields(unused_property_fields());
4777
4778   // If the map has pre-allocated properties always start out with a descriptor
4779   // array describing these properties.
4780   if (pre_allocated_property_fields() > 0) {
4781     ASSERT(constructor()->IsJSFunction());
4782     JSFunction* ctor = JSFunction::cast(constructor());
4783     Object* descriptors;
4784     { MaybeObject* maybe_descriptors =
4785           ctor->initial_map()->instance_descriptors()->RemoveTransitions();
4786       if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
4787     }
4788     Map::cast(result)->set_instance_descriptors(
4789         DescriptorArray::cast(descriptors));
4790     Map::cast(result)->set_pre_allocated_property_fields(
4791         pre_allocated_property_fields());
4792   }
4793   Map::cast(result)->set_bit_field(bit_field());
4794   Map::cast(result)->set_bit_field2(bit_field2());
4795   Map::cast(result)->set_bit_field3(bit_field3());
4796   Map::cast(result)->set_is_shared(false);
4797   Map::cast(result)->ClearCodeCache(heap);
4798   return result;
4799 }
4800
4801
4802 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
4803                                  NormalizedMapSharingMode sharing) {
4804   int new_instance_size = instance_size();
4805   if (mode == CLEAR_INOBJECT_PROPERTIES) {
4806     new_instance_size -= inobject_properties() * kPointerSize;
4807   }
4808
4809   Object* result;
4810   { MaybeObject* maybe_result =
4811         GetHeap()->AllocateMap(instance_type(), new_instance_size);
4812     if (!maybe_result->ToObject(&result)) return maybe_result;
4813   }
4814
4815   if (mode != CLEAR_INOBJECT_PROPERTIES) {
4816     Map::cast(result)->set_inobject_properties(inobject_properties());
4817   }
4818
4819   Map::cast(result)->set_prototype(prototype());
4820   Map::cast(result)->set_constructor(constructor());
4821
4822   Map::cast(result)->set_bit_field(bit_field());
4823   Map::cast(result)->set_bit_field2(bit_field2());
4824   Map::cast(result)->set_bit_field3(bit_field3());
4825
4826   Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
4827
4828 #ifdef DEBUG
4829   if (FLAG_verify_heap && Map::cast(result)->is_shared()) {
4830     Map::cast(result)->SharedMapVerify();
4831   }
4832 #endif
4833
4834   return result;
4835 }
4836
4837
4838 MaybeObject* Map::CopyDropTransitions() {
4839   Object* new_map;
4840   { MaybeObject* maybe_new_map = CopyDropDescriptors();
4841     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
4842   }
4843   Object* descriptors;
4844   { MaybeObject* maybe_descriptors =
4845         instance_descriptors()->RemoveTransitions();
4846     if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
4847   }
4848   cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
4849   return new_map;
4850 }
4851
4852 void Map::UpdateCodeCache(Handle<Map> map,
4853                           Handle<String> name,
4854                           Handle<Code> code) {
4855   Isolate* isolate = map->GetIsolate();
4856   CALL_HEAP_FUNCTION_VOID(isolate,
4857                           map->UpdateCodeCache(*name, *code));
4858 }
4859
4860 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
4861   // Allocate the code cache if not present.
4862   if (code_cache()->IsFixedArray()) {
4863     Object* result;
4864     { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
4865       if (!maybe_result->ToObject(&result)) return maybe_result;
4866     }
4867     set_code_cache(result);
4868   }
4869
4870   // Update the code cache.
4871   return CodeCache::cast(code_cache())->Update(name, code);
4872 }
4873
4874
4875 Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
4876   // Do a lookup if a code cache exists.
4877   if (!code_cache()->IsFixedArray()) {
4878     return CodeCache::cast(code_cache())->Lookup(name, flags);
4879   } else {
4880     return GetHeap()->undefined_value();
4881   }
4882 }
4883
4884
4885 int Map::IndexInCodeCache(Object* name, Code* code) {
4886   // Get the internal index if a code cache exists.
4887   if (!code_cache()->IsFixedArray()) {
4888     return CodeCache::cast(code_cache())->GetIndex(name, code);
4889   }
4890   return -1;
4891 }
4892
4893
4894 void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
4895   // No GC is supposed to happen between a call to IndexInCodeCache and
4896   // RemoveFromCodeCache so the code cache must be there.
4897   ASSERT(!code_cache()->IsFixedArray());
4898   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
4899 }
4900
4901
4902 // An iterator over all map transitions in an descriptor array, reusing the map
4903 // field of the contens array while it is running.
4904 class IntrusiveMapTransitionIterator {
4905  public:
4906   explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array)
4907       : descriptor_array_(descriptor_array) { }
4908
4909   void Start() {
4910     ASSERT(!IsIterating());
4911     if (HasContentArray()) *ContentHeader() = Smi::FromInt(0);
4912   }
4913
4914   bool IsIterating() {
4915     return HasContentArray() && (*ContentHeader())->IsSmi();
4916   }
4917
4918   Map* Next() {
4919     ASSERT(IsIterating());
4920     FixedArray* contents = ContentArray();
4921     // Attention, tricky index manipulation ahead: Every entry in the contents
4922     // array consists of a value/details pair, so the index is typically even.
4923     // An exception is made for CALLBACKS entries: An even index means we look
4924     // at its getter, and an odd index means we look at its setter.
4925     int index = Smi::cast(*ContentHeader())->value();
4926     while (index < contents->length()) {
4927       PropertyDetails details(Smi::cast(contents->get(index | 1)));
4928       switch (details.type()) {
4929         case MAP_TRANSITION:
4930         case CONSTANT_TRANSITION:
4931         case ELEMENTS_TRANSITION:
4932           // We definitely have a map transition.
4933           *ContentHeader() = Smi::FromInt(index + 2);
4934           return static_cast<Map*>(contents->get(index));
4935         case CALLBACKS: {
4936           // We might have a map transition in a getter or in a setter.
4937           AccessorPair* accessors =
4938               static_cast<AccessorPair*>(contents->get(index & ~1));
4939           Object* accessor =
4940               ((index & 1) == 0) ? accessors->getter() : accessors->setter();
4941           index++;
4942           if (accessor->IsMap()) {
4943             *ContentHeader() = Smi::FromInt(index);
4944             return static_cast<Map*>(accessor);
4945           }
4946           break;
4947         }
4948         case NORMAL:
4949         case FIELD:
4950         case CONSTANT_FUNCTION:
4951         case HANDLER:
4952         case INTERCEPTOR:
4953         case NULL_DESCRIPTOR:
4954           // We definitely have no map transition.
4955           index += 2;
4956           break;
4957       }
4958     }
4959     *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map();
4960     return NULL;
4961   }
4962
4963  private:
4964   bool HasContentArray() {
4965     return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex;
4966   }
4967
4968   FixedArray* ContentArray() {
4969     Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex);
4970     return static_cast<FixedArray*>(array);
4971   }
4972
4973   Object** ContentHeader() {
4974     return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset);
4975   }
4976
4977   DescriptorArray* descriptor_array_;
4978 };
4979
4980
4981 // An iterator over all prototype transitions, reusing the map field of the
4982 // underlying array while it is running.
4983 class IntrusivePrototypeTransitionIterator {
4984  public:
4985   explicit IntrusivePrototypeTransitionIterator(FixedArray* proto_trans)
4986       : proto_trans_(proto_trans) { }
4987
4988   void Start() {
4989     ASSERT(!IsIterating());
4990     if (HasTransitions()) *Header() = Smi::FromInt(0);
4991   }
4992
4993   bool IsIterating() {
4994     return HasTransitions() && (*Header())->IsSmi();
4995   }
4996
4997   Map* Next() {
4998     ASSERT(IsIterating());
4999     int transitionNumber = Smi::cast(*Header())->value();
5000     if (transitionNumber < NumberOfTransitions()) {
5001       *Header() = Smi::FromInt(transitionNumber + 1);
5002       return GetTransition(transitionNumber);
5003     }
5004     *Header() = proto_trans_->GetHeap()->fixed_array_map();
5005     return NULL;
5006   }
5007
5008  private:
5009   bool HasTransitions() {
5010     return proto_trans_->length() >= Map::kProtoTransitionHeaderSize;
5011   }
5012
5013   Object** Header() {
5014     return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
5015   }
5016
5017   int NumberOfTransitions() {
5018     Object* num = proto_trans_->get(Map::kProtoTransitionNumberOfEntriesOffset);
5019     return Smi::cast(num)->value();
5020   }
5021
5022   Map* GetTransition(int transitionNumber) {
5023     return Map::cast(proto_trans_->get(IndexFor(transitionNumber)));
5024   }
5025
5026   int IndexFor(int transitionNumber) {
5027     return Map::kProtoTransitionHeaderSize +
5028         Map::kProtoTransitionMapOffset +
5029         transitionNumber * Map::kProtoTransitionElementsPerEntry;
5030   }
5031
5032   FixedArray* proto_trans_;
5033 };
5034
5035
5036 // To traverse the transition tree iteratively, we have to store two kinds of
5037 // information in a map: The parent map in the traversal and which children of a
5038 // node have already been visited. To do this without additional memory, we
5039 // temporarily reuse two maps with known values:
5040 //
5041 //  (1) The map of the map temporarily holds the parent, and is restored to the
5042 //      meta map afterwards.
5043 //
5044 //  (2) The info which children have already been visited depends on which part
5045 //      of the map we currently iterate:
5046 //
5047 //    (a) If we currently follow normal map transitions, we temporarily store
5048 //        the current index in the map of the FixedArray of the desciptor
5049 //        array's contents, and restore it to the fixed array map afterwards.
5050 //        Note that a single descriptor can have 0, 1, or 2 transitions.
5051 //
5052 //    (b) If we currently follow prototype transitions, we temporarily store
5053 //        the current index in the map of the FixedArray holding the prototype
5054 //        transitions, and restore it to the fixed array map afterwards.
5055 //
5056 // Note that the child iterator is just a concatenation of two iterators: One
5057 // iterating over map transitions and one iterating over prototype transisitons.
5058 class TraversableMap : public Map {
5059  public:
5060   // Record the parent in the traversal within this map. Note that this destroys
5061   // this map's map!
5062   void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
5063
5064   // Reset the current map's map, returning the parent previously stored in it.
5065   TraversableMap* GetAndResetParent() {
5066     TraversableMap* old_parent = static_cast<TraversableMap*>(map());
5067     set_map_no_write_barrier(GetHeap()->meta_map());
5068     return old_parent;
5069   }
5070
5071   // Start iterating over this map's children, possibly destroying a FixedArray
5072   // map (see explanation above).
5073   void ChildIteratorStart() {
5074     IntrusiveMapTransitionIterator(instance_descriptors()).Start();
5075     IntrusivePrototypeTransitionIterator(
5076         unchecked_prototype_transitions()).Start();
5077   }
5078
5079   // If we have an unvisited child map, return that one and advance. If we have
5080   // none, return NULL and reset any destroyed FixedArray maps.
5081   TraversableMap* ChildIteratorNext() {
5082     IntrusiveMapTransitionIterator descriptor_iterator(instance_descriptors());
5083     if (descriptor_iterator.IsIterating()) {
5084       Map* next = descriptor_iterator.Next();
5085       if (next != NULL) return static_cast<TraversableMap*>(next);
5086     }
5087     IntrusivePrototypeTransitionIterator
5088         proto_iterator(unchecked_prototype_transitions());
5089     if (proto_iterator.IsIterating()) {
5090       Map* next = proto_iterator.Next();
5091       if (next != NULL) return static_cast<TraversableMap*>(next);
5092     }
5093     return NULL;
5094   }
5095 };
5096
5097
5098 // Traverse the transition tree in postorder without using the C++ stack by
5099 // doing pointer reversal.
5100 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
5101   TraversableMap* current = static_cast<TraversableMap*>(this);
5102   current->ChildIteratorStart();
5103   while (true) {
5104     TraversableMap* child = current->ChildIteratorNext();
5105     if (child != NULL) {
5106       child->ChildIteratorStart();
5107       child->SetParent(current);
5108       current = child;
5109     } else {
5110       TraversableMap* parent = current->GetAndResetParent();
5111       callback(current, data);
5112       if (current == this) break;
5113       current = parent;
5114     }
5115   }
5116 }
5117
5118
5119 MaybeObject* CodeCache::Update(String* name, Code* code) {
5120   // The number of monomorphic stubs for normal load/store/call IC's can grow to
5121   // a large number and therefore they need to go into a hash table. They are
5122   // used to load global properties from cells.
5123   if (code->type() == NORMAL) {
5124     // Make sure that a hash table is allocated for the normal load code cache.
5125     if (normal_type_cache()->IsUndefined()) {
5126       Object* result;
5127       { MaybeObject* maybe_result =
5128             CodeCacheHashTable::Allocate(CodeCacheHashTable::kInitialSize);
5129         if (!maybe_result->ToObject(&result)) return maybe_result;
5130       }
5131       set_normal_type_cache(result);
5132     }
5133     return UpdateNormalTypeCache(name, code);
5134   } else {
5135     ASSERT(default_cache()->IsFixedArray());
5136     return UpdateDefaultCache(name, code);
5137   }
5138 }
5139
5140
5141 MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) {
5142   // When updating the default code cache we disregard the type encoded in the
5143   // flags. This allows call constant stubs to overwrite call field
5144   // stubs, etc.
5145   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
5146
5147   // First check whether we can update existing code cache without
5148   // extending it.
5149   FixedArray* cache = default_cache();
5150   int length = cache->length();
5151   int deleted_index = -1;
5152   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
5153     Object* key = cache->get(i);
5154     if (key->IsNull()) {
5155       if (deleted_index < 0) deleted_index = i;
5156       continue;
5157     }
5158     if (key->IsUndefined()) {
5159       if (deleted_index >= 0) i = deleted_index;
5160       cache->set(i + kCodeCacheEntryNameOffset, name);
5161       cache->set(i + kCodeCacheEntryCodeOffset, code);
5162       return this;
5163     }
5164     if (name->Equals(String::cast(key))) {
5165       Code::Flags found =
5166           Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
5167       if (Code::RemoveTypeFromFlags(found) == flags) {
5168         cache->set(i + kCodeCacheEntryCodeOffset, code);
5169         return this;
5170       }
5171     }
5172   }
5173
5174   // Reached the end of the code cache.  If there were deleted
5175   // elements, reuse the space for the first of them.
5176   if (deleted_index >= 0) {
5177     cache->set(deleted_index + kCodeCacheEntryNameOffset, name);
5178     cache->set(deleted_index + kCodeCacheEntryCodeOffset, code);
5179     return this;
5180   }
5181
5182   // Extend the code cache with some new entries (at least one). Must be a
5183   // multiple of the entry size.
5184   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
5185   new_length = new_length - new_length % kCodeCacheEntrySize;
5186   ASSERT((new_length % kCodeCacheEntrySize) == 0);
5187   Object* result;
5188   { MaybeObject* maybe_result = cache->CopySize(new_length);
5189     if (!maybe_result->ToObject(&result)) return maybe_result;
5190   }
5191
5192   // Add the (name, code) pair to the new cache.
5193   cache = FixedArray::cast(result);
5194   cache->set(length + kCodeCacheEntryNameOffset, name);
5195   cache->set(length + kCodeCacheEntryCodeOffset, code);
5196   set_default_cache(cache);
5197   return this;
5198 }
5199
5200
5201 MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) {
5202   // Adding a new entry can cause a new cache to be allocated.
5203   CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5204   Object* new_cache;
5205   { MaybeObject* maybe_new_cache = cache->Put(name, code);
5206     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5207   }
5208   set_normal_type_cache(new_cache);
5209   return this;
5210 }
5211
5212
5213 Object* CodeCache::Lookup(String* name, Code::Flags flags) {
5214   if (Code::ExtractTypeFromFlags(flags) == NORMAL) {
5215     return LookupNormalTypeCache(name, flags);
5216   } else {
5217     return LookupDefaultCache(name, flags);
5218   }
5219 }
5220
5221
5222 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) {
5223   FixedArray* cache = default_cache();
5224   int length = cache->length();
5225   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
5226     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
5227     // Skip deleted elements.
5228     if (key->IsNull()) continue;
5229     if (key->IsUndefined()) return key;
5230     if (name->Equals(String::cast(key))) {
5231       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
5232       if (code->flags() == flags) {
5233         return code;
5234       }
5235     }
5236   }
5237   return GetHeap()->undefined_value();
5238 }
5239
5240
5241 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) {
5242   if (!normal_type_cache()->IsUndefined()) {
5243     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5244     return cache->Lookup(name, flags);
5245   } else {
5246     return GetHeap()->undefined_value();
5247   }
5248 }
5249
5250
5251 int CodeCache::GetIndex(Object* name, Code* code) {
5252   if (code->type() == NORMAL) {
5253     if (normal_type_cache()->IsUndefined()) return -1;
5254     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5255     return cache->GetIndex(String::cast(name), code->flags());
5256   }
5257
5258   FixedArray* array = default_cache();
5259   int len = array->length();
5260   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
5261     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
5262   }
5263   return -1;
5264 }
5265
5266
5267 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
5268   if (code->type() == NORMAL) {
5269     ASSERT(!normal_type_cache()->IsUndefined());
5270     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5271     ASSERT(cache->GetIndex(String::cast(name), code->flags()) == index);
5272     cache->RemoveByIndex(index);
5273   } else {
5274     FixedArray* array = default_cache();
5275     ASSERT(array->length() >= index && array->get(index)->IsCode());
5276     // Use null instead of undefined for deleted elements to distinguish
5277     // deleted elements from unused elements.  This distinction is used
5278     // when looking up in the cache and when updating the cache.
5279     ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
5280     array->set_null(index - 1);  // Name.
5281     array->set_null(index);  // Code.
5282   }
5283 }
5284
5285
5286 // The key in the code cache hash table consists of the property name and the
5287 // code object. The actual match is on the name and the code flags. If a key
5288 // is created using the flags and not a code object it can only be used for
5289 // lookup not to create a new entry.
5290 class CodeCacheHashTableKey : public HashTableKey {
5291  public:
5292   CodeCacheHashTableKey(String* name, Code::Flags flags)
5293       : name_(name), flags_(flags), code_(NULL) { }
5294
5295   CodeCacheHashTableKey(String* name, Code* code)
5296       : name_(name),
5297         flags_(code->flags()),
5298         code_(code) { }
5299
5300
5301   bool IsMatch(Object* other) {
5302     if (!other->IsFixedArray()) return false;
5303     FixedArray* pair = FixedArray::cast(other);
5304     String* name = String::cast(pair->get(0));
5305     Code::Flags flags = Code::cast(pair->get(1))->flags();
5306     if (flags != flags_) {
5307       return false;
5308     }
5309     return name_->Equals(name);
5310   }
5311
5312   static uint32_t NameFlagsHashHelper(String* name, Code::Flags flags) {
5313     return name->Hash() ^ flags;
5314   }
5315
5316   uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); }
5317
5318   uint32_t HashForObject(Object* obj) {
5319     FixedArray* pair = FixedArray::cast(obj);
5320     String* name = String::cast(pair->get(0));
5321     Code* code = Code::cast(pair->get(1));
5322     return NameFlagsHashHelper(name, code->flags());
5323   }
5324
5325   MUST_USE_RESULT MaybeObject* AsObject() {
5326     ASSERT(code_ != NULL);
5327     Object* obj;
5328     { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2);
5329       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5330     }
5331     FixedArray* pair = FixedArray::cast(obj);
5332     pair->set(0, name_);
5333     pair->set(1, code_);
5334     return pair;
5335   }
5336
5337  private:
5338   String* name_;
5339   Code::Flags flags_;
5340   // TODO(jkummerow): We should be able to get by without this.
5341   Code* code_;
5342 };
5343
5344
5345 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) {
5346   CodeCacheHashTableKey key(name, flags);
5347   int entry = FindEntry(&key);
5348   if (entry == kNotFound) return GetHeap()->undefined_value();
5349   return get(EntryToIndex(entry) + 1);
5350 }
5351
5352
5353 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) {
5354   CodeCacheHashTableKey key(name, code);
5355   Object* obj;
5356   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5357     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5358   }
5359
5360   // Don't use |this|, as the table might have grown.
5361   CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
5362
5363   int entry = cache->FindInsertionEntry(key.Hash());
5364   Object* k;
5365   { MaybeObject* maybe_k = key.AsObject();
5366     if (!maybe_k->ToObject(&k)) return maybe_k;
5367   }
5368
5369   cache->set(EntryToIndex(entry), k);
5370   cache->set(EntryToIndex(entry) + 1, code);
5371   cache->ElementAdded();
5372   return cache;
5373 }
5374
5375
5376 int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) {
5377   CodeCacheHashTableKey key(name, flags);
5378   int entry = FindEntry(&key);
5379   return (entry == kNotFound) ? -1 : entry;
5380 }
5381
5382
5383 void CodeCacheHashTable::RemoveByIndex(int index) {
5384   ASSERT(index >= 0);
5385   Heap* heap = GetHeap();
5386   set(EntryToIndex(index), heap->the_hole_value());
5387   set(EntryToIndex(index) + 1, heap->the_hole_value());
5388   ElementRemoved();
5389 }
5390
5391
5392 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache,
5393                                   MapHandleList* maps,
5394                                   Code::Flags flags,
5395                                   Handle<Code> code) {
5396   Isolate* isolate = cache->GetIsolate();
5397   CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code));
5398 }
5399
5400
5401 MaybeObject* PolymorphicCodeCache::Update(MapHandleList* maps,
5402                                           Code::Flags flags,
5403                                           Code* code) {
5404   // Initialize cache if necessary.
5405   if (cache()->IsUndefined()) {
5406     Object* result;
5407     { MaybeObject* maybe_result =
5408           PolymorphicCodeCacheHashTable::Allocate(
5409               PolymorphicCodeCacheHashTable::kInitialSize);
5410       if (!maybe_result->ToObject(&result)) return maybe_result;
5411     }
5412     set_cache(result);
5413   } else {
5414     // This entry shouldn't be contained in the cache yet.
5415     ASSERT(PolymorphicCodeCacheHashTable::cast(cache())
5416                ->Lookup(maps, flags)->IsUndefined());
5417   }
5418   PolymorphicCodeCacheHashTable* hash_table =
5419       PolymorphicCodeCacheHashTable::cast(cache());
5420   Object* new_cache;
5421   { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
5422     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5423   }
5424   set_cache(new_cache);
5425   return this;
5426 }
5427
5428
5429 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
5430                                             Code::Flags flags) {
5431   if (!cache()->IsUndefined()) {
5432     PolymorphicCodeCacheHashTable* hash_table =
5433         PolymorphicCodeCacheHashTable::cast(cache());
5434     return Handle<Object>(hash_table->Lookup(maps, flags));
5435   } else {
5436     return GetIsolate()->factory()->undefined_value();
5437   }
5438 }
5439
5440
5441 // Despite their name, object of this class are not stored in the actual
5442 // hash table; instead they're temporarily used for lookups. It is therefore
5443 // safe to have a weak (non-owning) pointer to a MapList as a member field.
5444 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
5445  public:
5446   // Callers must ensure that |maps| outlives the newly constructed object.
5447   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
5448       : maps_(maps),
5449         code_flags_(code_flags) {}
5450
5451   bool IsMatch(Object* other) {
5452     MapHandleList other_maps(kDefaultListAllocationSize);
5453     int other_flags;
5454     FromObject(other, &other_flags, &other_maps);
5455     if (code_flags_ != other_flags) return false;
5456     if (maps_->length() != other_maps.length()) return false;
5457     // Compare just the hashes first because it's faster.
5458     int this_hash = MapsHashHelper(maps_, code_flags_);
5459     int other_hash = MapsHashHelper(&other_maps, other_flags);
5460     if (this_hash != other_hash) return false;
5461
5462     // Full comparison: for each map in maps_, look for an equivalent map in
5463     // other_maps. This implementation is slow, but probably good enough for
5464     // now because the lists are short (<= 4 elements currently).
5465     for (int i = 0; i < maps_->length(); ++i) {
5466       bool match_found = false;
5467       for (int j = 0; j < other_maps.length(); ++j) {
5468         if (*(maps_->at(i)) == *(other_maps.at(j))) {
5469           match_found = true;
5470           break;
5471         }
5472       }
5473       if (!match_found) return false;
5474     }
5475     return true;
5476   }
5477
5478   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
5479     uint32_t hash = code_flags;
5480     for (int i = 0; i < maps->length(); ++i) {
5481       hash ^= maps->at(i)->Hash();
5482     }
5483     return hash;
5484   }
5485
5486   uint32_t Hash() {
5487     return MapsHashHelper(maps_, code_flags_);
5488   }
5489
5490   uint32_t HashForObject(Object* obj) {
5491     MapHandleList other_maps(kDefaultListAllocationSize);
5492     int other_flags;
5493     FromObject(obj, &other_flags, &other_maps);
5494     return MapsHashHelper(&other_maps, other_flags);
5495   }
5496
5497   MUST_USE_RESULT MaybeObject* AsObject() {
5498     Object* obj;
5499     // The maps in |maps_| must be copied to a newly allocated FixedArray,
5500     // both because the referenced MapList is short-lived, and because C++
5501     // objects can't be stored in the heap anyway.
5502     { MaybeObject* maybe_obj =
5503         HEAP->AllocateUninitializedFixedArray(maps_->length() + 1);
5504       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5505     }
5506     FixedArray* list = FixedArray::cast(obj);
5507     list->set(0, Smi::FromInt(code_flags_));
5508     for (int i = 0; i < maps_->length(); ++i) {
5509       list->set(i + 1, *maps_->at(i));
5510     }
5511     return list;
5512   }
5513
5514  private:
5515   static MapHandleList* FromObject(Object* obj,
5516                                    int* code_flags,
5517                                    MapHandleList* maps) {
5518     FixedArray* list = FixedArray::cast(obj);
5519     maps->Rewind(0);
5520     *code_flags = Smi::cast(list->get(0))->value();
5521     for (int i = 1; i < list->length(); ++i) {
5522       maps->Add(Handle<Map>(Map::cast(list->get(i))));
5523     }
5524     return maps;
5525   }
5526
5527   MapHandleList* maps_;  // weak.
5528   int code_flags_;
5529   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
5530 };
5531
5532
5533 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
5534                                               int code_flags) {
5535   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5536   int entry = FindEntry(&key);
5537   if (entry == kNotFound) return GetHeap()->undefined_value();
5538   return get(EntryToIndex(entry) + 1);
5539 }
5540
5541
5542 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps,
5543                                                 int code_flags,
5544                                                 Code* code) {
5545   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5546   Object* obj;
5547   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5548     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5549   }
5550   PolymorphicCodeCacheHashTable* cache =
5551       reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
5552   int entry = cache->FindInsertionEntry(key.Hash());
5553   { MaybeObject* maybe_obj = key.AsObject();
5554     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5555   }
5556   cache->set(EntryToIndex(entry), obj);
5557   cache->set(EntryToIndex(entry) + 1, code);
5558   cache->ElementAdded();
5559   return cache;
5560 }
5561
5562
5563 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
5564   ElementsAccessor* accessor = array->GetElementsAccessor();
5565   MaybeObject* maybe_result =
5566       accessor->AddElementsToFixedArray(array, array, this);
5567   FixedArray* result;
5568   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
5569 #ifdef DEBUG
5570   if (FLAG_enable_slow_asserts) {
5571     for (int i = 0; i < result->length(); i++) {
5572       Object* current = result->get(i);
5573       ASSERT(current->IsNumber() || current->IsString());
5574     }
5575   }
5576 #endif
5577   return result;
5578 }
5579
5580
5581 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
5582   ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
5583   MaybeObject* maybe_result =
5584       accessor->AddElementsToFixedArray(NULL, NULL, this, other);
5585   FixedArray* result;
5586   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
5587 #ifdef DEBUG
5588   if (FLAG_enable_slow_asserts) {
5589     for (int i = 0; i < result->length(); i++) {
5590       Object* current = result->get(i);
5591       ASSERT(current->IsNumber() || current->IsString());
5592     }
5593   }
5594 #endif
5595   return result;
5596 }
5597
5598
5599 MaybeObject* FixedArray::CopySize(int new_length) {
5600   Heap* heap = GetHeap();
5601   if (new_length == 0) return heap->empty_fixed_array();
5602   Object* obj;
5603   { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length);
5604     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5605   }
5606   FixedArray* result = FixedArray::cast(obj);
5607   // Copy the content
5608   AssertNoAllocation no_gc;
5609   int len = length();
5610   if (new_length < len) len = new_length;
5611   // We are taking the map from the old fixed array so the map is sure to
5612   // be an immortal immutable object.
5613   result->set_map_no_write_barrier(map());
5614   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
5615   for (int i = 0; i < len; i++) {
5616     result->set(i, get(i), mode);
5617   }
5618   return result;
5619 }
5620
5621
5622 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
5623   AssertNoAllocation no_gc;
5624   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
5625   for (int index = 0; index < len; index++) {
5626     dest->set(dest_pos+index, get(pos+index), mode);
5627   }
5628 }
5629
5630
5631 #ifdef DEBUG
5632 bool FixedArray::IsEqualTo(FixedArray* other) {
5633   if (length() != other->length()) return false;
5634   for (int i = 0 ; i < length(); ++i) {
5635     if (get(i) != other->get(i)) return false;
5636   }
5637   return true;
5638 }
5639 #endif
5640
5641
5642 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
5643   Heap* heap = Isolate::Current()->heap();
5644   if (number_of_descriptors == 0) {
5645     return heap->empty_descriptor_array();
5646   }
5647   // Allocate the array of keys.
5648   Object* array;
5649   { MaybeObject* maybe_array =
5650         heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
5651     if (!maybe_array->ToObject(&array)) return maybe_array;
5652   }
5653   // Do not use DescriptorArray::cast on incomplete object.
5654   FixedArray* result = FixedArray::cast(array);
5655
5656   // Allocate the content array and set it in the descriptor array.
5657   { MaybeObject* maybe_array =
5658         heap->AllocateFixedArray(number_of_descriptors << 1);
5659     if (!maybe_array->ToObject(&array)) return maybe_array;
5660   }
5661   result->set(kBitField3StorageIndex, Smi::FromInt(0));
5662   result->set(kContentArrayIndex, array);
5663   result->set(kEnumerationIndexIndex,
5664               Smi::FromInt(PropertyDetails::kInitialIndex));
5665   return result;
5666 }
5667
5668
5669 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
5670                                    FixedArray* new_cache,
5671                                    Object* new_index_cache) {
5672   ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
5673   ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
5674   if (HasEnumCache()) {
5675     FixedArray::cast(get(kEnumerationIndexIndex))->
5676       set(kEnumCacheBridgeCacheIndex, new_cache);
5677     FixedArray::cast(get(kEnumerationIndexIndex))->
5678       set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
5679   } else {
5680     if (IsEmpty()) return;  // Do nothing for empty descriptor array.
5681     FixedArray::cast(bridge_storage)->
5682       set(kEnumCacheBridgeCacheIndex, new_cache);
5683     FixedArray::cast(bridge_storage)->
5684       set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
5685     NoWriteBarrierSet(FixedArray::cast(bridge_storage),
5686                       kEnumCacheBridgeEnumIndex,
5687                       get(kEnumerationIndexIndex));
5688     set(kEnumerationIndexIndex, bridge_storage);
5689   }
5690 }
5691
5692
5693 static bool InsertionPointFound(String* key1, String* key2) {
5694   return key1->Hash() > key2->Hash() || key1 == key2;
5695 }
5696
5697
5698 void DescriptorArray::CopyFrom(Handle<DescriptorArray> dst,
5699                                int dst_index,
5700                                Handle<DescriptorArray> src,
5701                                int src_index,
5702                                const WhitenessWitness& witness) {
5703   CALL_HEAP_FUNCTION_VOID(dst->GetIsolate(),
5704                           dst->CopyFrom(dst_index, *src, src_index, witness));
5705 }
5706
5707
5708 MaybeObject* DescriptorArray::CopyFrom(int dst_index,
5709                                        DescriptorArray* src,
5710                                        int src_index,
5711                                        const WhitenessWitness& witness) {
5712   Object* value = src->GetValue(src_index);
5713   PropertyDetails details(src->GetDetails(src_index));
5714   if (details.type() == CALLBACKS && value->IsAccessorPair()) {
5715     MaybeObject* maybe_copy =
5716         AccessorPair::cast(value)->CopyWithoutTransitions();
5717     if (!maybe_copy->To(&value)) return maybe_copy;
5718   }
5719   Descriptor desc(src->GetKey(src_index), value, details);
5720   Set(dst_index, &desc, witness);
5721   return this;
5722 }
5723
5724
5725 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor,
5726                                          TransitionFlag transition_flag) {
5727   // Transitions are only kept when inserting another transition.
5728   // This precondition is not required by this function's implementation, but
5729   // is currently required by the semantics of maps, so we check it.
5730   // Conversely, we filter after replacing, so replacing a transition and
5731   // removing all other transitions is not supported.
5732   bool remove_transitions = transition_flag == REMOVE_TRANSITIONS;
5733   ASSERT(remove_transitions == !descriptor->ContainsTransition());
5734   ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR);
5735
5736   // Ensure the key is a symbol.
5737   { MaybeObject* maybe_result = descriptor->KeyToSymbol();
5738     if (maybe_result->IsFailure()) return maybe_result;
5739   }
5740
5741   int new_size = 0;
5742   for (int i = 0; i < number_of_descriptors(); i++) {
5743     if (IsNullDescriptor(i)) continue;
5744     if (remove_transitions && IsTransitionOnly(i)) continue;
5745     new_size++;
5746   }
5747
5748   // If key is in descriptor, we replace it in-place when filtering.
5749   // Count a null descriptor for key as inserted, not replaced.
5750   int index = Search(descriptor->GetKey());
5751   const bool replacing = (index != kNotFound);
5752   bool keep_enumeration_index = false;
5753   if (replacing) {
5754     // We are replacing an existing descriptor.  We keep the enumeration
5755     // index of a visible property.
5756     PropertyType t = PropertyDetails(GetDetails(index)).type();
5757     if (t == CONSTANT_FUNCTION ||
5758         t == FIELD ||
5759         t == CALLBACKS ||
5760         t == INTERCEPTOR) {
5761       keep_enumeration_index = true;
5762     } else if (remove_transitions) {
5763      // Replaced descriptor has been counted as removed if it is
5764      // a transition that will be replaced.  Adjust count in this case.
5765       ++new_size;
5766     }
5767   } else {
5768     ++new_size;
5769   }
5770
5771   DescriptorArray* new_descriptors;
5772   { MaybeObject* maybe_result = Allocate(new_size);
5773     if (!maybe_result->To(&new_descriptors)) return maybe_result;
5774   }
5775
5776   DescriptorArray::WhitenessWitness witness(new_descriptors);
5777
5778   // Set the enumeration index in the descriptors and set the enumeration index
5779   // in the result.
5780   int enumeration_index = NextEnumerationIndex();
5781   if (!descriptor->ContainsTransition()) {
5782     if (keep_enumeration_index) {
5783       descriptor->SetEnumerationIndex(
5784           PropertyDetails(GetDetails(index)).index());
5785     } else {
5786       descriptor->SetEnumerationIndex(enumeration_index);
5787       ++enumeration_index;
5788     }
5789   }
5790   new_descriptors->SetNextEnumerationIndex(enumeration_index);
5791
5792   // Copy the descriptors, filtering out transitions and null descriptors,
5793   // and inserting or replacing a descriptor.
5794   int to_index = 0;
5795   int insertion_index = -1;
5796   int from_index = 0;
5797   while (from_index < number_of_descriptors()) {
5798     if (insertion_index < 0 &&
5799         InsertionPointFound(GetKey(from_index), descriptor->GetKey())) {
5800       insertion_index = to_index++;
5801       if (replacing) from_index++;
5802     } else {
5803       if (!(IsNullDescriptor(from_index) ||
5804             (remove_transitions && IsTransitionOnly(from_index)))) {
5805         MaybeObject* copy_result =
5806             new_descriptors->CopyFrom(to_index++, this, from_index, witness);
5807         if (copy_result->IsFailure()) return copy_result;
5808       }
5809       from_index++;
5810     }
5811   }
5812   if (insertion_index < 0) insertion_index = to_index++;
5813   new_descriptors->Set(insertion_index, descriptor, witness);
5814
5815   ASSERT(to_index == new_descriptors->number_of_descriptors());
5816   SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5817
5818   return new_descriptors;
5819 }
5820
5821
5822 MaybeObject* DescriptorArray::RemoveTransitions() {
5823   // Allocate the new descriptor array.
5824   int new_number_of_descriptors = 0;
5825   for (int i = 0; i < number_of_descriptors(); i++) {
5826     if (IsProperty(i)) new_number_of_descriptors++;
5827   }
5828   DescriptorArray* new_descriptors;
5829   { MaybeObject* maybe_result = Allocate(new_number_of_descriptors);
5830     if (!maybe_result->To(&new_descriptors)) return maybe_result;
5831   }
5832
5833   // Copy the content.
5834   DescriptorArray::WhitenessWitness witness(new_descriptors);
5835   int next_descriptor = 0;
5836   for (int i = 0; i < number_of_descriptors(); i++) {
5837     if (IsProperty(i)) {
5838       MaybeObject* copy_result =
5839           new_descriptors->CopyFrom(next_descriptor++, this, i, witness);
5840       if (copy_result->IsFailure()) return copy_result;
5841     }
5842   }
5843   ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
5844
5845   return new_descriptors;
5846 }
5847
5848
5849 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
5850   // In-place heap sort.
5851   int len = number_of_descriptors();
5852
5853   // Bottom-up max-heap construction.
5854   // Index of the last node with children
5855   const int max_parent_index = (len / 2) - 1;
5856   for (int i = max_parent_index; i >= 0; --i) {
5857     int parent_index = i;
5858     const uint32_t parent_hash = GetKey(i)->Hash();
5859     while (parent_index <= max_parent_index) {
5860       int child_index = 2 * parent_index + 1;
5861       uint32_t child_hash = GetKey(child_index)->Hash();
5862       if (child_index + 1 < len) {
5863         uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
5864         if (right_child_hash > child_hash) {
5865           child_index++;
5866           child_hash = right_child_hash;
5867         }
5868       }
5869       if (child_hash <= parent_hash) break;
5870       NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
5871       // Now element at child_index could be < its children.
5872       parent_index = child_index;  // parent_hash remains correct.
5873     }
5874   }
5875
5876   // Extract elements and create sorted array.
5877   for (int i = len - 1; i > 0; --i) {
5878     // Put max element at the back of the array.
5879     NoIncrementalWriteBarrierSwapDescriptors(0, i);
5880     // Shift down the new top element.
5881     int parent_index = 0;
5882     const uint32_t parent_hash = GetKey(parent_index)->Hash();
5883     const int max_parent_index = (i / 2) - 1;
5884     while (parent_index <= max_parent_index) {
5885       int child_index = parent_index * 2 + 1;
5886       uint32_t child_hash = GetKey(child_index)->Hash();
5887       if (child_index + 1 < i) {
5888         uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
5889         if (right_child_hash > child_hash) {
5890           child_index++;
5891           child_hash = right_child_hash;
5892         }
5893       }
5894       if (child_hash <= parent_hash) break;
5895       NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
5896       parent_index = child_index;
5897     }
5898   }
5899 }
5900
5901
5902 void DescriptorArray::Sort(const WhitenessWitness& witness) {
5903   SortUnchecked(witness);
5904   SLOW_ASSERT(IsSortedNoDuplicates());
5905 }
5906
5907
5908 int DescriptorArray::BinarySearch(String* name, int low, int high) {
5909   uint32_t hash = name->Hash();
5910
5911   while (low <= high) {
5912     int mid = (low + high) / 2;
5913     String* mid_name = GetKey(mid);
5914     uint32_t mid_hash = mid_name->Hash();
5915
5916     if (mid_hash > hash) {
5917       high = mid - 1;
5918       continue;
5919     }
5920     if (mid_hash < hash) {
5921       low = mid + 1;
5922       continue;
5923     }
5924     // Found an element with the same hash-code.
5925     ASSERT(hash == mid_hash);
5926     // There might be more, so we find the first one and
5927     // check them all to see if we have a match.
5928     if (name == mid_name  && !is_null_descriptor(mid)) return mid;
5929     while ((mid > low) && (GetKey(mid - 1)->Hash() == hash)) mid--;
5930     for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) {
5931       if (GetKey(mid)->Equals(name) && !is_null_descriptor(mid)) return mid;
5932     }
5933     break;
5934   }
5935   return kNotFound;
5936 }
5937
5938
5939 int DescriptorArray::LinearSearch(String* name, int len) {
5940   uint32_t hash = name->Hash();
5941   for (int number = 0; number < len; number++) {
5942     String* entry = GetKey(number);
5943     if ((entry->Hash() == hash) &&
5944         name->Equals(entry) &&
5945         !is_null_descriptor(number)) {
5946       return number;
5947     }
5948   }
5949   return kNotFound;
5950 }
5951
5952
5953 MaybeObject* AccessorPair::CopyWithoutTransitions() {
5954   Heap* heap = GetHeap();
5955   AccessorPair* copy;
5956   { MaybeObject* maybe_copy = heap->AllocateAccessorPair();
5957     if (!maybe_copy->To(&copy)) return maybe_copy;
5958   }
5959   copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter());
5960   copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter());
5961   return copy;
5962 }
5963
5964
5965 Object* AccessorPair::GetComponent(AccessorComponent component) {
5966     Object* accessor = (component == ACCESSOR_GETTER) ? getter() : setter();
5967     return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
5968 }
5969
5970
5971 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count,
5972                                                PretenureFlag pretenure) {
5973   ASSERT(deopt_entry_count > 0);
5974   return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count),
5975                                   pretenure);
5976 }
5977
5978
5979 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points,
5980                                                 PretenureFlag pretenure) {
5981   if (number_of_deopt_points == 0) return HEAP->empty_fixed_array();
5982   return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points),
5983                                   pretenure);
5984 }
5985
5986
5987 #ifdef DEBUG
5988 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
5989   if (IsEmpty()) return other->IsEmpty();
5990   if (other->IsEmpty()) return false;
5991   if (length() != other->length()) return false;
5992   for (int i = 0; i < length(); ++i) {
5993     if (get(i) != other->get(i) && i != kContentArrayIndex) return false;
5994   }
5995   return GetContentArray()->IsEqualTo(other->GetContentArray());
5996 }
5997 #endif
5998
5999
6000 bool String::LooksValid() {
6001   if (!Isolate::Current()->heap()->Contains(this)) return false;
6002   return true;
6003 }
6004
6005
6006 String::FlatContent String::GetFlatContent() {
6007   int length = this->length();
6008   StringShape shape(this);
6009   String* string = this;
6010   int offset = 0;
6011   if (shape.representation_tag() == kConsStringTag) {
6012     ConsString* cons = ConsString::cast(string);
6013     if (cons->second()->length() != 0) {
6014       return FlatContent();
6015     }
6016     string = cons->first();
6017     shape = StringShape(string);
6018   }
6019   if (shape.representation_tag() == kSlicedStringTag) {
6020     SlicedString* slice = SlicedString::cast(string);
6021     offset = slice->offset();
6022     string = slice->parent();
6023     shape = StringShape(string);
6024     ASSERT(shape.representation_tag() != kConsStringTag &&
6025            shape.representation_tag() != kSlicedStringTag);
6026   }
6027   if (shape.encoding_tag() == kAsciiStringTag) {
6028     const char* start;
6029     if (shape.representation_tag() == kSeqStringTag) {
6030       start = SeqAsciiString::cast(string)->GetChars();
6031     } else {
6032       start = ExternalAsciiString::cast(string)->GetChars();
6033     }
6034     return FlatContent(Vector<const char>(start + offset, length));
6035   } else {
6036     ASSERT(shape.encoding_tag() == kTwoByteStringTag);
6037     const uc16* start;
6038     if (shape.representation_tag() == kSeqStringTag) {
6039       start = SeqTwoByteString::cast(string)->GetChars();
6040     } else {
6041       start = ExternalTwoByteString::cast(string)->GetChars();
6042     }
6043     return FlatContent(Vector<const uc16>(start + offset, length));
6044   }
6045 }
6046
6047
6048 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
6049                                           RobustnessFlag robust_flag,
6050                                           int offset,
6051                                           int length,
6052                                           int* length_return) {
6053   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
6054     return SmartArrayPointer<char>(NULL);
6055   }
6056   Heap* heap = GetHeap();
6057
6058   // Negative length means the to the end of the string.
6059   if (length < 0) length = kMaxInt - offset;
6060
6061   // Compute the size of the UTF-8 string. Start at the specified offset.
6062   Access<StringInputBuffer> buffer(
6063       heap->isolate()->objects_string_input_buffer());
6064   buffer->Reset(offset, this);
6065   int character_position = offset;
6066   int utf8_bytes = 0;
6067   int last = unibrow::Utf16::kNoPreviousCharacter;
6068   while (buffer->has_more() && character_position++ < offset + length) {
6069     uint16_t character = buffer->GetNext();
6070     utf8_bytes += unibrow::Utf8::Length(character, last);
6071     last = character;
6072   }
6073
6074   if (length_return) {
6075     *length_return = utf8_bytes;
6076   }
6077
6078   char* result = NewArray<char>(utf8_bytes + 1);
6079
6080   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
6081   buffer->Rewind();
6082   buffer->Seek(offset);
6083   character_position = offset;
6084   int utf8_byte_position = 0;
6085   last = unibrow::Utf16::kNoPreviousCharacter;
6086   while (buffer->has_more() && character_position++ < offset + length) {
6087     uint16_t character = buffer->GetNext();
6088     if (allow_nulls == DISALLOW_NULLS && character == 0) {
6089       character = ' ';
6090     }
6091     utf8_byte_position +=
6092         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
6093     last = character;
6094   }
6095   result[utf8_byte_position] = 0;
6096   return SmartArrayPointer<char>(result);
6097 }
6098
6099
6100 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
6101                                           RobustnessFlag robust_flag,
6102                                           int* length_return) {
6103   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
6104 }
6105
6106
6107 const uc16* String::GetTwoByteData() {
6108   return GetTwoByteData(0);
6109 }
6110
6111
6112 const uc16* String::GetTwoByteData(unsigned start) {
6113   ASSERT(!IsAsciiRepresentationUnderneath());
6114   switch (StringShape(this).representation_tag()) {
6115     case kSeqStringTag:
6116       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
6117     case kExternalStringTag:
6118       return ExternalTwoByteString::cast(this)->
6119         ExternalTwoByteStringGetData(start);
6120     case kSlicedStringTag: {
6121       SlicedString* slice = SlicedString::cast(this);
6122       return slice->parent()->GetTwoByteData(start + slice->offset());
6123     }
6124     case kConsStringTag:
6125       UNREACHABLE();
6126       return NULL;
6127   }
6128   UNREACHABLE();
6129   return NULL;
6130 }
6131
6132
6133 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
6134   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
6135     return SmartArrayPointer<uc16>();
6136   }
6137   Heap* heap = GetHeap();
6138
6139   Access<StringInputBuffer> buffer(
6140       heap->isolate()->objects_string_input_buffer());
6141   buffer->Reset(this);
6142
6143   uc16* result = NewArray<uc16>(length() + 1);
6144
6145   int i = 0;
6146   while (buffer->has_more()) {
6147     uint16_t character = buffer->GetNext();
6148     result[i++] = character;
6149   }
6150   result[i] = 0;
6151   return SmartArrayPointer<uc16>(result);
6152 }
6153
6154
6155 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
6156   return reinterpret_cast<uc16*>(
6157       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
6158 }
6159
6160
6161 void SeqTwoByteString::SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
6162                                                            unsigned* offset_ptr,
6163                                                            unsigned max_chars) {
6164   unsigned chars_read = 0;
6165   unsigned offset = *offset_ptr;
6166   while (chars_read < max_chars) {
6167     uint16_t c = *reinterpret_cast<uint16_t*>(
6168         reinterpret_cast<char*>(this) -
6169             kHeapObjectTag + kHeaderSize + offset * kShortSize);
6170     if (c <= kMaxAsciiCharCode) {
6171       // Fast case for ASCII characters.   Cursor is an input output argument.
6172       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
6173                                                           rbb->util_buffer,
6174                                                           rbb->capacity,
6175                                                           rbb->cursor)) {
6176         break;
6177       }
6178     } else {
6179       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
6180                                                              rbb->util_buffer,
6181                                                              rbb->capacity,
6182                                                              rbb->cursor)) {
6183         break;
6184       }
6185     }
6186     offset++;
6187     chars_read++;
6188   }
6189   *offset_ptr = offset;
6190   rbb->remaining += chars_read;
6191 }
6192
6193
6194 const unibrow::byte* SeqAsciiString::SeqAsciiStringReadBlock(
6195     unsigned* remaining,
6196     unsigned* offset_ptr,
6197     unsigned max_chars) {
6198   const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
6199       kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
6200   *remaining = max_chars;
6201   *offset_ptr += max_chars;
6202   return b;
6203 }
6204
6205
6206 // This will iterate unless the block of string data spans two 'halves' of
6207 // a ConsString, in which case it will recurse.  Since the block of string
6208 // data to be read has a maximum size this limits the maximum recursion
6209 // depth to something sane.  Since C++ does not have tail call recursion
6210 // elimination, the iteration must be explicit. Since this is not an
6211 // -IntoBuffer method it can delegate to one of the efficient
6212 // *AsciiStringReadBlock routines.
6213 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
6214                                                      unsigned* offset_ptr,
6215                                                      unsigned max_chars) {
6216   ConsString* current = this;
6217   unsigned offset = *offset_ptr;
6218   int offset_correction = 0;
6219
6220   while (true) {
6221     String* left = current->first();
6222     unsigned left_length = (unsigned)left->length();
6223     if (left_length > offset &&
6224         (max_chars <= left_length - offset ||
6225          (rbb->capacity <= left_length - offset &&
6226           (max_chars = left_length - offset, true)))) {  // comma operator!
6227       // Left hand side only - iterate unless we have reached the bottom of
6228       // the cons tree.  The assignment on the left of the comma operator is
6229       // in order to make use of the fact that the -IntoBuffer routines can
6230       // produce at most 'capacity' characters.  This enables us to postpone
6231       // the point where we switch to the -IntoBuffer routines (below) in order
6232       // to maximize the chances of delegating a big chunk of work to the
6233       // efficient *AsciiStringReadBlock routines.
6234       if (StringShape(left).IsCons()) {
6235         current = ConsString::cast(left);
6236         continue;
6237       } else {
6238         const unibrow::byte* answer =
6239             String::ReadBlock(left, rbb, &offset, max_chars);
6240         *offset_ptr = offset + offset_correction;
6241         return answer;
6242       }
6243     } else if (left_length <= offset) {
6244       // Right hand side only - iterate unless we have reached the bottom of
6245       // the cons tree.
6246       String* right = current->second();
6247       offset -= left_length;
6248       offset_correction += left_length;
6249       if (StringShape(right).IsCons()) {
6250         current = ConsString::cast(right);
6251         continue;
6252       } else {
6253         const unibrow::byte* answer =
6254             String::ReadBlock(right, rbb, &offset, max_chars);
6255         *offset_ptr = offset + offset_correction;
6256         return answer;
6257       }
6258     } else {
6259       // The block to be read spans two sides of the ConsString, so we call the
6260       // -IntoBuffer version, which will recurse.  The -IntoBuffer methods
6261       // are able to assemble data from several part strings because they use
6262       // the util_buffer to store their data and never return direct pointers
6263       // to their storage.  We don't try to read more than the buffer capacity
6264       // here or we can get too much recursion.
6265       ASSERT(rbb->remaining == 0);
6266       ASSERT(rbb->cursor == 0);
6267       current->ConsStringReadBlockIntoBuffer(
6268           rbb,
6269           &offset,
6270           max_chars > rbb->capacity ? rbb->capacity : max_chars);
6271       *offset_ptr = offset + offset_correction;
6272       return rbb->util_buffer;
6273     }
6274   }
6275 }
6276
6277
6278 const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock(
6279       unsigned* remaining,
6280       unsigned* offset_ptr,
6281       unsigned max_chars) {
6282   // Cast const char* to unibrow::byte* (signedness difference).
6283   const unibrow::byte* b =
6284       reinterpret_cast<const unibrow::byte*>(GetChars()) + *offset_ptr;
6285   *remaining = max_chars;
6286   *offset_ptr += max_chars;
6287   return b;
6288 }
6289
6290
6291 void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer(
6292       ReadBlockBuffer* rbb,
6293       unsigned* offset_ptr,
6294       unsigned max_chars) {
6295   unsigned chars_read = 0;
6296   unsigned offset = *offset_ptr;
6297   const uint16_t* data = GetChars();
6298   while (chars_read < max_chars) {
6299     uint16_t c = data[offset];
6300     if (c <= kMaxAsciiCharCode) {
6301       // Fast case for ASCII characters. Cursor is an input output argument.
6302       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
6303                                                           rbb->util_buffer,
6304                                                           rbb->capacity,
6305                                                           rbb->cursor))
6306         break;
6307     } else {
6308       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
6309                                                              rbb->util_buffer,
6310                                                              rbb->capacity,
6311                                                              rbb->cursor))
6312         break;
6313     }
6314     offset++;
6315     chars_read++;
6316   }
6317   *offset_ptr = offset;
6318   rbb->remaining += chars_read;
6319 }
6320
6321
6322 void SeqAsciiString::SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
6323                                                  unsigned* offset_ptr,
6324                                                  unsigned max_chars) {
6325   unsigned capacity = rbb->capacity - rbb->cursor;
6326   if (max_chars > capacity) max_chars = capacity;
6327   memcpy(rbb->util_buffer + rbb->cursor,
6328          reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
6329              *offset_ptr * kCharSize,
6330          max_chars);
6331   rbb->remaining += max_chars;
6332   *offset_ptr += max_chars;
6333   rbb->cursor += max_chars;
6334 }
6335
6336
6337 void ExternalAsciiString::ExternalAsciiStringReadBlockIntoBuffer(
6338       ReadBlockBuffer* rbb,
6339       unsigned* offset_ptr,
6340       unsigned max_chars) {
6341   unsigned capacity = rbb->capacity - rbb->cursor;
6342   if (max_chars > capacity) max_chars = capacity;
6343   memcpy(rbb->util_buffer + rbb->cursor, GetChars() + *offset_ptr, max_chars);
6344   rbb->remaining += max_chars;
6345   *offset_ptr += max_chars;
6346   rbb->cursor += max_chars;
6347 }
6348
6349
6350 // This method determines the type of string involved and then copies
6351 // a whole chunk of characters into a buffer, or returns a pointer to a buffer
6352 // where they can be found.  The pointer is not necessarily valid across a GC
6353 // (see AsciiStringReadBlock).
6354 const unibrow::byte* String::ReadBlock(String* input,
6355                                        ReadBlockBuffer* rbb,
6356                                        unsigned* offset_ptr,
6357                                        unsigned max_chars) {
6358   ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
6359   if (max_chars == 0) {
6360     rbb->remaining = 0;
6361     return NULL;
6362   }
6363   switch (StringShape(input).representation_tag()) {
6364     case kSeqStringTag:
6365       if (input->IsAsciiRepresentation()) {
6366         SeqAsciiString* str = SeqAsciiString::cast(input);
6367         return str->SeqAsciiStringReadBlock(&rbb->remaining,
6368                                             offset_ptr,
6369                                             max_chars);
6370       } else {
6371         SeqTwoByteString* str = SeqTwoByteString::cast(input);
6372         str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
6373                                                  offset_ptr,
6374                                                  max_chars);
6375         return rbb->util_buffer;
6376       }
6377     case kConsStringTag:
6378       return ConsString::cast(input)->ConsStringReadBlock(rbb,
6379                                                           offset_ptr,
6380                                                           max_chars);
6381     case kExternalStringTag:
6382       if (input->IsAsciiRepresentation()) {
6383         return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
6384             &rbb->remaining,
6385             offset_ptr,
6386             max_chars);
6387       } else {
6388         ExternalTwoByteString::cast(input)->
6389             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6390                                                      offset_ptr,
6391                                                      max_chars);
6392         return rbb->util_buffer;
6393       }
6394     case kSlicedStringTag:
6395       return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
6396                                                               offset_ptr,
6397                                                               max_chars);
6398     default:
6399       break;
6400   }
6401
6402   UNREACHABLE();
6403   return 0;
6404 }
6405
6406
6407 void Relocatable::PostGarbageCollectionProcessing() {
6408   Isolate* isolate = Isolate::Current();
6409   Relocatable* current = isolate->relocatable_top();
6410   while (current != NULL) {
6411     current->PostGarbageCollection();
6412     current = current->prev_;
6413   }
6414 }
6415
6416
6417 // Reserve space for statics needing saving and restoring.
6418 int Relocatable::ArchiveSpacePerThread() {
6419   return sizeof(Isolate::Current()->relocatable_top());
6420 }
6421
6422
6423 // Archive statics that are thread local.
6424 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
6425   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
6426   isolate->set_relocatable_top(NULL);
6427   return to + ArchiveSpacePerThread();
6428 }
6429
6430
6431 // Restore statics that are thread local.
6432 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
6433   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
6434   return from + ArchiveSpacePerThread();
6435 }
6436
6437
6438 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
6439   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
6440   Iterate(v, top);
6441   return thread_storage + ArchiveSpacePerThread();
6442 }
6443
6444
6445 void Relocatable::Iterate(ObjectVisitor* v) {
6446   Isolate* isolate = Isolate::Current();
6447   Iterate(v, isolate->relocatable_top());
6448 }
6449
6450
6451 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
6452   Relocatable* current = top;
6453   while (current != NULL) {
6454     current->IterateInstance(v);
6455     current = current->prev_;
6456   }
6457 }
6458
6459
6460 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
6461     : Relocatable(isolate),
6462       str_(str.location()),
6463       length_(str->length()) {
6464   PostGarbageCollection();
6465 }
6466
6467
6468 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
6469     : Relocatable(isolate),
6470       str_(0),
6471       is_ascii_(true),
6472       length_(input.length()),
6473       start_(input.start()) { }
6474
6475
6476 void FlatStringReader::PostGarbageCollection() {
6477   if (str_ == NULL) return;
6478   Handle<String> str(str_);
6479   ASSERT(str->IsFlat());
6480   String::FlatContent content = str->GetFlatContent();
6481   ASSERT(content.IsFlat());
6482   is_ascii_ = content.IsAscii();
6483   if (is_ascii_) {
6484     start_ = content.ToAsciiVector().start();
6485   } else {
6486     start_ = content.ToUC16Vector().start();
6487   }
6488 }
6489
6490
6491 void StringInputBuffer::Seek(unsigned pos) {
6492   Reset(pos, input_);
6493 }
6494
6495
6496 void SafeStringInputBuffer::Seek(unsigned pos) {
6497   Reset(pos, input_);
6498 }
6499
6500
6501 // This method determines the type of string involved and then copies
6502 // a whole chunk of characters into a buffer.  It can be used with strings
6503 // that have been glued together to form a ConsString and which must cooperate
6504 // to fill up a buffer.
6505 void String::ReadBlockIntoBuffer(String* input,
6506                                  ReadBlockBuffer* rbb,
6507                                  unsigned* offset_ptr,
6508                                  unsigned max_chars) {
6509   ASSERT(*offset_ptr <= (unsigned)input->length());
6510   if (max_chars == 0) return;
6511
6512   switch (StringShape(input).representation_tag()) {
6513     case kSeqStringTag:
6514       if (input->IsAsciiRepresentation()) {
6515         SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
6516                                                                  offset_ptr,
6517                                                                  max_chars);
6518         return;
6519       } else {
6520         SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
6521                                                                      offset_ptr,
6522                                                                      max_chars);
6523         return;
6524       }
6525     case kConsStringTag:
6526       ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
6527                                                              offset_ptr,
6528                                                              max_chars);
6529       return;
6530     case kExternalStringTag:
6531       if (input->IsAsciiRepresentation()) {
6532         ExternalAsciiString::cast(input)->
6533             ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
6534       } else {
6535         ExternalTwoByteString::cast(input)->
6536             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6537                                                      offset_ptr,
6538                                                      max_chars);
6539        }
6540        return;
6541     case kSlicedStringTag:
6542       SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
6543                                                                  offset_ptr,
6544                                                                  max_chars);
6545       return;
6546     default:
6547       break;
6548   }
6549
6550   UNREACHABLE();
6551   return;
6552 }
6553
6554
6555 const unibrow::byte* String::ReadBlock(String* input,
6556                                        unibrow::byte* util_buffer,
6557                                        unsigned capacity,
6558                                        unsigned* remaining,
6559                                        unsigned* offset_ptr) {
6560   ASSERT(*offset_ptr <= (unsigned)input->length());
6561   unsigned chars = input->length() - *offset_ptr;
6562   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6563   const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
6564   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6565   *remaining = rbb.remaining;
6566   return answer;
6567 }
6568
6569
6570 const unibrow::byte* String::ReadBlock(String** raw_input,
6571                                        unibrow::byte* util_buffer,
6572                                        unsigned capacity,
6573                                        unsigned* remaining,
6574                                        unsigned* offset_ptr) {
6575   Handle<String> input(raw_input);
6576   ASSERT(*offset_ptr <= (unsigned)input->length());
6577   unsigned chars = input->length() - *offset_ptr;
6578   if (chars > capacity) chars = capacity;
6579   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6580   ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
6581   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6582   *remaining = rbb.remaining;
6583   return rbb.util_buffer;
6584 }
6585
6586
6587 // This will iterate unless the block of string data spans two 'halves' of
6588 // a ConsString, in which case it will recurse.  Since the block of string
6589 // data to be read has a maximum size this limits the maximum recursion
6590 // depth to something sane.  Since C++ does not have tail call recursion
6591 // elimination, the iteration must be explicit.
6592 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
6593                                                unsigned* offset_ptr,
6594                                                unsigned max_chars) {
6595   ConsString* current = this;
6596   unsigned offset = *offset_ptr;
6597   int offset_correction = 0;
6598
6599   while (true) {
6600     String* left = current->first();
6601     unsigned left_length = (unsigned)left->length();
6602     if (left_length > offset &&
6603       max_chars <= left_length - offset) {
6604       // Left hand side only - iterate unless we have reached the bottom of
6605       // the cons tree.
6606       if (StringShape(left).IsCons()) {
6607         current = ConsString::cast(left);
6608         continue;
6609       } else {
6610         String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
6611         *offset_ptr = offset + offset_correction;
6612         return;
6613       }
6614     } else if (left_length <= offset) {
6615       // Right hand side only - iterate unless we have reached the bottom of
6616       // the cons tree.
6617       offset -= left_length;
6618       offset_correction += left_length;
6619       String* right = current->second();
6620       if (StringShape(right).IsCons()) {
6621         current = ConsString::cast(right);
6622         continue;
6623       } else {
6624         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6625         *offset_ptr = offset + offset_correction;
6626         return;
6627       }
6628     } else {
6629       // The block to be read spans two sides of the ConsString, so we recurse.
6630       // First recurse on the left.
6631       max_chars -= left_length - offset;
6632       String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
6633       // We may have reached the max or there may not have been enough space
6634       // in the buffer for the characters in the left hand side.
6635       if (offset == left_length) {
6636         // Recurse on the right.
6637         String* right = String::cast(current->second());
6638         offset -= left_length;
6639         offset_correction += left_length;
6640         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6641       }
6642       *offset_ptr = offset + offset_correction;
6643       return;
6644     }
6645   }
6646 }
6647
6648
6649 uint16_t ConsString::ConsStringGet(int index) {
6650   ASSERT(index >= 0 && index < this->length());
6651
6652   // Check for a flattened cons string
6653   if (second()->length() == 0) {
6654     String* left = first();
6655     return left->Get(index);
6656   }
6657
6658   String* string = String::cast(this);
6659
6660   while (true) {
6661     if (StringShape(string).IsCons()) {
6662       ConsString* cons_string = ConsString::cast(string);
6663       String* left = cons_string->first();
6664       if (left->length() > index) {
6665         string = left;
6666       } else {
6667         index -= left->length();
6668         string = cons_string->second();
6669       }
6670     } else {
6671       return string->Get(index);
6672     }
6673   }
6674
6675   UNREACHABLE();
6676   return 0;
6677 }
6678
6679
6680 uint16_t SlicedString::SlicedStringGet(int index) {
6681   return parent()->Get(offset() + index);
6682 }
6683
6684
6685 const unibrow::byte* SlicedString::SlicedStringReadBlock(
6686     ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6687   unsigned offset = this->offset();
6688   *offset_ptr += offset;
6689   const unibrow::byte* answer = String::ReadBlock(String::cast(parent()),
6690                                                   buffer, offset_ptr, chars);
6691   *offset_ptr -= offset;
6692   return answer;
6693 }
6694
6695
6696 void SlicedString::SlicedStringReadBlockIntoBuffer(
6697     ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6698   unsigned offset = this->offset();
6699   *offset_ptr += offset;
6700   String::ReadBlockIntoBuffer(String::cast(parent()),
6701                               buffer, offset_ptr, chars);
6702   *offset_ptr -= offset;
6703 }
6704
6705 template <typename sinkchar>
6706 void String::WriteToFlat(String* src,
6707                          sinkchar* sink,
6708                          int f,
6709                          int t) {
6710   String* source = src;
6711   int from = f;
6712   int to = t;
6713   while (true) {
6714     ASSERT(0 <= from && from <= to && to <= source->length());
6715     switch (StringShape(source).full_representation_tag()) {
6716       case kAsciiStringTag | kExternalStringTag: {
6717         CopyChars(sink,
6718                   ExternalAsciiString::cast(source)->GetChars() + from,
6719                   to - from);
6720         return;
6721       }
6722       case kTwoByteStringTag | kExternalStringTag: {
6723         const uc16* data =
6724             ExternalTwoByteString::cast(source)->GetChars();
6725         CopyChars(sink,
6726                   data + from,
6727                   to - from);
6728         return;
6729       }
6730       case kAsciiStringTag | kSeqStringTag: {
6731         CopyChars(sink,
6732                   SeqAsciiString::cast(source)->GetChars() + from,
6733                   to - from);
6734         return;
6735       }
6736       case kTwoByteStringTag | kSeqStringTag: {
6737         CopyChars(sink,
6738                   SeqTwoByteString::cast(source)->GetChars() + from,
6739                   to - from);
6740         return;
6741       }
6742       case kAsciiStringTag | kConsStringTag:
6743       case kTwoByteStringTag | kConsStringTag: {
6744         ConsString* cons_string = ConsString::cast(source);
6745         String* first = cons_string->first();
6746         int boundary = first->length();
6747         if (to - boundary >= boundary - from) {
6748           // Right hand side is longer.  Recurse over left.
6749           if (from < boundary) {
6750             WriteToFlat(first, sink, from, boundary);
6751             sink += boundary - from;
6752             from = 0;
6753           } else {
6754             from -= boundary;
6755           }
6756           to -= boundary;
6757           source = cons_string->second();
6758         } else {
6759           // Left hand side is longer.  Recurse over right.
6760           if (to > boundary) {
6761             String* second = cons_string->second();
6762             // When repeatedly appending to a string, we get a cons string that
6763             // is unbalanced to the left, a list, essentially.  We inline the
6764             // common case of sequential ascii right child.
6765             if (to - boundary == 1) {
6766               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
6767             } else if (second->IsSeqAsciiString()) {
6768               CopyChars(sink + boundary - from,
6769                         SeqAsciiString::cast(second)->GetChars(),
6770                         to - boundary);
6771             } else {
6772               WriteToFlat(second,
6773                           sink + boundary - from,
6774                           0,
6775                           to - boundary);
6776             }
6777             to = boundary;
6778           }
6779           source = first;
6780         }
6781         break;
6782       }
6783       case kAsciiStringTag | kSlicedStringTag:
6784       case kTwoByteStringTag | kSlicedStringTag: {
6785         SlicedString* slice = SlicedString::cast(source);
6786         unsigned offset = slice->offset();
6787         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
6788         return;
6789       }
6790     }
6791   }
6792 }
6793
6794
6795 template <typename IteratorA, typename IteratorB>
6796 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
6797   // General slow case check.  We know that the ia and ib iterators
6798   // have the same length.
6799   while (ia->has_more()) {
6800     uint32_t ca = ia->GetNext();
6801     uint32_t cb = ib->GetNext();
6802     ASSERT(ca <= unibrow::Utf16::kMaxNonSurrogateCharCode);
6803     ASSERT(cb <= unibrow::Utf16::kMaxNonSurrogateCharCode);
6804     if (ca != cb)
6805       return false;
6806   }
6807   return true;
6808 }
6809
6810
6811 // Compares the contents of two strings by reading and comparing
6812 // int-sized blocks of characters.
6813 template <typename Char>
6814 static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
6815   int length = a.length();
6816   ASSERT_EQ(length, b.length());
6817   const Char* pa = a.start();
6818   const Char* pb = b.start();
6819   int i = 0;
6820 #ifndef V8_HOST_CAN_READ_UNALIGNED
6821   // If this architecture isn't comfortable reading unaligned ints
6822   // then we have to check that the strings are aligned before
6823   // comparing them blockwise.
6824   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
6825   uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
6826   uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
6827   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
6828 #endif
6829     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
6830     int endpoint = length - kStepSize;
6831     // Compare blocks until we reach near the end of the string.
6832     for (; i <= endpoint; i += kStepSize) {
6833       uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
6834       uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
6835       if (wa != wb) {
6836         return false;
6837       }
6838     }
6839 #ifndef V8_HOST_CAN_READ_UNALIGNED
6840   }
6841 #endif
6842   // Compare the remaining characters that didn't fit into a block.
6843   for (; i < length; i++) {
6844     if (a[i] != b[i]) {
6845       return false;
6846     }
6847   }
6848   return true;
6849 }
6850
6851
6852 template <typename IteratorA>
6853 static inline bool CompareStringContentsPartial(Isolate* isolate,
6854                                                 IteratorA* ia,
6855                                                 String* b) {
6856   String::FlatContent content = b->GetFlatContent();
6857   if (content.IsFlat()) {
6858     if (content.IsAscii()) {
6859       VectorIterator<char> ib(content.ToAsciiVector());
6860       return CompareStringContents(ia, &ib);
6861     } else {
6862       VectorIterator<uc16> ib(content.ToUC16Vector());
6863       return CompareStringContents(ia, &ib);
6864     }
6865   } else {
6866     isolate->objects_string_compare_buffer_b()->Reset(0, b);
6867     return CompareStringContents(ia,
6868                                  isolate->objects_string_compare_buffer_b());
6869   }
6870 }
6871
6872
6873 bool String::SlowEqualsExternal(uc16 *string, int length) {
6874   int len = this->length();
6875   if (len != length) return false;
6876   if (len == 0) return true;
6877
6878   // We know the strings are both non-empty. Compare the first chars
6879   // before we try to flatten the strings.
6880   if (this->Get(0) != string[0]) return false;
6881
6882   String* lhs = this->TryFlattenGetString();
6883
6884   if (lhs->IsFlat()) {
6885     String::FlatContent lhs_content = lhs->GetFlatContent();
6886     if (lhs->IsAsciiRepresentation()) {
6887       Vector<const char> vec1 = lhs_content.ToAsciiVector();
6888       VectorIterator<char> buf1(vec1);
6889       VectorIterator<uc16> ib(string, length);
6890       return CompareStringContents(&buf1, &ib);
6891     } else {
6892       Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
6893       Vector<const uc16> vec2(string, length);
6894       return CompareRawStringContents(vec1, vec2);
6895     }
6896   } else {
6897     Isolate* isolate = GetIsolate();
6898     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
6899     VectorIterator<uc16> ib(string, length);
6900     return CompareStringContents(isolate->objects_string_compare_buffer_a(),
6901                                  &ib);
6902   }
6903 }
6904
6905
6906 bool String::SlowEqualsExternal(char *string, int length) {
6907   int len = this->length();
6908   if (len != length) return false;
6909   if (len == 0) return true;
6910
6911   // We know the strings are both non-empty. Compare the first chars
6912   // before we try to flatten the strings.
6913   if (this->Get(0) != string[0]) return false;
6914
6915   String* lhs = this->TryFlattenGetString();
6916
6917   if (StringShape(lhs).IsSequentialAscii()) {
6918       const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
6919       return CompareRawStringContents(Vector<const char>(str1, len),
6920                                       Vector<const char>(string, len));
6921   }
6922
6923   if (lhs->IsFlat()) {
6924     String::FlatContent lhs_content = lhs->GetFlatContent();
6925     Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
6926     VectorIterator<const uc16> buf1(vec1);
6927     VectorIterator<char> buf2(string, length);
6928     return CompareStringContents(&buf1, &buf2);
6929   } else {
6930     Isolate* isolate = GetIsolate();
6931     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
6932     VectorIterator<char> ib(string, length);
6933     return CompareStringContents(isolate->objects_string_compare_buffer_a(),
6934                                  &ib);
6935   }
6936 }
6937
6938
6939 bool String::SlowEquals(String* other) {
6940   // Fast check: negative check with lengths.
6941   int len = length();
6942   if (len != other->length()) return false;
6943   if (len == 0) return true;
6944
6945   // Fast check: if hash code is computed for both strings
6946   // a fast negative check can be performed.
6947   if (HasHashCode() && other->HasHashCode()) {
6948 #ifdef DEBUG
6949     if (FLAG_enable_slow_asserts) {
6950       if (Hash() != other->Hash()) {
6951         bool found_difference = false;
6952         for (int i = 0; i < len; i++) {
6953           if (Get(i) != other->Get(i)) {
6954             found_difference = true;
6955             break;
6956           }
6957         }
6958         ASSERT(found_difference);
6959       }
6960     }
6961 #endif
6962     if (Hash() != other->Hash()) return false;
6963   }
6964
6965   // We know the strings are both non-empty. Compare the first chars
6966   // before we try to flatten the strings.
6967   if (this->Get(0) != other->Get(0)) return false;
6968
6969   String* lhs = this->TryFlattenGetString();
6970   String* rhs = other->TryFlattenGetString();
6971
6972   if (StringShape(lhs).IsSequentialAscii() &&
6973       StringShape(rhs).IsSequentialAscii()) {
6974     const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
6975     const char* str2 = SeqAsciiString::cast(rhs)->GetChars();
6976     return CompareRawStringContents(Vector<const char>(str1, len),
6977                                     Vector<const char>(str2, len));
6978   }
6979
6980   Isolate* isolate = GetIsolate();
6981   String::FlatContent lhs_content = lhs->GetFlatContent();
6982   String::FlatContent rhs_content = rhs->GetFlatContent();
6983   if (lhs_content.IsFlat()) {
6984     if (lhs_content.IsAscii()) {
6985       Vector<const char> vec1 = lhs_content.ToAsciiVector();
6986       if (rhs_content.IsFlat()) {
6987         if (rhs_content.IsAscii()) {
6988           Vector<const char> vec2 = rhs_content.ToAsciiVector();
6989           return CompareRawStringContents(vec1, vec2);
6990         } else {
6991           VectorIterator<char> buf1(vec1);
6992           VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
6993           return CompareStringContents(&buf1, &ib);
6994         }
6995       } else {
6996         VectorIterator<char> buf1(vec1);
6997         isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
6998         return CompareStringContents(&buf1,
6999             isolate->objects_string_compare_buffer_b());
7000       }
7001     } else {
7002       Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
7003       if (rhs_content.IsFlat()) {
7004         if (rhs_content.IsAscii()) {
7005           VectorIterator<uc16> buf1(vec1);
7006           VectorIterator<char> ib(rhs_content.ToAsciiVector());
7007           return CompareStringContents(&buf1, &ib);
7008         } else {
7009           Vector<const uc16> vec2(rhs_content.ToUC16Vector());
7010           return CompareRawStringContents(vec1, vec2);
7011         }
7012       } else {
7013         VectorIterator<uc16> buf1(vec1);
7014         isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
7015         return CompareStringContents(&buf1,
7016             isolate->objects_string_compare_buffer_b());
7017       }
7018     }
7019   } else {
7020     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
7021     return CompareStringContentsPartial(isolate,
7022         isolate->objects_string_compare_buffer_a(), rhs);
7023   }
7024 }
7025
7026
7027 bool String::MarkAsUndetectable() {
7028   if (StringShape(this).IsSymbol()) return false;
7029
7030   Map* map = this->map();
7031   Heap* heap = GetHeap();
7032   if (map == heap->string_map()) {
7033     this->set_map(heap->undetectable_string_map());
7034     return true;
7035   } else if (map == heap->ascii_string_map()) {
7036     this->set_map(heap->undetectable_ascii_string_map());
7037     return true;
7038   }
7039   // Rest cannot be marked as undetectable
7040   return false;
7041 }
7042
7043
7044 bool String::IsEqualTo(Vector<const char> str) {
7045   Isolate* isolate = GetIsolate();
7046   int slen = length();
7047   Access<UnicodeCache::Utf8Decoder>
7048       decoder(isolate->unicode_cache()->utf8_decoder());
7049   decoder->Reset(str.start(), str.length());
7050   int i;
7051   for (i = 0; i < slen && decoder->has_more(); i++) {
7052     uint32_t r = decoder->GetNext();
7053     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
7054       if (i > slen - 1) return false;
7055       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
7056       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
7057     } else {
7058       if (Get(i) != r) return false;
7059     }
7060   }
7061   return i == slen && !decoder->has_more();
7062 }
7063
7064
7065 bool String::IsAsciiEqualTo(Vector<const char> str) {
7066   int slen = length();
7067   if (str.length() != slen) return false;
7068   FlatContent content = GetFlatContent();
7069   if (content.IsAscii()) {
7070     return CompareChars(content.ToAsciiVector().start(),
7071                         str.start(), slen) == 0;
7072   }
7073   for (int i = 0; i < slen; i++) {
7074     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
7075   }
7076   return true;
7077 }
7078
7079
7080 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
7081   int slen = length();
7082   if (str.length() != slen) return false;
7083   FlatContent content = GetFlatContent();
7084   if (content.IsTwoByte()) {
7085     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
7086   }
7087   for (int i = 0; i < slen; i++) {
7088     if (Get(i) != str[i]) return false;
7089   }
7090   return true;
7091 }
7092
7093
7094 uint32_t String::ComputeAndSetHash() {
7095   // Should only be called if hash code has not yet been computed.
7096   ASSERT(!HasHashCode());
7097
7098   const int len = length();
7099
7100   // Compute the hash code.
7101   uint32_t field = 0;
7102   if (StringShape(this).IsSequentialAscii()) {
7103     field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(),
7104                                  len,
7105                                  GetHeap()->HashSeed());
7106   } else if (StringShape(this).IsSequentialTwoByte()) {
7107     field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(),
7108                                  len,
7109                                  GetHeap()->HashSeed());
7110   } else {
7111     StringInputBuffer buffer(this);
7112     field = ComputeHashField(&buffer, len, GetHeap()->HashSeed());
7113   }
7114
7115   // Store the hash code in the object.
7116   set_hash_field(field);
7117
7118   // Check the hash code is there.
7119   ASSERT(HasHashCode());
7120   uint32_t result = field >> kHashShift;
7121   ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
7122   return result;
7123 }
7124
7125
7126 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
7127                                uint32_t* index,
7128                                int length) {
7129   if (length == 0 || length > kMaxArrayIndexSize) return false;
7130   uc32 ch = buffer->GetNext();
7131
7132   // If the string begins with a '0' character, it must only consist
7133   // of it to be a legal array index.
7134   if (ch == '0') {
7135     *index = 0;
7136     return length == 1;
7137   }
7138
7139   // Convert string to uint32 array index; character by character.
7140   int d = ch - '0';
7141   if (d < 0 || d > 9) return false;
7142   uint32_t result = d;
7143   while (buffer->has_more()) {
7144     d = buffer->GetNext() - '0';
7145     if (d < 0 || d > 9) return false;
7146     // Check that the new result is below the 32 bit limit.
7147     if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
7148     result = (result * 10) + d;
7149   }
7150
7151   *index = result;
7152   return true;
7153 }
7154
7155
7156 bool String::SlowAsArrayIndex(uint32_t* index) {
7157   if (length() <= kMaxCachedArrayIndexLength) {
7158     Hash();  // force computation of hash code
7159     uint32_t field = hash_field();
7160     if ((field & kIsNotArrayIndexMask) != 0) return false;
7161     // Isolate the array index form the full hash field.
7162     *index = (kArrayIndexHashMask & field) >> kHashShift;
7163     return true;
7164   } else {
7165     StringInputBuffer buffer(this);
7166     return ComputeArrayIndex(&buffer, index, length());
7167   }
7168 }
7169
7170
7171 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
7172   // For array indexes mix the length into the hash as an array index could
7173   // be zero.
7174   ASSERT(length > 0);
7175   ASSERT(length <= String::kMaxArrayIndexSize);
7176   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
7177          (1 << String::kArrayIndexValueBits));
7178
7179   value <<= String::kHashShift;
7180   value |= length << String::kArrayIndexHashLengthShift;
7181
7182   ASSERT((value & String::kIsNotArrayIndexMask) == 0);
7183   ASSERT((length > String::kMaxCachedArrayIndexLength) ||
7184          (value & String::kContainsCachedArrayIndexMask) == 0);
7185   return value;
7186 }
7187
7188
7189 void StringHasher::AddSurrogatePair(uc32 c) {
7190   uint16_t lead = unibrow::Utf16::LeadSurrogate(c);
7191   AddCharacter(lead);
7192   uint16_t trail = unibrow::Utf16::TrailSurrogate(c);
7193   AddCharacter(trail);
7194 }
7195
7196
7197 void StringHasher::AddSurrogatePairNoIndex(uc32 c) {
7198   uint16_t lead = unibrow::Utf16::LeadSurrogate(c);
7199   AddCharacterNoIndex(lead);
7200   uint16_t trail = unibrow::Utf16::TrailSurrogate(c);
7201   AddCharacterNoIndex(trail);
7202 }
7203
7204
7205 uint32_t StringHasher::GetHashField() {
7206   ASSERT(is_valid());
7207   if (length_ <= String::kMaxHashCalcLength) {
7208     if (is_array_index()) {
7209       return MakeArrayIndexHash(array_index(), length_);
7210     }
7211     return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask;
7212   } else {
7213     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
7214   }
7215 }
7216
7217
7218 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer,
7219                                   int length,
7220                                   uint32_t seed) {
7221   StringHasher hasher(length, seed);
7222
7223   // Very long strings have a trivial hash that doesn't inspect the
7224   // string contents.
7225   if (hasher.has_trivial_hash()) {
7226     return hasher.GetHashField();
7227   }
7228
7229   // Do the iterative array index computation as long as there is a
7230   // chance this is an array index.
7231   while (buffer->has_more() && hasher.is_array_index()) {
7232     hasher.AddCharacter(buffer->GetNext());
7233   }
7234
7235   // Process the remaining characters without updating the array
7236   // index.
7237   while (buffer->has_more()) {
7238     hasher.AddCharacterNoIndex(buffer->GetNext());
7239   }
7240
7241   return hasher.GetHashField();
7242 }
7243
7244
7245 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
7246   Heap* heap = GetHeap();
7247   if (start == 0 && end == length()) return this;
7248   MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
7249   return result;
7250 }
7251
7252
7253 void String::PrintOn(FILE* file) {
7254   int length = this->length();
7255   for (int i = 0; i < length; i++) {
7256     fprintf(file, "%c", Get(i));
7257   }
7258 }
7259
7260
7261 void Map::CreateOneBackPointer(Object* transition_target) {
7262   if (!transition_target->IsMap()) return;
7263   Map* target = Map::cast(transition_target);
7264 #ifdef DEBUG
7265   // Verify target.
7266   Object* source_prototype = prototype();
7267   Object* target_prototype = target->prototype();
7268   ASSERT(source_prototype->IsJSReceiver() ||
7269          source_prototype->IsMap() ||
7270          source_prototype->IsNull());
7271   ASSERT(target_prototype->IsJSReceiver() ||
7272          target_prototype->IsNull());
7273   ASSERT(source_prototype->IsMap() ||
7274          source_prototype == target_prototype);
7275 #endif
7276   // Point target back to source.  set_prototype() will not let us set
7277   // the prototype to a map, as we do here.
7278   *RawField(target, kPrototypeOffset) = this;
7279 }
7280
7281
7282 void Map::CreateBackPointers() {
7283   DescriptorArray* descriptors = instance_descriptors();
7284   for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
7285     switch (descriptors->GetType(i)) {
7286       case MAP_TRANSITION:
7287       case CONSTANT_TRANSITION:
7288         CreateOneBackPointer(descriptors->GetValue(i));
7289         break;
7290       case ELEMENTS_TRANSITION: {
7291         Object* object = descriptors->GetValue(i);
7292         if (object->IsMap()) {
7293           CreateOneBackPointer(object);
7294         } else {
7295           FixedArray* array = FixedArray::cast(object);
7296           for (int i = 0; i < array->length(); ++i) {
7297             CreateOneBackPointer(array->get(i));
7298           }
7299         }
7300         break;
7301       }
7302       case CALLBACKS: {
7303         Object* object = descriptors->GetValue(i);
7304         if (object->IsAccessorPair()) {
7305           AccessorPair* accessors = AccessorPair::cast(object);
7306           CreateOneBackPointer(accessors->getter());
7307           CreateOneBackPointer(accessors->setter());
7308         }
7309         break;
7310       }
7311       case NORMAL:
7312       case FIELD:
7313       case CONSTANT_FUNCTION:
7314       case HANDLER:
7315       case INTERCEPTOR:
7316       case NULL_DESCRIPTOR:
7317         break;
7318     }
7319   }
7320 }
7321
7322
7323 bool Map::RestoreOneBackPointer(Object* object,
7324                                 Object* real_prototype,
7325                                 bool* keep_entry) {
7326   if (!object->IsMap()) return false;
7327   Map* map = Map::cast(object);
7328   if (Marking::MarkBitFrom(map).Get()) {
7329     *keep_entry = true;
7330     return false;
7331   }
7332   ASSERT(map->prototype() == this || map->prototype() == real_prototype);
7333   // Getter prototype() is read-only, set_prototype() has side effects.
7334   *RawField(map, Map::kPrototypeOffset) = real_prototype;
7335   return true;
7336 }
7337
7338
7339 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
7340   DescriptorArray* d = DescriptorArray::cast(
7341       *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset));
7342   if (d->IsEmpty()) return;
7343   Smi* NullDescriptorDetails =
7344     PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
7345   FixedArray* contents = FixedArray::cast(
7346       d->get(DescriptorArray::kContentArrayIndex));
7347   ASSERT(contents->length() >= 2);
7348   for (int i = 0; i < contents->length(); i += 2) {
7349     // If the pair (value, details) is a map transition, check if the target is
7350     // live. If not, null the descriptor. Also drop the back pointer for that
7351     // map transition, so that this map is not reached again by following a back
7352     // pointer from a non-live object.
7353     bool keep_entry = false;
7354     PropertyDetails details(Smi::cast(contents->get(i + 1)));
7355     switch (details.type()) {
7356       case MAP_TRANSITION:
7357       case CONSTANT_TRANSITION:
7358         RestoreOneBackPointer(contents->get(i), real_prototype, &keep_entry);
7359         break;
7360       case ELEMENTS_TRANSITION: {
7361         Object* object = contents->get(i);
7362         if (object->IsMap()) {
7363           RestoreOneBackPointer(object, real_prototype, &keep_entry);
7364         } else {
7365           FixedArray* array = FixedArray::cast(object);
7366           for (int j = 0; j < array->length(); ++j) {
7367             if (RestoreOneBackPointer(array->get(j),
7368                                       real_prototype,
7369                                       &keep_entry)) {
7370               array->set_undefined(j);
7371             }
7372           }
7373         }
7374         break;
7375       }
7376       case CALLBACKS: {
7377         Object* object = contents->get(i);
7378         if (object->IsAccessorPair()) {
7379           AccessorPair* accessors = AccessorPair::cast(object);
7380           if (RestoreOneBackPointer(accessors->getter(),
7381                                     real_prototype,
7382                                     &keep_entry)) {
7383             accessors->set_getter(heap->the_hole_value());
7384           }
7385           if (RestoreOneBackPointer(accessors->setter(),
7386                                     real_prototype,
7387                                     &keep_entry)) {
7388             accessors->set_setter(heap->the_hole_value());
7389           }
7390         } else {
7391           keep_entry = true;
7392         }
7393         break;
7394       }
7395       case NORMAL:
7396       case FIELD:
7397       case CONSTANT_FUNCTION:
7398       case HANDLER:
7399       case INTERCEPTOR:
7400       case NULL_DESCRIPTOR:
7401         keep_entry = true;
7402         break;
7403     }
7404     // Make sure that an entry containing only dead transitions gets collected.
7405     // What we *really* want to do here is removing this entry completely, but
7406     // for technical reasons we can't do this, so we zero it out instead.
7407     if (!keep_entry) {
7408       contents->set_unchecked(i + 1, NullDescriptorDetails);
7409       contents->set_null_unchecked(heap, i);
7410     }
7411   }
7412 }
7413
7414
7415 int Map::Hash() {
7416   // For performance reasons we only hash the 3 most variable fields of a map:
7417   // constructor, prototype and bit_field2.
7418
7419   // Shift away the tag.
7420   int hash = (static_cast<uint32_t>(
7421         reinterpret_cast<uintptr_t>(constructor())) >> 2);
7422
7423   // XOR-ing the prototype and constructor directly yields too many zero bits
7424   // when the two pointers are close (which is fairly common).
7425   // To avoid this we shift the prototype 4 bits relatively to the constructor.
7426   hash ^= (static_cast<uint32_t>(
7427         reinterpret_cast<uintptr_t>(prototype())) << 2);
7428
7429   return hash ^ (hash >> 16) ^ bit_field2();
7430 }
7431
7432
7433 bool Map::EquivalentToForNormalization(Map* other,
7434                                        PropertyNormalizationMode mode) {
7435   return
7436     constructor() == other->constructor() &&
7437     prototype() == other->prototype() &&
7438     inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
7439                               0 :
7440                               other->inobject_properties()) &&
7441     instance_type() == other->instance_type() &&
7442     bit_field() == other->bit_field() &&
7443     bit_field2() == other->bit_field2() &&
7444     (bit_field3() & ~(1<<Map::kIsShared)) ==
7445         (other->bit_field3() & ~(1<<Map::kIsShared));
7446 }
7447
7448
7449 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
7450   // Iterate over all fields in the body but take care in dealing with
7451   // the code entry.
7452   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
7453   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
7454   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
7455 }
7456
7457
7458 void JSFunction::MarkForLazyRecompilation() {
7459   ASSERT(is_compiled() && !IsOptimized());
7460   ASSERT(shared()->allows_lazy_compilation() ||
7461          code()->optimizable());
7462   Builtins* builtins = GetIsolate()->builtins();
7463   ReplaceCode(builtins->builtin(Builtins::kLazyRecompile));
7464 }
7465
7466
7467 bool SharedFunctionInfo::EnsureCompiled(Handle<SharedFunctionInfo> shared,
7468                                         ClearExceptionFlag flag) {
7469   return shared->is_compiled() || CompileLazy(shared, flag);
7470 }
7471
7472
7473 static bool CompileLazyHelper(CompilationInfo* info,
7474                               ClearExceptionFlag flag) {
7475   // Compile the source information to a code object.
7476   ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
7477   ASSERT(!info->isolate()->has_pending_exception());
7478   bool result = Compiler::CompileLazy(info);
7479   ASSERT(result != Isolate::Current()->has_pending_exception());
7480   if (!result && flag == CLEAR_EXCEPTION) {
7481     info->isolate()->clear_pending_exception();
7482   }
7483   return result;
7484 }
7485
7486
7487 bool SharedFunctionInfo::CompileLazy(Handle<SharedFunctionInfo> shared,
7488                                      ClearExceptionFlag flag) {
7489   CompilationInfo info(shared);
7490   return CompileLazyHelper(&info, flag);
7491 }
7492
7493
7494 bool JSFunction::CompileLazy(Handle<JSFunction> function,
7495                              ClearExceptionFlag flag) {
7496   bool result = true;
7497   if (function->shared()->is_compiled()) {
7498     function->ReplaceCode(function->shared()->code());
7499     function->shared()->set_code_age(0);
7500   } else {
7501     CompilationInfo info(function);
7502     result = CompileLazyHelper(&info, flag);
7503     ASSERT(!result || function->is_compiled());
7504   }
7505   return result;
7506 }
7507
7508
7509 bool JSFunction::CompileOptimized(Handle<JSFunction> function,
7510                                   int osr_ast_id,
7511                                   ClearExceptionFlag flag) {
7512   CompilationInfo info(function);
7513   info.SetOptimizing(osr_ast_id);
7514   return CompileLazyHelper(&info, flag);
7515 }
7516
7517
7518 bool JSFunction::IsInlineable() {
7519   if (IsBuiltin()) return false;
7520   SharedFunctionInfo* shared_info = shared();
7521   // Check that the function has a script associated with it.
7522   if (!shared_info->script()->IsScript()) return false;
7523   if (shared_info->optimization_disabled()) return false;
7524   Code* code = shared_info->code();
7525   if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
7526   // If we never ran this (unlikely) then lets try to optimize it.
7527   if (code->kind() != Code::FUNCTION) return true;
7528   return code->optimizable();
7529 }
7530
7531
7532 MaybeObject* JSFunction::SetInstancePrototype(Object* value) {
7533   ASSERT(value->IsJSReceiver());
7534   Heap* heap = GetHeap();
7535   if (has_initial_map()) {
7536     // If the function has allocated the initial map
7537     // replace it with a copy containing the new prototype.
7538     Map* new_map;
7539     MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions();
7540     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7541     new_map->set_prototype(value);
7542     MaybeObject* maybe_object =
7543         set_initial_map_and_cache_transitions(new_map);
7544     if (maybe_object->IsFailure()) return maybe_object;
7545   } else {
7546     // Put the value in the initial map field until an initial map is
7547     // needed.  At that point, a new initial map is created and the
7548     // prototype is put into the initial map where it belongs.
7549     set_prototype_or_initial_map(value);
7550   }
7551   heap->ClearInstanceofCache();
7552   return value;
7553 }
7554
7555
7556 MaybeObject* JSFunction::SetPrototype(Object* value) {
7557   ASSERT(should_have_prototype());
7558   Object* construct_prototype = value;
7559
7560   // If the value is not a JSReceiver, store the value in the map's
7561   // constructor field so it can be accessed.  Also, set the prototype
7562   // used for constructing objects to the original object prototype.
7563   // See ECMA-262 13.2.2.
7564   if (!value->IsJSReceiver()) {
7565     // Copy the map so this does not affect unrelated functions.
7566     // Remove map transitions because they point to maps with a
7567     // different prototype.
7568     Map* new_map;
7569     { MaybeObject* maybe_new_map = map()->CopyDropTransitions();
7570       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7571     }
7572     Heap* heap = new_map->GetHeap();
7573     set_map(new_map);
7574     new_map->set_constructor(value);
7575     new_map->set_non_instance_prototype(true);
7576     construct_prototype =
7577         heap->isolate()->context()->global_context()->
7578             initial_object_prototype();
7579   } else {
7580     map()->set_non_instance_prototype(false);
7581   }
7582
7583   return SetInstancePrototype(construct_prototype);
7584 }
7585
7586
7587 Object* JSFunction::RemovePrototype() {
7588   Context* global_context = context()->global_context();
7589   Map* no_prototype_map = shared()->is_classic_mode()
7590       ? global_context->function_without_prototype_map()
7591       : global_context->strict_mode_function_without_prototype_map();
7592
7593   if (map() == no_prototype_map) {
7594     // Be idempotent.
7595     return this;
7596   }
7597
7598   ASSERT(map() == (shared()->is_classic_mode()
7599                    ? global_context->function_map()
7600                    : global_context->strict_mode_function_map()));
7601
7602   set_map(no_prototype_map);
7603   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
7604   return this;
7605 }
7606
7607
7608 Object* JSFunction::SetInstanceClassName(String* name) {
7609   shared()->set_instance_class_name(name);
7610   return this;
7611 }
7612
7613
7614 void JSFunction::PrintName(FILE* out) {
7615   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
7616   PrintF(out, "%s", *name);
7617 }
7618
7619
7620 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) {
7621   return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex));
7622 }
7623
7624
7625 MaybeObject* Oddball::Initialize(const char* to_string,
7626                                  Object* to_number,
7627                                  byte kind) {
7628   String* symbol;
7629   { MaybeObject* maybe_symbol =
7630         Isolate::Current()->heap()->LookupAsciiSymbol(to_string);
7631     if (!maybe_symbol->To(&symbol)) return maybe_symbol;
7632   }
7633   set_to_string(symbol);
7634   set_to_number(to_number);
7635   set_kind(kind);
7636   return this;
7637 }
7638
7639
7640 String* SharedFunctionInfo::DebugName() {
7641   Object* n = name();
7642   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
7643   return String::cast(n);
7644 }
7645
7646
7647 bool SharedFunctionInfo::HasSourceCode() {
7648   return !script()->IsUndefined() &&
7649          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
7650 }
7651
7652
7653 Handle<Object> SharedFunctionInfo::GetSourceCode() {
7654   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
7655   Handle<String> source(String::cast(Script::cast(script())->source()));
7656   return SubString(source, start_position(), end_position());
7657 }
7658
7659
7660 int SharedFunctionInfo::SourceSize() {
7661   return end_position() - start_position();
7662 }
7663
7664
7665 int SharedFunctionInfo::CalculateInstanceSize() {
7666   int instance_size =
7667       JSObject::kHeaderSize +
7668       expected_nof_properties() * kPointerSize;
7669   if (instance_size > JSObject::kMaxInstanceSize) {
7670     instance_size = JSObject::kMaxInstanceSize;
7671   }
7672   return instance_size;
7673 }
7674
7675
7676 int SharedFunctionInfo::CalculateInObjectProperties() {
7677   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
7678 }
7679
7680
7681 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
7682   // Check the basic conditions for generating inline constructor code.
7683   if (!FLAG_inline_new
7684       || !has_only_simple_this_property_assignments()
7685       || this_property_assignments_count() == 0) {
7686     return false;
7687   }
7688
7689   // If the prototype is null inline constructors cause no problems.
7690   if (!prototype->IsJSObject()) {
7691     ASSERT(prototype->IsNull());
7692     return true;
7693   }
7694
7695   Heap* heap = GetHeap();
7696
7697   // Traverse the proposed prototype chain looking for setters for properties of
7698   // the same names as are set by the inline constructor.
7699   for (Object* obj = prototype;
7700        obj != heap->null_value();
7701        obj = obj->GetPrototype()) {
7702     JSObject* js_object = JSObject::cast(obj);
7703     for (int i = 0; i < this_property_assignments_count(); i++) {
7704       LookupResult result(heap->isolate());
7705       String* name = GetThisPropertyAssignmentName(i);
7706       js_object->LocalLookupRealNamedProperty(name, &result);
7707       if (result.IsFound() && result.type() == CALLBACKS) {
7708         return false;
7709       }
7710     }
7711   }
7712
7713   return true;
7714 }
7715
7716
7717 void SharedFunctionInfo::ForbidInlineConstructor() {
7718   set_compiler_hints(BooleanBit::set(compiler_hints(),
7719                                      kHasOnlySimpleThisPropertyAssignments,
7720                                      false));
7721 }
7722
7723
7724 void SharedFunctionInfo::SetThisPropertyAssignmentsInfo(
7725     bool only_simple_this_property_assignments,
7726     FixedArray* assignments) {
7727   set_compiler_hints(BooleanBit::set(compiler_hints(),
7728                                      kHasOnlySimpleThisPropertyAssignments,
7729                                      only_simple_this_property_assignments));
7730   set_this_property_assignments(assignments);
7731   set_this_property_assignments_count(assignments->length() / 3);
7732 }
7733
7734
7735 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() {
7736   Heap* heap = GetHeap();
7737   set_compiler_hints(BooleanBit::set(compiler_hints(),
7738                                      kHasOnlySimpleThisPropertyAssignments,
7739                                      false));
7740   set_this_property_assignments(heap->undefined_value());
7741   set_this_property_assignments_count(0);
7742 }
7743
7744
7745 String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) {
7746   Object* obj = this_property_assignments();
7747   ASSERT(obj->IsFixedArray());
7748   ASSERT(index < this_property_assignments_count());
7749   obj = FixedArray::cast(obj)->get(index * 3);
7750   ASSERT(obj->IsString());
7751   return String::cast(obj);
7752 }
7753
7754
7755 bool SharedFunctionInfo::IsThisPropertyAssignmentArgument(int index) {
7756   Object* obj = this_property_assignments();
7757   ASSERT(obj->IsFixedArray());
7758   ASSERT(index < this_property_assignments_count());
7759   obj = FixedArray::cast(obj)->get(index * 3 + 1);
7760   return Smi::cast(obj)->value() != -1;
7761 }
7762
7763
7764 int SharedFunctionInfo::GetThisPropertyAssignmentArgument(int index) {
7765   ASSERT(IsThisPropertyAssignmentArgument(index));
7766   Object* obj =
7767       FixedArray::cast(this_property_assignments())->get(index * 3 + 1);
7768   return Smi::cast(obj)->value();
7769 }
7770
7771
7772 Object* SharedFunctionInfo::GetThisPropertyAssignmentConstant(int index) {
7773   ASSERT(!IsThisPropertyAssignmentArgument(index));
7774   Object* obj =
7775       FixedArray::cast(this_property_assignments())->get(index * 3 + 2);
7776   return obj;
7777 }
7778
7779
7780 // Support function for printing the source code to a StringStream
7781 // without any allocation in the heap.
7782 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
7783                                          int max_length) {
7784   // For some native functions there is no source.
7785   if (!HasSourceCode()) {
7786     accumulator->Add("<No Source>");
7787     return;
7788   }
7789
7790   // Get the source for the script which this function came from.
7791   // Don't use String::cast because we don't want more assertion errors while
7792   // we are already creating a stack dump.
7793   String* script_source =
7794       reinterpret_cast<String*>(Script::cast(script())->source());
7795
7796   if (!script_source->LooksValid()) {
7797     accumulator->Add("<Invalid Source>");
7798     return;
7799   }
7800
7801   if (!is_toplevel()) {
7802     accumulator->Add("function ");
7803     Object* name = this->name();
7804     if (name->IsString() && String::cast(name)->length() > 0) {
7805       accumulator->PrintName(name);
7806     }
7807   }
7808
7809   int len = end_position() - start_position();
7810   if (len <= max_length || max_length < 0) {
7811     accumulator->Put(script_source, start_position(), end_position());
7812   } else {
7813     accumulator->Put(script_source,
7814                      start_position(),
7815                      start_position() + max_length);
7816     accumulator->Add("...\n");
7817   }
7818 }
7819
7820
7821 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
7822   if (code->instruction_size() != recompiled->instruction_size()) return false;
7823   ByteArray* code_relocation = code->relocation_info();
7824   ByteArray* recompiled_relocation = recompiled->relocation_info();
7825   int length = code_relocation->length();
7826   if (length != recompiled_relocation->length()) return false;
7827   int compare = memcmp(code_relocation->GetDataStartAddress(),
7828                        recompiled_relocation->GetDataStartAddress(),
7829                        length);
7830   return compare == 0;
7831 }
7832
7833
7834 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
7835   ASSERT(!has_deoptimization_support());
7836   AssertNoAllocation no_allocation;
7837   Code* code = this->code();
7838   if (IsCodeEquivalent(code, recompiled)) {
7839     // Copy the deoptimization data from the recompiled code.
7840     code->set_deoptimization_data(recompiled->deoptimization_data());
7841     code->set_has_deoptimization_support(true);
7842   } else {
7843     // TODO(3025757): In case the recompiled isn't equivalent to the
7844     // old code, we have to replace it. We should try to avoid this
7845     // altogether because it flushes valuable type feedback by
7846     // effectively resetting all IC state.
7847     set_code(recompiled);
7848   }
7849   ASSERT(has_deoptimization_support());
7850 }
7851
7852
7853 void SharedFunctionInfo::DisableOptimization() {
7854   // Disable optimization for the shared function info and mark the
7855   // code as non-optimizable. The marker on the shared function info
7856   // is there because we flush non-optimized code thereby loosing the
7857   // non-optimizable information for the code. When the code is
7858   // regenerated and set on the shared function info it is marked as
7859   // non-optimizable if optimization is disabled for the shared
7860   // function info.
7861   set_optimization_disabled(true);
7862   // Code should be the lazy compilation stub or else unoptimized.  If the
7863   // latter, disable optimization for the code too.
7864   ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
7865   if (code()->kind() == Code::FUNCTION) {
7866     code()->set_optimizable(false);
7867   }
7868   if (FLAG_trace_opt) {
7869     PrintF("[disabled optimization for %s]\n", *DebugName()->ToCString());
7870   }
7871 }
7872
7873
7874 bool SharedFunctionInfo::VerifyBailoutId(int id) {
7875   ASSERT(id != AstNode::kNoNumber);
7876   Code* unoptimized = code();
7877   DeoptimizationOutputData* data =
7878       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
7879   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
7880   USE(ignore);
7881   return true;  // Return true if there was no ASSERT.
7882 }
7883
7884
7885 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) {
7886   ASSERT(!IsInobjectSlackTrackingInProgress());
7887
7888   if (!FLAG_clever_optimizations) return;
7889
7890   // Only initiate the tracking the first time.
7891   if (live_objects_may_exist()) return;
7892   set_live_objects_may_exist(true);
7893
7894   // No tracking during the snapshot construction phase.
7895   if (Serializer::enabled()) return;
7896
7897   if (map->unused_property_fields() == 0) return;
7898
7899   // Nonzero counter is a leftover from the previous attempt interrupted
7900   // by GC, keep it.
7901   if (construction_count() == 0) {
7902     set_construction_count(kGenerousAllocationCount);
7903   }
7904   set_initial_map(map);
7905   Builtins* builtins = map->GetHeap()->isolate()->builtins();
7906   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
7907             construct_stub());
7908   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
7909 }
7910
7911
7912 // Called from GC, hence reinterpret_cast and unchecked accessors.
7913 void SharedFunctionInfo::DetachInitialMap() {
7914   Map* map = reinterpret_cast<Map*>(initial_map());
7915
7916   // Make the map remember to restore the link if it survives the GC.
7917   map->set_bit_field3(
7918       map->bit_field3() | (1 << Map::kAttachedToSharedFunctionInfo));
7919
7920   // Undo state changes made by StartInobjectTracking (except the
7921   // construction_count). This way if the initial map does not survive the GC
7922   // then StartInobjectTracking will be called again the next time the
7923   // constructor is called. The countdown will continue and (possibly after
7924   // several more GCs) CompleteInobjectSlackTracking will eventually be called.
7925   Heap* heap = map->GetHeap();
7926   set_initial_map(heap->raw_unchecked_undefined_value());
7927   Builtins* builtins = heap->isolate()->builtins();
7928   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
7929             *RawField(this, kConstructStubOffset));
7930   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
7931   // It is safe to clear the flag: it will be set again if the map is live.
7932   set_live_objects_may_exist(false);
7933 }
7934
7935
7936 // Called from GC, hence reinterpret_cast and unchecked accessors.
7937 void SharedFunctionInfo::AttachInitialMap(Map* map) {
7938   map->set_bit_field3(
7939       map->bit_field3() & ~(1 << Map::kAttachedToSharedFunctionInfo));
7940
7941   // Resume inobject slack tracking.
7942   set_initial_map(map);
7943   Builtins* builtins = map->GetHeap()->isolate()->builtins();
7944   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
7945             *RawField(this, kConstructStubOffset));
7946   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
7947   // The map survived the gc, so there may be objects referencing it.
7948   set_live_objects_may_exist(true);
7949 }
7950
7951
7952 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
7953   code()->ClearInlineCaches();
7954   set_ic_age(new_ic_age);
7955   if (code()->kind() == Code::FUNCTION) {
7956     code()->set_profiler_ticks(0);
7957     if (optimization_disabled() &&
7958         opt_count() >= Compiler::kDefaultMaxOptCount) {
7959       // Re-enable optimizations if they were disabled due to opt_count limit.
7960       set_optimization_disabled(false);
7961       code()->set_optimizable(true);
7962     }
7963     set_opt_count(0);
7964   }
7965 }
7966
7967
7968 static void GetMinInobjectSlack(Map* map, void* data) {
7969   int slack = map->unused_property_fields();
7970   if (*reinterpret_cast<int*>(data) > slack) {
7971     *reinterpret_cast<int*>(data) = slack;
7972   }
7973 }
7974
7975
7976 static void ShrinkInstanceSize(Map* map, void* data) {
7977   int slack = *reinterpret_cast<int*>(data);
7978   map->set_inobject_properties(map->inobject_properties() - slack);
7979   map->set_unused_property_fields(map->unused_property_fields() - slack);
7980   map->set_instance_size(map->instance_size() - slack * kPointerSize);
7981
7982   // Visitor id might depend on the instance size, recalculate it.
7983   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
7984 }
7985
7986
7987 void SharedFunctionInfo::CompleteInobjectSlackTracking() {
7988   ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
7989   Map* map = Map::cast(initial_map());
7990
7991   Heap* heap = map->GetHeap();
7992   set_initial_map(heap->undefined_value());
7993   Builtins* builtins = heap->isolate()->builtins();
7994   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
7995             construct_stub());
7996   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
7997
7998   int slack = map->unused_property_fields();
7999   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
8000   if (slack != 0) {
8001     // Resize the initial map and all maps in its transition tree.
8002     map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
8003
8004     // Give the correct expected_nof_properties to initial maps created later.
8005     ASSERT(expected_nof_properties() >= slack);
8006     set_expected_nof_properties(expected_nof_properties() - slack);
8007   }
8008 }
8009
8010
8011 void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) {
8012   v->VisitSharedFunctionInfo(this);
8013   SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
8014 }
8015
8016
8017 #define DECLARE_TAG(ignore1, name, ignore2) name,
8018 const char* const VisitorSynchronization::kTags[
8019     VisitorSynchronization::kNumberOfSyncTags] = {
8020   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
8021 };
8022 #undef DECLARE_TAG
8023
8024
8025 #define DECLARE_TAG(ignore1, ignore2, name) name,
8026 const char* const VisitorSynchronization::kTagNames[
8027     VisitorSynchronization::kNumberOfSyncTags] = {
8028   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
8029 };
8030 #undef DECLARE_TAG
8031
8032
8033 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
8034   ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
8035   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
8036   Object* old_target = target;
8037   VisitPointer(&target);
8038   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
8039 }
8040
8041
8042 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
8043   Object* code = Code::GetObjectFromEntryAddress(entry_address);
8044   Object* old_code = code;
8045   VisitPointer(&code);
8046   if (code != old_code) {
8047     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
8048   }
8049 }
8050
8051
8052 void ObjectVisitor::VisitGlobalPropertyCell(RelocInfo* rinfo) {
8053   ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
8054   Object* cell = rinfo->target_cell();
8055   Object* old_cell = cell;
8056   VisitPointer(&cell);
8057   if (cell != old_cell) {
8058     rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
8059   }
8060 }
8061
8062
8063 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
8064   ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
8065           rinfo->IsPatchedReturnSequence()) ||
8066          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
8067           rinfo->IsPatchedDebugBreakSlotSequence()));
8068   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
8069   Object* old_target = target;
8070   VisitPointer(&target);
8071   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
8072 }
8073
8074 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
8075   ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
8076   VisitPointer(rinfo->target_object_address());
8077 }
8078
8079 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
8080   Address* p = rinfo->target_reference_address();
8081   VisitExternalReferences(p, p + 1);
8082 }
8083
8084 void Code::InvalidateRelocation() {
8085   set_relocation_info(GetHeap()->empty_byte_array());
8086 }
8087
8088
8089 void Code::Relocate(intptr_t delta) {
8090   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
8091     it.rinfo()->apply(delta);
8092   }
8093   CPU::FlushICache(instruction_start(), instruction_size());
8094 }
8095
8096
8097 void Code::CopyFrom(const CodeDesc& desc) {
8098   ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
8099
8100   // copy code
8101   memmove(instruction_start(), desc.buffer, desc.instr_size);
8102
8103   // copy reloc info
8104   memmove(relocation_start(),
8105           desc.buffer + desc.buffer_size - desc.reloc_size,
8106           desc.reloc_size);
8107
8108   // unbox handles and relocate
8109   intptr_t delta = instruction_start() - desc.buffer;
8110   int mode_mask = RelocInfo::kCodeTargetMask |
8111                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
8112                   RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
8113                   RelocInfo::kApplyMask;
8114   Assembler* origin = desc.origin;  // Needed to find target_object on X64.
8115   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
8116     RelocInfo::Mode mode = it.rinfo()->rmode();
8117     if (mode == RelocInfo::EMBEDDED_OBJECT) {
8118       Handle<Object> p = it.rinfo()->target_object_handle(origin);
8119       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
8120     } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
8121       Handle<JSGlobalPropertyCell> cell  = it.rinfo()->target_cell_handle();
8122       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
8123     } else if (RelocInfo::IsCodeTarget(mode)) {
8124       // rewrite code handles in inline cache targets to direct
8125       // pointers to the first instruction in the code object
8126       Handle<Object> p = it.rinfo()->target_object_handle(origin);
8127       Code* code = Code::cast(*p);
8128       it.rinfo()->set_target_address(code->instruction_start(),
8129                                      SKIP_WRITE_BARRIER);
8130     } else {
8131       it.rinfo()->apply(delta);
8132     }
8133   }
8134   CPU::FlushICache(instruction_start(), instruction_size());
8135 }
8136
8137
8138 // Locate the source position which is closest to the address in the code. This
8139 // is using the source position information embedded in the relocation info.
8140 // The position returned is relative to the beginning of the script where the
8141 // source for this function is found.
8142 int Code::SourcePosition(Address pc) {
8143   int distance = kMaxInt;
8144   int position = RelocInfo::kNoPosition;  // Initially no position found.
8145   // Run through all the relocation info to find the best matching source
8146   // position. All the code needs to be considered as the sequence of the
8147   // instructions in the code does not necessarily follow the same order as the
8148   // source.
8149   RelocIterator it(this, RelocInfo::kPositionMask);
8150   while (!it.done()) {
8151     // Only look at positions after the current pc.
8152     if (it.rinfo()->pc() < pc) {
8153       // Get position and distance.
8154
8155       int dist = static_cast<int>(pc - it.rinfo()->pc());
8156       int pos = static_cast<int>(it.rinfo()->data());
8157       // If this position is closer than the current candidate or if it has the
8158       // same distance as the current candidate and the position is higher then
8159       // this position is the new candidate.
8160       if ((dist < distance) ||
8161           (dist == distance && pos > position)) {
8162         position = pos;
8163         distance = dist;
8164       }
8165     }
8166     it.next();
8167   }
8168   return position;
8169 }
8170
8171
8172 // Same as Code::SourcePosition above except it only looks for statement
8173 // positions.
8174 int Code::SourceStatementPosition(Address pc) {
8175   // First find the position as close as possible using all position
8176   // information.
8177   int position = SourcePosition(pc);
8178   // Now find the closest statement position before the position.
8179   int statement_position = 0;
8180   RelocIterator it(this, RelocInfo::kPositionMask);
8181   while (!it.done()) {
8182     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
8183       int p = static_cast<int>(it.rinfo()->data());
8184       if (statement_position < p && p <= position) {
8185         statement_position = p;
8186       }
8187     }
8188     it.next();
8189   }
8190   return statement_position;
8191 }
8192
8193
8194 SafepointEntry Code::GetSafepointEntry(Address pc) {
8195   SafepointTable table(this);
8196   return table.FindEntry(pc);
8197 }
8198
8199
8200 void Code::SetNoStackCheckTable() {
8201   // Indicate the absence of a stack-check table by a table start after the
8202   // end of the instructions.  Table start must be aligned, so round up.
8203   set_stack_check_table_offset(RoundUp(instruction_size(), kIntSize));
8204 }
8205
8206
8207 Map* Code::FindFirstMap() {
8208   ASSERT(is_inline_cache_stub());
8209   AssertNoAllocation no_allocation;
8210   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
8211   for (RelocIterator it(this, mask); !it.done(); it.next()) {
8212     RelocInfo* info = it.rinfo();
8213     Object* object = info->target_object();
8214     if (object->IsMap()) return Map::cast(object);
8215   }
8216   return NULL;
8217 }
8218
8219
8220 void Code::ClearInlineCaches() {
8221   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
8222              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
8223              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
8224              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
8225   for (RelocIterator it(this, mask); !it.done(); it.next()) {
8226     RelocInfo* info = it.rinfo();
8227     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
8228     if (target->is_inline_cache_stub()) {
8229       IC::Clear(info->pc());
8230     }
8231   }
8232 }
8233
8234
8235 #ifdef ENABLE_DISASSEMBLER
8236
8237 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
8238   disasm::NameConverter converter;
8239   int deopt_count = DeoptCount();
8240   PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
8241   if (0 == deopt_count) return;
8242
8243   PrintF(out, "%6s  %6s  %6s %6s %12s\n", "index", "ast id", "argc", "pc",
8244          FLAG_print_code_verbose ? "commands" : "");
8245   for (int i = 0; i < deopt_count; i++) {
8246     PrintF(out, "%6d  %6d  %6d %6d",
8247            i,
8248            AstId(i)->value(),
8249            ArgumentsStackHeight(i)->value(),
8250            Pc(i)->value());
8251
8252     if (!FLAG_print_code_verbose) {
8253       PrintF(out, "\n");
8254       continue;
8255     }
8256     // Print details of the frame translation.
8257     int translation_index = TranslationIndex(i)->value();
8258     TranslationIterator iterator(TranslationByteArray(), translation_index);
8259     Translation::Opcode opcode =
8260         static_cast<Translation::Opcode>(iterator.Next());
8261     ASSERT(Translation::BEGIN == opcode);
8262     int frame_count = iterator.Next();
8263     int jsframe_count = iterator.Next();
8264     PrintF(out, "  %s {frame count=%d, js frame count=%d}\n",
8265            Translation::StringFor(opcode),
8266            frame_count,
8267            jsframe_count);
8268
8269     while (iterator.HasNext() &&
8270            Translation::BEGIN !=
8271            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
8272       PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
8273
8274       switch (opcode) {
8275         case Translation::BEGIN:
8276           UNREACHABLE();
8277           break;
8278
8279         case Translation::JS_FRAME: {
8280           int ast_id = iterator.Next();
8281           int function_id = iterator.Next();
8282           JSFunction* function =
8283               JSFunction::cast(LiteralArray()->get(function_id));
8284           unsigned height = iterator.Next();
8285           PrintF(out, "{ast_id=%d, function=", ast_id);
8286           function->PrintName(out);
8287           PrintF(out, ", height=%u}", height);
8288           break;
8289         }
8290
8291         case Translation::ARGUMENTS_ADAPTOR_FRAME:
8292         case Translation::CONSTRUCT_STUB_FRAME: {
8293           int function_id = iterator.Next();
8294           JSFunction* function =
8295               JSFunction::cast(LiteralArray()->get(function_id));
8296           unsigned height = iterator.Next();
8297           PrintF(out, "{function=");
8298           function->PrintName(out);
8299           PrintF(out, ", height=%u}", height);
8300           break;
8301         }
8302
8303         case Translation::DUPLICATE:
8304           break;
8305
8306         case Translation::REGISTER: {
8307           int reg_code = iterator.Next();
8308             PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
8309           break;
8310         }
8311
8312         case Translation::INT32_REGISTER: {
8313           int reg_code = iterator.Next();
8314           PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
8315           break;
8316         }
8317
8318         case Translation::DOUBLE_REGISTER: {
8319           int reg_code = iterator.Next();
8320           PrintF(out, "{input=%s}",
8321                  DoubleRegister::AllocationIndexToString(reg_code));
8322           break;
8323         }
8324
8325         case Translation::STACK_SLOT: {
8326           int input_slot_index = iterator.Next();
8327           PrintF(out, "{input=%d}", input_slot_index);
8328           break;
8329         }
8330
8331         case Translation::INT32_STACK_SLOT: {
8332           int input_slot_index = iterator.Next();
8333           PrintF(out, "{input=%d}", input_slot_index);
8334           break;
8335         }
8336
8337         case Translation::DOUBLE_STACK_SLOT: {
8338           int input_slot_index = iterator.Next();
8339           PrintF(out, "{input=%d}", input_slot_index);
8340           break;
8341         }
8342
8343         case Translation::LITERAL: {
8344           unsigned literal_index = iterator.Next();
8345           PrintF(out, "{literal_id=%u}", literal_index);
8346           break;
8347         }
8348
8349         case Translation::ARGUMENTS_OBJECT:
8350           break;
8351       }
8352       PrintF(out, "\n");
8353     }
8354   }
8355 }
8356
8357
8358 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
8359   PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
8360          this->DeoptPoints());
8361   if (this->DeoptPoints() == 0) return;
8362
8363   PrintF("%6s  %8s  %s\n", "ast id", "pc", "state");
8364   for (int i = 0; i < this->DeoptPoints(); i++) {
8365     int pc_and_state = this->PcAndState(i)->value();
8366     PrintF("%6d  %8d  %s\n",
8367            this->AstId(i)->value(),
8368            FullCodeGenerator::PcField::decode(pc_and_state),
8369            FullCodeGenerator::State2String(
8370                FullCodeGenerator::StateField::decode(pc_and_state)));
8371   }
8372 }
8373
8374
8375 // Identify kind of code.
8376 const char* Code::Kind2String(Kind kind) {
8377   switch (kind) {
8378     case FUNCTION: return "FUNCTION";
8379     case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION";
8380     case STUB: return "STUB";
8381     case BUILTIN: return "BUILTIN";
8382     case LOAD_IC: return "LOAD_IC";
8383     case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
8384     case STORE_IC: return "STORE_IC";
8385     case KEYED_STORE_IC: return "KEYED_STORE_IC";
8386     case CALL_IC: return "CALL_IC";
8387     case KEYED_CALL_IC: return "KEYED_CALL_IC";
8388     case UNARY_OP_IC: return "UNARY_OP_IC";
8389     case BINARY_OP_IC: return "BINARY_OP_IC";
8390     case COMPARE_IC: return "COMPARE_IC";
8391     case TO_BOOLEAN_IC: return "TO_BOOLEAN_IC";
8392   }
8393   UNREACHABLE();
8394   return NULL;
8395 }
8396
8397
8398 const char* Code::ICState2String(InlineCacheState state) {
8399   switch (state) {
8400     case UNINITIALIZED: return "UNINITIALIZED";
8401     case PREMONOMORPHIC: return "PREMONOMORPHIC";
8402     case MONOMORPHIC: return "MONOMORPHIC";
8403     case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
8404     case MEGAMORPHIC: return "MEGAMORPHIC";
8405     case DEBUG_BREAK: return "DEBUG_BREAK";
8406     case DEBUG_PREPARE_STEP_IN: return "DEBUG_PREPARE_STEP_IN";
8407   }
8408   UNREACHABLE();
8409   return NULL;
8410 }
8411
8412
8413 const char* Code::PropertyType2String(PropertyType type) {
8414   switch (type) {
8415     case NORMAL: return "NORMAL";
8416     case FIELD: return "FIELD";
8417     case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
8418     case CALLBACKS: return "CALLBACKS";
8419     case HANDLER: return "HANDLER";
8420     case INTERCEPTOR: return "INTERCEPTOR";
8421     case MAP_TRANSITION: return "MAP_TRANSITION";
8422     case ELEMENTS_TRANSITION: return "ELEMENTS_TRANSITION";
8423     case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
8424     case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
8425   }
8426   UNREACHABLE();  // keep the compiler happy
8427   return NULL;
8428 }
8429
8430
8431 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
8432   const char* name = NULL;
8433   switch (kind) {
8434     case CALL_IC:
8435       if (extra == STRING_INDEX_OUT_OF_BOUNDS) {
8436         name = "STRING_INDEX_OUT_OF_BOUNDS";
8437       }
8438       break;
8439     case STORE_IC:
8440     case KEYED_STORE_IC:
8441       if (extra == kStrictMode) {
8442         name = "STRICT";
8443       }
8444       break;
8445     default:
8446       break;
8447   }
8448   if (name != NULL) {
8449     PrintF(out, "extra_ic_state = %s\n", name);
8450   } else {
8451     PrintF(out, "extra_ic_state = %d\n", extra);
8452   }
8453 }
8454
8455
8456 void Code::Disassemble(const char* name, FILE* out) {
8457   PrintF(out, "kind = %s\n", Kind2String(kind()));
8458   if (is_inline_cache_stub()) {
8459     PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
8460     PrintExtraICState(out, kind(), extra_ic_state());
8461     if (ic_state() == MONOMORPHIC) {
8462       PrintF(out, "type = %s\n", PropertyType2String(type()));
8463     }
8464     if (is_call_stub() || is_keyed_call_stub()) {
8465       PrintF(out, "argc = %d\n", arguments_count());
8466     }
8467   }
8468   if ((name != NULL) && (name[0] != '\0')) {
8469     PrintF(out, "name = %s\n", name);
8470   }
8471   if (kind() == OPTIMIZED_FUNCTION) {
8472     PrintF(out, "stack_slots = %d\n", stack_slots());
8473   }
8474
8475   PrintF(out, "Instructions (size = %d)\n", instruction_size());
8476   Disassembler::Decode(out, this);
8477   PrintF(out, "\n");
8478
8479   if (kind() == FUNCTION) {
8480     DeoptimizationOutputData* data =
8481         DeoptimizationOutputData::cast(this->deoptimization_data());
8482     data->DeoptimizationOutputDataPrint(out);
8483   } else if (kind() == OPTIMIZED_FUNCTION) {
8484     DeoptimizationInputData* data =
8485         DeoptimizationInputData::cast(this->deoptimization_data());
8486     data->DeoptimizationInputDataPrint(out);
8487   }
8488   PrintF("\n");
8489
8490   if (kind() == OPTIMIZED_FUNCTION) {
8491     SafepointTable table(this);
8492     PrintF(out, "Safepoints (size = %u)\n", table.size());
8493     for (unsigned i = 0; i < table.length(); i++) {
8494       unsigned pc_offset = table.GetPcOffset(i);
8495       PrintF(out, "%p  %4d  ", (instruction_start() + pc_offset), pc_offset);
8496       table.PrintEntry(i);
8497       PrintF(out, " (sp -> fp)");
8498       SafepointEntry entry = table.GetEntry(i);
8499       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
8500         PrintF(out, "  %6d", entry.deoptimization_index());
8501       } else {
8502         PrintF(out, "  <none>");
8503       }
8504       if (entry.argument_count() > 0) {
8505         PrintF(out, " argc: %d", entry.argument_count());
8506       }
8507       PrintF(out, "\n");
8508     }
8509     PrintF(out, "\n");
8510   } else if (kind() == FUNCTION) {
8511     unsigned offset = stack_check_table_offset();
8512     // If there is no stack check table, the "table start" will at or after
8513     // (due to alignment) the end of the instruction stream.
8514     if (static_cast<int>(offset) < instruction_size()) {
8515       unsigned* address =
8516           reinterpret_cast<unsigned*>(instruction_start() + offset);
8517       unsigned length = address[0];
8518       PrintF(out, "Stack checks (size = %u)\n", length);
8519       PrintF(out, "ast_id  pc_offset\n");
8520       for (unsigned i = 0; i < length; ++i) {
8521         unsigned index = (2 * i) + 1;
8522         PrintF(out, "%6u  %9u\n", address[index], address[index + 1]);
8523       }
8524       PrintF(out, "\n");
8525     }
8526   }
8527
8528   PrintF("RelocInfo (size = %d)\n", relocation_size());
8529   for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
8530   PrintF(out, "\n");
8531 }
8532 #endif  // ENABLE_DISASSEMBLER
8533
8534
8535 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
8536     int capacity,
8537     int length,
8538     SetFastElementsCapacityMode set_capacity_mode) {
8539   Heap* heap = GetHeap();
8540   // We should never end in here with a pixel or external array.
8541   ASSERT(!HasExternalArrayElements());
8542
8543   // Allocate a new fast elements backing store.
8544   FixedArray* new_elements;
8545   { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
8546     if (!maybe->To(&new_elements)) return maybe;
8547   }
8548
8549   // Find the new map to use for this object if there is a map change.
8550   Map* new_map = NULL;
8551   if (elements()->map() != heap->non_strict_arguments_elements_map()) {
8552     // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces
8553     // it, or if it's allowed and the old elements array contained only SMIs.
8554     bool has_fast_smi_only_elements =
8555         (set_capacity_mode == kForceSmiOnlyElements) ||
8556         ((set_capacity_mode == kAllowSmiOnlyElements) &&
8557          (elements()->map()->has_fast_smi_only_elements() ||
8558           elements() == heap->empty_fixed_array()));
8559     ElementsKind elements_kind = has_fast_smi_only_elements
8560         ? FAST_SMI_ONLY_ELEMENTS
8561         : FAST_ELEMENTS;
8562     MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind);
8563     if (!maybe->To(&new_map)) return maybe;
8564   }
8565
8566   FixedArrayBase* old_elements = elements();
8567   ElementsKind elements_kind = GetElementsKind();
8568   ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8569   ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS)
8570       ? FAST_SMI_ONLY_ELEMENTS
8571       : FAST_ELEMENTS;
8572   //  int copy_size = Min(old_elements_raw->length(), new_elements->length());
8573   accessor->CopyElements(this, new_elements, to_kind);
8574   if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8575     set_map_and_elements(new_map, new_elements);
8576   } else {
8577     FixedArray* parameter_map = FixedArray::cast(old_elements);
8578     parameter_map->set(1, new_elements);
8579   }
8580
8581   if (FLAG_trace_elements_transitions) {
8582     PrintElementsTransition(stdout, elements_kind, old_elements,
8583                             GetElementsKind(), new_elements);
8584   }
8585
8586   // Update the length if necessary.
8587   if (IsJSArray()) {
8588     JSArray::cast(this)->set_length(Smi::FromInt(length));
8589   }
8590
8591   return new_elements;
8592 }
8593
8594
8595 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
8596     int capacity,
8597     int length) {
8598   Heap* heap = GetHeap();
8599   // We should never end in here with a pixel or external array.
8600   ASSERT(!HasExternalArrayElements());
8601
8602   FixedDoubleArray* elems;
8603   { MaybeObject* maybe_obj =
8604         heap->AllocateUninitializedFixedDoubleArray(capacity);
8605     if (!maybe_obj->To(&elems)) return maybe_obj;
8606   }
8607
8608   Map* new_map;
8609   { MaybeObject* maybe_obj =
8610         GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS);
8611     if (!maybe_obj->To(&new_map)) return maybe_obj;
8612   }
8613
8614   FixedArrayBase* old_elements = elements();
8615   ElementsKind elements_kind = GetElementsKind();
8616   ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8617   accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
8618   if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8619     set_map_and_elements(new_map, elems);
8620   } else {
8621     FixedArray* parameter_map = FixedArray::cast(old_elements);
8622     parameter_map->set(1, elems);
8623   }
8624
8625   if (FLAG_trace_elements_transitions) {
8626     PrintElementsTransition(stdout, elements_kind, old_elements,
8627                             FAST_DOUBLE_ELEMENTS, elems);
8628   }
8629
8630   if (IsJSArray()) {
8631     JSArray::cast(this)->set_length(Smi::FromInt(length));
8632   }
8633
8634   return this;
8635 }
8636
8637
8638 MaybeObject* JSArray::Initialize(int capacity) {
8639   Heap* heap = GetHeap();
8640   ASSERT(capacity >= 0);
8641   set_length(Smi::FromInt(0));
8642   FixedArray* new_elements;
8643   if (capacity == 0) {
8644     new_elements = heap->empty_fixed_array();
8645   } else {
8646     MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
8647     if (!maybe_obj->To(&new_elements)) return maybe_obj;
8648   }
8649   set_elements(new_elements);
8650   return this;
8651 }
8652
8653
8654 void JSArray::Expand(int required_size) {
8655   GetIsolate()->factory()->SetElementsCapacityAndLength(
8656       Handle<JSArray>(this), required_size, required_size);
8657 }
8658
8659
8660 MaybeObject* JSArray::SetElementsLength(Object* len) {
8661   // We should never end in here with a pixel or external array.
8662   ASSERT(AllowsSetElementsLength());
8663   return GetElementsAccessor()->SetLength(this, len);
8664 }
8665
8666
8667 Object* Map::GetPrototypeTransition(Object* prototype) {
8668   FixedArray* cache = prototype_transitions();
8669   int number_of_transitions = NumberOfProtoTransitions();
8670   const int proto_offset =
8671       kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
8672   const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
8673   const int step = kProtoTransitionElementsPerEntry;
8674   for (int i = 0; i < number_of_transitions; i++) {
8675     if (cache->get(proto_offset + i * step) == prototype) {
8676       Object* map = cache->get(map_offset + i * step);
8677       ASSERT(map->IsMap());
8678       return map;
8679     }
8680   }
8681   return NULL;
8682 }
8683
8684
8685 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
8686   ASSERT(map->IsMap());
8687   ASSERT(HeapObject::cast(prototype)->map()->IsMap());
8688   // Don't cache prototype transition if this map is shared.
8689   if (is_shared() || !FLAG_cache_prototype_transitions) return this;
8690
8691   FixedArray* cache = prototype_transitions();
8692
8693   const int step = kProtoTransitionElementsPerEntry;
8694   const int header = kProtoTransitionHeaderSize;
8695
8696   int capacity = (cache->length() - header) / step;
8697
8698   int transitions = NumberOfProtoTransitions() + 1;
8699
8700   if (transitions > capacity) {
8701     if (capacity > kMaxCachedPrototypeTransitions) return this;
8702
8703     FixedArray* new_cache;
8704     // Grow array by factor 2 over and above what we need.
8705     { MaybeObject* maybe_cache =
8706           GetHeap()->AllocateFixedArray(transitions * 2 * step + header);
8707       if (!maybe_cache->To(&new_cache)) return maybe_cache;
8708     }
8709
8710     for (int i = 0; i < capacity * step; i++) {
8711       new_cache->set(i + header, cache->get(i + header));
8712     }
8713     cache = new_cache;
8714     set_prototype_transitions(cache);
8715   }
8716
8717   int last = transitions - 1;
8718
8719   cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype);
8720   cache->set(header + last * step + kProtoTransitionMapOffset, map);
8721   SetNumberOfProtoTransitions(transitions);
8722
8723   return cache;
8724 }
8725
8726
8727 MaybeObject* JSReceiver::SetPrototype(Object* value,
8728                                       bool skip_hidden_prototypes) {
8729 #ifdef DEBUG
8730   int size = Size();
8731 #endif
8732
8733   Heap* heap = GetHeap();
8734   // Silently ignore the change if value is not a JSObject or null.
8735   // SpiderMonkey behaves this way.
8736   if (!value->IsJSReceiver() && !value->IsNull()) return value;
8737
8738   // From 8.6.2 Object Internal Methods
8739   // ...
8740   // In addition, if [[Extensible]] is false the value of the [[Class]] and
8741   // [[Prototype]] internal properties of the object may not be modified.
8742   // ...
8743   // Implementation specific extensions that modify [[Class]], [[Prototype]]
8744   // or [[Extensible]] must not violate the invariants defined in the preceding
8745   // paragraph.
8746   if (!this->map()->is_extensible()) {
8747     HandleScope scope(heap->isolate());
8748     Handle<Object> handle(this, heap->isolate());
8749     return heap->isolate()->Throw(
8750         *FACTORY->NewTypeError("non_extensible_proto",
8751                                HandleVector<Object>(&handle, 1)));
8752   }
8753
8754   // Before we can set the prototype we need to be sure
8755   // prototype cycles are prevented.
8756   // It is sufficient to validate that the receiver is not in the new prototype
8757   // chain.
8758   for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
8759     if (JSReceiver::cast(pt) == this) {
8760       // Cycle detected.
8761       HandleScope scope(heap->isolate());
8762       return heap->isolate()->Throw(
8763           *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
8764     }
8765   }
8766
8767   JSReceiver* real_receiver = this;
8768
8769   if (skip_hidden_prototypes) {
8770     // Find the first object in the chain whose prototype object is not
8771     // hidden and set the new prototype on that object.
8772     Object* current_proto = real_receiver->GetPrototype();
8773     while (current_proto->IsJSObject() &&
8774           JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) {
8775       real_receiver = JSReceiver::cast(current_proto);
8776       current_proto = current_proto->GetPrototype();
8777     }
8778   }
8779
8780   // Set the new prototype of the object.
8781   Map* map = real_receiver->map();
8782
8783   // Nothing to do if prototype is already set.
8784   if (map->prototype() == value) return value;
8785
8786   Object* new_map = map->GetPrototypeTransition(value);
8787   if (new_map == NULL) {
8788     { MaybeObject* maybe_new_map = map->CopyDropTransitions();
8789       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
8790     }
8791
8792     { MaybeObject* maybe_new_cache =
8793           map->PutPrototypeTransition(value, Map::cast(new_map));
8794       if (maybe_new_cache->IsFailure()) return maybe_new_cache;
8795     }
8796
8797     Map::cast(new_map)->set_prototype(value);
8798   }
8799   ASSERT(Map::cast(new_map)->prototype() == value);
8800   real_receiver->set_map(Map::cast(new_map));
8801
8802   heap->ClearInstanceofCache();
8803   ASSERT(size == Size());
8804   return value;
8805 }
8806
8807
8808 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args,
8809                                                 uint32_t first_arg,
8810                                                 uint32_t arg_count,
8811                                                 EnsureElementsMode mode) {
8812   // Elements in |Arguments| are ordered backwards (because they're on the
8813   // stack), but the method that's called here iterates over them in forward
8814   // direction.
8815   return EnsureCanContainElements(
8816       args->arguments() - first_arg - (arg_count - 1),
8817       arg_count, mode);
8818 }
8819
8820
8821 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) {
8822   Isolate* isolate = GetIsolate();
8823   // Make sure that the top context does not change when doing
8824   // callbacks or interceptor calls.
8825   AssertNoContextChange ncc;
8826   HandleScope scope(isolate);
8827   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
8828   Handle<JSReceiver> receiver_handle(receiver);
8829   Handle<JSObject> holder_handle(this);
8830   CustomArguments args(isolate, interceptor->data(), receiver, this);
8831   v8::AccessorInfo info(args.end());
8832   if (!interceptor->query()->IsUndefined()) {
8833     v8::IndexedPropertyQuery query =
8834         v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
8835     LOG(isolate,
8836         ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
8837     v8::Handle<v8::Integer> result;
8838     {
8839       // Leaving JavaScript.
8840       VMState state(isolate, EXTERNAL);
8841       result = query(index, info);
8842     }
8843     if (!result.IsEmpty()) {
8844       ASSERT(result->IsInt32());
8845       return true;  // absence of property is signaled by empty handle.
8846     }
8847   } else if (!interceptor->getter()->IsUndefined()) {
8848     v8::IndexedPropertyGetter getter =
8849         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
8850     LOG(isolate,
8851         ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
8852     v8::Handle<v8::Value> result;
8853     {
8854       // Leaving JavaScript.
8855       VMState state(isolate, EXTERNAL);
8856       result = getter(index, info);
8857     }
8858     if (!result.IsEmpty()) return true;
8859   }
8860
8861   if (holder_handle->GetElementsAccessor()->HasElement(
8862           *receiver_handle, *holder_handle, index)) {
8863     return true;
8864   }
8865
8866   if (holder_handle->IsStringObjectWithCharacterAt(index)) return true;
8867   Object* pt = holder_handle->GetPrototype();
8868   if (pt->IsJSProxy()) {
8869     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
8870     return JSProxy::cast(pt)->GetElementAttributeWithHandler(
8871         receiver, index) != ABSENT;
8872   }
8873   if (pt->IsNull()) return false;
8874   return JSObject::cast(pt)->HasElementWithReceiver(*receiver_handle, index);
8875 }
8876
8877
8878 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) {
8879   // Check access rights if needed.
8880   if (IsAccessCheckNeeded()) {
8881     Heap* heap = GetHeap();
8882     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
8883       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
8884       return UNDEFINED_ELEMENT;
8885     }
8886   }
8887
8888   if (IsJSGlobalProxy()) {
8889     Object* proto = GetPrototype();
8890     if (proto->IsNull()) return UNDEFINED_ELEMENT;
8891     ASSERT(proto->IsJSGlobalObject());
8892     return JSObject::cast(proto)->HasLocalElement(index);
8893   }
8894
8895   // Check for lookup interceptor
8896   if (HasIndexedInterceptor()) {
8897     return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
8898                                                   : UNDEFINED_ELEMENT;
8899   }
8900
8901   // Handle [] on String objects.
8902   if (this->IsStringObjectWithCharacterAt(index)) {
8903     return STRING_CHARACTER_ELEMENT;
8904   }
8905
8906   switch (GetElementsKind()) {
8907     case FAST_SMI_ONLY_ELEMENTS:
8908     case FAST_ELEMENTS: {
8909       uint32_t length = IsJSArray() ?
8910           static_cast<uint32_t>
8911               (Smi::cast(JSArray::cast(this)->length())->value()) :
8912           static_cast<uint32_t>(FixedArray::cast(elements())->length());
8913       if ((index < length) &&
8914           !FixedArray::cast(elements())->get(index)->IsTheHole()) {
8915         return FAST_ELEMENT;
8916       }
8917       break;
8918     }
8919     case FAST_DOUBLE_ELEMENTS: {
8920       uint32_t length = IsJSArray() ?
8921           static_cast<uint32_t>
8922               (Smi::cast(JSArray::cast(this)->length())->value()) :
8923           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
8924       if ((index < length) &&
8925           !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
8926         return FAST_ELEMENT;
8927       }
8928       break;
8929     }
8930     case EXTERNAL_PIXEL_ELEMENTS: {
8931       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
8932       if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT;
8933       break;
8934     }
8935     case EXTERNAL_BYTE_ELEMENTS:
8936     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8937     case EXTERNAL_SHORT_ELEMENTS:
8938     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8939     case EXTERNAL_INT_ELEMENTS:
8940     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8941     case EXTERNAL_FLOAT_ELEMENTS:
8942     case EXTERNAL_DOUBLE_ELEMENTS: {
8943       ExternalArray* array = ExternalArray::cast(elements());
8944       if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
8945       break;
8946     }
8947     case DICTIONARY_ELEMENTS: {
8948       if (element_dictionary()->FindEntry(index) !=
8949           SeededNumberDictionary::kNotFound) {
8950         return DICTIONARY_ELEMENT;
8951       }
8952       break;
8953     }
8954     case NON_STRICT_ARGUMENTS_ELEMENTS: {
8955       // Aliased parameters and non-aliased elements in a fast backing store
8956       // behave as FAST_ELEMENT.  Non-aliased elements in a dictionary
8957       // backing store behave as DICTIONARY_ELEMENT.
8958       FixedArray* parameter_map = FixedArray::cast(elements());
8959       uint32_t length = parameter_map->length();
8960       Object* probe =
8961           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
8962       if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
8963       // If not aliased, check the arguments.
8964       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
8965       if (arguments->IsDictionary()) {
8966         SeededNumberDictionary* dictionary =
8967             SeededNumberDictionary::cast(arguments);
8968         if (dictionary->FindEntry(index) != SeededNumberDictionary::kNotFound) {
8969           return DICTIONARY_ELEMENT;
8970         }
8971       } else {
8972         length = arguments->length();
8973         probe = (index < length) ? arguments->get(index) : NULL;
8974         if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
8975       }
8976       break;
8977     }
8978   }
8979
8980   return UNDEFINED_ELEMENT;
8981 }
8982
8983
8984 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
8985   // Check access rights if needed.
8986   if (IsAccessCheckNeeded()) {
8987     Heap* heap = GetHeap();
8988     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
8989       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
8990       return false;
8991     }
8992   }
8993
8994   // Check for lookup interceptor
8995   if (HasIndexedInterceptor()) {
8996     return HasElementWithInterceptor(receiver, index);
8997   }
8998
8999   ElementsAccessor* accessor = GetElementsAccessor();
9000   if (accessor->HasElement(receiver, this, index)) {
9001     return true;
9002   }
9003
9004   // Handle [] on String objects.
9005   if (this->IsStringObjectWithCharacterAt(index)) return true;
9006
9007   Object* pt = GetPrototype();
9008   if (pt->IsNull()) return false;
9009   if (pt->IsJSProxy()) {
9010     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
9011     return JSProxy::cast(pt)->GetElementAttributeWithHandler(
9012         receiver, index) != ABSENT;
9013   }
9014   return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
9015 }
9016
9017
9018 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
9019                                                  Object* value,
9020                                                  PropertyAttributes attributes,
9021                                                  StrictModeFlag strict_mode,
9022                                                  bool check_prototype,
9023                                                  SetPropertyMode set_mode) {
9024   Isolate* isolate = GetIsolate();
9025   // Make sure that the top context does not change when doing
9026   // callbacks or interceptor calls.
9027   AssertNoContextChange ncc;
9028   HandleScope scope(isolate);
9029   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
9030   Handle<JSObject> this_handle(this);
9031   Handle<Object> value_handle(value, isolate);
9032   if (!interceptor->setter()->IsUndefined()) {
9033     v8::IndexedPropertySetter setter =
9034         v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
9035     LOG(isolate,
9036         ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
9037     CustomArguments args(isolate, interceptor->data(), this, this);
9038     v8::AccessorInfo info(args.end());
9039     v8::Handle<v8::Value> result;
9040     {
9041       // Leaving JavaScript.
9042       VMState state(isolate, EXTERNAL);
9043       result = setter(index, v8::Utils::ToLocal(value_handle), info);
9044     }
9045     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9046     if (!result.IsEmpty()) return *value_handle;
9047   }
9048   MaybeObject* raw_result =
9049       this_handle->SetElementWithoutInterceptor(index,
9050                                                 *value_handle,
9051                                                 attributes,
9052                                                 strict_mode,
9053                                                 check_prototype,
9054                                                 set_mode);
9055   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9056   return raw_result;
9057 }
9058
9059
9060 MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
9061                                               Object* structure,
9062                                               uint32_t index,
9063                                               Object* holder) {
9064   Isolate* isolate = GetIsolate();
9065   ASSERT(!structure->IsForeign());
9066
9067   // api style callbacks.
9068   if (structure->IsAccessorInfo()) {
9069     Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9070     Object* fun_obj = data->getter();
9071     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
9072     HandleScope scope(isolate);
9073     Handle<JSObject> self(JSObject::cast(receiver));
9074     Handle<JSObject> holder_handle(JSObject::cast(holder));
9075     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9076     Handle<String> key = isolate->factory()->NumberToString(number);
9077     LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
9078     CustomArguments args(isolate, data->data(), *self, *holder_handle);
9079     v8::AccessorInfo info(args.end());
9080     v8::Handle<v8::Value> result;
9081     {
9082       // Leaving JavaScript.
9083       VMState state(isolate, EXTERNAL);
9084       result = call_fun(v8::Utils::ToLocal(key), info);
9085     }
9086     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9087     if (result.IsEmpty()) return isolate->heap()->undefined_value();
9088     return *v8::Utils::OpenHandle(*result);
9089   }
9090
9091   // __defineGetter__ callback
9092   if (structure->IsAccessorPair()) {
9093     Object* getter = AccessorPair::cast(structure)->getter();
9094     if (getter->IsSpecFunction()) {
9095       // TODO(rossberg): nicer would be to cast to some JSCallable here...
9096       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
9097     }
9098     // Getter is not a function.
9099     return isolate->heap()->undefined_value();
9100   }
9101
9102   UNREACHABLE();
9103   return NULL;
9104 }
9105
9106
9107 MaybeObject* JSObject::SetElementWithCallback(Object* structure,
9108                                               uint32_t index,
9109                                               Object* value,
9110                                               JSObject* holder,
9111                                               StrictModeFlag strict_mode) {
9112   Isolate* isolate = GetIsolate();
9113   HandleScope scope(isolate);
9114
9115   // We should never get here to initialize a const with the hole
9116   // value since a const declaration would conflict with the setter.
9117   ASSERT(!value->IsTheHole());
9118   Handle<Object> value_handle(value, isolate);
9119
9120   // To accommodate both the old and the new api we switch on the
9121   // data structure used to store the callbacks.  Eventually foreign
9122   // callbacks should be phased out.
9123   ASSERT(!structure->IsForeign());
9124
9125   if (structure->IsAccessorInfo()) {
9126     // api style callbacks
9127     Handle<JSObject> self(this);
9128     Handle<JSObject> holder_handle(JSObject::cast(holder));
9129     Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9130     Object* call_obj = data->setter();
9131     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
9132     if (call_fun == NULL) return value;
9133     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9134     Handle<String> key(isolate->factory()->NumberToString(number));
9135     LOG(isolate, ApiNamedPropertyAccess("store", *self, *key));
9136     CustomArguments args(isolate, data->data(), *self, *holder_handle);
9137     v8::AccessorInfo info(args.end());
9138     {
9139       // Leaving JavaScript.
9140       VMState state(isolate, EXTERNAL);
9141       call_fun(v8::Utils::ToLocal(key),
9142                v8::Utils::ToLocal(value_handle),
9143                info);
9144     }
9145     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9146     return *value_handle;
9147   }
9148
9149   if (structure->IsAccessorPair()) {
9150     Handle<Object> setter(AccessorPair::cast(structure)->setter());
9151     if (setter->IsSpecFunction()) {
9152       // TODO(rossberg): nicer would be to cast to some JSCallable here...
9153       return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
9154     } else {
9155       if (strict_mode == kNonStrictMode) {
9156         return value;
9157       }
9158       Handle<Object> holder_handle(holder, isolate);
9159       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
9160       Handle<Object> args[2] = { key, holder_handle };
9161       return isolate->Throw(
9162           *isolate->factory()->NewTypeError("no_setter_in_callback",
9163                                             HandleVector(args, 2)));
9164     }
9165   }
9166
9167   UNREACHABLE();
9168   return NULL;
9169 }
9170
9171
9172 bool JSObject::HasFastArgumentsElements() {
9173   Heap* heap = GetHeap();
9174   if (!elements()->IsFixedArray()) return false;
9175   FixedArray* elements = FixedArray::cast(this->elements());
9176   if (elements->map() != heap->non_strict_arguments_elements_map()) {
9177     return false;
9178   }
9179   FixedArray* arguments = FixedArray::cast(elements->get(1));
9180   return !arguments->IsDictionary();
9181 }
9182
9183
9184 bool JSObject::HasDictionaryArgumentsElements() {
9185   Heap* heap = GetHeap();
9186   if (!elements()->IsFixedArray()) return false;
9187   FixedArray* elements = FixedArray::cast(this->elements());
9188   if (elements->map() != heap->non_strict_arguments_elements_map()) {
9189     return false;
9190   }
9191   FixedArray* arguments = FixedArray::cast(elements->get(1));
9192   return arguments->IsDictionary();
9193 }
9194
9195
9196 // Adding n elements in fast case is O(n*n).
9197 // Note: revisit design to have dual undefined values to capture absent
9198 // elements.
9199 MaybeObject* JSObject::SetFastElement(uint32_t index,
9200                                       Object* value,
9201                                       StrictModeFlag strict_mode,
9202                                       bool check_prototype) {
9203   ASSERT(HasFastTypeElements() ||
9204          HasFastArgumentsElements());
9205
9206   FixedArray* backing_store = FixedArray::cast(elements());
9207   if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
9208     backing_store = FixedArray::cast(backing_store->get(1));
9209   } else {
9210     MaybeObject* maybe = EnsureWritableFastElements();
9211     if (!maybe->To(&backing_store)) return maybe;
9212   }
9213   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
9214
9215   if (check_prototype &&
9216       (index >= capacity || backing_store->get(index)->IsTheHole())) {
9217     bool found;
9218     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9219                                                                    value,
9220                                                                    &found,
9221                                                                    strict_mode);
9222     if (found) return result;
9223   }
9224
9225   uint32_t new_capacity = capacity;
9226   // Check if the length property of this object needs to be updated.
9227   uint32_t array_length = 0;
9228   bool must_update_array_length = false;
9229   if (IsJSArray()) {
9230     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9231     if (index >= array_length) {
9232       must_update_array_length = true;
9233       array_length = index + 1;
9234     }
9235   }
9236   // Check if the capacity of the backing store needs to be increased, or if
9237   // a transition to slow elements is necessary.
9238   if (index >= capacity) {
9239     bool convert_to_slow = true;
9240     if ((index - capacity) < kMaxGap) {
9241       new_capacity = NewElementsCapacity(index + 1);
9242       ASSERT(new_capacity > index);
9243       if (!ShouldConvertToSlowElements(new_capacity)) {
9244         convert_to_slow = false;
9245       }
9246     }
9247     if (convert_to_slow) {
9248       MaybeObject* result = NormalizeElements();
9249       if (result->IsFailure()) return result;
9250       return SetDictionaryElement(index, value, NONE, strict_mode,
9251                                   check_prototype);
9252     }
9253   }
9254   // Convert to fast double elements if appropriate.
9255   if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) {
9256     MaybeObject* maybe =
9257         SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
9258     if (maybe->IsFailure()) return maybe;
9259     FixedDoubleArray::cast(elements())->set(index, value->Number());
9260     return value;
9261   }
9262   // Change elements kind from SMI_ONLY to generic FAST if necessary.
9263   if (HasFastSmiOnlyElements() && !value->IsSmi()) {
9264     Map* new_map;
9265     { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
9266                                                             FAST_ELEMENTS);
9267       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9268     }
9269     set_map(new_map);
9270     if (FLAG_trace_elements_transitions) {
9271       PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
9272                               FAST_ELEMENTS, elements());
9273     }
9274   }
9275   // Increase backing store capacity if that's been decided previously.
9276   if (new_capacity != capacity) {
9277     FixedArray* new_elements;
9278     SetFastElementsCapacityMode set_capacity_mode =
9279         value->IsSmi() && HasFastSmiOnlyElements()
9280             ? kAllowSmiOnlyElements
9281             : kDontAllowSmiOnlyElements;
9282     { MaybeObject* maybe =
9283           SetFastElementsCapacityAndLength(new_capacity,
9284                                            array_length,
9285                                            set_capacity_mode);
9286       if (!maybe->To(&new_elements)) return maybe;
9287     }
9288     new_elements->set(index, value);
9289     return value;
9290   }
9291   // Finally, set the new element and length.
9292   ASSERT(elements()->IsFixedArray());
9293   backing_store->set(index, value);
9294   if (must_update_array_length) {
9295     JSArray::cast(this)->set_length(Smi::FromInt(array_length));
9296   }
9297   return value;
9298 }
9299
9300
9301 MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
9302                                             Object* value,
9303                                             PropertyAttributes attributes,
9304                                             StrictModeFlag strict_mode,
9305                                             bool check_prototype,
9306                                             SetPropertyMode set_mode) {
9307   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
9308   Isolate* isolate = GetIsolate();
9309   Heap* heap = isolate->heap();
9310
9311   // Insert element in the dictionary.
9312   FixedArray* elements = FixedArray::cast(this->elements());
9313   bool is_arguments =
9314       (elements->map() == heap->non_strict_arguments_elements_map());
9315   SeededNumberDictionary* dictionary = NULL;
9316   if (is_arguments) {
9317     dictionary = SeededNumberDictionary::cast(elements->get(1));
9318   } else {
9319     dictionary = SeededNumberDictionary::cast(elements);
9320   }
9321
9322   int entry = dictionary->FindEntry(index);
9323   if (entry != SeededNumberDictionary::kNotFound) {
9324     Object* element = dictionary->ValueAt(entry);
9325     PropertyDetails details = dictionary->DetailsAt(entry);
9326     if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
9327       return SetElementWithCallback(element, index, value, this, strict_mode);
9328     } else {
9329       dictionary->UpdateMaxNumberKey(index);
9330       // If a value has not been initialized we allow writing to it even if it
9331       // is read-only (a declared const that has not been initialized).  If a
9332       // value is being defined we skip attribute checks completely.
9333       if (set_mode == DEFINE_PROPERTY) {
9334         details = PropertyDetails(attributes, NORMAL, details.index());
9335         dictionary->DetailsAtPut(entry, details);
9336       } else if (details.IsReadOnly() && !element->IsTheHole()) {
9337         if (strict_mode == kNonStrictMode) {
9338           return isolate->heap()->undefined_value();
9339         } else {
9340           Handle<Object> holder(this);
9341           Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9342           Handle<Object> args[2] = { number, holder };
9343           Handle<Object> error =
9344               isolate->factory()->NewTypeError("strict_read_only_property",
9345                                                HandleVector(args, 2));
9346           return isolate->Throw(*error);
9347         }
9348       }
9349       // Elements of the arguments object in slow mode might be slow aliases.
9350       if (is_arguments && element->IsAliasedArgumentsEntry()) {
9351         AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(element);
9352         Context* context = Context::cast(elements->get(0));
9353         int context_index = entry->aliased_context_slot();
9354         ASSERT(!context->get(context_index)->IsTheHole());
9355         context->set(context_index, value);
9356         // For elements that are still writable we keep slow aliasing.
9357         if (!details.IsReadOnly()) value = element;
9358       }
9359       dictionary->ValueAtPut(entry, value);
9360     }
9361   } else {
9362     // Index not already used. Look for an accessor in the prototype chain.
9363     if (check_prototype) {
9364       bool found;
9365       MaybeObject* result =
9366           SetElementWithCallbackSetterInPrototypes(
9367               index, value, &found, strict_mode);
9368       if (found) return result;
9369     }
9370     // When we set the is_extensible flag to false we always force the
9371     // element into dictionary mode (and force them to stay there).
9372     if (!map()->is_extensible()) {
9373       if (strict_mode == kNonStrictMode) {
9374         return isolate->heap()->undefined_value();
9375       } else {
9376         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9377         Handle<String> name = isolate->factory()->NumberToString(number);
9378         Handle<Object> args[1] = { name };
9379         Handle<Object> error =
9380             isolate->factory()->NewTypeError("object_not_extensible",
9381                                              HandleVector(args, 1));
9382         return isolate->Throw(*error);
9383       }
9384     }
9385     FixedArrayBase* new_dictionary;
9386     PropertyDetails details = PropertyDetails(attributes, NORMAL);
9387     MaybeObject* maybe = dictionary->AddNumberEntry(index, value, details);
9388     if (!maybe->To(&new_dictionary)) return maybe;
9389     if (dictionary != SeededNumberDictionary::cast(new_dictionary)) {
9390       if (is_arguments) {
9391         elements->set(1, new_dictionary);
9392       } else {
9393         set_elements(new_dictionary);
9394       }
9395       dictionary = SeededNumberDictionary::cast(new_dictionary);
9396     }
9397   }
9398
9399   // Update the array length if this JSObject is an array.
9400   if (IsJSArray()) {
9401     MaybeObject* result =
9402         JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
9403     if (result->IsFailure()) return result;
9404   }
9405
9406   // Attempt to put this object back in fast case.
9407   if (ShouldConvertToFastElements()) {
9408     uint32_t new_length = 0;
9409     if (IsJSArray()) {
9410       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
9411     } else {
9412       new_length = dictionary->max_number_key() + 1;
9413     }
9414     SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays
9415         ? kAllowSmiOnlyElements
9416         : kDontAllowSmiOnlyElements;
9417     bool has_smi_only_elements = false;
9418     bool should_convert_to_fast_double_elements =
9419         ShouldConvertToFastDoubleElements(&has_smi_only_elements);
9420     if (has_smi_only_elements) {
9421       set_capacity_mode = kForceSmiOnlyElements;
9422     }
9423     MaybeObject* result = should_convert_to_fast_double_elements
9424         ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
9425         : SetFastElementsCapacityAndLength(new_length,
9426                                            new_length,
9427                                            set_capacity_mode);
9428     if (result->IsFailure()) return result;
9429 #ifdef DEBUG
9430     if (FLAG_trace_normalization) {
9431       PrintF("Object elements are fast case again:\n");
9432       Print();
9433     }
9434 #endif
9435   }
9436   return value;
9437 }
9438
9439
9440 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
9441     uint32_t index,
9442     Object* value,
9443     StrictModeFlag strict_mode,
9444     bool check_prototype) {
9445   ASSERT(HasFastDoubleElements());
9446
9447   FixedArrayBase* base_elms = FixedArrayBase::cast(elements());
9448   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
9449
9450   // If storing to an element that isn't in the array, pass the store request
9451   // up the prototype chain before storing in the receiver's elements.
9452   if (check_prototype &&
9453       (index >= elms_length ||
9454        FixedDoubleArray::cast(base_elms)->is_the_hole(index))) {
9455     bool found;
9456     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9457                                                                    value,
9458                                                                    &found,
9459                                                                    strict_mode);
9460     if (found) return result;
9461   }
9462
9463   // If the value object is not a heap number, switch to fast elements and try
9464   // again.
9465   bool value_is_smi = value->IsSmi();
9466   if (!value->IsNumber()) {
9467     Object* obj;
9468     uint32_t length = elms_length;
9469     if (IsJSArray()) {
9470       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9471     }
9472     MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
9473         elms_length,
9474         length,
9475         kDontAllowSmiOnlyElements);
9476     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9477     return SetFastElement(index,
9478                           value,
9479                           strict_mode,
9480                           check_prototype);
9481   }
9482
9483   double double_value = value_is_smi
9484       ? static_cast<double>(Smi::cast(value)->value())
9485       : HeapNumber::cast(value)->value();
9486
9487   // Check whether there is extra space in the fixed array.
9488   if (index < elms_length) {
9489     FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9490     elms->set(index, double_value);
9491     if (IsJSArray()) {
9492       // Update the length of the array if needed.
9493       uint32_t array_length = 0;
9494       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9495       if (index >= array_length) {
9496         JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
9497       }
9498     }
9499     return value;
9500   }
9501
9502   // Allow gap in fast case.
9503   if ((index - elms_length) < kMaxGap) {
9504     // Try allocating extra space.
9505     int new_capacity = NewElementsCapacity(index+1);
9506     if (!ShouldConvertToSlowElements(new_capacity)) {
9507       ASSERT(static_cast<uint32_t>(new_capacity) > index);
9508       Object* obj;
9509       { MaybeObject* maybe_obj =
9510             SetFastDoubleElementsCapacityAndLength(new_capacity,
9511                                                    index + 1);
9512         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9513       }
9514       FixedDoubleArray::cast(elements())->set(index, double_value);
9515       return value;
9516     }
9517   }
9518
9519   // Otherwise default to slow case.
9520   ASSERT(HasFastDoubleElements());
9521   ASSERT(map()->has_fast_double_elements());
9522   ASSERT(elements()->IsFixedDoubleArray());
9523   Object* obj;
9524   { MaybeObject* maybe_obj = NormalizeElements();
9525     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9526   }
9527   ASSERT(HasDictionaryElements());
9528   return SetElement(index, value, NONE, strict_mode, check_prototype);
9529 }
9530
9531
9532 MaybeObject* JSReceiver::SetElement(uint32_t index,
9533                                     Object* value,
9534                                     PropertyAttributes attributes,
9535                                     StrictModeFlag strict_mode,
9536                                     bool check_proto) {
9537   if (IsJSProxy()) {
9538     return JSProxy::cast(this)->SetElementWithHandler(
9539         index, value, strict_mode);
9540   } else {
9541     return JSObject::cast(this)->SetElement(
9542         index, value, attributes, strict_mode, check_proto);
9543   }
9544 }
9545
9546
9547 Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
9548                                        uint32_t index,
9549                                        Handle<Object> value,
9550                                        StrictModeFlag strict_mode) {
9551   ASSERT(!object->HasExternalArrayElements());
9552   CALL_HEAP_FUNCTION(
9553       object->GetIsolate(),
9554       object->SetElement(index, *value, NONE, strict_mode, false),
9555       Object);
9556 }
9557
9558
9559 Handle<Object> JSObject::SetElement(Handle<JSObject> object,
9560                                     uint32_t index,
9561                                     Handle<Object> value,
9562                                     PropertyAttributes attr,
9563                                     StrictModeFlag strict_mode,
9564                                     SetPropertyMode set_mode) {
9565   if (object->HasExternalArrayElements()) {
9566     if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
9567       bool has_exception;
9568       Handle<Object> number = Execution::ToNumber(value, &has_exception);
9569       if (has_exception) return Handle<Object>();
9570       value = number;
9571     }
9572   }
9573   CALL_HEAP_FUNCTION(
9574       object->GetIsolate(),
9575       object->SetElement(index, *value, attr, strict_mode, true, set_mode),
9576       Object);
9577 }
9578
9579
9580 MaybeObject* JSObject::SetElement(uint32_t index,
9581                                   Object* value,
9582                                   PropertyAttributes attributes,
9583                                   StrictModeFlag strict_mode,
9584                                   bool check_prototype,
9585                                   SetPropertyMode set_mode) {
9586   // Check access rights if needed.
9587   if (IsAccessCheckNeeded()) {
9588     Heap* heap = GetHeap();
9589     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
9590       HandleScope scope(heap->isolate());
9591       Handle<Object> value_handle(value);
9592       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
9593       return *value_handle;
9594     }
9595   }
9596
9597   if (IsJSGlobalProxy()) {
9598     Object* proto = GetPrototype();
9599     if (proto->IsNull()) return value;
9600     ASSERT(proto->IsJSGlobalObject());
9601     return JSObject::cast(proto)->SetElement(index,
9602                                              value,
9603                                              attributes,
9604                                              strict_mode,
9605                                              check_prototype,
9606                                              set_mode);
9607   }
9608
9609   // Don't allow element properties to be redefined for external arrays.
9610   if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) {
9611     Isolate* isolate = GetHeap()->isolate();
9612     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9613     Handle<Object> args[] = { Handle<Object>(this), number };
9614     Handle<Object> error = isolate->factory()->NewTypeError(
9615         "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
9616     return isolate->Throw(*error);
9617   }
9618
9619   // Normalize the elements to enable attributes on the property.
9620   if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
9621     SeededNumberDictionary* dictionary;
9622     MaybeObject* maybe_object = NormalizeElements();
9623     if (!maybe_object->To(&dictionary)) return maybe_object;
9624     // Make sure that we never go back to fast case.
9625     dictionary->set_requires_slow_elements();
9626   }
9627
9628   // Check for lookup interceptor
9629   if (HasIndexedInterceptor()) {
9630     return SetElementWithInterceptor(index,
9631                                      value,
9632                                      attributes,
9633                                      strict_mode,
9634                                      check_prototype,
9635                                      set_mode);
9636   }
9637
9638   return SetElementWithoutInterceptor(index,
9639                                       value,
9640                                       attributes,
9641                                       strict_mode,
9642                                       check_prototype,
9643                                       set_mode);
9644 }
9645
9646
9647 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
9648                                                     Object* value,
9649                                                     PropertyAttributes attr,
9650                                                     StrictModeFlag strict_mode,
9651                                                     bool check_prototype,
9652                                                     SetPropertyMode set_mode) {
9653   ASSERT(HasDictionaryElements() ||
9654          HasDictionaryArgumentsElements() ||
9655          (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
9656   Isolate* isolate = GetIsolate();
9657   switch (GetElementsKind()) {
9658     case FAST_SMI_ONLY_ELEMENTS:
9659     case FAST_ELEMENTS:
9660       return SetFastElement(index, value, strict_mode, check_prototype);
9661     case FAST_DOUBLE_ELEMENTS:
9662       return SetFastDoubleElement(index, value, strict_mode, check_prototype);
9663     case EXTERNAL_PIXEL_ELEMENTS: {
9664       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9665       return pixels->SetValue(index, value);
9666     }
9667     case EXTERNAL_BYTE_ELEMENTS: {
9668       ExternalByteArray* array = ExternalByteArray::cast(elements());
9669       return array->SetValue(index, value);
9670     }
9671     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
9672       ExternalUnsignedByteArray* array =
9673           ExternalUnsignedByteArray::cast(elements());
9674       return array->SetValue(index, value);
9675     }
9676     case EXTERNAL_SHORT_ELEMENTS: {
9677       ExternalShortArray* array = ExternalShortArray::cast(elements());
9678       return array->SetValue(index, value);
9679     }
9680     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
9681       ExternalUnsignedShortArray* array =
9682           ExternalUnsignedShortArray::cast(elements());
9683       return array->SetValue(index, value);
9684     }
9685     case EXTERNAL_INT_ELEMENTS: {
9686       ExternalIntArray* array = ExternalIntArray::cast(elements());
9687       return array->SetValue(index, value);
9688     }
9689     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
9690       ExternalUnsignedIntArray* array =
9691           ExternalUnsignedIntArray::cast(elements());
9692       return array->SetValue(index, value);
9693     }
9694     case EXTERNAL_FLOAT_ELEMENTS: {
9695       ExternalFloatArray* array = ExternalFloatArray::cast(elements());
9696       return array->SetValue(index, value);
9697     }
9698     case EXTERNAL_DOUBLE_ELEMENTS: {
9699       ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
9700       return array->SetValue(index, value);
9701     }
9702     case DICTIONARY_ELEMENTS:
9703       return SetDictionaryElement(index, value, attr, strict_mode,
9704                                   check_prototype, set_mode);
9705     case NON_STRICT_ARGUMENTS_ELEMENTS: {
9706       FixedArray* parameter_map = FixedArray::cast(elements());
9707       uint32_t length = parameter_map->length();
9708       Object* probe =
9709           (index < length - 2) ? parameter_map->get(index + 2) : NULL;
9710       if (probe != NULL && !probe->IsTheHole()) {
9711         Context* context = Context::cast(parameter_map->get(0));
9712         int context_index = Smi::cast(probe)->value();
9713         ASSERT(!context->get(context_index)->IsTheHole());
9714         context->set(context_index, value);
9715         // Redefining attributes of an aliased element destroys fast aliasing.
9716         if (set_mode == SET_PROPERTY || attr == NONE) return value;
9717         parameter_map->set_the_hole(index + 2);
9718         // For elements that are still writable we re-establish slow aliasing.
9719         if ((attr & READ_ONLY) == 0) {
9720           MaybeObject* maybe_entry =
9721               isolate->heap()->AllocateAliasedArgumentsEntry(context_index);
9722           if (!maybe_entry->ToObject(&value)) return maybe_entry;
9723         }
9724       }
9725       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9726       if (arguments->IsDictionary()) {
9727         return SetDictionaryElement(index, value, attr, strict_mode,
9728                                     check_prototype, set_mode);
9729       } else {
9730         return SetFastElement(index, value, strict_mode, check_prototype);
9731       }
9732     }
9733   }
9734   // All possible cases have been handled above. Add a return to avoid the
9735   // complaints from the compiler.
9736   UNREACHABLE();
9737   return isolate->heap()->null_value();
9738 }
9739
9740
9741 Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object,
9742                                                 ElementsKind to_kind) {
9743   CALL_HEAP_FUNCTION(object->GetIsolate(),
9744                      object->TransitionElementsKind(to_kind),
9745                      Object);
9746 }
9747
9748
9749 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
9750   ElementsKind from_kind = map()->elements_kind();
9751
9752   Isolate* isolate = GetIsolate();
9753   if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
9754       (to_kind == FAST_ELEMENTS ||
9755        elements() == isolate->heap()->empty_fixed_array())) {
9756     MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
9757     Map* new_map;
9758     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9759     set_map(new_map);
9760     if (FLAG_trace_elements_transitions) {
9761       FixedArrayBase* elms = FixedArrayBase::cast(elements());
9762       PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
9763     }
9764     return this;
9765   }
9766
9767   FixedArrayBase* elms = FixedArrayBase::cast(elements());
9768   uint32_t capacity = static_cast<uint32_t>(elms->length());
9769   uint32_t length = capacity;
9770
9771   if (IsJSArray()) {
9772     Object* raw_length = JSArray::cast(this)->length();
9773     if (raw_length->IsUndefined()) {
9774       // If length is undefined, then JSArray is being initialized and has no
9775       // elements, assume a length of zero.
9776       length = 0;
9777     } else {
9778       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9779     }
9780   }
9781
9782   if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
9783       to_kind == FAST_DOUBLE_ELEMENTS) {
9784     MaybeObject* maybe_result =
9785         SetFastDoubleElementsCapacityAndLength(capacity, length);
9786     if (maybe_result->IsFailure()) return maybe_result;
9787     return this;
9788   }
9789
9790   if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
9791     MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
9792         capacity, length, kDontAllowSmiOnlyElements);
9793     if (maybe_result->IsFailure()) return maybe_result;
9794     return this;
9795   }
9796
9797   // This method should never be called for any other case than the ones
9798   // handled above.
9799   UNREACHABLE();
9800   return GetIsolate()->heap()->null_value();
9801 }
9802
9803
9804 // static
9805 bool Map::IsValidElementsTransition(ElementsKind from_kind,
9806                                     ElementsKind to_kind) {
9807   return
9808       (from_kind == FAST_SMI_ONLY_ELEMENTS &&
9809           (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) ||
9810       (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS);
9811 }
9812
9813
9814 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
9815                                                    Object* value) {
9816   uint32_t old_len = 0;
9817   CHECK(length()->ToArrayIndex(&old_len));
9818   // Check to see if we need to update the length. For now, we make
9819   // sure that the length stays within 32-bits (unsigned).
9820   if (index >= old_len && index != 0xffffffff) {
9821     Object* len;
9822     { MaybeObject* maybe_len =
9823           GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
9824       if (!maybe_len->ToObject(&len)) return maybe_len;
9825     }
9826     set_length(len);
9827   }
9828   return value;
9829 }
9830
9831
9832 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
9833                                                  uint32_t index) {
9834   Isolate* isolate = GetIsolate();
9835   // Make sure that the top context does not change when doing
9836   // callbacks or interceptor calls.
9837   AssertNoContextChange ncc;
9838   HandleScope scope(isolate);
9839   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
9840   Handle<Object> this_handle(receiver, isolate);
9841   Handle<JSObject> holder_handle(this, isolate);
9842   if (!interceptor->getter()->IsUndefined()) {
9843     v8::IndexedPropertyGetter getter =
9844         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
9845     LOG(isolate,
9846         ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
9847     CustomArguments args(isolate, interceptor->data(), receiver, this);
9848     v8::AccessorInfo info(args.end());
9849     v8::Handle<v8::Value> result;
9850     {
9851       // Leaving JavaScript.
9852       VMState state(isolate, EXTERNAL);
9853       result = getter(index, info);
9854     }
9855     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9856     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
9857   }
9858
9859   Heap* heap = holder_handle->GetHeap();
9860   ElementsAccessor* handler = holder_handle->GetElementsAccessor();
9861   MaybeObject* raw_result = handler->Get(*this_handle,
9862                                          *holder_handle,
9863                                          index);
9864   if (raw_result != heap->the_hole_value()) return raw_result;
9865
9866   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9867
9868   Object* pt = holder_handle->GetPrototype();
9869   if (pt == heap->null_value()) return heap->undefined_value();
9870   return pt->GetElementWithReceiver(*this_handle, index);
9871 }
9872
9873
9874 bool JSObject::HasDenseElements() {
9875   int capacity = 0;
9876   int used = 0;
9877   GetElementsCapacityAndUsage(&capacity, &used);
9878   return (capacity == 0) || (used > (capacity / 2));
9879 }
9880
9881
9882 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
9883   *capacity = 0;
9884   *used = 0;
9885
9886   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
9887   FixedArray* backing_store = NULL;
9888   switch (GetElementsKind()) {
9889     case NON_STRICT_ARGUMENTS_ELEMENTS:
9890       backing_store_base =
9891           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
9892       backing_store = FixedArray::cast(backing_store_base);
9893       if (backing_store->IsDictionary()) {
9894         SeededNumberDictionary* dictionary =
9895             SeededNumberDictionary::cast(backing_store);
9896         *capacity = dictionary->Capacity();
9897         *used = dictionary->NumberOfElements();
9898         break;
9899       }
9900       // Fall through.
9901     case FAST_SMI_ONLY_ELEMENTS:
9902     case FAST_ELEMENTS:
9903       backing_store = FixedArray::cast(backing_store_base);
9904       *capacity = backing_store->length();
9905       for (int i = 0; i < *capacity; ++i) {
9906         if (!backing_store->get(i)->IsTheHole()) ++(*used);
9907       }
9908       break;
9909     case DICTIONARY_ELEMENTS: {
9910       SeededNumberDictionary* dictionary =
9911           SeededNumberDictionary::cast(FixedArray::cast(elements()));
9912       *capacity = dictionary->Capacity();
9913       *used = dictionary->NumberOfElements();
9914       break;
9915     }
9916     case FAST_DOUBLE_ELEMENTS: {
9917       FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9918       *capacity = elms->length();
9919       for (int i = 0; i < *capacity; i++) {
9920         if (!elms->is_the_hole(i)) ++(*used);
9921       }
9922       break;
9923     }
9924     case EXTERNAL_BYTE_ELEMENTS:
9925     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9926     case EXTERNAL_SHORT_ELEMENTS:
9927     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9928     case EXTERNAL_INT_ELEMENTS:
9929     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9930     case EXTERNAL_FLOAT_ELEMENTS:
9931     case EXTERNAL_DOUBLE_ELEMENTS:
9932     case EXTERNAL_PIXEL_ELEMENTS:
9933       // External arrays are considered 100% used.
9934       ExternalArray* external_array = ExternalArray::cast(elements());
9935       *capacity = external_array->length();
9936       *used = external_array->length();
9937       break;
9938   }
9939 }
9940
9941
9942 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
9943   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
9944                 kMaxUncheckedFastElementsLength);
9945   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
9946       (new_capacity <= kMaxUncheckedFastElementsLength &&
9947        GetHeap()->InNewSpace(this))) {
9948     return false;
9949   }
9950   // If the fast-case backing storage takes up roughly three times as
9951   // much space (in machine words) as a dictionary backing storage
9952   // would, the object should have slow elements.
9953   int old_capacity = 0;
9954   int used_elements = 0;
9955   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
9956   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
9957       SeededNumberDictionary::kEntrySize;
9958   return 3 * dictionary_size <= new_capacity;
9959 }
9960
9961
9962 bool JSObject::ShouldConvertToFastElements() {
9963   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
9964   // If the elements are sparse, we should not go back to fast case.
9965   if (!HasDenseElements()) return false;
9966   // An object requiring access checks is never allowed to have fast
9967   // elements.  If it had fast elements we would skip security checks.
9968   if (IsAccessCheckNeeded()) return false;
9969
9970   FixedArray* elements = FixedArray::cast(this->elements());
9971   SeededNumberDictionary* dictionary = NULL;
9972   if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
9973     dictionary = SeededNumberDictionary::cast(elements->get(1));
9974   } else {
9975     dictionary = SeededNumberDictionary::cast(elements);
9976   }
9977   // If an element has been added at a very high index in the elements
9978   // dictionary, we cannot go back to fast case.
9979   if (dictionary->requires_slow_elements()) return false;
9980   // If the dictionary backing storage takes up roughly half as much
9981   // space (in machine words) as a fast-case backing storage would,
9982   // the object should have fast elements.
9983   uint32_t array_size = 0;
9984   if (IsJSArray()) {
9985     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
9986   } else {
9987     array_size = dictionary->max_number_key();
9988   }
9989   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
9990       SeededNumberDictionary::kEntrySize;
9991   return 2 * dictionary_size >= array_size;
9992 }
9993
9994
9995 bool JSObject::ShouldConvertToFastDoubleElements(
9996     bool* has_smi_only_elements) {
9997   *has_smi_only_elements = false;
9998   if (FLAG_unbox_double_arrays) {
9999     ASSERT(HasDictionaryElements());
10000     SeededNumberDictionary* dictionary =
10001         SeededNumberDictionary::cast(elements());
10002     bool found_double = false;
10003     for (int i = 0; i < dictionary->Capacity(); i++) {
10004       Object* key = dictionary->KeyAt(i);
10005       if (key->IsNumber()) {
10006         Object* value = dictionary->ValueAt(i);
10007         if (!value->IsNumber()) return false;
10008         if (!value->IsSmi()) {
10009           found_double = true;
10010         }
10011       }
10012     }
10013     *has_smi_only_elements = !found_double;
10014     return found_double;
10015   } else {
10016     return false;
10017   }
10018 }
10019
10020
10021 // Certain compilers request function template instantiation when they
10022 // see the definition of the other template functions in the
10023 // class. This requires us to have the template functions put
10024 // together, so even though this function belongs in objects-debug.cc,
10025 // we keep it here instead to satisfy certain compilers.
10026 #ifdef OBJECT_PRINT
10027 template<typename Shape, typename Key>
10028 void Dictionary<Shape, Key>::Print(FILE* out) {
10029   int capacity = HashTable<Shape, Key>::Capacity();
10030   for (int i = 0; i < capacity; i++) {
10031     Object* k = HashTable<Shape, Key>::KeyAt(i);
10032     if (HashTable<Shape, Key>::IsKey(k)) {
10033       PrintF(out, " ");
10034       if (k->IsString()) {
10035         String::cast(k)->StringPrint(out);
10036       } else {
10037         k->ShortPrint(out);
10038       }
10039       PrintF(out, ": ");
10040       ValueAt(i)->ShortPrint(out);
10041       PrintF(out, "\n");
10042     }
10043   }
10044 }
10045 #endif
10046
10047
10048 template<typename Shape, typename Key>
10049 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
10050   int pos = 0;
10051   int capacity = HashTable<Shape, Key>::Capacity();
10052   AssertNoAllocation no_gc;
10053   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
10054   for (int i = 0; i < capacity; i++) {
10055     Object* k =  Dictionary<Shape, Key>::KeyAt(i);
10056     if (Dictionary<Shape, Key>::IsKey(k)) {
10057       elements->set(pos++, ValueAt(i), mode);
10058     }
10059   }
10060   ASSERT(pos == elements->length());
10061 }
10062
10063
10064 InterceptorInfo* JSObject::GetNamedInterceptor() {
10065   ASSERT(map()->has_named_interceptor());
10066   JSFunction* constructor = JSFunction::cast(map()->constructor());
10067   ASSERT(constructor->shared()->IsApiFunction());
10068   Object* result =
10069       constructor->shared()->get_api_func_data()->named_property_handler();
10070   return InterceptorInfo::cast(result);
10071 }
10072
10073
10074 InterceptorInfo* JSObject::GetIndexedInterceptor() {
10075   ASSERT(map()->has_indexed_interceptor());
10076   JSFunction* constructor = JSFunction::cast(map()->constructor());
10077   ASSERT(constructor->shared()->IsApiFunction());
10078   Object* result =
10079       constructor->shared()->get_api_func_data()->indexed_property_handler();
10080   return InterceptorInfo::cast(result);
10081 }
10082
10083
10084 MaybeObject* JSObject::GetPropertyPostInterceptor(
10085     JSReceiver* receiver,
10086     String* name,
10087     PropertyAttributes* attributes) {
10088   // Check local property in holder, ignore interceptor.
10089   LookupResult result(GetIsolate());
10090   LocalLookupRealNamedProperty(name, &result);
10091   if (result.IsProperty()) {
10092     return GetProperty(receiver, &result, name, attributes);
10093   }
10094   // Continue searching via the prototype chain.
10095   Object* pt = GetPrototype();
10096   *attributes = ABSENT;
10097   if (pt->IsNull()) return GetHeap()->undefined_value();
10098   return pt->GetPropertyWithReceiver(receiver, name, attributes);
10099 }
10100
10101
10102 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
10103     JSReceiver* receiver,
10104     String* name,
10105     PropertyAttributes* attributes) {
10106   // Check local property in holder, ignore interceptor.
10107   LookupResult result(GetIsolate());
10108   LocalLookupRealNamedProperty(name, &result);
10109   if (result.IsProperty()) {
10110     return GetProperty(receiver, &result, name, attributes);
10111   }
10112   return GetHeap()->undefined_value();
10113 }
10114
10115
10116 MaybeObject* JSObject::GetPropertyWithInterceptor(
10117     JSReceiver* receiver,
10118     String* name,
10119     PropertyAttributes* attributes) {
10120   Isolate* isolate = GetIsolate();
10121   InterceptorInfo* interceptor = GetNamedInterceptor();
10122   HandleScope scope(isolate);
10123   Handle<JSReceiver> receiver_handle(receiver);
10124   Handle<JSObject> holder_handle(this);
10125   Handle<String> name_handle(name);
10126
10127   if (!interceptor->getter()->IsUndefined()) {
10128     v8::NamedPropertyGetter getter =
10129         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
10130     LOG(isolate,
10131         ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
10132     CustomArguments args(isolate, interceptor->data(), receiver, this);
10133     v8::AccessorInfo info(args.end());
10134     v8::Handle<v8::Value> result;
10135     {
10136       // Leaving JavaScript.
10137       VMState state(isolate, EXTERNAL);
10138       result = getter(v8::Utils::ToLocal(name_handle), info);
10139     }
10140     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
10141     if (!result.IsEmpty()) {
10142       *attributes = NONE;
10143       return *v8::Utils::OpenHandle(*result);
10144     }
10145   }
10146
10147   MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
10148       *receiver_handle,
10149       *name_handle,
10150       attributes);
10151   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
10152   return result;
10153 }
10154
10155
10156 bool JSObject::HasRealNamedProperty(String* key) {
10157   // Check access rights if needed.
10158   Isolate* isolate = GetIsolate();
10159   if (IsAccessCheckNeeded()) {
10160     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10161       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10162       return false;
10163     }
10164   }
10165
10166   LookupResult result(isolate);
10167   LocalLookupRealNamedProperty(key, &result);
10168   return result.IsProperty() && (result.type() != INTERCEPTOR);
10169 }
10170
10171
10172 bool JSObject::HasRealElementProperty(uint32_t index) {
10173   // Check access rights if needed.
10174   if (IsAccessCheckNeeded()) {
10175     Heap* heap = GetHeap();
10176     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
10177       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10178       return false;
10179     }
10180   }
10181
10182   // Handle [] on String objects.
10183   if (this->IsStringObjectWithCharacterAt(index)) return true;
10184
10185   switch (GetElementsKind()) {
10186     case FAST_SMI_ONLY_ELEMENTS:
10187     case FAST_ELEMENTS: {
10188       uint32_t length = IsJSArray() ?
10189           static_cast<uint32_t>(
10190               Smi::cast(JSArray::cast(this)->length())->value()) :
10191           static_cast<uint32_t>(FixedArray::cast(elements())->length());
10192       return (index < length) &&
10193           !FixedArray::cast(elements())->get(index)->IsTheHole();
10194     }
10195     case FAST_DOUBLE_ELEMENTS: {
10196       uint32_t length = IsJSArray() ?
10197           static_cast<uint32_t>(
10198               Smi::cast(JSArray::cast(this)->length())->value()) :
10199           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
10200       return (index < length) &&
10201           !FixedDoubleArray::cast(elements())->is_the_hole(index);
10202       break;
10203     }
10204     case EXTERNAL_PIXEL_ELEMENTS: {
10205       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
10206       return index < static_cast<uint32_t>(pixels->length());
10207     }
10208     case EXTERNAL_BYTE_ELEMENTS:
10209     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
10210     case EXTERNAL_SHORT_ELEMENTS:
10211     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
10212     case EXTERNAL_INT_ELEMENTS:
10213     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
10214     case EXTERNAL_FLOAT_ELEMENTS:
10215     case EXTERNAL_DOUBLE_ELEMENTS: {
10216       ExternalArray* array = ExternalArray::cast(elements());
10217       return index < static_cast<uint32_t>(array->length());
10218     }
10219     case DICTIONARY_ELEMENTS: {
10220       return element_dictionary()->FindEntry(index)
10221           != SeededNumberDictionary::kNotFound;
10222     }
10223     case NON_STRICT_ARGUMENTS_ELEMENTS:
10224       UNIMPLEMENTED();
10225       break;
10226   }
10227   // All possibilities have been handled above already.
10228   UNREACHABLE();
10229   return GetHeap()->null_value();
10230 }
10231
10232
10233 bool JSObject::HasRealNamedCallbackProperty(String* key) {
10234   // Check access rights if needed.
10235   Isolate* isolate = GetIsolate();
10236   if (IsAccessCheckNeeded()) {
10237     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10238       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10239       return false;
10240     }
10241   }
10242
10243   LookupResult result(isolate);
10244   LocalLookupRealNamedProperty(key, &result);
10245   return result.IsFound() && (result.type() == CALLBACKS);
10246 }
10247
10248
10249 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
10250   return HasFastProperties() ?
10251       map()->NumberOfDescribedProperties(filter) :
10252       property_dictionary()->NumberOfElementsFilterAttributes(filter);
10253 }
10254
10255
10256 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
10257   Object* temp = get(i);
10258   set(i, get(j));
10259   set(j, temp);
10260   if (this != numbers) {
10261     temp = numbers->get(i);
10262     numbers->set(i, Smi::cast(numbers->get(j)));
10263     numbers->set(j, Smi::cast(temp));
10264   }
10265 }
10266
10267
10268 static void InsertionSortPairs(FixedArray* content,
10269                                FixedArray* numbers,
10270                                int len) {
10271   for (int i = 1; i < len; i++) {
10272     int j = i;
10273     while (j > 0 &&
10274            (NumberToUint32(numbers->get(j - 1)) >
10275             NumberToUint32(numbers->get(j)))) {
10276       content->SwapPairs(numbers, j - 1, j);
10277       j--;
10278     }
10279   }
10280 }
10281
10282
10283 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
10284   // In-place heap sort.
10285   ASSERT(content->length() == numbers->length());
10286
10287   // Bottom-up max-heap construction.
10288   for (int i = 1; i < len; ++i) {
10289     int child_index = i;
10290     while (child_index > 0) {
10291       int parent_index = ((child_index + 1) >> 1) - 1;
10292       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10293       uint32_t child_value = NumberToUint32(numbers->get(child_index));
10294       if (parent_value < child_value) {
10295         content->SwapPairs(numbers, parent_index, child_index);
10296       } else {
10297         break;
10298       }
10299       child_index = parent_index;
10300     }
10301   }
10302
10303   // Extract elements and create sorted array.
10304   for (int i = len - 1; i > 0; --i) {
10305     // Put max element at the back of the array.
10306     content->SwapPairs(numbers, 0, i);
10307     // Sift down the new top element.
10308     int parent_index = 0;
10309     while (true) {
10310       int child_index = ((parent_index + 1) << 1) - 1;
10311       if (child_index >= i) break;
10312       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
10313       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
10314       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10315       if (child_index + 1 >= i || child1_value > child2_value) {
10316         if (parent_value > child1_value) break;
10317         content->SwapPairs(numbers, parent_index, child_index);
10318         parent_index = child_index;
10319       } else {
10320         if (parent_value > child2_value) break;
10321         content->SwapPairs(numbers, parent_index, child_index + 1);
10322         parent_index = child_index + 1;
10323       }
10324     }
10325   }
10326 }
10327
10328
10329 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
10330 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
10331   ASSERT(this->length() == numbers->length());
10332   // For small arrays, simply use insertion sort.
10333   if (len <= 10) {
10334     InsertionSortPairs(this, numbers, len);
10335     return;
10336   }
10337   // Check the range of indices.
10338   uint32_t min_index = NumberToUint32(numbers->get(0));
10339   uint32_t max_index = min_index;
10340   uint32_t i;
10341   for (i = 1; i < len; i++) {
10342     if (NumberToUint32(numbers->get(i)) < min_index) {
10343       min_index = NumberToUint32(numbers->get(i));
10344     } else if (NumberToUint32(numbers->get(i)) > max_index) {
10345       max_index = NumberToUint32(numbers->get(i));
10346     }
10347   }
10348   if (max_index - min_index + 1 == len) {
10349     // Indices form a contiguous range, unless there are duplicates.
10350     // Do an in-place linear time sort assuming distinct numbers, but
10351     // avoid hanging in case they are not.
10352     for (i = 0; i < len; i++) {
10353       uint32_t p;
10354       uint32_t j = 0;
10355       // While the current element at i is not at its correct position p,
10356       // swap the elements at these two positions.
10357       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
10358              j++ < len) {
10359         SwapPairs(numbers, i, p);
10360       }
10361     }
10362   } else {
10363     HeapSortPairs(this, numbers, len);
10364     return;
10365   }
10366 }
10367
10368
10369 // Fill in the names of local properties into the supplied storage. The main
10370 // purpose of this function is to provide reflection information for the object
10371 // mirrors.
10372 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
10373   ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
10374   if (HasFastProperties()) {
10375     DescriptorArray* descs = map()->instance_descriptors();
10376     for (int i = 0; i < descs->number_of_descriptors(); i++) {
10377       if (descs->IsProperty(i)) storage->set(index++, descs->GetKey(i));
10378     }
10379     ASSERT(storage->length() >= index);
10380   } else {
10381     property_dictionary()->CopyKeysTo(storage,
10382                                       index,
10383                                       StringDictionary::UNSORTED);
10384   }
10385 }
10386
10387
10388 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
10389   return GetLocalElementKeys(NULL, filter);
10390 }
10391
10392
10393 int JSObject::NumberOfEnumElements() {
10394   // Fast case for objects with no elements.
10395   if (!IsJSValue() && HasFastElements()) {
10396     uint32_t length = IsJSArray() ?
10397         static_cast<uint32_t>(
10398             Smi::cast(JSArray::cast(this)->length())->value()) :
10399         static_cast<uint32_t>(FixedArray::cast(elements())->length());
10400     if (length == 0) return 0;
10401   }
10402   // Compute the number of enumerable elements.
10403   return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
10404 }
10405
10406
10407 int JSObject::GetLocalElementKeys(FixedArray* storage,
10408                                   PropertyAttributes filter) {
10409   int counter = 0;
10410   switch (GetElementsKind()) {
10411     case FAST_SMI_ONLY_ELEMENTS:
10412     case FAST_ELEMENTS: {
10413       int length = IsJSArray() ?
10414           Smi::cast(JSArray::cast(this)->length())->value() :
10415           FixedArray::cast(elements())->length();
10416       for (int i = 0; i < length; i++) {
10417         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
10418           if (storage != NULL) {
10419             storage->set(counter, Smi::FromInt(i));
10420           }
10421           counter++;
10422         }
10423       }
10424       ASSERT(!storage || storage->length() >= counter);
10425       break;
10426     }
10427     case FAST_DOUBLE_ELEMENTS: {
10428       int length = IsJSArray() ?
10429           Smi::cast(JSArray::cast(this)->length())->value() :
10430           FixedDoubleArray::cast(elements())->length();
10431       for (int i = 0; i < length; i++) {
10432         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
10433           if (storage != NULL) {
10434             storage->set(counter, Smi::FromInt(i));
10435           }
10436           counter++;
10437         }
10438       }
10439       ASSERT(!storage || storage->length() >= counter);
10440       break;
10441     }
10442     case EXTERNAL_PIXEL_ELEMENTS: {
10443       int length = ExternalPixelArray::cast(elements())->length();
10444       while (counter < length) {
10445         if (storage != NULL) {
10446           storage->set(counter, Smi::FromInt(counter));
10447         }
10448         counter++;
10449       }
10450       ASSERT(!storage || storage->length() >= counter);
10451       break;
10452     }
10453     case EXTERNAL_BYTE_ELEMENTS:
10454     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
10455     case EXTERNAL_SHORT_ELEMENTS:
10456     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
10457     case EXTERNAL_INT_ELEMENTS:
10458     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
10459     case EXTERNAL_FLOAT_ELEMENTS:
10460     case EXTERNAL_DOUBLE_ELEMENTS: {
10461       int length = ExternalArray::cast(elements())->length();
10462       while (counter < length) {
10463         if (storage != NULL) {
10464           storage->set(counter, Smi::FromInt(counter));
10465         }
10466         counter++;
10467       }
10468       ASSERT(!storage || storage->length() >= counter);
10469       break;
10470     }
10471     case DICTIONARY_ELEMENTS: {
10472       if (storage != NULL) {
10473         element_dictionary()->CopyKeysTo(storage,
10474                                          filter,
10475                                          SeededNumberDictionary::SORTED);
10476       }
10477       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
10478       break;
10479     }
10480     case NON_STRICT_ARGUMENTS_ELEMENTS: {
10481       FixedArray* parameter_map = FixedArray::cast(elements());
10482       int mapped_length = parameter_map->length() - 2;
10483       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
10484       if (arguments->IsDictionary()) {
10485         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
10486         // will insert in storage starting at index 0.
10487         SeededNumberDictionary* dictionary =
10488             SeededNumberDictionary::cast(arguments);
10489         if (storage != NULL) {
10490           dictionary->CopyKeysTo(
10491               storage, filter, SeededNumberDictionary::UNSORTED);
10492         }
10493         counter += dictionary->NumberOfElementsFilterAttributes(filter);
10494         for (int i = 0; i < mapped_length; ++i) {
10495           if (!parameter_map->get(i + 2)->IsTheHole()) {
10496             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10497             ++counter;
10498           }
10499         }
10500         if (storage != NULL) storage->SortPairs(storage, counter);
10501
10502       } else {
10503         int backing_length = arguments->length();
10504         int i = 0;
10505         for (; i < mapped_length; ++i) {
10506           if (!parameter_map->get(i + 2)->IsTheHole()) {
10507             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10508             ++counter;
10509           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
10510             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10511             ++counter;
10512           }
10513         }
10514         for (; i < backing_length; ++i) {
10515           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10516           ++counter;
10517         }
10518       }
10519       break;
10520     }
10521   }
10522
10523   if (this->IsJSValue()) {
10524     Object* val = JSValue::cast(this)->value();
10525     if (val->IsString()) {
10526       String* str = String::cast(val);
10527       if (storage) {
10528         for (int i = 0; i < str->length(); i++) {
10529           storage->set(counter + i, Smi::FromInt(i));
10530         }
10531       }
10532       counter += str->length();
10533     }
10534   }
10535   ASSERT(!storage || storage->length() == counter);
10536   return counter;
10537 }
10538
10539
10540 int JSObject::GetEnumElementKeys(FixedArray* storage) {
10541   return GetLocalElementKeys(storage,
10542                              static_cast<PropertyAttributes>(DONT_ENUM));
10543 }
10544
10545
10546 // StringKey simply carries a string object as key.
10547 class StringKey : public HashTableKey {
10548  public:
10549   explicit StringKey(String* string) :
10550       string_(string),
10551       hash_(HashForObject(string)) { }
10552
10553   bool IsMatch(Object* string) {
10554     // We know that all entries in a hash table had their hash keys created.
10555     // Use that knowledge to have fast failure.
10556     if (hash_ != HashForObject(string)) {
10557       return false;
10558     }
10559     return string_->Equals(String::cast(string));
10560   }
10561
10562   uint32_t Hash() { return hash_; }
10563
10564   uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
10565
10566   Object* AsObject() { return string_; }
10567
10568   String* string_;
10569   uint32_t hash_;
10570 };
10571
10572
10573 // StringSharedKeys are used as keys in the eval cache.
10574 class StringSharedKey : public HashTableKey {
10575  public:
10576   StringSharedKey(String* source,
10577                   SharedFunctionInfo* shared,
10578                   LanguageMode language_mode,
10579                   int scope_position)
10580       : source_(source),
10581         shared_(shared),
10582         language_mode_(language_mode),
10583         scope_position_(scope_position) { }
10584
10585   bool IsMatch(Object* other) {
10586     if (!other->IsFixedArray()) return false;
10587     FixedArray* other_array = FixedArray::cast(other);
10588     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
10589     if (shared != shared_) return false;
10590     int language_unchecked = Smi::cast(other_array->get(2))->value();
10591     ASSERT(language_unchecked == CLASSIC_MODE ||
10592            language_unchecked == STRICT_MODE ||
10593            language_unchecked == EXTENDED_MODE);
10594     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
10595     if (language_mode != language_mode_) return false;
10596     int scope_position = Smi::cast(other_array->get(3))->value();
10597     if (scope_position != scope_position_) return false;
10598     String* source = String::cast(other_array->get(1));
10599     return source->Equals(source_);
10600   }
10601
10602   static uint32_t StringSharedHashHelper(String* source,
10603                                          SharedFunctionInfo* shared,
10604                                          LanguageMode language_mode,
10605                                          int scope_position) {
10606     uint32_t hash = source->Hash();
10607     if (shared->HasSourceCode()) {
10608       // Instead of using the SharedFunctionInfo pointer in the hash
10609       // code computation, we use a combination of the hash of the
10610       // script source code and the start position of the calling scope.
10611       // We do this to ensure that the cache entries can survive garbage
10612       // collection.
10613       Script* script = Script::cast(shared->script());
10614       hash ^= String::cast(script->source())->Hash();
10615       if (language_mode == STRICT_MODE) hash ^= 0x8000;
10616       if (language_mode == EXTENDED_MODE) hash ^= 0x0080;
10617       hash += scope_position;
10618     }
10619     return hash;
10620   }
10621
10622   uint32_t Hash() {
10623     return StringSharedHashHelper(
10624         source_, shared_, language_mode_, scope_position_);
10625   }
10626
10627   uint32_t HashForObject(Object* obj) {
10628     FixedArray* other_array = FixedArray::cast(obj);
10629     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
10630     String* source = String::cast(other_array->get(1));
10631     int language_unchecked = Smi::cast(other_array->get(2))->value();
10632     ASSERT(language_unchecked == CLASSIC_MODE ||
10633            language_unchecked == STRICT_MODE ||
10634            language_unchecked == EXTENDED_MODE);
10635     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
10636     int scope_position = Smi::cast(other_array->get(3))->value();
10637     return StringSharedHashHelper(
10638         source, shared, language_mode, scope_position);
10639   }
10640
10641   MUST_USE_RESULT MaybeObject* AsObject() {
10642     Object* obj;
10643     { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(4);
10644       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10645     }
10646     FixedArray* other_array = FixedArray::cast(obj);
10647     other_array->set(0, shared_);
10648     other_array->set(1, source_);
10649     other_array->set(2, Smi::FromInt(language_mode_));
10650     other_array->set(3, Smi::FromInt(scope_position_));
10651     return other_array;
10652   }
10653
10654  private:
10655   String* source_;
10656   SharedFunctionInfo* shared_;
10657   LanguageMode language_mode_;
10658   int scope_position_;
10659 };
10660
10661
10662 // RegExpKey carries the source and flags of a regular expression as key.
10663 class RegExpKey : public HashTableKey {
10664  public:
10665   RegExpKey(String* string, JSRegExp::Flags flags)
10666       : string_(string),
10667         flags_(Smi::FromInt(flags.value())) { }
10668
10669   // Rather than storing the key in the hash table, a pointer to the
10670   // stored value is stored where the key should be.  IsMatch then
10671   // compares the search key to the found object, rather than comparing
10672   // a key to a key.
10673   bool IsMatch(Object* obj) {
10674     FixedArray* val = FixedArray::cast(obj);
10675     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
10676         && (flags_ == val->get(JSRegExp::kFlagsIndex));
10677   }
10678
10679   uint32_t Hash() { return RegExpHash(string_, flags_); }
10680
10681   Object* AsObject() {
10682     // Plain hash maps, which is where regexp keys are used, don't
10683     // use this function.
10684     UNREACHABLE();
10685     return NULL;
10686   }
10687
10688   uint32_t HashForObject(Object* obj) {
10689     FixedArray* val = FixedArray::cast(obj);
10690     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
10691                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
10692   }
10693
10694   static uint32_t RegExpHash(String* string, Smi* flags) {
10695     return string->Hash() + flags->value();
10696   }
10697
10698   String* string_;
10699   Smi* flags_;
10700 };
10701
10702 // Utf8SymbolKey carries a vector of chars as key.
10703 class Utf8SymbolKey : public HashTableKey {
10704  public:
10705   explicit Utf8SymbolKey(Vector<const char> string, uint32_t seed)
10706       : string_(string), hash_field_(0), seed_(seed) { }
10707
10708   bool IsMatch(Object* string) {
10709     return String::cast(string)->IsEqualTo(string_);
10710   }
10711
10712   uint32_t Hash() {
10713     if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
10714     unibrow::Utf8InputBuffer<> buffer(string_.start(),
10715                                       static_cast<unsigned>(string_.length()));
10716     chars_ = buffer.Utf16Length();
10717     hash_field_ = String::ComputeHashField(&buffer, chars_, seed_);
10718     uint32_t result = hash_field_ >> String::kHashShift;
10719     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
10720     return result;
10721   }
10722
10723   uint32_t HashForObject(Object* other) {
10724     return String::cast(other)->Hash();
10725   }
10726
10727   MaybeObject* AsObject() {
10728     if (hash_field_ == 0) Hash();
10729     return Isolate::Current()->heap()->AllocateSymbol(
10730         string_, chars_, hash_field_);
10731   }
10732
10733   Vector<const char> string_;
10734   uint32_t hash_field_;
10735   int chars_;  // Caches the number of characters when computing the hash code.
10736   uint32_t seed_;
10737 };
10738
10739
10740 template <typename Char>
10741 class SequentialSymbolKey : public HashTableKey {
10742  public:
10743   explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed)
10744       : string_(string), hash_field_(0), seed_(seed) { }
10745
10746   uint32_t Hash() {
10747     StringHasher hasher(string_.length(), seed_);
10748
10749     // Very long strings have a trivial hash that doesn't inspect the
10750     // string contents.
10751     if (hasher.has_trivial_hash()) {
10752       hash_field_ = hasher.GetHashField();
10753     } else {
10754       int i = 0;
10755       // Do the iterative array index computation as long as there is a
10756       // chance this is an array index.
10757       while (i < string_.length() && hasher.is_array_index()) {
10758         hasher.AddCharacter(static_cast<uc32>(string_[i]));
10759         i++;
10760       }
10761
10762       // Process the remaining characters without updating the array
10763       // index.
10764       while (i < string_.length()) {
10765         hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i]));
10766         i++;
10767       }
10768       hash_field_ = hasher.GetHashField();
10769     }
10770
10771     uint32_t result = hash_field_ >> String::kHashShift;
10772     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
10773     return result;
10774   }
10775
10776
10777   uint32_t HashForObject(Object* other) {
10778     return String::cast(other)->Hash();
10779   }
10780
10781   Vector<const Char> string_;
10782   uint32_t hash_field_;
10783   uint32_t seed_;
10784 };
10785
10786
10787
10788 class AsciiSymbolKey : public SequentialSymbolKey<char> {
10789  public:
10790   AsciiSymbolKey(Vector<const char> str, uint32_t seed)
10791       : SequentialSymbolKey<char>(str, seed) { }
10792
10793   bool IsMatch(Object* string) {
10794     return String::cast(string)->IsAsciiEqualTo(string_);
10795   }
10796
10797   MaybeObject* AsObject() {
10798     if (hash_field_ == 0) Hash();
10799     MaybeObject *result = HEAP->AllocateAsciiSymbol(string_, hash_field_);
10800     if (!result->IsFailure() && result->ToObjectUnchecked()->IsSeqString()) {
10801         while (true) {
10802             Atomic32 my_symbol_id = next_symbol_id;
10803             if (my_symbol_id > Smi::kMaxValue)
10804                 break;
10805             if (my_symbol_id == NoBarrier_CompareAndSwap(&next_symbol_id,
10806                                                          my_symbol_id,
10807                                                          my_symbol_id + 1)) {
10808                 SeqString::cast(result->ToObjectUnchecked())->
10809                     set_symbol_id(my_symbol_id);
10810                 break;
10811             }
10812         }
10813     }
10814     return result;
10815   }
10816
10817   static Atomic32 next_symbol_id;
10818 };
10819 Atomic32 AsciiSymbolKey::next_symbol_id = 1;
10820
10821
10822 class SubStringAsciiSymbolKey : public HashTableKey {
10823  public:
10824   explicit SubStringAsciiSymbolKey(Handle<SeqAsciiString> string,
10825                                    int from,
10826                                    int length,
10827                                    uint32_t seed)
10828       : string_(string), from_(from), length_(length), seed_(seed) { }
10829
10830   uint32_t Hash() {
10831     ASSERT(length_ >= 0);
10832     ASSERT(from_ + length_ <= string_->length());
10833     StringHasher hasher(length_, string_->GetHeap()->HashSeed());
10834
10835     // Very long strings have a trivial hash that doesn't inspect the
10836     // string contents.
10837     if (hasher.has_trivial_hash()) {
10838       hash_field_ = hasher.GetHashField();
10839     } else {
10840       int i = 0;
10841       // Do the iterative array index computation as long as there is a
10842       // chance this is an array index.
10843       while (i < length_ && hasher.is_array_index()) {
10844         hasher.AddCharacter(static_cast<uc32>(
10845             string_->SeqAsciiStringGet(i + from_)));
10846         i++;
10847       }
10848
10849       // Process the remaining characters without updating the array
10850       // index.
10851       while (i < length_) {
10852         hasher.AddCharacterNoIndex(static_cast<uc32>(
10853             string_->SeqAsciiStringGet(i + from_)));
10854         i++;
10855       }
10856       hash_field_ = hasher.GetHashField();
10857     }
10858
10859     uint32_t result = hash_field_ >> String::kHashShift;
10860     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
10861     return result;
10862   }
10863
10864
10865   uint32_t HashForObject(Object* other) {
10866     return String::cast(other)->Hash();
10867   }
10868
10869   bool IsMatch(Object* string) {
10870     Vector<const char> chars(string_->GetChars() + from_, length_);
10871     return String::cast(string)->IsAsciiEqualTo(chars);
10872   }
10873
10874   MaybeObject* AsObject() {
10875     if (hash_field_ == 0) Hash();
10876     Vector<const char> chars(string_->GetChars() + from_, length_);
10877     return HEAP->AllocateAsciiSymbol(chars, hash_field_);
10878   }
10879
10880  private:
10881   Handle<SeqAsciiString> string_;
10882   int from_;
10883   int length_;
10884   uint32_t hash_field_;
10885   uint32_t seed_;
10886 };
10887
10888
10889 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
10890  public:
10891   explicit TwoByteSymbolKey(Vector<const uc16> str, uint32_t seed)
10892       : SequentialSymbolKey<uc16>(str, seed) { }
10893
10894   bool IsMatch(Object* string) {
10895     return String::cast(string)->IsTwoByteEqualTo(string_);
10896   }
10897
10898   MaybeObject* AsObject() {
10899     if (hash_field_ == 0) Hash();
10900     return HEAP->AllocateTwoByteSymbol(string_, hash_field_);
10901   }
10902 };
10903
10904
10905 // SymbolKey carries a string/symbol object as key.
10906 class SymbolKey : public HashTableKey {
10907  public:
10908   explicit SymbolKey(String* string)
10909       : string_(string) { }
10910
10911   bool IsMatch(Object* string) {
10912     return String::cast(string)->Equals(string_);
10913   }
10914
10915   uint32_t Hash() { return string_->Hash(); }
10916
10917   uint32_t HashForObject(Object* other) {
10918     return String::cast(other)->Hash();
10919   }
10920
10921   MaybeObject* AsObject() {
10922     // Attempt to flatten the string, so that symbols will most often
10923     // be flat strings.
10924     string_ = string_->TryFlattenGetString();
10925     Heap* heap = string_->GetHeap();
10926     // Transform string to symbol if possible.
10927     Map* map = heap->SymbolMapForString(string_);
10928     if (map != NULL) {
10929       string_->set_map_no_write_barrier(map);
10930       ASSERT(string_->IsSymbol());
10931       return string_;
10932     }
10933     // Otherwise allocate a new symbol.
10934     StringInputBuffer buffer(string_);
10935     return heap->AllocateInternalSymbol(&buffer,
10936                                         string_->length(),
10937                                         string_->hash_field());
10938   }
10939
10940   static uint32_t StringHash(Object* obj) {
10941     return String::cast(obj)->Hash();
10942   }
10943
10944   String* string_;
10945 };
10946
10947
10948 template<typename Shape, typename Key>
10949 void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
10950   IteratePointers(v, 0, kElementsStartOffset);
10951 }
10952
10953
10954 template<typename Shape, typename Key>
10955 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
10956   IteratePointers(v,
10957                   kElementsStartOffset,
10958                   kHeaderSize + length() * kPointerSize);
10959 }
10960
10961
10962 template<typename Shape, typename Key>
10963 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for,
10964                                              PretenureFlag pretenure) {
10965   int capacity = ComputeCapacity(at_least_space_for);
10966   if (capacity > HashTable::kMaxCapacity) {
10967     return Failure::OutOfMemoryException();
10968   }
10969
10970   Object* obj;
10971   { MaybeObject* maybe_obj = Isolate::Current()->heap()->
10972         AllocateHashTable(EntryToIndex(capacity), pretenure);
10973     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10974   }
10975   HashTable::cast(obj)->SetNumberOfElements(0);
10976   HashTable::cast(obj)->SetNumberOfDeletedElements(0);
10977   HashTable::cast(obj)->SetCapacity(capacity);
10978   return obj;
10979 }
10980
10981
10982 // Find entry for key otherwise return kNotFound.
10983 int StringDictionary::FindEntry(String* key) {
10984   if (!key->IsSymbol()) {
10985     return HashTable<StringDictionaryShape, String*>::FindEntry(key);
10986   }
10987
10988   // Optimized for symbol key. Knowledge of the key type allows:
10989   // 1. Move the check if the key is a symbol out of the loop.
10990   // 2. Avoid comparing hash codes in symbol to symbol comparison.
10991   // 3. Detect a case when a dictionary key is not a symbol but the key is.
10992   //    In case of positive result the dictionary key may be replaced by
10993   //    the symbol with minimal performance penalty. It gives a chance to
10994   //    perform further lookups in code stubs (and significant performance boost
10995   //    a certain style of code).
10996
10997   // EnsureCapacity will guarantee the hash table is never full.
10998   uint32_t capacity = Capacity();
10999   uint32_t entry = FirstProbe(key->Hash(), capacity);
11000   uint32_t count = 1;
11001
11002   while (true) {
11003     int index = EntryToIndex(entry);
11004     Object* element = get(index);
11005     if (element->IsUndefined()) break;  // Empty entry.
11006     if (key == element) return entry;
11007     if (!element->IsSymbol() &&
11008         !element->IsTheHole() &&
11009         String::cast(element)->Equals(key)) {
11010       // Replace a non-symbol key by the equivalent symbol for faster further
11011       // lookups.
11012       set(index, key);
11013       return entry;
11014     }
11015     ASSERT(element->IsTheHole() || !String::cast(element)->Equals(key));
11016     entry = NextProbe(entry, count++, capacity);
11017   }
11018   return kNotFound;
11019 }
11020
11021
11022 bool StringDictionary::ContainsTransition(int entry) {
11023   switch (DetailsAt(entry).type()) {
11024     case MAP_TRANSITION:
11025     case CONSTANT_TRANSITION:
11026     case ELEMENTS_TRANSITION:
11027       return true;
11028     case CALLBACKS: {
11029       Object* value = ValueAt(entry);
11030       if (!value->IsAccessorPair()) return false;
11031       AccessorPair* accessors = AccessorPair::cast(value);
11032       return accessors->getter()->IsMap() || accessors->setter()->IsMap();
11033     }
11034     case NORMAL:
11035     case FIELD:
11036     case CONSTANT_FUNCTION:
11037     case HANDLER:
11038     case INTERCEPTOR:
11039     case NULL_DESCRIPTOR:
11040       return false;
11041   }
11042   UNREACHABLE();  // Keep the compiler happy.
11043   return false;
11044 }
11045
11046
11047 template<typename Shape, typename Key>
11048 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
11049   ASSERT(NumberOfElements() < new_table->Capacity());
11050
11051   AssertNoAllocation no_gc;
11052   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
11053
11054   // Copy prefix to new array.
11055   for (int i = kPrefixStartIndex;
11056        i < kPrefixStartIndex + Shape::kPrefixSize;
11057        i++) {
11058     new_table->set(i, get(i), mode);
11059   }
11060
11061   // Rehash the elements.
11062   int capacity = Capacity();
11063   for (int i = 0; i < capacity; i++) {
11064     uint32_t from_index = EntryToIndex(i);
11065     Object* k = get(from_index);
11066     if (IsKey(k)) {
11067       uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k);
11068       uint32_t insertion_index =
11069           EntryToIndex(new_table->FindInsertionEntry(hash));
11070       for (int j = 0; j < Shape::kEntrySize; j++) {
11071         new_table->set(insertion_index + j, get(from_index + j), mode);
11072       }
11073     }
11074   }
11075   new_table->SetNumberOfElements(NumberOfElements());
11076   new_table->SetNumberOfDeletedElements(0);
11077   return new_table;
11078 }
11079
11080
11081 template<typename Shape, typename Key>
11082 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
11083   int capacity = Capacity();
11084   int nof = NumberOfElements() + n;
11085   int nod = NumberOfDeletedElements();
11086   // Return if:
11087   //   50% is still free after adding n elements and
11088   //   at most 50% of the free elements are deleted elements.
11089   if (nod <= (capacity - nof) >> 1) {
11090     int needed_free = nof >> 1;
11091     if (nof + needed_free <= capacity) return this;
11092   }
11093
11094   const int kMinCapacityForPretenure = 256;
11095   bool pretenure =
11096       (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this);
11097   Object* obj;
11098   { MaybeObject* maybe_obj =
11099         Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED);
11100     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11101   }
11102
11103   return Rehash(HashTable::cast(obj), key);
11104 }
11105
11106
11107 template<typename Shape, typename Key>
11108 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
11109   int capacity = Capacity();
11110   int nof = NumberOfElements();
11111
11112   // Shrink to fit the number of elements if only a quarter of the
11113   // capacity is filled with elements.
11114   if (nof > (capacity >> 2)) return this;
11115   // Allocate a new dictionary with room for at least the current
11116   // number of elements. The allocation method will make sure that
11117   // there is extra room in the dictionary for additions. Don't go
11118   // lower than room for 16 elements.
11119   int at_least_room_for = nof;
11120   if (at_least_room_for < 16) return this;
11121
11122   const int kMinCapacityForPretenure = 256;
11123   bool pretenure =
11124       (at_least_room_for > kMinCapacityForPretenure) &&
11125       !GetHeap()->InNewSpace(this);
11126   Object* obj;
11127   { MaybeObject* maybe_obj =
11128         Allocate(at_least_room_for, pretenure ? TENURED : NOT_TENURED);
11129     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11130   }
11131
11132   return Rehash(HashTable::cast(obj), key);
11133 }
11134
11135
11136 template<typename Shape, typename Key>
11137 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
11138   uint32_t capacity = Capacity();
11139   uint32_t entry = FirstProbe(hash, capacity);
11140   uint32_t count = 1;
11141   // EnsureCapacity will guarantee the hash table is never full.
11142   while (true) {
11143     Object* element = KeyAt(entry);
11144     if (element->IsUndefined() || element->IsTheHole()) break;
11145     entry = NextProbe(entry, count++, capacity);
11146   }
11147   return entry;
11148 }
11149
11150 // Force instantiation of template instances class.
11151 // Please note this list is compiler dependent.
11152
11153 template class HashTable<SymbolTableShape, HashTableKey*>;
11154
11155 template class HashTable<CompilationCacheShape, HashTableKey*>;
11156
11157 template class HashTable<MapCacheShape, HashTableKey*>;
11158
11159 template class HashTable<ObjectHashTableShape<1>, Object*>;
11160
11161 template class HashTable<ObjectHashTableShape<2>, Object*>;
11162
11163 template class Dictionary<StringDictionaryShape, String*>;
11164
11165 template class Dictionary<SeededNumberDictionaryShape, uint32_t>;
11166
11167 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>;
11168
11169 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11170     Allocate(int at_least_space_for);
11171
11172 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11173     Allocate(int at_least_space_for);
11174
11175 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate(
11176     int);
11177
11178 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut(
11179     uint32_t, Object*);
11180
11181 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11182     AtPut(uint32_t, Object*);
11183
11184 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11185     SlowReverseLookup(Object* value);
11186
11187 template Object* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11188     SlowReverseLookup(Object* value);
11189
11190 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
11191     Object*);
11192
11193 template void Dictionary<SeededNumberDictionaryShape, uint32_t>::CopyKeysTo(
11194     FixedArray*,
11195     PropertyAttributes,
11196     Dictionary<SeededNumberDictionaryShape, uint32_t>::SortMode);
11197
11198 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
11199     int, JSObject::DeleteMode);
11200
11201 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11202     DeleteProperty(int, JSObject::DeleteMode);
11203
11204 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink(
11205     String*);
11206
11207 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink(
11208     uint32_t);
11209
11210 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
11211     FixedArray*,
11212     int,
11213     Dictionary<StringDictionaryShape, String*>::SortMode);
11214
11215 template int
11216 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
11217     PropertyAttributes);
11218
11219 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add(
11220     String*, Object*, PropertyDetails);
11221
11222 template MaybeObject*
11223 Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
11224
11225 template int
11226 Dictionary<SeededNumberDictionaryShape, uint32_t>::
11227     NumberOfElementsFilterAttributes(PropertyAttributes);
11228
11229 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Add(
11230     uint32_t, Object*, PropertyDetails);
11231
11232 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::Add(
11233     uint32_t, Object*, PropertyDetails);
11234
11235 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11236     EnsureCapacity(int, uint32_t);
11237
11238 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11239     EnsureCapacity(int, uint32_t);
11240
11241 template MaybeObject* Dictionary<StringDictionaryShape, String*>::
11242     EnsureCapacity(int, String*);
11243
11244 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11245     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
11246
11247 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11248     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
11249
11250 template MaybeObject* Dictionary<StringDictionaryShape, String*>::AddEntry(
11251     String*, Object*, PropertyDetails, uint32_t);
11252
11253 template
11254 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements();
11255
11256 template
11257 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
11258
11259 template
11260 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
11261
11262
11263 // Collates undefined and unexisting elements below limit from position
11264 // zero of the elements. The object stays in Dictionary mode.
11265 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
11266   ASSERT(HasDictionaryElements());
11267   // Must stay in dictionary mode, either because of requires_slow_elements,
11268   // or because we are not going to sort (and therefore compact) all of the
11269   // elements.
11270   SeededNumberDictionary* dict = element_dictionary();
11271   HeapNumber* result_double = NULL;
11272   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11273     // Allocate space for result before we start mutating the object.
11274     Object* new_double;
11275     { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0);
11276       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11277     }
11278     result_double = HeapNumber::cast(new_double);
11279   }
11280
11281   Object* obj;
11282   { MaybeObject* maybe_obj =
11283         SeededNumberDictionary::Allocate(dict->NumberOfElements());
11284     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11285   }
11286   SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj);
11287
11288   AssertNoAllocation no_alloc;
11289
11290   uint32_t pos = 0;
11291   uint32_t undefs = 0;
11292   int capacity = dict->Capacity();
11293   for (int i = 0; i < capacity; i++) {
11294     Object* k = dict->KeyAt(i);
11295     if (dict->IsKey(k)) {
11296       ASSERT(k->IsNumber());
11297       ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
11298       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
11299       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
11300       Object* value = dict->ValueAt(i);
11301       PropertyDetails details = dict->DetailsAt(i);
11302       if (details.type() == CALLBACKS) {
11303         // Bail out and do the sorting of undefineds and array holes in JS.
11304         return Smi::FromInt(-1);
11305       }
11306       uint32_t key = NumberToUint32(k);
11307       // In the following we assert that adding the entry to the new dictionary
11308       // does not cause GC.  This is the case because we made sure to allocate
11309       // the dictionary big enough above, so it need not grow.
11310       if (key < limit) {
11311         if (value->IsUndefined()) {
11312           undefs++;
11313         } else {
11314           if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11315             // Adding an entry with the key beyond smi-range requires
11316             // allocation. Bailout.
11317             return Smi::FromInt(-1);
11318           }
11319           new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
11320           pos++;
11321         }
11322       } else {
11323         if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
11324           // Adding an entry with the key beyond smi-range requires
11325           // allocation. Bailout.
11326           return Smi::FromInt(-1);
11327         }
11328         new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
11329       }
11330     }
11331   }
11332
11333   uint32_t result = pos;
11334   PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
11335   Heap* heap = GetHeap();
11336   while (undefs > 0) {
11337     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11338       // Adding an entry with the key beyond smi-range requires
11339       // allocation. Bailout.
11340       return Smi::FromInt(-1);
11341     }
11342     new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
11343         ToObjectUnchecked();
11344     pos++;
11345     undefs--;
11346   }
11347
11348   set_elements(new_dict);
11349
11350   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11351     return Smi::FromInt(static_cast<int>(result));
11352   }
11353
11354   ASSERT_NE(NULL, result_double);
11355   result_double->set_value(static_cast<double>(result));
11356   return result_double;
11357 }
11358
11359
11360 // Collects all defined (non-hole) and non-undefined (array) elements at
11361 // the start of the elements array.
11362 // If the object is in dictionary mode, it is converted to fast elements
11363 // mode.
11364 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
11365   Heap* heap = GetHeap();
11366
11367   if (HasDictionaryElements()) {
11368     // Convert to fast elements containing only the existing properties.
11369     // Ordering is irrelevant, since we are going to sort anyway.
11370     SeededNumberDictionary* dict = element_dictionary();
11371     if (IsJSArray() || dict->requires_slow_elements() ||
11372         dict->max_number_key() >= limit) {
11373       return PrepareSlowElementsForSort(limit);
11374     }
11375     // Convert to fast elements.
11376
11377     Object* obj;
11378     { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
11379                                                         FAST_ELEMENTS);
11380       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11381     }
11382     Map* new_map = Map::cast(obj);
11383
11384     PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
11385     Object* new_array;
11386     { MaybeObject* maybe_new_array =
11387           heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
11388       if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
11389     }
11390     FixedArray* fast_elements = FixedArray::cast(new_array);
11391     dict->CopyValuesTo(fast_elements);
11392
11393     set_map(new_map);
11394     set_elements(fast_elements);
11395   } else if (HasExternalArrayElements()) {
11396     // External arrays cannot have holes or undefined elements.
11397     return Smi::FromInt(ExternalArray::cast(elements())->length());
11398   } else if (!HasFastDoubleElements()) {
11399     Object* obj;
11400     { MaybeObject* maybe_obj = EnsureWritableFastElements();
11401       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11402     }
11403   }
11404   ASSERT(HasFastTypeElements() || HasFastDoubleElements());
11405
11406   // Collect holes at the end, undefined before that and the rest at the
11407   // start, and return the number of non-hole, non-undefined values.
11408
11409   FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
11410   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
11411   if (limit > elements_length) {
11412     limit = elements_length ;
11413   }
11414   if (limit == 0) {
11415     return Smi::FromInt(0);
11416   }
11417
11418   HeapNumber* result_double = NULL;
11419   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11420     // Pessimistically allocate space for return value before
11421     // we start mutating the array.
11422     Object* new_double;
11423     { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0);
11424       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11425     }
11426     result_double = HeapNumber::cast(new_double);
11427   }
11428
11429   uint32_t result = 0;
11430   if (elements_base->map() == heap->fixed_double_array_map()) {
11431     FixedDoubleArray* elements = FixedDoubleArray::cast(elements_base);
11432     // Split elements into defined and the_hole, in that order.
11433     unsigned int holes = limit;
11434     // Assume most arrays contain no holes and undefined values, so minimize the
11435     // number of stores of non-undefined, non-the-hole values.
11436     for (unsigned int i = 0; i < holes; i++) {
11437       if (elements->is_the_hole(i)) {
11438         holes--;
11439       } else {
11440         continue;
11441       }
11442       // Position i needs to be filled.
11443       while (holes > i) {
11444         if (elements->is_the_hole(holes)) {
11445           holes--;
11446         } else {
11447           elements->set(i, elements->get_scalar(holes));
11448           break;
11449         }
11450       }
11451     }
11452     result = holes;
11453     while (holes < limit) {
11454       elements->set_the_hole(holes);
11455       holes++;
11456     }
11457   } else {
11458     FixedArray* elements = FixedArray::cast(elements_base);
11459     AssertNoAllocation no_alloc;
11460
11461     // Split elements into defined, undefined and the_hole, in that order.  Only
11462     // count locations for undefined and the hole, and fill them afterwards.
11463     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
11464     unsigned int undefs = limit;
11465     unsigned int holes = limit;
11466     // Assume most arrays contain no holes and undefined values, so minimize the
11467     // number of stores of non-undefined, non-the-hole values.
11468     for (unsigned int i = 0; i < undefs; i++) {
11469       Object* current = elements->get(i);
11470       if (current->IsTheHole()) {
11471         holes--;
11472         undefs--;
11473       } else if (current->IsUndefined()) {
11474         undefs--;
11475       } else {
11476         continue;
11477       }
11478       // Position i needs to be filled.
11479       while (undefs > i) {
11480         current = elements->get(undefs);
11481         if (current->IsTheHole()) {
11482           holes--;
11483           undefs--;
11484         } else if (current->IsUndefined()) {
11485           undefs--;
11486         } else {
11487           elements->set(i, current, write_barrier);
11488           break;
11489         }
11490       }
11491     }
11492     result = undefs;
11493     while (undefs < holes) {
11494       elements->set_undefined(undefs);
11495       undefs++;
11496     }
11497     while (holes < limit) {
11498       elements->set_the_hole(holes);
11499       holes++;
11500     }
11501   }
11502
11503   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11504     return Smi::FromInt(static_cast<int>(result));
11505   }
11506   ASSERT_NE(NULL, result_double);
11507   result_double->set_value(static_cast<double>(result));
11508   return result_double;
11509 }
11510
11511
11512 Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
11513   uint8_t clamped_value = 0;
11514   if (index < static_cast<uint32_t>(length())) {
11515     if (value->IsSmi()) {
11516       int int_value = Smi::cast(value)->value();
11517       if (int_value < 0) {
11518         clamped_value = 0;
11519       } else if (int_value > 255) {
11520         clamped_value = 255;
11521       } else {
11522         clamped_value = static_cast<uint8_t>(int_value);
11523       }
11524     } else if (value->IsHeapNumber()) {
11525       double double_value = HeapNumber::cast(value)->value();
11526       if (!(double_value > 0)) {
11527         // NaN and less than zero clamp to zero.
11528         clamped_value = 0;
11529       } else if (double_value > 255) {
11530         // Greater than 255 clamp to 255.
11531         clamped_value = 255;
11532       } else {
11533         // Other doubles are rounded to the nearest integer.
11534         clamped_value = static_cast<uint8_t>(double_value + 0.5);
11535       }
11536     } else {
11537       // Clamp undefined to zero (default). All other types have been
11538       // converted to a number type further up in the call chain.
11539       ASSERT(value->IsUndefined());
11540     }
11541     set(index, clamped_value);
11542   }
11543   return Smi::FromInt(clamped_value);
11544 }
11545
11546
11547 template<typename ExternalArrayClass, typename ValueType>
11548 static MaybeObject* ExternalArrayIntSetter(Heap* heap,
11549                                            ExternalArrayClass* receiver,
11550                                            uint32_t index,
11551                                            Object* value) {
11552   ValueType cast_value = 0;
11553   if (index < static_cast<uint32_t>(receiver->length())) {
11554     if (value->IsSmi()) {
11555       int int_value = Smi::cast(value)->value();
11556       cast_value = static_cast<ValueType>(int_value);
11557     } else if (value->IsHeapNumber()) {
11558       double double_value = HeapNumber::cast(value)->value();
11559       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
11560     } else {
11561       // Clamp undefined to zero (default). All other types have been
11562       // converted to a number type further up in the call chain.
11563       ASSERT(value->IsUndefined());
11564     }
11565     receiver->set(index, cast_value);
11566   }
11567   return heap->NumberFromInt32(cast_value);
11568 }
11569
11570
11571 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) {
11572   return ExternalArrayIntSetter<ExternalByteArray, int8_t>
11573       (GetHeap(), this, index, value);
11574 }
11575
11576
11577 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index,
11578                                                  Object* value) {
11579   return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
11580       (GetHeap(), this, index, value);
11581 }
11582
11583
11584 MaybeObject* ExternalShortArray::SetValue(uint32_t index,
11585                                           Object* value) {
11586   return ExternalArrayIntSetter<ExternalShortArray, int16_t>
11587       (GetHeap(), this, index, value);
11588 }
11589
11590
11591 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index,
11592                                                   Object* value) {
11593   return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
11594       (GetHeap(), this, index, value);
11595 }
11596
11597
11598 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) {
11599   return ExternalArrayIntSetter<ExternalIntArray, int32_t>
11600       (GetHeap(), this, index, value);
11601 }
11602
11603
11604 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
11605   uint32_t cast_value = 0;
11606   Heap* heap = GetHeap();
11607   if (index < static_cast<uint32_t>(length())) {
11608     if (value->IsSmi()) {
11609       int int_value = Smi::cast(value)->value();
11610       cast_value = static_cast<uint32_t>(int_value);
11611     } else if (value->IsHeapNumber()) {
11612       double double_value = HeapNumber::cast(value)->value();
11613       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
11614     } else {
11615       // Clamp undefined to zero (default). All other types have been
11616       // converted to a number type further up in the call chain.
11617       ASSERT(value->IsUndefined());
11618     }
11619     set(index, cast_value);
11620   }
11621   return heap->NumberFromUint32(cast_value);
11622 }
11623
11624
11625 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
11626   float cast_value = static_cast<float>(OS::nan_value());
11627   Heap* heap = GetHeap();
11628   if (index < static_cast<uint32_t>(length())) {
11629     if (value->IsSmi()) {
11630       int int_value = Smi::cast(value)->value();
11631       cast_value = static_cast<float>(int_value);
11632     } else if (value->IsHeapNumber()) {
11633       double double_value = HeapNumber::cast(value)->value();
11634       cast_value = static_cast<float>(double_value);
11635     } else {
11636       // Clamp undefined to NaN (default). All other types have been
11637       // converted to a number type further up in the call chain.
11638       ASSERT(value->IsUndefined());
11639     }
11640     set(index, cast_value);
11641   }
11642   return heap->AllocateHeapNumber(cast_value);
11643 }
11644
11645
11646 MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) {
11647   double double_value = OS::nan_value();
11648   Heap* heap = GetHeap();
11649   if (index < static_cast<uint32_t>(length())) {
11650     if (value->IsSmi()) {
11651       int int_value = Smi::cast(value)->value();
11652       double_value = static_cast<double>(int_value);
11653     } else if (value->IsHeapNumber()) {
11654       double_value = HeapNumber::cast(value)->value();
11655     } else {
11656       // Clamp undefined to NaN (default). All other types have been
11657       // converted to a number type further up in the call chain.
11658       ASSERT(value->IsUndefined());
11659     }
11660     set(index, double_value);
11661   }
11662   return heap->AllocateHeapNumber(double_value);
11663 }
11664
11665
11666 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
11667   ASSERT(!HasFastProperties());
11668   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
11669   return JSGlobalPropertyCell::cast(value);
11670 }
11671
11672
11673 Handle<JSGlobalPropertyCell> GlobalObject::EnsurePropertyCell(
11674     Handle<GlobalObject> global,
11675     Handle<String> name) {
11676   Isolate* isolate = global->GetIsolate();
11677   CALL_HEAP_FUNCTION(isolate,
11678                      global->EnsurePropertyCell(*name),
11679                      JSGlobalPropertyCell);
11680 }
11681
11682
11683 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) {
11684   ASSERT(!HasFastProperties());
11685   int entry = property_dictionary()->FindEntry(name);
11686   if (entry == StringDictionary::kNotFound) {
11687     Heap* heap = GetHeap();
11688     Object* cell;
11689     { MaybeObject* maybe_cell =
11690           heap->AllocateJSGlobalPropertyCell(heap->the_hole_value());
11691       if (!maybe_cell->ToObject(&cell)) return maybe_cell;
11692     }
11693     PropertyDetails details(NONE, NORMAL);
11694     details = details.AsDeleted();
11695     Object* dictionary;
11696     { MaybeObject* maybe_dictionary =
11697           property_dictionary()->Add(name, cell, details);
11698       if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
11699     }
11700     set_properties(StringDictionary::cast(dictionary));
11701     return cell;
11702   } else {
11703     Object* value = property_dictionary()->ValueAt(entry);
11704     ASSERT(value->IsJSGlobalPropertyCell());
11705     return value;
11706   }
11707 }
11708
11709
11710 MaybeObject* SymbolTable::LookupString(String* string, Object** s) {
11711   SymbolKey key(string);
11712   return LookupKey(&key, s);
11713 }
11714
11715
11716 // This class is used for looking up two character strings in the symbol table.
11717 // If we don't have a hit we don't want to waste much time so we unroll the
11718 // string hash calculation loop here for speed.  Doesn't work if the two
11719 // characters form a decimal integer, since such strings have a different hash
11720 // algorithm.
11721 class TwoCharHashTableKey : public HashTableKey {
11722  public:
11723   TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed)
11724     : c1_(c1), c2_(c2) {
11725     // Char 1.
11726     uint32_t hash = seed;
11727     hash += c1;
11728     hash += hash << 10;
11729     hash ^= hash >> 6;
11730     // Char 2.
11731     hash += c2;
11732     hash += hash << 10;
11733     hash ^= hash >> 6;
11734     // GetHash.
11735     hash += hash << 3;
11736     hash ^= hash >> 11;
11737     hash += hash << 15;
11738     if ((hash & String::kHashBitMask) == 0) hash = String::kZeroHash;
11739 #ifdef DEBUG
11740     StringHasher hasher(2, seed);
11741     hasher.AddCharacter(c1);
11742     hasher.AddCharacter(c2);
11743     // If this assert fails then we failed to reproduce the two-character
11744     // version of the string hashing algorithm above.  One reason could be
11745     // that we were passed two digits as characters, since the hash
11746     // algorithm is different in that case.
11747     ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
11748 #endif
11749     hash_ = hash;
11750   }
11751
11752   bool IsMatch(Object* o) {
11753     if (!o->IsString()) return false;
11754     String* other = String::cast(o);
11755     if (other->length() != 2) return false;
11756     if (other->Get(0) != c1_) return false;
11757     return other->Get(1) == c2_;
11758   }
11759
11760   uint32_t Hash() { return hash_; }
11761   uint32_t HashForObject(Object* key) {
11762     if (!key->IsString()) return 0;
11763     return String::cast(key)->Hash();
11764   }
11765
11766   Object* AsObject() {
11767     // The TwoCharHashTableKey is only used for looking in the symbol
11768     // table, not for adding to it.
11769     UNREACHABLE();
11770     return NULL;
11771   }
11772
11773  private:
11774   uint32_t c1_;
11775   uint32_t c2_;
11776   uint32_t hash_;
11777 };
11778
11779
11780 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
11781   SymbolKey key(string);
11782   int entry = FindEntry(&key);
11783   if (entry == kNotFound) {
11784     return false;
11785   } else {
11786     String* result = String::cast(KeyAt(entry));
11787     ASSERT(StringShape(result).IsSymbol());
11788     *symbol = result;
11789     return true;
11790   }
11791 }
11792
11793
11794 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
11795                                                uint32_t c2,
11796                                                String** symbol) {
11797   TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed());
11798   int entry = FindEntry(&key);
11799   if (entry == kNotFound) {
11800     return false;
11801   } else {
11802     String* result = String::cast(KeyAt(entry));
11803     ASSERT(StringShape(result).IsSymbol());
11804     *symbol = result;
11805     return true;
11806   }
11807 }
11808
11809
11810 MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str,
11811                                        Object** s) {
11812   Utf8SymbolKey key(str, GetHeap()->HashSeed());
11813   return LookupKey(&key, s);
11814 }
11815
11816
11817 MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str,
11818                                             Object** s) {
11819   AsciiSymbolKey key(str, GetHeap()->HashSeed());
11820   return LookupKey(&key, s);
11821 }
11822
11823
11824 MaybeObject* SymbolTable::LookupSubStringAsciiSymbol(Handle<SeqAsciiString> str,
11825                                                      int from,
11826                                                      int length,
11827                                                      Object** s) {
11828   SubStringAsciiSymbolKey key(str, from, length, GetHeap()->HashSeed());
11829   return LookupKey(&key, s);
11830 }
11831
11832
11833 MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
11834                                               Object** s) {
11835   TwoByteSymbolKey key(str, GetHeap()->HashSeed());
11836   return LookupKey(&key, s);
11837 }
11838
11839 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
11840   int entry = FindEntry(key);
11841
11842   // Symbol already in table.
11843   if (entry != kNotFound) {
11844     *s = KeyAt(entry);
11845     return this;
11846   }
11847
11848   // Adding new symbol. Grow table if needed.
11849   Object* obj;
11850   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
11851     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11852   }
11853
11854   // Create symbol object.
11855   Object* symbol;
11856   { MaybeObject* maybe_symbol = key->AsObject();
11857     if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol;
11858   }
11859
11860   // If the symbol table grew as part of EnsureCapacity, obj is not
11861   // the current symbol table and therefore we cannot use
11862   // SymbolTable::cast here.
11863   SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
11864
11865   // Add the new symbol and return it along with the symbol table.
11866   entry = table->FindInsertionEntry(key->Hash());
11867   table->set(EntryToIndex(entry), symbol);
11868   table->ElementAdded();
11869   *s = symbol;
11870   return table;
11871 }
11872
11873
11874 Object* CompilationCacheTable::Lookup(String* src) {
11875   StringKey key(src);
11876   int entry = FindEntry(&key);
11877   if (entry == kNotFound) return GetHeap()->undefined_value();
11878   return get(EntryToIndex(entry) + 1);
11879 }
11880
11881
11882 Object* CompilationCacheTable::LookupEval(String* src,
11883                                           Context* context,
11884                                           LanguageMode language_mode,
11885                                           int scope_position) {
11886   StringSharedKey key(src,
11887                       context->closure()->shared(),
11888                       language_mode,
11889                       scope_position);
11890   int entry = FindEntry(&key);
11891   if (entry == kNotFound) return GetHeap()->undefined_value();
11892   return get(EntryToIndex(entry) + 1);
11893 }
11894
11895
11896 Object* CompilationCacheTable::LookupRegExp(String* src,
11897                                             JSRegExp::Flags flags) {
11898   RegExpKey key(src, flags);
11899   int entry = FindEntry(&key);
11900   if (entry == kNotFound) return GetHeap()->undefined_value();
11901   return get(EntryToIndex(entry) + 1);
11902 }
11903
11904
11905 MaybeObject* CompilationCacheTable::Put(String* src, Object* value) {
11906   StringKey key(src);
11907   Object* obj;
11908   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11909     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11910   }
11911
11912   CompilationCacheTable* cache =
11913       reinterpret_cast<CompilationCacheTable*>(obj);
11914   int entry = cache->FindInsertionEntry(key.Hash());
11915   cache->set(EntryToIndex(entry), src);
11916   cache->set(EntryToIndex(entry) + 1, value);
11917   cache->ElementAdded();
11918   return cache;
11919 }
11920
11921
11922 MaybeObject* CompilationCacheTable::PutEval(String* src,
11923                                             Context* context,
11924                                             SharedFunctionInfo* value,
11925                                             int scope_position) {
11926   StringSharedKey key(src,
11927                       context->closure()->shared(),
11928                       value->language_mode(),
11929                       scope_position);
11930   Object* obj;
11931   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11932     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11933   }
11934
11935   CompilationCacheTable* cache =
11936       reinterpret_cast<CompilationCacheTable*>(obj);
11937   int entry = cache->FindInsertionEntry(key.Hash());
11938
11939   Object* k;
11940   { MaybeObject* maybe_k = key.AsObject();
11941     if (!maybe_k->ToObject(&k)) return maybe_k;
11942   }
11943
11944   cache->set(EntryToIndex(entry), k);
11945   cache->set(EntryToIndex(entry) + 1, value);
11946   cache->ElementAdded();
11947   return cache;
11948 }
11949
11950
11951 MaybeObject* CompilationCacheTable::PutRegExp(String* src,
11952                                               JSRegExp::Flags flags,
11953                                               FixedArray* value) {
11954   RegExpKey key(src, flags);
11955   Object* obj;
11956   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11957     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11958   }
11959
11960   CompilationCacheTable* cache =
11961       reinterpret_cast<CompilationCacheTable*>(obj);
11962   int entry = cache->FindInsertionEntry(key.Hash());
11963   // We store the value in the key slot, and compare the search key
11964   // to the stored value with a custon IsMatch function during lookups.
11965   cache->set(EntryToIndex(entry), value);
11966   cache->set(EntryToIndex(entry) + 1, value);
11967   cache->ElementAdded();
11968   return cache;
11969 }
11970
11971
11972 void CompilationCacheTable::Remove(Object* value) {
11973   Object* the_hole_value = GetHeap()->the_hole_value();
11974   for (int entry = 0, size = Capacity(); entry < size; entry++) {
11975     int entry_index = EntryToIndex(entry);
11976     int value_index = entry_index + 1;
11977     if (get(value_index) == value) {
11978       NoWriteBarrierSet(this, entry_index, the_hole_value);
11979       NoWriteBarrierSet(this, value_index, the_hole_value);
11980       ElementRemoved();
11981     }
11982   }
11983   return;
11984 }
11985
11986
11987 // SymbolsKey used for HashTable where key is array of symbols.
11988 class SymbolsKey : public HashTableKey {
11989  public:
11990   explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
11991
11992   bool IsMatch(Object* symbols) {
11993     FixedArray* o = FixedArray::cast(symbols);
11994     int len = symbols_->length();
11995     if (o->length() != len) return false;
11996     for (int i = 0; i < len; i++) {
11997       if (o->get(i) != symbols_->get(i)) return false;
11998     }
11999     return true;
12000   }
12001
12002   uint32_t Hash() { return HashForObject(symbols_); }
12003
12004   uint32_t HashForObject(Object* obj) {
12005     FixedArray* symbols = FixedArray::cast(obj);
12006     int len = symbols->length();
12007     uint32_t hash = 0;
12008     for (int i = 0; i < len; i++) {
12009       hash ^= String::cast(symbols->get(i))->Hash();
12010     }
12011     return hash;
12012   }
12013
12014   Object* AsObject() { return symbols_; }
12015
12016  private:
12017   FixedArray* symbols_;
12018 };
12019
12020
12021 Object* MapCache::Lookup(FixedArray* array) {
12022   SymbolsKey key(array);
12023   int entry = FindEntry(&key);
12024   if (entry == kNotFound) return GetHeap()->undefined_value();
12025   return get(EntryToIndex(entry) + 1);
12026 }
12027
12028
12029 MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
12030   SymbolsKey key(array);
12031   Object* obj;
12032   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
12033     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12034   }
12035
12036   MapCache* cache = reinterpret_cast<MapCache*>(obj);
12037   int entry = cache->FindInsertionEntry(key.Hash());
12038   cache->set(EntryToIndex(entry), array);
12039   cache->set(EntryToIndex(entry) + 1, value);
12040   cache->ElementAdded();
12041   return cache;
12042 }
12043
12044
12045 template<typename Shape, typename Key>
12046 MaybeObject* Dictionary<Shape, Key>::Allocate(int at_least_space_for) {
12047   Object* obj;
12048   { MaybeObject* maybe_obj =
12049         HashTable<Shape, Key>::Allocate(at_least_space_for);
12050     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12051   }
12052   // Initialize the next enumeration index.
12053   Dictionary<Shape, Key>::cast(obj)->
12054       SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
12055   return obj;
12056 }
12057
12058
12059 template<typename Shape, typename Key>
12060 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
12061   Heap* heap = Dictionary<Shape, Key>::GetHeap();
12062   int length = HashTable<Shape, Key>::NumberOfElements();
12063
12064   // Allocate and initialize iteration order array.
12065   Object* obj;
12066   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12067     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12068   }
12069   FixedArray* iteration_order = FixedArray::cast(obj);
12070   for (int i = 0; i < length; i++) {
12071     iteration_order->set(i, Smi::FromInt(i));
12072   }
12073
12074   // Allocate array with enumeration order.
12075   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12076     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12077   }
12078   FixedArray* enumeration_order = FixedArray::cast(obj);
12079
12080   // Fill the enumeration order array with property details.
12081   int capacity = HashTable<Shape, Key>::Capacity();
12082   int pos = 0;
12083   for (int i = 0; i < capacity; i++) {
12084     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
12085       enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
12086     }
12087   }
12088
12089   // Sort the arrays wrt. enumeration order.
12090   iteration_order->SortPairs(enumeration_order, enumeration_order->length());
12091
12092   // Overwrite the enumeration_order with the enumeration indices.
12093   for (int i = 0; i < length; i++) {
12094     int index = Smi::cast(iteration_order->get(i))->value();
12095     int enum_index = PropertyDetails::kInitialIndex + i;
12096     enumeration_order->set(index, Smi::FromInt(enum_index));
12097   }
12098
12099   // Update the dictionary with new indices.
12100   capacity = HashTable<Shape, Key>::Capacity();
12101   pos = 0;
12102   for (int i = 0; i < capacity; i++) {
12103     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
12104       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
12105       PropertyDetails details = DetailsAt(i);
12106       PropertyDetails new_details =
12107           PropertyDetails(details.attributes(), details.type(), enum_index);
12108       DetailsAtPut(i, new_details);
12109     }
12110   }
12111
12112   // Set the next enumeration index.
12113   SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
12114   return this;
12115 }
12116
12117 template<typename Shape, typename Key>
12118 MaybeObject* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
12119   // Check whether there are enough enumeration indices to add n elements.
12120   if (Shape::kIsEnumerable &&
12121       !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
12122     // If not, we generate new indices for the properties.
12123     Object* result;
12124     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12125       if (!maybe_result->ToObject(&result)) return maybe_result;
12126     }
12127   }
12128   return HashTable<Shape, Key>::EnsureCapacity(n, key);
12129 }
12130
12131
12132 template<typename Shape, typename Key>
12133 Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
12134                                                JSReceiver::DeleteMode mode) {
12135   Heap* heap = Dictionary<Shape, Key>::GetHeap();
12136   PropertyDetails details = DetailsAt(entry);
12137   // Ignore attributes if forcing a deletion.
12138   if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
12139     return heap->false_value();
12140   }
12141   SetEntry(entry, heap->the_hole_value(), heap->the_hole_value());
12142   HashTable<Shape, Key>::ElementRemoved();
12143   return heap->true_value();
12144 }
12145
12146
12147 template<typename Shape, typename Key>
12148 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
12149   return HashTable<Shape, Key>::Shrink(key);
12150 }
12151
12152
12153 template<typename Shape, typename Key>
12154 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
12155   int entry = this->FindEntry(key);
12156
12157   // If the entry is present set the value;
12158   if (entry != Dictionary<Shape, Key>::kNotFound) {
12159     ValueAtPut(entry, value);
12160     return this;
12161   }
12162
12163   // Check whether the dictionary should be extended.
12164   Object* obj;
12165   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12166     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12167   }
12168
12169   Object* k;
12170   { MaybeObject* maybe_k = Shape::AsObject(key);
12171     if (!maybe_k->ToObject(&k)) return maybe_k;
12172   }
12173   PropertyDetails details = PropertyDetails(NONE, NORMAL);
12174
12175   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
12176       Dictionary<Shape, Key>::Hash(key));
12177 }
12178
12179
12180 template<typename Shape, typename Key>
12181 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
12182                                          Object* value,
12183                                          PropertyDetails details) {
12184   // Valdate key is absent.
12185   SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
12186   // Check whether the dictionary should be extended.
12187   Object* obj;
12188   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12189     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12190   }
12191
12192   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
12193       Dictionary<Shape, Key>::Hash(key));
12194 }
12195
12196
12197 // Add a key, value pair to the dictionary.
12198 template<typename Shape, typename Key>
12199 MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key,
12200                                               Object* value,
12201                                               PropertyDetails details,
12202                                               uint32_t hash) {
12203   // Compute the key object.
12204   Object* k;
12205   { MaybeObject* maybe_k = Shape::AsObject(key);
12206     if (!maybe_k->ToObject(&k)) return maybe_k;
12207   }
12208
12209   uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
12210   // Insert element at empty or deleted entry
12211   if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
12212     // Assign an enumeration index to the property and update
12213     // SetNextEnumerationIndex.
12214     int index = NextEnumerationIndex();
12215     details = PropertyDetails(details.attributes(), details.type(), index);
12216     SetNextEnumerationIndex(index + 1);
12217   }
12218   SetEntry(entry, k, value, details);
12219   ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
12220           || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
12221   HashTable<Shape, Key>::ElementAdded();
12222   return this;
12223 }
12224
12225
12226 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
12227   // If the dictionary requires slow elements an element has already
12228   // been added at a high index.
12229   if (requires_slow_elements()) return;
12230   // Check if this index is high enough that we should require slow
12231   // elements.
12232   if (key > kRequiresSlowElementsLimit) {
12233     set_requires_slow_elements();
12234     return;
12235   }
12236   // Update max key value.
12237   Object* max_index_object = get(kMaxNumberKeyIndex);
12238   if (!max_index_object->IsSmi() || max_number_key() < key) {
12239     FixedArray::set(kMaxNumberKeyIndex,
12240                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
12241   }
12242 }
12243
12244
12245 MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key,
12246                                                     Object* value,
12247                                                     PropertyDetails details) {
12248   UpdateMaxNumberKey(key);
12249   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
12250   return Add(key, value, details);
12251 }
12252
12253
12254 MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key,
12255                                                       Object* value) {
12256   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
12257   return Add(key, value, PropertyDetails(NONE, NORMAL));
12258 }
12259
12260
12261 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) {
12262   UpdateMaxNumberKey(key);
12263   return AtPut(key, value);
12264 }
12265
12266
12267 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key,
12268                                                    Object* value) {
12269   return AtPut(key, value);
12270 }
12271
12272
12273 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
12274     Handle<SeededNumberDictionary> dictionary,
12275     uint32_t index,
12276     Handle<Object> value,
12277     PropertyDetails details) {
12278   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
12279                      dictionary->Set(index, *value, details),
12280                      SeededNumberDictionary);
12281 }
12282
12283
12284 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
12285     Handle<UnseededNumberDictionary> dictionary,
12286     uint32_t index,
12287     Handle<Object> value) {
12288   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
12289                      dictionary->Set(index, *value),
12290                      UnseededNumberDictionary);
12291 }
12292
12293
12294 MaybeObject* SeededNumberDictionary::Set(uint32_t key,
12295                                          Object* value,
12296                                          PropertyDetails details) {
12297   int entry = FindEntry(key);
12298   if (entry == kNotFound) return AddNumberEntry(key, value, details);
12299   // Preserve enumeration index.
12300   details = PropertyDetails(details.attributes(),
12301                             details.type(),
12302                             DetailsAt(entry).index());
12303   MaybeObject* maybe_object_key = SeededNumberDictionaryShape::AsObject(key);
12304   Object* object_key;
12305   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
12306   SetEntry(entry, object_key, value, details);
12307   return this;
12308 }
12309
12310
12311 MaybeObject* UnseededNumberDictionary::Set(uint32_t key,
12312                                            Object* value) {
12313   int entry = FindEntry(key);
12314   if (entry == kNotFound) return AddNumberEntry(key, value);
12315   MaybeObject* maybe_object_key = UnseededNumberDictionaryShape::AsObject(key);
12316   Object* object_key;
12317   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
12318   SetEntry(entry, object_key, value);
12319   return this;
12320 }
12321
12322
12323
12324 template<typename Shape, typename Key>
12325 int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
12326     PropertyAttributes filter) {
12327   int capacity = HashTable<Shape, Key>::Capacity();
12328   int result = 0;
12329   for (int i = 0; i < capacity; i++) {
12330     Object* k = HashTable<Shape, Key>::KeyAt(i);
12331     if (HashTable<Shape, Key>::IsKey(k)) {
12332       PropertyDetails details = DetailsAt(i);
12333       if (details.IsDeleted()) continue;
12334       PropertyAttributes attr = details.attributes();
12335       if ((attr & filter) == 0) result++;
12336     }
12337   }
12338   return result;
12339 }
12340
12341
12342 template<typename Shape, typename Key>
12343 int Dictionary<Shape, Key>::NumberOfEnumElements() {
12344   return NumberOfElementsFilterAttributes(
12345       static_cast<PropertyAttributes>(DONT_ENUM));
12346 }
12347
12348
12349 template<typename Shape, typename Key>
12350 void Dictionary<Shape, Key>::CopyKeysTo(
12351     FixedArray* storage,
12352     PropertyAttributes filter,
12353     typename Dictionary<Shape, Key>::SortMode sort_mode) {
12354   ASSERT(storage->length() >= NumberOfEnumElements());
12355   int capacity = HashTable<Shape, Key>::Capacity();
12356   int index = 0;
12357   for (int i = 0; i < capacity; i++) {
12358      Object* k = HashTable<Shape, Key>::KeyAt(i);
12359      if (HashTable<Shape, Key>::IsKey(k)) {
12360        PropertyDetails details = DetailsAt(i);
12361        if (details.IsDeleted()) continue;
12362        PropertyAttributes attr = details.attributes();
12363        if ((attr & filter) == 0) storage->set(index++, k);
12364      }
12365   }
12366   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12367     storage->SortPairs(storage, index);
12368   }
12369   ASSERT(storage->length() >= index);
12370 }
12371
12372
12373 void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
12374                                       FixedArray* sort_array) {
12375   ASSERT(storage->length() >= NumberOfEnumElements());
12376   int capacity = Capacity();
12377   int index = 0;
12378   for (int i = 0; i < capacity; i++) {
12379      Object* k = KeyAt(i);
12380      if (IsKey(k)) {
12381        PropertyDetails details = DetailsAt(i);
12382        if (details.IsDeleted() || details.IsDontEnum()) continue;
12383        storage->set(index, k);
12384        sort_array->set(index, Smi::FromInt(details.index()));
12385        index++;
12386      }
12387   }
12388   storage->SortPairs(sort_array, sort_array->length());
12389   ASSERT(storage->length() >= index);
12390 }
12391
12392
12393 template<typename Shape, typename Key>
12394 void Dictionary<Shape, Key>::CopyKeysTo(
12395     FixedArray* storage,
12396     int index,
12397     typename Dictionary<Shape, Key>::SortMode sort_mode) {
12398   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
12399       static_cast<PropertyAttributes>(NONE)));
12400   int capacity = HashTable<Shape, Key>::Capacity();
12401   for (int i = 0; i < capacity; i++) {
12402     Object* k = HashTable<Shape, Key>::KeyAt(i);
12403     if (HashTable<Shape, Key>::IsKey(k)) {
12404       PropertyDetails details = DetailsAt(i);
12405       if (details.IsDeleted()) continue;
12406       storage->set(index++, k);
12407     }
12408   }
12409   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12410     storage->SortPairs(storage, index);
12411   }
12412   ASSERT(storage->length() >= index);
12413 }
12414
12415
12416 // Backwards lookup (slow).
12417 template<typename Shape, typename Key>
12418 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
12419   int capacity = HashTable<Shape, Key>::Capacity();
12420   for (int i = 0; i < capacity; i++) {
12421     Object* k =  HashTable<Shape, Key>::KeyAt(i);
12422     if (Dictionary<Shape, Key>::IsKey(k)) {
12423       Object* e = ValueAt(i);
12424       if (e->IsJSGlobalPropertyCell()) {
12425         e = JSGlobalPropertyCell::cast(e)->value();
12426       }
12427       if (e == value) return k;
12428     }
12429   }
12430   Heap* heap = Dictionary<Shape, Key>::GetHeap();
12431   return heap->undefined_value();
12432 }
12433
12434
12435 MaybeObject* StringDictionary::TransformPropertiesToFastFor(
12436     JSObject* obj, int unused_property_fields) {
12437   // Make sure we preserve dictionary representation if there are too many
12438   // descriptors.
12439   if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
12440
12441   // Figure out if it is necessary to generate new enumeration indices.
12442   int max_enumeration_index =
12443       NextEnumerationIndex() +
12444           (DescriptorArray::kMaxNumberOfDescriptors -
12445            NumberOfElements());
12446   if (!PropertyDetails::IsValidIndex(max_enumeration_index)) {
12447     Object* result;
12448     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12449       if (!maybe_result->ToObject(&result)) return maybe_result;
12450     }
12451   }
12452
12453   int instance_descriptor_length = 0;
12454   int number_of_fields = 0;
12455
12456   Heap* heap = GetHeap();
12457
12458   // Compute the length of the instance descriptor.
12459   int capacity = Capacity();
12460   for (int i = 0; i < capacity; i++) {
12461     Object* k = KeyAt(i);
12462     if (IsKey(k)) {
12463       Object* value = ValueAt(i);
12464       PropertyType type = DetailsAt(i).type();
12465       ASSERT(type != FIELD);
12466       instance_descriptor_length++;
12467       if (type == NORMAL &&
12468           (!value->IsJSFunction() || heap->InNewSpace(value))) {
12469         number_of_fields += 1;
12470       }
12471     }
12472   }
12473
12474   // Allocate the instance descriptor.
12475   DescriptorArray* descriptors;
12476   { MaybeObject* maybe_descriptors =
12477         DescriptorArray::Allocate(instance_descriptor_length);
12478     if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) {
12479       return maybe_descriptors;
12480     }
12481   }
12482
12483   DescriptorArray::WhitenessWitness witness(descriptors);
12484
12485   int inobject_props = obj->map()->inobject_properties();
12486   int number_of_allocated_fields =
12487       number_of_fields + unused_property_fields - inobject_props;
12488   if (number_of_allocated_fields < 0) {
12489     // There is enough inobject space for all fields (including unused).
12490     number_of_allocated_fields = 0;
12491     unused_property_fields = inobject_props - number_of_fields;
12492   }
12493
12494   // Allocate the fixed array for the fields.
12495   Object* fields;
12496   { MaybeObject* maybe_fields =
12497         heap->AllocateFixedArray(number_of_allocated_fields);
12498     if (!maybe_fields->ToObject(&fields)) return maybe_fields;
12499   }
12500
12501   // Fill in the instance descriptor and the fields.
12502   int next_descriptor = 0;
12503   int current_offset = 0;
12504   for (int i = 0; i < capacity; i++) {
12505     Object* k = KeyAt(i);
12506     if (IsKey(k)) {
12507       Object* value = ValueAt(i);
12508       // Ensure the key is a symbol before writing into the instance descriptor.
12509       Object* key;
12510       { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
12511         if (!maybe_key->ToObject(&key)) return maybe_key;
12512       }
12513       PropertyDetails details = DetailsAt(i);
12514       PropertyType type = details.type();
12515
12516       if (value->IsJSFunction() && !heap->InNewSpace(value)) {
12517         ConstantFunctionDescriptor d(String::cast(key),
12518                                      JSFunction::cast(value),
12519                                      details.attributes(),
12520                                      details.index());
12521         descriptors->Set(next_descriptor++, &d, witness);
12522       } else if (type == NORMAL) {
12523         if (current_offset < inobject_props) {
12524           obj->InObjectPropertyAtPut(current_offset,
12525                                      value,
12526                                      UPDATE_WRITE_BARRIER);
12527         } else {
12528           int offset = current_offset - inobject_props;
12529           FixedArray::cast(fields)->set(offset, value);
12530         }
12531         FieldDescriptor d(String::cast(key),
12532                           current_offset++,
12533                           details.attributes(),
12534                           details.index());
12535         descriptors->Set(next_descriptor++, &d, witness);
12536       } else if (type == CALLBACKS) {
12537         if (value->IsAccessorPair()) {
12538           MaybeObject* maybe_copy =
12539               AccessorPair::cast(value)->CopyWithoutTransitions();
12540           if (!maybe_copy->To(&value)) return maybe_copy;
12541         }
12542         CallbacksDescriptor d(String::cast(key),
12543                               value,
12544                               details.attributes(),
12545                               details.index());
12546         descriptors->Set(next_descriptor++, &d, witness);
12547       } else {
12548         UNREACHABLE();
12549       }
12550     }
12551   }
12552   ASSERT(current_offset == number_of_fields);
12553
12554   descriptors->Sort(witness);
12555   // Allocate new map.
12556   Object* new_map;
12557   { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
12558     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
12559   }
12560
12561   // Transform the object.
12562   obj->set_map(Map::cast(new_map));
12563   obj->map()->set_instance_descriptors(descriptors);
12564   obj->map()->set_unused_property_fields(unused_property_fields);
12565
12566   obj->set_properties(FixedArray::cast(fields));
12567   ASSERT(obj->IsJSObject());
12568
12569   descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
12570   // Check that it really works.
12571   ASSERT(obj->HasFastProperties());
12572
12573   return obj;
12574 }
12575
12576
12577 bool ObjectHashSet::Contains(Object* key) {
12578   ASSERT(IsKey(key));
12579
12580   // If the object does not have an identity hash, it was never used as a key.
12581   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12582     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false;
12583   }
12584   return (FindEntry(key) != kNotFound);
12585 }
12586
12587
12588 MaybeObject* ObjectHashSet::Add(Object* key) {
12589   ASSERT(IsKey(key));
12590
12591   // Make sure the key object has an identity hash code.
12592   int hash;
12593   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
12594     if (maybe_hash->IsFailure()) return maybe_hash;
12595     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
12596   }
12597   int entry = FindEntry(key);
12598
12599   // Check whether key is already present.
12600   if (entry != kNotFound) return this;
12601
12602   // Check whether the hash set should be extended and add entry.
12603   Object* obj;
12604   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12605     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12606   }
12607   ObjectHashSet* table = ObjectHashSet::cast(obj);
12608   entry = table->FindInsertionEntry(hash);
12609   table->set(EntryToIndex(entry), key);
12610   table->ElementAdded();
12611   return table;
12612 }
12613
12614
12615 MaybeObject* ObjectHashSet::Remove(Object* key) {
12616   ASSERT(IsKey(key));
12617
12618   // If the object does not have an identity hash, it was never used as a key.
12619   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12620     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this;
12621   }
12622   int entry = FindEntry(key);
12623
12624   // Check whether key is actually present.
12625   if (entry == kNotFound) return this;
12626
12627   // Remove entry and try to shrink this hash set.
12628   set_the_hole(EntryToIndex(entry));
12629   ElementRemoved();
12630   return Shrink(key);
12631 }
12632
12633
12634 Object* ObjectHashTable::Lookup(Object* key) {
12635   ASSERT(IsKey(key));
12636
12637   // If the object does not have an identity hash, it was never used as a key.
12638   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12639     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) {
12640       return GetHeap()->undefined_value();
12641     }
12642   }
12643   int entry = FindEntry(key);
12644   if (entry == kNotFound) return GetHeap()->undefined_value();
12645   return get(EntryToIndex(entry) + 1);
12646 }
12647
12648
12649 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) {
12650   ASSERT(IsKey(key));
12651
12652   // Make sure the key object has an identity hash code.
12653   int hash;
12654   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
12655     if (maybe_hash->IsFailure()) return maybe_hash;
12656     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
12657   }
12658   int entry = FindEntry(key);
12659
12660   // Check whether to perform removal operation.
12661   if (value->IsUndefined()) {
12662     if (entry == kNotFound) return this;
12663     RemoveEntry(entry);
12664     return Shrink(key);
12665   }
12666
12667   // Key is already in table, just overwrite value.
12668   if (entry != kNotFound) {
12669     set(EntryToIndex(entry) + 1, value);
12670     return this;
12671   }
12672
12673   // Check whether the hash table should be extended.
12674   Object* obj;
12675   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12676     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12677   }
12678   ObjectHashTable* table = ObjectHashTable::cast(obj);
12679   table->AddEntry(table->FindInsertionEntry(hash), key, value);
12680   return table;
12681 }
12682
12683
12684 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
12685   set(EntryToIndex(entry), key);
12686   set(EntryToIndex(entry) + 1, value);
12687   ElementAdded();
12688 }
12689
12690
12691 void ObjectHashTable::RemoveEntry(int entry) {
12692   set_the_hole(EntryToIndex(entry));
12693   set_the_hole(EntryToIndex(entry) + 1);
12694   ElementRemoved();
12695 }
12696
12697
12698 #ifdef ENABLE_DEBUGGER_SUPPORT
12699 // Check if there is a break point at this code position.
12700 bool DebugInfo::HasBreakPoint(int code_position) {
12701   // Get the break point info object for this code position.
12702   Object* break_point_info = GetBreakPointInfo(code_position);
12703
12704   // If there is no break point info object or no break points in the break
12705   // point info object there is no break point at this code position.
12706   if (break_point_info->IsUndefined()) return false;
12707   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
12708 }
12709
12710
12711 // Get the break point info object for this code position.
12712 Object* DebugInfo::GetBreakPointInfo(int code_position) {
12713   // Find the index of the break point info object for this code position.
12714   int index = GetBreakPointInfoIndex(code_position);
12715
12716   // Return the break point info object if any.
12717   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
12718   return BreakPointInfo::cast(break_points()->get(index));
12719 }
12720
12721
12722 // Clear a break point at the specified code position.
12723 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
12724                                 int code_position,
12725                                 Handle<Object> break_point_object) {
12726   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
12727   if (break_point_info->IsUndefined()) return;
12728   BreakPointInfo::ClearBreakPoint(
12729       Handle<BreakPointInfo>::cast(break_point_info),
12730       break_point_object);
12731 }
12732
12733
12734 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
12735                               int code_position,
12736                               int source_position,
12737                               int statement_position,
12738                               Handle<Object> break_point_object) {
12739   Isolate* isolate = Isolate::Current();
12740   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
12741   if (!break_point_info->IsUndefined()) {
12742     BreakPointInfo::SetBreakPoint(
12743         Handle<BreakPointInfo>::cast(break_point_info),
12744         break_point_object);
12745     return;
12746   }
12747
12748   // Adding a new break point for a code position which did not have any
12749   // break points before. Try to find a free slot.
12750   int index = kNoBreakPointInfo;
12751   for (int i = 0; i < debug_info->break_points()->length(); i++) {
12752     if (debug_info->break_points()->get(i)->IsUndefined()) {
12753       index = i;
12754       break;
12755     }
12756   }
12757   if (index == kNoBreakPointInfo) {
12758     // No free slot - extend break point info array.
12759     Handle<FixedArray> old_break_points =
12760         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
12761     Handle<FixedArray> new_break_points =
12762         isolate->factory()->NewFixedArray(
12763             old_break_points->length() +
12764             Debug::kEstimatedNofBreakPointsInFunction);
12765
12766     debug_info->set_break_points(*new_break_points);
12767     for (int i = 0; i < old_break_points->length(); i++) {
12768       new_break_points->set(i, old_break_points->get(i));
12769     }
12770     index = old_break_points->length();
12771   }
12772   ASSERT(index != kNoBreakPointInfo);
12773
12774   // Allocate new BreakPointInfo object and set the break point.
12775   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
12776       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
12777   new_break_point_info->set_code_position(Smi::FromInt(code_position));
12778   new_break_point_info->set_source_position(Smi::FromInt(source_position));
12779   new_break_point_info->
12780       set_statement_position(Smi::FromInt(statement_position));
12781   new_break_point_info->set_break_point_objects(
12782       isolate->heap()->undefined_value());
12783   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
12784   debug_info->break_points()->set(index, *new_break_point_info);
12785 }
12786
12787
12788 // Get the break point objects for a code position.
12789 Object* DebugInfo::GetBreakPointObjects(int code_position) {
12790   Object* break_point_info = GetBreakPointInfo(code_position);
12791   if (break_point_info->IsUndefined()) {
12792     return GetHeap()->undefined_value();
12793   }
12794   return BreakPointInfo::cast(break_point_info)->break_point_objects();
12795 }
12796
12797
12798 // Get the total number of break points.
12799 int DebugInfo::GetBreakPointCount() {
12800   if (break_points()->IsUndefined()) return 0;
12801   int count = 0;
12802   for (int i = 0; i < break_points()->length(); i++) {
12803     if (!break_points()->get(i)->IsUndefined()) {
12804       BreakPointInfo* break_point_info =
12805           BreakPointInfo::cast(break_points()->get(i));
12806       count += break_point_info->GetBreakPointCount();
12807     }
12808   }
12809   return count;
12810 }
12811
12812
12813 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
12814                                       Handle<Object> break_point_object) {
12815   Heap* heap = debug_info->GetHeap();
12816   if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
12817   for (int i = 0; i < debug_info->break_points()->length(); i++) {
12818     if (!debug_info->break_points()->get(i)->IsUndefined()) {
12819       Handle<BreakPointInfo> break_point_info =
12820           Handle<BreakPointInfo>(BreakPointInfo::cast(
12821               debug_info->break_points()->get(i)));
12822       if (BreakPointInfo::HasBreakPointObject(break_point_info,
12823                                               break_point_object)) {
12824         return *break_point_info;
12825       }
12826     }
12827   }
12828   return heap->undefined_value();
12829 }
12830
12831
12832 // Find the index of the break point info object for the specified code
12833 // position.
12834 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
12835   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
12836   for (int i = 0; i < break_points()->length(); i++) {
12837     if (!break_points()->get(i)->IsUndefined()) {
12838       BreakPointInfo* break_point_info =
12839           BreakPointInfo::cast(break_points()->get(i));
12840       if (break_point_info->code_position()->value() == code_position) {
12841         return i;
12842       }
12843     }
12844   }
12845   return kNoBreakPointInfo;
12846 }
12847
12848
12849 // Remove the specified break point object.
12850 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
12851                                      Handle<Object> break_point_object) {
12852   Isolate* isolate = Isolate::Current();
12853   // If there are no break points just ignore.
12854   if (break_point_info->break_point_objects()->IsUndefined()) return;
12855   // If there is a single break point clear it if it is the same.
12856   if (!break_point_info->break_point_objects()->IsFixedArray()) {
12857     if (break_point_info->break_point_objects() == *break_point_object) {
12858       break_point_info->set_break_point_objects(
12859           isolate->heap()->undefined_value());
12860     }
12861     return;
12862   }
12863   // If there are multiple break points shrink the array
12864   ASSERT(break_point_info->break_point_objects()->IsFixedArray());
12865   Handle<FixedArray> old_array =
12866       Handle<FixedArray>(
12867           FixedArray::cast(break_point_info->break_point_objects()));
12868   Handle<FixedArray> new_array =
12869       isolate->factory()->NewFixedArray(old_array->length() - 1);
12870   int found_count = 0;
12871   for (int i = 0; i < old_array->length(); i++) {
12872     if (old_array->get(i) == *break_point_object) {
12873       ASSERT(found_count == 0);
12874       found_count++;
12875     } else {
12876       new_array->set(i - found_count, old_array->get(i));
12877     }
12878   }
12879   // If the break point was found in the list change it.
12880   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
12881 }
12882
12883
12884 // Add the specified break point object.
12885 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
12886                                    Handle<Object> break_point_object) {
12887   // If there was no break point objects before just set it.
12888   if (break_point_info->break_point_objects()->IsUndefined()) {
12889     break_point_info->set_break_point_objects(*break_point_object);
12890     return;
12891   }
12892   // If the break point object is the same as before just ignore.
12893   if (break_point_info->break_point_objects() == *break_point_object) return;
12894   // If there was one break point object before replace with array.
12895   if (!break_point_info->break_point_objects()->IsFixedArray()) {
12896     Handle<FixedArray> array = FACTORY->NewFixedArray(2);
12897     array->set(0, break_point_info->break_point_objects());
12898     array->set(1, *break_point_object);
12899     break_point_info->set_break_point_objects(*array);
12900     return;
12901   }
12902   // If there was more than one break point before extend array.
12903   Handle<FixedArray> old_array =
12904       Handle<FixedArray>(
12905           FixedArray::cast(break_point_info->break_point_objects()));
12906   Handle<FixedArray> new_array =
12907       FACTORY->NewFixedArray(old_array->length() + 1);
12908   for (int i = 0; i < old_array->length(); i++) {
12909     // If the break point was there before just ignore.
12910     if (old_array->get(i) == *break_point_object) return;
12911     new_array->set(i, old_array->get(i));
12912   }
12913   // Add the new break point.
12914   new_array->set(old_array->length(), *break_point_object);
12915   break_point_info->set_break_point_objects(*new_array);
12916 }
12917
12918
12919 bool BreakPointInfo::HasBreakPointObject(
12920     Handle<BreakPointInfo> break_point_info,
12921     Handle<Object> break_point_object) {
12922   // No break point.
12923   if (break_point_info->break_point_objects()->IsUndefined()) return false;
12924   // Single break point.
12925   if (!break_point_info->break_point_objects()->IsFixedArray()) {
12926     return break_point_info->break_point_objects() == *break_point_object;
12927   }
12928   // Multiple break points.
12929   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
12930   for (int i = 0; i < array->length(); i++) {
12931     if (array->get(i) == *break_point_object) {
12932       return true;
12933     }
12934   }
12935   return false;
12936 }
12937
12938
12939 // Get the number of break points.
12940 int BreakPointInfo::GetBreakPointCount() {
12941   // No break point.
12942   if (break_point_objects()->IsUndefined()) return 0;
12943   // Single break point.
12944   if (!break_point_objects()->IsFixedArray()) return 1;
12945   // Multiple break points.
12946   return FixedArray::cast(break_point_objects())->length();
12947 }
12948 #endif  // ENABLE_DEBUGGER_SUPPORT
12949
12950
12951 MaybeObject* JSDate::GetField(Object* object, Smi* index) {
12952   return JSDate::cast(object)->DoGetField(
12953       static_cast<FieldIndex>(index->value()));
12954 }
12955
12956
12957 Object* JSDate::DoGetField(FieldIndex index) {
12958   ASSERT(index != kDateValue);
12959
12960   DateCache* date_cache = GetIsolate()->date_cache();
12961
12962   if (index < kFirstUncachedField) {
12963     Object* stamp = cache_stamp();
12964     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
12965       // Since the stamp is not NaN, the value is also not NaN.
12966       int64_t local_time_ms =
12967           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
12968       SetLocalFields(local_time_ms, date_cache);
12969     }
12970     switch (index) {
12971       case kYear: return year();
12972       case kMonth: return month();
12973       case kDay: return day();
12974       case kWeekday: return weekday();
12975       case kHour: return hour();
12976       case kMinute: return min();
12977       case kSecond: return sec();
12978       default: UNREACHABLE();
12979     }
12980   }
12981
12982   if (index >= kFirstUTCField) {
12983     return GetUTCField(index, value()->Number(), date_cache);
12984   }
12985
12986   double time = value()->Number();
12987   if (isnan(time)) return GetIsolate()->heap()->nan_value();
12988
12989   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
12990   int days = DateCache::DaysFromTime(local_time_ms);
12991
12992   if (index == kDays) return Smi::FromInt(days);
12993
12994   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
12995   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
12996   ASSERT(index == kTimeInDay);
12997   return Smi::FromInt(time_in_day_ms);
12998 }
12999
13000
13001 Object* JSDate::GetUTCField(FieldIndex index,
13002                             double value,
13003                             DateCache* date_cache) {
13004   ASSERT(index >= kFirstUTCField);
13005
13006   if (isnan(value)) return GetIsolate()->heap()->nan_value();
13007
13008   int64_t time_ms = static_cast<int64_t>(value);
13009
13010   if (index == kTimezoneOffset) {
13011     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
13012   }
13013
13014   int days = DateCache::DaysFromTime(time_ms);
13015
13016   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
13017
13018   if (index <= kDayUTC) {
13019     int year, month, day;
13020     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
13021     if (index == kYearUTC) return Smi::FromInt(year);
13022     if (index == kMonthUTC) return Smi::FromInt(month);
13023     ASSERT(index == kDayUTC);
13024     return Smi::FromInt(day);
13025   }
13026
13027   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
13028   switch (index) {
13029     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
13030     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
13031     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
13032     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
13033     case kDaysUTC: return Smi::FromInt(days);
13034     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
13035     default: UNREACHABLE();
13036   }
13037
13038   UNREACHABLE();
13039   return NULL;
13040 }
13041
13042
13043 void JSDate::SetValue(Object* value, bool is_value_nan) {
13044   set_value(value);
13045   if (is_value_nan) {
13046     HeapNumber* nan = GetIsolate()->heap()->nan_value();
13047     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
13048     set_year(nan, SKIP_WRITE_BARRIER);
13049     set_month(nan, SKIP_WRITE_BARRIER);
13050     set_day(nan, SKIP_WRITE_BARRIER);
13051     set_hour(nan, SKIP_WRITE_BARRIER);
13052     set_min(nan, SKIP_WRITE_BARRIER);
13053     set_sec(nan, SKIP_WRITE_BARRIER);
13054     set_weekday(nan, SKIP_WRITE_BARRIER);
13055   } else {
13056     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
13057   }
13058 }
13059
13060
13061 void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) {
13062   int days = DateCache::DaysFromTime(local_time_ms);
13063   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
13064   int year, month, day;
13065   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
13066   int weekday = date_cache->Weekday(days);
13067   int hour = time_in_day_ms / (60 * 60 * 1000);
13068   int min = (time_in_day_ms / (60 * 1000)) % 60;
13069   int sec = (time_in_day_ms / 1000) % 60;
13070   set_cache_stamp(date_cache->stamp());
13071   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13072   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13073   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13074   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13075   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13076   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13077   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13078 }
13079
13080 } }  // namespace v8::internal