[V8] Fix compilation with Intel CC.
[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_MODULE_TYPE:
1342     case JS_VALUE_TYPE:
1343     case JS_DATE_TYPE:
1344     case JS_ARRAY_TYPE:
1345     case JS_SET_TYPE:
1346     case JS_MAP_TYPE:
1347     case JS_WEAK_MAP_TYPE:
1348     case JS_REGEXP_TYPE:
1349     case JS_GLOBAL_PROXY_TYPE:
1350     case JS_GLOBAL_OBJECT_TYPE:
1351     case JS_BUILTINS_OBJECT_TYPE:
1352     case JS_MESSAGE_OBJECT_TYPE:
1353       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1354       break;
1355     case JS_FUNCTION_TYPE:
1356       reinterpret_cast<JSFunction*>(this)
1357           ->JSFunctionIterateBody(object_size, v);
1358       break;
1359     case ODDBALL_TYPE:
1360       Oddball::BodyDescriptor::IterateBody(this, v);
1361       break;
1362     case JS_PROXY_TYPE:
1363       JSProxy::BodyDescriptor::IterateBody(this, v);
1364       break;
1365     case JS_FUNCTION_PROXY_TYPE:
1366       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1367       break;
1368     case FOREIGN_TYPE:
1369       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1370       break;
1371     case MAP_TYPE:
1372       Map::BodyDescriptor::IterateBody(this, v);
1373       break;
1374     case CODE_TYPE:
1375       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1376       break;
1377     case JS_GLOBAL_PROPERTY_CELL_TYPE:
1378       JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v);
1379       break;
1380     case HEAP_NUMBER_TYPE:
1381     case FILLER_TYPE:
1382     case BYTE_ARRAY_TYPE:
1383     case FREE_SPACE_TYPE:
1384     case EXTERNAL_PIXEL_ARRAY_TYPE:
1385     case EXTERNAL_BYTE_ARRAY_TYPE:
1386     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1387     case EXTERNAL_SHORT_ARRAY_TYPE:
1388     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1389     case EXTERNAL_INT_ARRAY_TYPE:
1390     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1391     case EXTERNAL_FLOAT_ARRAY_TYPE:
1392     case EXTERNAL_DOUBLE_ARRAY_TYPE:
1393       break;
1394     case SHARED_FUNCTION_INFO_TYPE: {
1395       SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this);
1396       shared->SharedFunctionInfoIterateBody(v);
1397       break;
1398     }
1399
1400 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1401         case NAME##_TYPE:
1402       STRUCT_LIST(MAKE_STRUCT_CASE)
1403 #undef MAKE_STRUCT_CASE
1404       StructBodyDescriptor::IterateBody(this, object_size, v);
1405       break;
1406     default:
1407       PrintF("Unknown type: %d\n", type);
1408       UNREACHABLE();
1409   }
1410 }
1411
1412
1413 Object* HeapNumber::HeapNumberToBoolean() {
1414   // NaN, +0, and -0 should return the false object
1415 #if __BYTE_ORDER == __LITTLE_ENDIAN
1416   union IeeeDoubleLittleEndianArchType u;
1417 #elif __BYTE_ORDER == __BIG_ENDIAN
1418   union IeeeDoubleBigEndianArchType u;
1419 #endif
1420   u.d = value();
1421   if (u.bits.exp == 2047) {
1422     // Detect NaN for IEEE double precision floating point.
1423     if ((u.bits.man_low | u.bits.man_high) != 0)
1424       return GetHeap()->false_value();
1425   }
1426   if (u.bits.exp == 0) {
1427     // Detect +0, and -0 for IEEE double precision floating point.
1428     if ((u.bits.man_low | u.bits.man_high) == 0)
1429       return GetHeap()->false_value();
1430   }
1431   return GetHeap()->true_value();
1432 }
1433
1434
1435 void HeapNumber::HeapNumberPrint(FILE* out) {
1436   PrintF(out, "%.16g", Number());
1437 }
1438
1439
1440 void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
1441   // The Windows version of vsnprintf can allocate when printing a %g string
1442   // into a buffer that may not be big enough.  We don't want random memory
1443   // allocation when producing post-crash stack traces, so we print into a
1444   // buffer that is plenty big enough for any floating point number, then
1445   // print that using vsnprintf (which may truncate but never allocate if
1446   // there is no more space in the buffer).
1447   EmbeddedVector<char, 100> buffer;
1448   OS::SNPrintF(buffer, "%.16g", Number());
1449   accumulator->Add("%s", buffer.start());
1450 }
1451
1452
1453 String* JSReceiver::class_name() {
1454   if (IsJSFunction() && IsJSFunctionProxy()) {
1455     return GetHeap()->function_class_symbol();
1456   }
1457   if (map()->constructor()->IsJSFunction()) {
1458     JSFunction* constructor = JSFunction::cast(map()->constructor());
1459     return String::cast(constructor->shared()->instance_class_name());
1460   }
1461   // If the constructor is not present, return "Object".
1462   return GetHeap()->Object_symbol();
1463 }
1464
1465
1466 String* JSReceiver::constructor_name() {
1467   if (map()->constructor()->IsJSFunction()) {
1468     JSFunction* constructor = JSFunction::cast(map()->constructor());
1469     String* name = String::cast(constructor->shared()->name());
1470     if (name->length() > 0) return name;
1471     String* inferred_name = constructor->shared()->inferred_name();
1472     if (inferred_name->length() > 0) return inferred_name;
1473     Object* proto = GetPrototype();
1474     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1475   }
1476   // TODO(rossberg): what about proxies?
1477   // If the constructor is not present, return "Object".
1478   return GetHeap()->Object_symbol();
1479 }
1480
1481
1482 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
1483                                                String* name,
1484                                                Object* value) {
1485   int index = new_map->PropertyIndexFor(name);
1486   if (map()->unused_property_fields() == 0) {
1487     ASSERT(map()->unused_property_fields() == 0);
1488     int new_unused = new_map->unused_property_fields();
1489     Object* values;
1490     { MaybeObject* maybe_values =
1491           properties()->CopySize(properties()->length() + new_unused + 1);
1492       if (!maybe_values->ToObject(&values)) return maybe_values;
1493     }
1494     set_properties(FixedArray::cast(values));
1495   }
1496   set_map(new_map);
1497   return FastPropertyAtPut(index, value);
1498 }
1499
1500
1501 static bool IsIdentifier(UnicodeCache* cache,
1502                          unibrow::CharacterStream* buffer) {
1503   // Checks whether the buffer contains an identifier (no escape).
1504   if (!buffer->has_more()) return false;
1505   if (!cache->IsIdentifierStart(buffer->GetNext())) {
1506     return false;
1507   }
1508   while (buffer->has_more()) {
1509     if (!cache->IsIdentifierPart(buffer->GetNext())) {
1510       return false;
1511     }
1512   }
1513   return true;
1514 }
1515
1516
1517 MaybeObject* JSObject::AddFastProperty(String* name,
1518                                        Object* value,
1519                                        PropertyAttributes attributes) {
1520   ASSERT(!IsJSGlobalProxy());
1521
1522   // Normalize the object if the name is an actual string (not the
1523   // hidden symbols) and is not a real identifier.
1524   Isolate* isolate = GetHeap()->isolate();
1525   StringInputBuffer buffer(name);
1526   if (!IsIdentifier(isolate->unicode_cache(), &buffer)
1527       && name != isolate->heap()->hidden_symbol()) {
1528     Object* obj;
1529     { MaybeObject* maybe_obj =
1530           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1531       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1532     }
1533     return AddSlowProperty(name, value, attributes);
1534   }
1535
1536   DescriptorArray* old_descriptors = map()->instance_descriptors();
1537   // Compute the new index for new field.
1538   int index = map()->NextFreePropertyIndex();
1539
1540   // Allocate new instance descriptors with (name, index) added
1541   FieldDescriptor new_field(name, index, attributes);
1542   Object* new_descriptors;
1543   { MaybeObject* maybe_new_descriptors =
1544         old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
1545     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1546       return maybe_new_descriptors;
1547     }
1548   }
1549
1550   // Only allow map transition if the object isn't the global object and there
1551   // is not a transition for the name, or there's a transition for the name but
1552   // it's unrelated to properties.
1553   int descriptor_index = old_descriptors->Search(name);
1554
1555   // Element transitions are stored in the descriptor for property "", which is
1556   // not a identifier and should have forced a switch to slow properties above.
1557   ASSERT(descriptor_index == DescriptorArray::kNotFound ||
1558       old_descriptors->GetType(descriptor_index) != ELEMENTS_TRANSITION);
1559   bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound ||
1560       old_descriptors->GetType(descriptor_index) == ELEMENTS_TRANSITION;
1561   bool allow_map_transition =
1562       can_insert_transition &&
1563       (isolate->context()->global_context()->object_function()->map() != map());
1564
1565   ASSERT(index < map()->inobject_properties() ||
1566          (index - map()->inobject_properties()) < properties()->length() ||
1567          map()->unused_property_fields() == 0);
1568   // Allocate a new map for the object.
1569   Object* r;
1570   { MaybeObject* maybe_r = map()->CopyDropDescriptors();
1571     if (!maybe_r->ToObject(&r)) return maybe_r;
1572   }
1573   Map* new_map = Map::cast(r);
1574   if (allow_map_transition) {
1575     // Allocate new instance descriptors for the old map with map transition.
1576     MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
1577     Object* r;
1578     { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
1579       if (!maybe_r->ToObject(&r)) return maybe_r;
1580     }
1581     old_descriptors = DescriptorArray::cast(r);
1582   }
1583
1584   if (map()->unused_property_fields() == 0) {
1585     if (properties()->length() > MaxFastProperties()) {
1586       Object* obj;
1587       { MaybeObject* maybe_obj =
1588             NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1589         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1590       }
1591       return AddSlowProperty(name, value, attributes);
1592     }
1593     // Make room for the new value
1594     Object* values;
1595     { MaybeObject* maybe_values =
1596           properties()->CopySize(properties()->length() + kFieldsAdded);
1597       if (!maybe_values->ToObject(&values)) return maybe_values;
1598     }
1599     set_properties(FixedArray::cast(values));
1600     new_map->set_unused_property_fields(kFieldsAdded - 1);
1601   } else {
1602     new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
1603   }
1604   // We have now allocated all the necessary objects.
1605   // All the changes can be applied at once, so they are atomic.
1606   map()->set_instance_descriptors(old_descriptors);
1607   new_map->SetBackPointer(map());
1608   new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1609   set_map(new_map);
1610   return FastPropertyAtPut(index, value);
1611 }
1612
1613
1614 MaybeObject* JSObject::AddConstantFunctionProperty(
1615     String* name,
1616     JSFunction* function,
1617     PropertyAttributes attributes) {
1618   // Allocate new instance descriptors with (name, function) added
1619   ConstantFunctionDescriptor d(name, function, attributes);
1620   Object* new_descriptors;
1621   { MaybeObject* maybe_new_descriptors =
1622         map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS);
1623     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1624       return maybe_new_descriptors;
1625     }
1626   }
1627
1628   // Allocate a new map for the object.
1629   Object* new_map;
1630   { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
1631     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1632   }
1633
1634   DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
1635   Map::cast(new_map)->set_instance_descriptors(descriptors);
1636   Map* old_map = map();
1637   set_map(Map::cast(new_map));
1638
1639   // If the old map is the global object map (from new Object()),
1640   // then transitions are not added to it, so we are done.
1641   Heap* heap = GetHeap();
1642   if (old_map == heap->isolate()->context()->global_context()->
1643       object_function()->map()) {
1644     return function;
1645   }
1646
1647   // Do not add CONSTANT_TRANSITIONS to global objects
1648   if (IsGlobalObject()) {
1649     return function;
1650   }
1651
1652   // Add a CONSTANT_TRANSITION descriptor to the old map,
1653   // so future assignments to this property on other objects
1654   // of the same type will create a normal field, not a constant function.
1655   // Don't do this for special properties, with non-trival attributes.
1656   if (attributes != NONE) {
1657     return function;
1658   }
1659   ConstTransitionDescriptor mark(name, Map::cast(new_map));
1660   { MaybeObject* maybe_new_descriptors =
1661         old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS);
1662     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1663       // We have accomplished the main goal, so return success.
1664       return function;
1665     }
1666   }
1667   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1668   Map::cast(new_map)->SetBackPointer(old_map);
1669
1670   return function;
1671 }
1672
1673
1674 // Add property in slow mode
1675 MaybeObject* JSObject::AddSlowProperty(String* name,
1676                                        Object* value,
1677                                        PropertyAttributes attributes) {
1678   ASSERT(!HasFastProperties());
1679   StringDictionary* dict = property_dictionary();
1680   Object* store_value = value;
1681   if (IsGlobalObject()) {
1682     // In case name is an orphaned property reuse the cell.
1683     int entry = dict->FindEntry(name);
1684     if (entry != StringDictionary::kNotFound) {
1685       store_value = dict->ValueAt(entry);
1686       JSGlobalPropertyCell::cast(store_value)->set_value(value);
1687       // Assign an enumeration index to the property and update
1688       // SetNextEnumerationIndex.
1689       int index = dict->NextEnumerationIndex();
1690       PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
1691       dict->SetNextEnumerationIndex(index + 1);
1692       dict->SetEntry(entry, name, store_value, details);
1693       return value;
1694     }
1695     Heap* heap = GetHeap();
1696     { MaybeObject* maybe_store_value =
1697           heap->AllocateJSGlobalPropertyCell(value);
1698       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
1699     }
1700     JSGlobalPropertyCell::cast(store_value)->set_value(value);
1701   }
1702   PropertyDetails details = PropertyDetails(attributes, NORMAL);
1703   Object* result;
1704   { MaybeObject* maybe_result = dict->Add(name, store_value, details);
1705     if (!maybe_result->ToObject(&result)) return maybe_result;
1706   }
1707   if (dict != result) set_properties(StringDictionary::cast(result));
1708   return value;
1709 }
1710
1711
1712 MaybeObject* JSObject::AddProperty(String* name,
1713                                    Object* value,
1714                                    PropertyAttributes attributes,
1715                                    StrictModeFlag strict_mode) {
1716   ASSERT(!IsJSGlobalProxy());
1717   Map* map_of_this = map();
1718   Heap* heap = GetHeap();
1719   if (!map_of_this->is_extensible()) {
1720     if (strict_mode == kNonStrictMode) {
1721       return value;
1722     } else {
1723       Handle<Object> args[1] = {Handle<String>(name)};
1724       return heap->isolate()->Throw(
1725           *FACTORY->NewTypeError("object_not_extensible",
1726                                  HandleVector(args, 1)));
1727     }
1728   }
1729   if (HasFastProperties()) {
1730     // Ensure the descriptor array does not get too big.
1731     if (map_of_this->instance_descriptors()->number_of_descriptors() <
1732         DescriptorArray::kMaxNumberOfDescriptors) {
1733       if (value->IsJSFunction()) {
1734         return AddConstantFunctionProperty(name,
1735                                            JSFunction::cast(value),
1736                                            attributes);
1737       } else {
1738         return AddFastProperty(name, value, attributes);
1739       }
1740     } else {
1741       // Normalize the object to prevent very large instance descriptors.
1742       // This eliminates unwanted N^2 allocation and lookup behavior.
1743       Object* obj;
1744       { MaybeObject* maybe_obj =
1745             NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1746         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1747       }
1748     }
1749   }
1750   return AddSlowProperty(name, value, attributes);
1751 }
1752
1753
1754 MaybeObject* JSObject::SetPropertyPostInterceptor(
1755     String* name,
1756     Object* value,
1757     PropertyAttributes attributes,
1758     StrictModeFlag strict_mode) {
1759   // Check local property, ignore interceptor.
1760   LookupResult result(GetIsolate());
1761   LocalLookupRealNamedProperty(name, &result);
1762   if (result.IsFound()) {
1763     // An existing property, a map transition or a null descriptor was
1764     // found.  Use set property to handle all these cases.
1765     return SetProperty(&result, name, value, attributes, strict_mode);
1766   }
1767   bool found = false;
1768   MaybeObject* result_object;
1769   result_object = SetPropertyWithCallbackSetterInPrototypes(name,
1770                                                             value,
1771                                                             attributes,
1772                                                             &found,
1773                                                             strict_mode);
1774   if (found) return result_object;
1775   // Add a new real property.
1776   return AddProperty(name, value, attributes, strict_mode);
1777 }
1778
1779
1780 MaybeObject* JSObject::ReplaceSlowProperty(String* name,
1781                                            Object* value,
1782                                            PropertyAttributes attributes) {
1783   StringDictionary* dictionary = property_dictionary();
1784   int old_index = dictionary->FindEntry(name);
1785   int new_enumeration_index = 0;  // 0 means "Use the next available index."
1786   if (old_index != -1) {
1787     // All calls to ReplaceSlowProperty have had all transitions removed.
1788     ASSERT(!dictionary->ContainsTransition(old_index));
1789     new_enumeration_index = dictionary->DetailsAt(old_index).index();
1790   }
1791
1792   PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
1793   return SetNormalizedProperty(name, value, new_details);
1794 }
1795
1796
1797 MaybeObject* JSObject::ConvertDescriptorToFieldAndMapTransition(
1798     String* name,
1799     Object* new_value,
1800     PropertyAttributes attributes) {
1801   Map* old_map = map();
1802   Object* result;
1803   { MaybeObject* maybe_result =
1804         ConvertDescriptorToField(name, new_value, attributes);
1805     if (!maybe_result->ToObject(&result)) return maybe_result;
1806   }
1807   // If we get to this point we have succeeded - do not return failure
1808   // after this point.  Later stuff is optional.
1809   if (!HasFastProperties()) {
1810     return result;
1811   }
1812   // Do not add transitions to the map of "new Object()".
1813   if (map() == GetIsolate()->context()->global_context()->
1814       object_function()->map()) {
1815     return result;
1816   }
1817
1818   MapTransitionDescriptor transition(name,
1819                                      map(),
1820                                      attributes);
1821   Object* new_descriptors;
1822   { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()->
1823         CopyInsert(&transition, KEEP_TRANSITIONS);
1824     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
1825       return result;  // Yes, return _result_.
1826     }
1827   }
1828   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1829   map()->SetBackPointer(old_map);
1830   return result;
1831 }
1832
1833
1834 MaybeObject* JSObject::ConvertDescriptorToField(String* name,
1835                                                 Object* new_value,
1836                                                 PropertyAttributes attributes) {
1837   if (map()->unused_property_fields() == 0 &&
1838       properties()->length() > MaxFastProperties()) {
1839     Object* obj;
1840     { MaybeObject* maybe_obj =
1841           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1842       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1843     }
1844     return ReplaceSlowProperty(name, new_value, attributes);
1845   }
1846
1847   int index = map()->NextFreePropertyIndex();
1848   FieldDescriptor new_field(name, index, attributes);
1849   // Make a new DescriptorArray replacing an entry with FieldDescriptor.
1850   Object* descriptors_unchecked;
1851   { MaybeObject* maybe_descriptors_unchecked = map()->instance_descriptors()->
1852                                   CopyInsert(&new_field, REMOVE_TRANSITIONS);
1853     if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
1854       return maybe_descriptors_unchecked;
1855     }
1856   }
1857   DescriptorArray* new_descriptors =
1858       DescriptorArray::cast(descriptors_unchecked);
1859
1860   // Make a new map for the object.
1861   Object* new_map_unchecked;
1862   { MaybeObject* maybe_new_map_unchecked = map()->CopyDropDescriptors();
1863     if (!maybe_new_map_unchecked->ToObject(&new_map_unchecked)) {
1864       return maybe_new_map_unchecked;
1865     }
1866   }
1867   Map* new_map = Map::cast(new_map_unchecked);
1868   new_map->set_instance_descriptors(new_descriptors);
1869
1870   // Make new properties array if necessary.
1871   FixedArray* new_properties = 0;  // Will always be NULL or a valid pointer.
1872   int new_unused_property_fields = map()->unused_property_fields() - 1;
1873   if (map()->unused_property_fields() == 0) {
1874     new_unused_property_fields = kFieldsAdded - 1;
1875     Object* new_properties_object;
1876     { MaybeObject* maybe_new_properties_object =
1877           properties()->CopySize(properties()->length() + kFieldsAdded);
1878       if (!maybe_new_properties_object->ToObject(&new_properties_object)) {
1879         return maybe_new_properties_object;
1880       }
1881     }
1882     new_properties = FixedArray::cast(new_properties_object);
1883   }
1884
1885   // Update pointers to commit changes.
1886   // Object points to the new map.
1887   new_map->set_unused_property_fields(new_unused_property_fields);
1888   set_map(new_map);
1889   if (new_properties) {
1890     set_properties(FixedArray::cast(new_properties));
1891   }
1892   return FastPropertyAtPut(index, new_value);
1893 }
1894
1895
1896
1897 MaybeObject* JSObject::SetPropertyWithInterceptor(
1898     String* name,
1899     Object* value,
1900     PropertyAttributes attributes,
1901     StrictModeFlag strict_mode) {
1902   Isolate* isolate = GetIsolate();
1903   HandleScope scope(isolate);
1904   Handle<JSObject> this_handle(this);
1905   Handle<String> name_handle(name);
1906   Handle<Object> value_handle(value, isolate);
1907   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
1908   if (!interceptor->setter()->IsUndefined()) {
1909     LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name));
1910     CustomArguments args(isolate, interceptor->data(), this, this);
1911     v8::AccessorInfo info(args.end());
1912     v8::NamedPropertySetter setter =
1913         v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
1914     v8::Handle<v8::Value> result;
1915     {
1916       // Leaving JavaScript.
1917       VMState state(isolate, EXTERNAL);
1918       Handle<Object> value_unhole(value->IsTheHole() ?
1919                                   isolate->heap()->undefined_value() :
1920                                   value,
1921                                   isolate);
1922       result = setter(v8::Utils::ToLocal(name_handle),
1923                       v8::Utils::ToLocal(value_unhole),
1924                       info);
1925     }
1926     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1927     if (!result.IsEmpty()) return *value_handle;
1928   }
1929   MaybeObject* raw_result =
1930       this_handle->SetPropertyPostInterceptor(*name_handle,
1931                                               *value_handle,
1932                                               attributes,
1933                                               strict_mode);
1934   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1935   return raw_result;
1936 }
1937
1938
1939 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
1940                                        Handle<String> key,
1941                                        Handle<Object> value,
1942                                        PropertyAttributes attributes,
1943                                        StrictModeFlag strict_mode,
1944                                        bool skip_fallback_interceptor) {
1945   CALL_HEAP_FUNCTION(object->GetIsolate(),
1946                      object->SetProperty(*key, *value, attributes, strict_mode,
1947                                          skip_fallback_interceptor),
1948                      Object);
1949 }
1950
1951
1952 MaybeObject* JSReceiver::SetProperty(String* name,
1953                                      Object* value,
1954                                      PropertyAttributes attributes,
1955                                      StrictModeFlag strict_mode,
1956                                      bool skip_fallback_interceptor) {
1957   LookupResult result(GetIsolate());
1958   LocalLookup(name, &result, skip_fallback_interceptor);
1959   return SetProperty(&result, name, value, attributes, strict_mode);
1960 }
1961
1962
1963 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
1964                                                String* name,
1965                                                Object* value,
1966                                                JSObject* holder,
1967                                                StrictModeFlag strict_mode) {
1968   Isolate* isolate = GetIsolate();
1969   HandleScope scope(isolate);
1970
1971   // We should never get here to initialize a const with the hole
1972   // value since a const declaration would conflict with the setter.
1973   ASSERT(!value->IsTheHole());
1974   Handle<Object> value_handle(value, isolate);
1975
1976   // To accommodate both the old and the new api we switch on the
1977   // data structure used to store the callbacks.  Eventually foreign
1978   // callbacks should be phased out.
1979   if (structure->IsForeign()) {
1980     AccessorDescriptor* callback =
1981         reinterpret_cast<AccessorDescriptor*>(
1982             Foreign::cast(structure)->foreign_address());
1983     MaybeObject* obj = (callback->setter)(this,  value, callback->data);
1984     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1985     if (obj->IsFailure()) return obj;
1986     return *value_handle;
1987   }
1988
1989   if (structure->IsAccessorInfo()) {
1990     // api style callbacks
1991     AccessorInfo* data = AccessorInfo::cast(structure);
1992     Object* call_obj = data->setter();
1993     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
1994     if (call_fun == NULL) return value;
1995     Handle<String> key(name);
1996     LOG(isolate, ApiNamedPropertyAccess("store", this, name));
1997     CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
1998     v8::AccessorInfo info(args.end());
1999     {
2000       // Leaving JavaScript.
2001       VMState state(isolate, EXTERNAL);
2002       call_fun(v8::Utils::ToLocal(key),
2003                v8::Utils::ToLocal(value_handle),
2004                info);
2005     }
2006     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
2007     return *value_handle;
2008   }
2009
2010   if (structure->IsAccessorPair()) {
2011     Object* setter = AccessorPair::cast(structure)->setter();
2012     if (setter->IsSpecFunction()) {
2013       // TODO(rossberg): nicer would be to cast to some JSCallable here...
2014      return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
2015     } else {
2016       if (strict_mode == kNonStrictMode) {
2017         return value;
2018       }
2019       Handle<String> key(name);
2020       Handle<Object> holder_handle(holder, isolate);
2021       Handle<Object> args[2] = { key, holder_handle };
2022       return isolate->Throw(
2023           *isolate->factory()->NewTypeError("no_setter_in_callback",
2024                                             HandleVector(args, 2)));
2025     }
2026   }
2027
2028   UNREACHABLE();
2029   return NULL;
2030 }
2031
2032
2033 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter,
2034                                                       Object* value) {
2035   Isolate* isolate = GetIsolate();
2036   Handle<Object> value_handle(value, isolate);
2037   Handle<JSReceiver> fun(setter, isolate);
2038   Handle<JSReceiver> self(this, isolate);
2039 #ifdef ENABLE_DEBUGGER_SUPPORT
2040   Debug* debug = isolate->debug();
2041   // Handle stepping into a setter if step into is active.
2042   // TODO(rossberg): should this apply to getters that are function proxies?
2043   if (debug->StepInActive() && fun->IsJSFunction()) {
2044     debug->HandleStepIn(
2045         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
2046   }
2047 #endif
2048   bool has_pending_exception;
2049   Handle<Object> argv[] = { value_handle };
2050   Execution::Call(fun, self, ARRAY_SIZE(argv), argv, &has_pending_exception);
2051   // Check for pending exception and return the result.
2052   if (has_pending_exception) return Failure::Exception();
2053   return *value_handle;
2054 }
2055
2056
2057 void JSObject::LookupCallbackSetterInPrototypes(String* name,
2058                                                 LookupResult* result) {
2059   Heap* heap = GetHeap();
2060   for (Object* pt = GetPrototype();
2061        pt != heap->null_value();
2062        pt = pt->GetPrototype()) {
2063     if (pt->IsJSProxy()) {
2064       return result->HandlerResult(JSProxy::cast(pt));
2065     }
2066     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
2067     if (result->IsProperty()) {
2068       if (result->type() == CALLBACKS && !result->IsReadOnly()) return;
2069       // Found non-callback or read-only callback, stop looking.
2070       break;
2071     }
2072   }
2073   result->NotFound();
2074 }
2075
2076
2077 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
2078     uint32_t index,
2079     Object* value,
2080     bool* found,
2081     StrictModeFlag strict_mode) {
2082   Heap* heap = GetHeap();
2083   for (Object* pt = GetPrototype();
2084        pt != heap->null_value();
2085        pt = pt->GetPrototype()) {
2086     if (pt->IsJSProxy()) {
2087       String* name;
2088       MaybeObject* maybe = GetHeap()->Uint32ToString(index);
2089       if (!maybe->To<String>(&name)) {
2090         *found = true;  // Force abort
2091         return maybe;
2092       }
2093       return JSProxy::cast(pt)->SetPropertyWithHandlerIfDefiningSetter(
2094           name, value, NONE, strict_mode, found);
2095     }
2096     if (!JSObject::cast(pt)->HasDictionaryElements()) {
2097       continue;
2098     }
2099     SeededNumberDictionary* dictionary =
2100         JSObject::cast(pt)->element_dictionary();
2101     int entry = dictionary->FindEntry(index);
2102     if (entry != SeededNumberDictionary::kNotFound) {
2103       PropertyDetails details = dictionary->DetailsAt(entry);
2104       if (details.type() == CALLBACKS) {
2105         *found = true;
2106         return SetElementWithCallback(dictionary->ValueAt(entry),
2107                                       index,
2108                                       value,
2109                                       JSObject::cast(pt),
2110                                       strict_mode);
2111       }
2112     }
2113   }
2114   *found = false;
2115   return heap->the_hole_value();
2116 }
2117
2118 MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes(
2119     String* name,
2120     Object* value,
2121     PropertyAttributes attributes,
2122     bool* found,
2123     StrictModeFlag strict_mode) {
2124   Heap* heap = GetHeap();
2125   // We could not find a local property so let's check whether there is an
2126   // accessor that wants to handle the property.
2127   LookupResult accessor_result(heap->isolate());
2128   LookupCallbackSetterInPrototypes(name, &accessor_result);
2129   if (accessor_result.IsFound()) {
2130     *found = true;
2131     if (accessor_result.type() == CALLBACKS) {
2132       return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
2133                                      name,
2134                                      value,
2135                                      accessor_result.holder(),
2136                                      strict_mode);
2137     } else if (accessor_result.type() == HANDLER) {
2138       // There is a proxy in the prototype chain. Invoke its
2139       // getPropertyDescriptor trap.
2140       bool found = false;
2141       // SetPropertyWithHandlerIfDefiningSetter can cause GC,
2142       // make sure to use the handlified references after calling
2143       // the function.
2144       Handle<JSObject> self(this);
2145       Handle<String> hname(name);
2146       Handle<Object> hvalue(value);
2147       MaybeObject* result =
2148           accessor_result.proxy()->SetPropertyWithHandlerIfDefiningSetter(
2149               name, value, attributes, strict_mode, &found);
2150       if (found) return result;
2151       // The proxy does not define the property as an accessor.
2152       // Consequently, it has no effect on setting the receiver.
2153       return self->AddProperty(*hname, *hvalue, attributes, strict_mode);
2154     }
2155   }
2156   *found = false;
2157   return heap->the_hole_value();
2158 }
2159
2160
2161 void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
2162   DescriptorArray* descriptors = map()->instance_descriptors();
2163   int number = descriptors->SearchWithCache(name);
2164   if (number != DescriptorArray::kNotFound) {
2165     result->DescriptorResult(this, descriptors->GetDetails(number), number);
2166   } else {
2167     result->NotFound();
2168   }
2169 }
2170
2171
2172 void Map::LookupInDescriptors(JSObject* holder,
2173                               String* name,
2174                               LookupResult* result) {
2175   DescriptorArray* descriptors = instance_descriptors();
2176   DescriptorLookupCache* cache =
2177       GetHeap()->isolate()->descriptor_lookup_cache();
2178   int number = cache->Lookup(descriptors, name);
2179   if (number == DescriptorLookupCache::kAbsent) {
2180     number = descriptors->Search(name);
2181     cache->Update(descriptors, name, number);
2182   }
2183   if (number != DescriptorArray::kNotFound) {
2184     result->DescriptorResult(holder, descriptors->GetDetails(number), number);
2185   } else {
2186     result->NotFound();
2187   }
2188 }
2189
2190
2191 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
2192   ASSERT(!map.is_null());
2193   for (int i = 0; i < maps->length(); ++i) {
2194     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
2195   }
2196   return false;
2197 }
2198
2199
2200 template <class T>
2201 static Handle<T> MaybeNull(T* p) {
2202   if (p == NULL) return Handle<T>::null();
2203   return Handle<T>(p);
2204 }
2205
2206
2207 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
2208   ElementsKind elms_kind = elements_kind();
2209   if (elms_kind == FAST_DOUBLE_ELEMENTS) {
2210     bool dummy = true;
2211     Handle<Map> fast_map =
2212         MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy));
2213     if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
2214       return fast_map;
2215     }
2216     return Handle<Map>::null();
2217   }
2218   if (elms_kind == FAST_SMI_ONLY_ELEMENTS) {
2219     bool dummy = true;
2220     Handle<Map> double_map =
2221         MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy));
2222     // In the current implementation, if the DOUBLE map doesn't exist, the
2223     // FAST map can't exist either.
2224     if (double_map.is_null()) return Handle<Map>::null();
2225     Handle<Map> fast_map =
2226         MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
2227                                                           &dummy));
2228     if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
2229       return fast_map;
2230     }
2231     if (ContainsMap(candidates, double_map)) return double_map;
2232   }
2233   return Handle<Map>::null();
2234 }
2235
2236 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents,
2237                                                    ElementsKind elements_kind) {
2238   if (descriptor_contents->IsMap()) {
2239     Map* map = Map::cast(descriptor_contents);
2240     if (map->elements_kind() == elements_kind) {
2241       return map;
2242     }
2243     return NULL;
2244   }
2245
2246   FixedArray* map_array = FixedArray::cast(descriptor_contents);
2247   for (int i = 0; i < map_array->length(); ++i) {
2248     Object* current = map_array->get(i);
2249     // Skip undefined slots, they are sentinels for reclaimed maps.
2250     if (!current->IsUndefined()) {
2251       Map* current_map = Map::cast(map_array->get(i));
2252       if (current_map->elements_kind() == elements_kind) {
2253         return current_map;
2254       }
2255     }
2256   }
2257
2258   return NULL;
2259 }
2260
2261
2262 static MaybeObject* AddElementsTransitionMapToDescriptor(
2263     Object* descriptor_contents,
2264     Map* new_map) {
2265   // Nothing was in the descriptor for an ELEMENTS_TRANSITION,
2266   // simply add the map.
2267   if (descriptor_contents == NULL) {
2268     return new_map;
2269   }
2270
2271   // There was already a map in the descriptor, create a 2-element FixedArray
2272   // to contain the existing map plus the new one.
2273   FixedArray* new_array;
2274   Heap* heap = new_map->GetHeap();
2275   if (descriptor_contents->IsMap()) {
2276     // Must tenure, DescriptorArray expects no new-space objects.
2277     MaybeObject* maybe_new_array = heap->AllocateFixedArray(2, TENURED);
2278     if (!maybe_new_array->To<FixedArray>(&new_array)) {
2279       return maybe_new_array;
2280     }
2281     new_array->set(0, descriptor_contents);
2282     new_array->set(1, new_map);
2283     return new_array;
2284   }
2285
2286   // The descriptor already contained a list of maps for different ElementKinds
2287   // of ELEMENTS_TRANSITION, first check the existing array for an undefined
2288   // slot, and if that's not available, create a FixedArray to hold the existing
2289   // maps plus the new one and fill it in.
2290   FixedArray* array = FixedArray::cast(descriptor_contents);
2291   for (int i = 0; i < array->length(); ++i) {
2292     if (array->get(i)->IsUndefined()) {
2293       array->set(i, new_map);
2294       return array;
2295     }
2296   }
2297
2298   // Must tenure, DescriptorArray expects no new-space objects.
2299   MaybeObject* maybe_new_array =
2300       heap->AllocateFixedArray(array->length() + 1, TENURED);
2301   if (!maybe_new_array->To<FixedArray>(&new_array)) {
2302     return maybe_new_array;
2303   }
2304   int i = 0;
2305   while (i < array->length()) {
2306     new_array->set(i, array->get(i));
2307     ++i;
2308   }
2309   new_array->set(i, new_map);
2310   return new_array;
2311 }
2312
2313
2314 String* Map::elements_transition_sentinel_name() {
2315   return GetHeap()->empty_symbol();
2316 }
2317
2318
2319 Object* Map::GetDescriptorContents(String* sentinel_name,
2320                                    bool* safe_to_add_transition) {
2321   // Get the cached index for the descriptors lookup, or find and cache it.
2322   DescriptorArray* descriptors = instance_descriptors();
2323   DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
2324   int index = cache->Lookup(descriptors, sentinel_name);
2325   if (index == DescriptorLookupCache::kAbsent) {
2326     index = descriptors->Search(sentinel_name);
2327     cache->Update(descriptors, sentinel_name, index);
2328   }
2329   // If the transition already exists, return its descriptor.
2330   if (index != DescriptorArray::kNotFound) {
2331     PropertyDetails details = descriptors->GetDetails(index);
2332     if (details.type() == ELEMENTS_TRANSITION) {
2333       return descriptors->GetValue(index);
2334     } else {
2335       if (safe_to_add_transition != NULL) {
2336         *safe_to_add_transition = false;
2337       }
2338     }
2339   }
2340   return NULL;
2341 }
2342
2343
2344 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind,
2345                                       bool* safe_to_add_transition) {
2346   // Special case: indirect SMI->FAST transition (cf. comment in
2347   // AddElementsTransition()).
2348   if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2349       elements_kind == FAST_ELEMENTS) {
2350     Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
2351                                                         safe_to_add_transition);
2352     if (double_map == NULL) return double_map;
2353     return double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
2354                                                    safe_to_add_transition);
2355   }
2356   Object* descriptor_contents = GetDescriptorContents(
2357       elements_transition_sentinel_name(), safe_to_add_transition);
2358   if (descriptor_contents != NULL) {
2359     Map* maybe_transition_map =
2360         GetElementsTransitionMapFromDescriptor(descriptor_contents,
2361                                                elements_kind);
2362     ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap());
2363     return maybe_transition_map;
2364   }
2365   return NULL;
2366 }
2367
2368
2369 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind,
2370                                         Map* transitioned_map) {
2371   // The map transition graph should be a tree, therefore the transition
2372   // from SMI to FAST elements is not done directly, but by going through
2373   // DOUBLE elements first.
2374   if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2375       elements_kind == FAST_ELEMENTS) {
2376     bool safe_to_add = true;
2377     Map* double_map = this->LookupElementsTransitionMap(
2378         FAST_DOUBLE_ELEMENTS, &safe_to_add);
2379     // This method is only called when safe_to_add_transition has been found
2380     // to be true earlier.
2381     ASSERT(safe_to_add);
2382
2383     if (double_map == NULL) {
2384       MaybeObject* maybe_map = this->CopyDropTransitions();
2385       if (!maybe_map->To(&double_map)) return maybe_map;
2386       double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
2387       MaybeObject* maybe_double_transition = this->AddElementsTransition(
2388           FAST_DOUBLE_ELEMENTS, double_map);
2389       if (maybe_double_transition->IsFailure()) return maybe_double_transition;
2390     }
2391     return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map);
2392   }
2393
2394   bool safe_to_add_transition = true;
2395   Object* descriptor_contents = GetDescriptorContents(
2396       elements_transition_sentinel_name(), &safe_to_add_transition);
2397   // This method is only called when safe_to_add_transition has been found
2398   // to be true earlier.
2399   ASSERT(safe_to_add_transition);
2400   MaybeObject* maybe_new_contents =
2401       AddElementsTransitionMapToDescriptor(descriptor_contents,
2402                                            transitioned_map);
2403   Object* new_contents;
2404   if (!maybe_new_contents->ToObject(&new_contents)) {
2405     return maybe_new_contents;
2406   }
2407
2408   ElementsTransitionDescriptor desc(elements_transition_sentinel_name(),
2409                                     new_contents);
2410   Object* new_descriptors;
2411   MaybeObject* maybe_new_descriptors =
2412       instance_descriptors()->CopyInsert(&desc, KEEP_TRANSITIONS);
2413   if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
2414     return maybe_new_descriptors;
2415   }
2416   set_instance_descriptors(DescriptorArray::cast(new_descriptors));
2417   transitioned_map->SetBackPointer(this);
2418   return this;
2419 }
2420
2421
2422 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
2423                                                ElementsKind to_kind) {
2424   Isolate* isolate = object->GetIsolate();
2425   CALL_HEAP_FUNCTION(isolate,
2426                      object->GetElementsTransitionMap(isolate, to_kind),
2427                      Map);
2428 }
2429
2430
2431 MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
2432   Map* current_map = map();
2433   ElementsKind from_kind = current_map->elements_kind();
2434
2435   if (from_kind == to_kind) return current_map;
2436
2437   // Only objects with FastProperties can have DescriptorArrays and can track
2438   // element-related maps. Also don't add descriptors to maps that are shared.
2439   bool safe_to_add_transition = HasFastProperties() &&
2440       !current_map->IsUndefined() &&
2441       !current_map->is_shared();
2442
2443   // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects
2444   // with elements that switch back and forth between dictionary and fast
2445   // element mode.
2446   if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) {
2447     safe_to_add_transition = false;
2448   }
2449
2450   if (safe_to_add_transition) {
2451     // It's only safe to manipulate the descriptor array if it would be
2452     // safe to add a transition.
2453     Map* maybe_transition_map = current_map->LookupElementsTransitionMap(
2454         to_kind, &safe_to_add_transition);
2455     if (maybe_transition_map != NULL) {
2456       return maybe_transition_map;
2457     }
2458   }
2459
2460   Map* new_map = NULL;
2461
2462   // No transition to an existing map for the given ElementsKind. Make a new
2463   // one.
2464   { MaybeObject* maybe_map = current_map->CopyDropTransitions();
2465     if (!maybe_map->To(&new_map)) return maybe_map;
2466   }
2467
2468   new_map->set_elements_kind(to_kind);
2469
2470   // Only remember the map transition if the object's map is NOT equal to the
2471   // global object_function's map and there is not an already existing
2472   // non-matching element transition.
2473   Context* global_context = GetIsolate()->context()->global_context();
2474   bool allow_map_transition = safe_to_add_transition &&
2475       (global_context->object_function()->map() != map());
2476   if (allow_map_transition) {
2477     MaybeObject* maybe_transition =
2478         current_map->AddElementsTransition(to_kind, new_map);
2479     if (maybe_transition->IsFailure()) return maybe_transition;
2480   }
2481   return new_map;
2482 }
2483
2484
2485 void JSObject::LocalLookupRealNamedProperty(String* name,
2486                                             LookupResult* result) {
2487   if (IsJSGlobalProxy()) {
2488     Object* proto = GetPrototype();
2489     if (proto->IsNull()) return result->NotFound();
2490     ASSERT(proto->IsJSGlobalObject());
2491     // A GlobalProxy's prototype should always be a proper JSObject.
2492     return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
2493   }
2494
2495   if (HasFastProperties()) {
2496     LookupInDescriptor(name, result);
2497     if (result->IsFound()) {
2498       // A property, a map transition or a null descriptor was found.
2499       // We return all of these result types because
2500       // LocalLookupRealNamedProperty is used when setting properties
2501       // where map transitions and null descriptors are handled.
2502       ASSERT(result->holder() == this && result->type() != NORMAL);
2503       // Disallow caching for uninitialized constants. These can only
2504       // occur as fields.
2505       if (result->IsReadOnly() && result->type() == FIELD &&
2506           FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
2507         result->DisallowCaching();
2508       }
2509       return;
2510     }
2511   } else {
2512     int entry = property_dictionary()->FindEntry(name);
2513     if (entry != StringDictionary::kNotFound) {
2514       Object* value = property_dictionary()->ValueAt(entry);
2515       if (IsGlobalObject()) {
2516         PropertyDetails d = property_dictionary()->DetailsAt(entry);
2517         if (d.IsDeleted()) {
2518           result->NotFound();
2519           return;
2520         }
2521         value = JSGlobalPropertyCell::cast(value)->value();
2522       }
2523       // Make sure to disallow caching for uninitialized constants
2524       // found in the dictionary-mode objects.
2525       if (value->IsTheHole()) result->DisallowCaching();
2526       result->DictionaryResult(this, entry);
2527       return;
2528     }
2529   }
2530   result->NotFound();
2531 }
2532
2533
2534 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
2535   LocalLookupRealNamedProperty(name, result);
2536   if (result->IsProperty()) return;
2537
2538   LookupRealNamedPropertyInPrototypes(name, result);
2539 }
2540
2541
2542 void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
2543                                                    LookupResult* result) {
2544   Heap* heap = GetHeap();
2545   for (Object* pt = GetPrototype();
2546        pt != heap->null_value();
2547        pt = JSObject::cast(pt)->GetPrototype()) {
2548     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
2549     if (result->IsProperty() && (result->type() != INTERCEPTOR)) return;
2550   }
2551   result->NotFound();
2552 }
2553
2554
2555 // We only need to deal with CALLBACKS and INTERCEPTORS
2556 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
2557     LookupResult* result,
2558     String* name,
2559     Object* value,
2560     bool check_prototype,
2561     StrictModeFlag strict_mode) {
2562   if (check_prototype && !result->IsProperty()) {
2563     LookupCallbackSetterInPrototypes(name, result);
2564   }
2565
2566   if (result->IsProperty()) {
2567     if (!result->IsReadOnly()) {
2568       switch (result->type()) {
2569         case CALLBACKS: {
2570           Object* obj = result->GetCallbackObject();
2571           if (obj->IsAccessorInfo()) {
2572             AccessorInfo* info = AccessorInfo::cast(obj);
2573             if (info->all_can_write()) {
2574               return SetPropertyWithCallback(result->GetCallbackObject(),
2575                                              name,
2576                                              value,
2577                                              result->holder(),
2578                                              strict_mode);
2579             }
2580           }
2581           break;
2582         }
2583         case INTERCEPTOR: {
2584           // Try lookup real named properties. Note that only property can be
2585           // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
2586           LookupResult r(GetIsolate());
2587           LookupRealNamedProperty(name, &r);
2588           if (r.IsProperty()) {
2589             return SetPropertyWithFailedAccessCheck(&r,
2590                                                     name,
2591                                                     value,
2592                                                     check_prototype,
2593                                                     strict_mode);
2594           }
2595           break;
2596         }
2597         default: {
2598           break;
2599         }
2600       }
2601     }
2602   }
2603
2604   Isolate* isolate = GetIsolate();
2605   HandleScope scope(isolate);
2606   Handle<Object> value_handle(value);
2607   isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
2608   return *value_handle;
2609 }
2610
2611
2612 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
2613                                      String* key,
2614                                      Object* value,
2615                                      PropertyAttributes attributes,
2616                                      StrictModeFlag strict_mode) {
2617   if (result->IsFound() && result->type() == HANDLER) {
2618     return result->proxy()->SetPropertyWithHandler(
2619         key, value, attributes, strict_mode);
2620   } else {
2621     return JSObject::cast(this)->SetPropertyForResult(
2622         result, key, value, attributes, strict_mode);
2623   }
2624 }
2625
2626
2627 bool JSProxy::HasPropertyWithHandler(String* name_raw) {
2628   Isolate* isolate = GetIsolate();
2629   HandleScope scope(isolate);
2630   Handle<Object> receiver(this);
2631   Handle<Object> name(name_raw);
2632
2633   Handle<Object> args[] = { name };
2634   Handle<Object> result = CallTrap(
2635     "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
2636   if (isolate->has_pending_exception()) return Failure::Exception();
2637
2638   return result->ToBoolean()->IsTrue();
2639 }
2640
2641
2642 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
2643     String* name_raw,
2644     Object* value_raw,
2645     PropertyAttributes attributes,
2646     StrictModeFlag strict_mode) {
2647   Isolate* isolate = GetIsolate();
2648   HandleScope scope(isolate);
2649   Handle<Object> receiver(this);
2650   Handle<Object> name(name_raw);
2651   Handle<Object> value(value_raw);
2652
2653   Handle<Object> args[] = { receiver, name, value };
2654   CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
2655   if (isolate->has_pending_exception()) return Failure::Exception();
2656
2657   return *value;
2658 }
2659
2660
2661 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandlerIfDefiningSetter(
2662     String* name_raw,
2663     Object* value_raw,
2664     PropertyAttributes attributes,
2665     StrictModeFlag strict_mode,
2666     bool* found) {
2667   *found = true;  // except where defined otherwise...
2668   Isolate* isolate = GetHeap()->isolate();
2669   Handle<JSProxy> proxy(this);
2670   Handle<Object> handler(this->handler());  // Trap might morph proxy.
2671   Handle<String> name(name_raw);
2672   Handle<Object> value(value_raw);
2673   Handle<Object> args[] = { name };
2674   Handle<Object> result = proxy->CallTrap(
2675       "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2676   if (isolate->has_pending_exception()) return Failure::Exception();
2677
2678   if (!result->IsUndefined()) {
2679     // The proxy handler cares about this property.
2680     // Check whether it is virtualized as an accessor.
2681     // Emulate [[GetProperty]] semantics for proxies.
2682     bool has_pending_exception;
2683     Handle<Object> argv[] = { result };
2684     Handle<Object> desc =
2685         Execution::Call(isolate->to_complete_property_descriptor(), result,
2686                         ARRAY_SIZE(argv), argv, &has_pending_exception);
2687     if (has_pending_exception) return Failure::Exception();
2688
2689     Handle<String> conf_name =
2690         isolate->factory()->LookupAsciiSymbol("configurable_");
2691     Handle<Object> configurable(v8::internal::GetProperty(desc, conf_name));
2692     ASSERT(!isolate->has_pending_exception());
2693     if (configurable->IsFalse()) {
2694       Handle<String> trap =
2695           isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2696       Handle<Object> args[] = { handler, trap, name };
2697       Handle<Object> error = isolate->factory()->NewTypeError(
2698           "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2699       return isolate->Throw(*error);
2700     }
2701     ASSERT(configurable->IsTrue());
2702
2703     // Check for AccessorDescriptor.
2704     Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_");
2705     Handle<Object> setter(v8::internal::GetProperty(desc, set_name));
2706     ASSERT(!isolate->has_pending_exception());
2707     if (!setter->IsUndefined()) {
2708       // We have a setter -- invoke it.
2709       // TODO(rossberg): nicer would be to cast to some JSCallable here...
2710       return proxy->SetPropertyWithDefinedSetter(
2711           JSReceiver::cast(*setter), *value);
2712     } else {
2713       Handle<String> get_name = isolate->factory()->LookupAsciiSymbol("get_");
2714       Handle<Object> getter(v8::internal::GetProperty(desc, get_name));
2715       ASSERT(!isolate->has_pending_exception());
2716       if (!getter->IsUndefined()) {
2717         // We have a getter but no setter -- the property may not be
2718         // written. In strict mode, throw an error.
2719         if (strict_mode == kNonStrictMode) return *value;
2720         Handle<Object> args[] = { name, proxy };
2721         Handle<Object> error = isolate->factory()->NewTypeError(
2722             "no_setter_in_callback", HandleVector(args, ARRAY_SIZE(args)));
2723         return isolate->Throw(*error);
2724       }
2725     }
2726     // Fall-through.
2727   }
2728
2729   // The proxy does not define the property as an accessor.
2730   *found = false;
2731   return *value;
2732 }
2733
2734
2735 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
2736     String* name_raw, DeleteMode mode) {
2737   Isolate* isolate = GetIsolate();
2738   HandleScope scope(isolate);
2739   Handle<Object> receiver(this);
2740   Handle<Object> name(name_raw);
2741
2742   Handle<Object> args[] = { name };
2743   Handle<Object> result = CallTrap(
2744     "delete", Handle<Object>(), ARRAY_SIZE(args), args);
2745   if (isolate->has_pending_exception()) return Failure::Exception();
2746
2747   Object* bool_result = result->ToBoolean();
2748   if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
2749     Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
2750     Handle<Object> args[] = { Handle<Object>(handler()), trap_name };
2751     Handle<Object> error = isolate->factory()->NewTypeError(
2752         "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
2753     isolate->Throw(*error);
2754     return Failure::Exception();
2755   }
2756   return bool_result;
2757 }
2758
2759
2760 MUST_USE_RESULT MaybeObject* JSProxy::DeleteElementWithHandler(
2761     uint32_t index,
2762     DeleteMode mode) {
2763   Isolate* isolate = GetIsolate();
2764   HandleScope scope(isolate);
2765   Handle<String> name = isolate->factory()->Uint32ToString(index);
2766   return JSProxy::DeletePropertyWithHandler(*name, mode);
2767 }
2768
2769
2770 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
2771     JSReceiver* receiver_raw,
2772     String* name_raw) {
2773   Isolate* isolate = GetIsolate();
2774   HandleScope scope(isolate);
2775   Handle<JSProxy> proxy(this);
2776   Handle<Object> handler(this->handler());  // Trap might morph proxy.
2777   Handle<JSReceiver> receiver(receiver_raw);
2778   Handle<Object> name(name_raw);
2779
2780   Handle<Object> args[] = { name };
2781   Handle<Object> result = CallTrap(
2782     "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2783   if (isolate->has_pending_exception()) return NONE;
2784
2785   if (result->IsUndefined()) return ABSENT;
2786
2787   bool has_pending_exception;
2788   Handle<Object> argv[] = { result };
2789   Handle<Object> desc =
2790       Execution::Call(isolate->to_complete_property_descriptor(), result,
2791                       ARRAY_SIZE(argv), argv, &has_pending_exception);
2792   if (has_pending_exception) return NONE;
2793
2794   // Convert result to PropertyAttributes.
2795   Handle<String> enum_n = isolate->factory()->LookupAsciiSymbol("enumerable");
2796   Handle<Object> enumerable(v8::internal::GetProperty(desc, enum_n));
2797   if (isolate->has_pending_exception()) return NONE;
2798   Handle<String> conf_n = isolate->factory()->LookupAsciiSymbol("configurable");
2799   Handle<Object> configurable(v8::internal::GetProperty(desc, conf_n));
2800   if (isolate->has_pending_exception()) return NONE;
2801   Handle<String> writ_n = isolate->factory()->LookupAsciiSymbol("writable");
2802   Handle<Object> writable(v8::internal::GetProperty(desc, writ_n));
2803   if (isolate->has_pending_exception()) return NONE;
2804
2805   if (configurable->IsFalse()) {
2806     Handle<String> trap =
2807         isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2808     Handle<Object> args[] = { handler, trap, name };
2809     Handle<Object> error = isolate->factory()->NewTypeError(
2810         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2811     isolate->Throw(*error);
2812     return NONE;
2813   }
2814
2815   int attributes = NONE;
2816   if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM;
2817   if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE;
2818   if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY;
2819   return static_cast<PropertyAttributes>(attributes);
2820 }
2821
2822
2823 MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler(
2824     JSReceiver* receiver,
2825     uint32_t index) {
2826   Isolate* isolate = GetIsolate();
2827   HandleScope scope(isolate);
2828   Handle<String> name = isolate->factory()->Uint32ToString(index);
2829   return GetPropertyAttributeWithHandler(receiver, *name);
2830 }
2831
2832
2833 void JSProxy::Fix() {
2834   Isolate* isolate = GetIsolate();
2835   HandleScope scope(isolate);
2836   Handle<JSProxy> self(this);
2837
2838   // Save identity hash.
2839   MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
2840
2841   if (IsJSFunctionProxy()) {
2842     isolate->factory()->BecomeJSFunction(self);
2843     // Code will be set on the JavaScript side.
2844   } else {
2845     isolate->factory()->BecomeJSObject(self);
2846   }
2847   ASSERT(self->IsJSObject());
2848
2849   // Inherit identity, if it was present.
2850   Object* hash;
2851   if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
2852     Handle<JSObject> new_self(JSObject::cast(*self));
2853     isolate->factory()->SetIdentityHash(new_self, hash);
2854   }
2855 }
2856
2857
2858 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
2859                                                  Handle<Object> derived,
2860                                                  int argc,
2861                                                  Handle<Object> argv[]) {
2862   Isolate* isolate = GetIsolate();
2863   Handle<Object> handler(this->handler());
2864
2865   Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol(name);
2866   Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2867   if (isolate->has_pending_exception()) return trap;
2868
2869   if (trap->IsUndefined()) {
2870     if (derived.is_null()) {
2871       Handle<Object> args[] = { handler, trap_name };
2872       Handle<Object> error = isolate->factory()->NewTypeError(
2873         "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2874       isolate->Throw(*error);
2875       return Handle<Object>();
2876     }
2877     trap = Handle<Object>(derived);
2878   }
2879
2880   bool threw;
2881   return Execution::Call(trap, handler, argc, argv, &threw);
2882 }
2883
2884
2885 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
2886                                             String* name,
2887                                             Object* value,
2888                                             PropertyAttributes attributes,
2889                                             StrictModeFlag strict_mode) {
2890   Heap* heap = GetHeap();
2891   // Make sure that the top context does not change when doing callbacks or
2892   // interceptor calls.
2893   AssertNoContextChange ncc;
2894
2895   // Optimization for 2-byte strings often used as keys in a decompression
2896   // dictionary.  We make these short keys into symbols to avoid constantly
2897   // reallocating them.
2898   if (!name->IsSymbol() && name->length() <= 2) {
2899     Object* symbol_version;
2900     { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
2901       if (maybe_symbol_version->ToObject(&symbol_version)) {
2902         name = String::cast(symbol_version);
2903       }
2904     }
2905   }
2906
2907   // Check access rights if needed.
2908   if (IsAccessCheckNeeded()) {
2909     if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
2910       return SetPropertyWithFailedAccessCheck(
2911           result, name, value, true, strict_mode);
2912     }
2913   }
2914
2915   if (IsJSGlobalProxy()) {
2916     Object* proto = GetPrototype();
2917     if (proto->IsNull()) return value;
2918     ASSERT(proto->IsJSGlobalObject());
2919     return JSObject::cast(proto)->SetPropertyForResult(
2920         result, name, value, attributes, strict_mode);
2921   }
2922
2923   if (!result->IsProperty() && !IsJSContextExtensionObject()) {
2924     bool found = false;
2925     MaybeObject* result_object;
2926     result_object = SetPropertyWithCallbackSetterInPrototypes(name,
2927                                                               value,
2928                                                               attributes,
2929                                                               &found,
2930                                                               strict_mode);
2931     if (found) return result_object;
2932   }
2933
2934   // At this point, no GC should have happened, as this would invalidate
2935   // 'result', which we cannot handlify!
2936
2937   if (!result->IsFound()) {
2938     // Neither properties nor transitions found.
2939     return AddProperty(name, value, attributes, strict_mode);
2940   }
2941   if (result->IsReadOnly() && result->IsProperty()) {
2942     if (strict_mode == kStrictMode) {
2943       Handle<JSObject> self(this);
2944       Handle<String> hname(name);
2945       Handle<Object> args[] = { hname, self };
2946       return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
2947           "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2948     } else {
2949       return value;
2950     }
2951   }
2952   // This is a real property that is not read-only, or it is a
2953   // transition or null descriptor and there are no setters in the prototypes.
2954   switch (result->type()) {
2955     case NORMAL:
2956       return SetNormalizedProperty(result, value);
2957     case FIELD:
2958       return FastPropertyAtPut(result->GetFieldIndex(), value);
2959     case MAP_TRANSITION:
2960       if (attributes == result->GetAttributes()) {
2961         // Only use map transition if the attributes match.
2962         return AddFastPropertyUsingMap(result->GetTransitionMap(),
2963                                        name,
2964                                        value);
2965       }
2966       return ConvertDescriptorToField(name, value, attributes);
2967     case CONSTANT_FUNCTION:
2968       // Only replace the function if necessary.
2969       if (value == result->GetConstantFunction()) return value;
2970       // Preserve the attributes of this existing property.
2971       attributes = result->GetAttributes();
2972       return ConvertDescriptorToField(name, value, attributes);
2973     case CALLBACKS:
2974       return SetPropertyWithCallback(result->GetCallbackObject(),
2975                                      name,
2976                                      value,
2977                                      result->holder(),
2978                                      strict_mode);
2979     case INTERCEPTOR:
2980       return SetPropertyWithInterceptor(name, value, attributes, strict_mode);
2981     case CONSTANT_TRANSITION: {
2982       // If the same constant function is being added we can simply
2983       // transition to the target map.
2984       Map* target_map = result->GetTransitionMap();
2985       DescriptorArray* target_descriptors = target_map->instance_descriptors();
2986       int number = target_descriptors->SearchWithCache(name);
2987       ASSERT(number != DescriptorArray::kNotFound);
2988       ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
2989       JSFunction* function =
2990           JSFunction::cast(target_descriptors->GetValue(number));
2991       if (value == function) {
2992         set_map(target_map);
2993         return value;
2994       }
2995       // Otherwise, replace with a MAP_TRANSITION to a new map with a
2996       // FIELD, even if the value is a constant function.
2997       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
2998     }
2999     case NULL_DESCRIPTOR:
3000     case ELEMENTS_TRANSITION:
3001       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3002     case HANDLER:
3003       UNREACHABLE();
3004       return value;
3005   }
3006   UNREACHABLE();  // keep the compiler happy
3007   return value;
3008 }
3009
3010
3011 // Set a real local property, even if it is READ_ONLY.  If the property is not
3012 // present, add it with attributes NONE.  This code is an exact clone of
3013 // SetProperty, with the check for IsReadOnly and the check for a
3014 // callback setter removed.  The two lines looking up the LookupResult
3015 // result are also added.  If one of the functions is changed, the other
3016 // should be.
3017 // Note that this method cannot be used to set the prototype of a function
3018 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
3019 // doesn't handle function prototypes correctly.
3020 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
3021     Handle<JSObject> object,
3022     Handle<String> key,
3023     Handle<Object> value,
3024     PropertyAttributes attributes) {
3025   CALL_HEAP_FUNCTION(
3026     object->GetIsolate(),
3027     object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
3028     Object);
3029 }
3030
3031
3032 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
3033     String* name,
3034     Object* value,
3035     PropertyAttributes attributes) {
3036   // Make sure that the top context does not change when doing callbacks or
3037   // interceptor calls.
3038   AssertNoContextChange ncc;
3039   Isolate* isolate = GetIsolate();
3040   LookupResult result(isolate);
3041   LocalLookup(name, &result);
3042   // Check access rights if needed.
3043   if (IsAccessCheckNeeded()) {
3044     if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
3045       return SetPropertyWithFailedAccessCheck(&result,
3046                                               name,
3047                                               value,
3048                                               false,
3049                                               kNonStrictMode);
3050     }
3051   }
3052
3053   if (IsJSGlobalProxy()) {
3054     Object* proto = GetPrototype();
3055     if (proto->IsNull()) return value;
3056     ASSERT(proto->IsJSGlobalObject());
3057     return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
3058         name,
3059         value,
3060         attributes);
3061   }
3062
3063   // Check for accessor in prototype chain removed here in clone.
3064   if (!result.IsFound()) {
3065     // Neither properties nor transitions found.
3066     return AddProperty(name, value, attributes, kNonStrictMode);
3067   }
3068
3069   PropertyDetails details = PropertyDetails(attributes, NORMAL);
3070
3071   // Check of IsReadOnly removed from here in clone.
3072   switch (result.type()) {
3073     case NORMAL:
3074       return SetNormalizedProperty(name, value, details);
3075     case FIELD:
3076       return FastPropertyAtPut(result.GetFieldIndex(), value);
3077     case MAP_TRANSITION:
3078       if (attributes == result.GetAttributes()) {
3079         // Only use map transition if the attributes match.
3080         return AddFastPropertyUsingMap(result.GetTransitionMap(),
3081                                        name,
3082                                        value);
3083       }
3084       return ConvertDescriptorToField(name, value, attributes);
3085     case CONSTANT_FUNCTION:
3086       // Only replace the function if necessary.
3087       if (value == result.GetConstantFunction()) return value;
3088       // Preserve the attributes of this existing property.
3089       attributes = result.GetAttributes();
3090       return ConvertDescriptorToField(name, value, attributes);
3091     case CALLBACKS:
3092     case INTERCEPTOR:
3093       // Override callback in clone
3094       return ConvertDescriptorToField(name, value, attributes);
3095     case CONSTANT_TRANSITION:
3096       // Replace with a MAP_TRANSITION to a new map with a FIELD, even
3097       // if the value is a function.
3098       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3099     case NULL_DESCRIPTOR:
3100     case ELEMENTS_TRANSITION:
3101       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3102     case HANDLER:
3103       UNREACHABLE();
3104   }
3105   UNREACHABLE();  // keep the compiler happy
3106   return value;
3107 }
3108
3109
3110 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
3111       JSObject* receiver,
3112       String* name,
3113       bool continue_search) {
3114   // Check local property, ignore interceptor.
3115   LookupResult result(GetIsolate());
3116   LocalLookupRealNamedProperty(name, &result);
3117   if (result.IsProperty()) return result.GetAttributes();
3118
3119   if (continue_search) {
3120     // Continue searching via the prototype chain.
3121     Object* pt = GetPrototype();
3122     if (!pt->IsNull()) {
3123       return JSObject::cast(pt)->
3124         GetPropertyAttributeWithReceiver(receiver, name);
3125     }
3126   }
3127   return ABSENT;
3128 }
3129
3130
3131 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
3132       JSObject* receiver,
3133       String* name,
3134       bool continue_search) {
3135   Isolate* isolate = GetIsolate();
3136
3137   // Make sure that the top context does not change when doing
3138   // callbacks or interceptor calls.
3139   AssertNoContextChange ncc;
3140
3141   HandleScope scope(isolate);
3142   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
3143   Handle<JSObject> receiver_handle(receiver);
3144   Handle<JSObject> holder_handle(this);
3145   Handle<String> name_handle(name);
3146   CustomArguments args(isolate, interceptor->data(), receiver, this);
3147   v8::AccessorInfo info(args.end());
3148   if (!interceptor->query()->IsUndefined()) {
3149     v8::NamedPropertyQuery query =
3150         v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
3151     LOG(isolate,
3152         ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
3153     v8::Handle<v8::Integer> result;
3154     {
3155       // Leaving JavaScript.
3156       VMState state(isolate, EXTERNAL);
3157       result = query(v8::Utils::ToLocal(name_handle), info);
3158     }
3159     if (!result.IsEmpty()) {
3160       ASSERT(result->IsInt32());
3161       return static_cast<PropertyAttributes>(result->Int32Value());
3162     }
3163   } else if (!interceptor->getter()->IsUndefined()) {
3164     v8::NamedPropertyGetter getter =
3165         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
3166     LOG(isolate,
3167         ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
3168     v8::Handle<v8::Value> result;
3169     {
3170       // Leaving JavaScript.
3171       VMState state(isolate, EXTERNAL);
3172       result = getter(v8::Utils::ToLocal(name_handle), info);
3173     }
3174     if (!result.IsEmpty()) return DONT_ENUM;
3175   }
3176   return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
3177                                                             *name_handle,
3178                                                             continue_search);
3179 }
3180
3181
3182 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
3183       JSReceiver* receiver,
3184       String* key) {
3185   uint32_t index = 0;
3186   if (IsJSObject() && key->AsArrayIndex(&index)) {
3187     return JSObject::cast(this)->HasElementWithReceiver(receiver, index)
3188         ? NONE : ABSENT;
3189   }
3190   // Named property.
3191   LookupResult result(GetIsolate());
3192   Lookup(key, &result);
3193   return GetPropertyAttribute(receiver, &result, key, true);
3194 }
3195
3196
3197 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver,
3198                                                     LookupResult* result,
3199                                                     String* name,
3200                                                     bool continue_search) {
3201   // Check access rights if needed.
3202   if (IsAccessCheckNeeded()) {
3203     JSObject* this_obj = JSObject::cast(this);
3204     Heap* heap = GetHeap();
3205     if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
3206       return this_obj->GetPropertyAttributeWithFailedAccessCheck(
3207           receiver, result, name, continue_search);
3208     }
3209   }
3210   if (result->IsProperty()) {
3211     switch (result->type()) {
3212       case NORMAL:  // fall through
3213       case FIELD:
3214       case CONSTANT_FUNCTION:
3215       case CALLBACKS:
3216         return result->GetAttributes();
3217       case HANDLER: {
3218         return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler(
3219             receiver, name);
3220       }
3221       case INTERCEPTOR:
3222         return result->holder()->GetPropertyAttributeWithInterceptor(
3223             JSObject::cast(receiver), name, continue_search);
3224       default:
3225         UNREACHABLE();
3226     }
3227   }
3228   return ABSENT;
3229 }
3230
3231
3232 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
3233   // Check whether the name is an array index.
3234   uint32_t index = 0;
3235   if (IsJSObject() && name->AsArrayIndex(&index)) {
3236     if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
3237     return ABSENT;
3238   }
3239   // Named property.
3240   LookupResult result(GetIsolate());
3241   LocalLookup(name, &result);
3242   return GetPropertyAttribute(this, &result, name, false);
3243 }
3244
3245
3246 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
3247                                      PropertyNormalizationMode mode) {
3248   Isolate* isolate = obj->GetIsolate();
3249   Map* fast = obj->map();
3250   int index = fast->Hash() % kEntries;
3251   Object* result = get(index);
3252   if (result->IsMap() &&
3253       Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
3254 #ifdef DEBUG
3255     if (FLAG_verify_heap) {
3256       Map::cast(result)->SharedMapVerify();
3257     }
3258     if (FLAG_enable_slow_asserts) {
3259       // The cached map should match newly created normalized map bit-by-bit.
3260       Object* fresh;
3261       { MaybeObject* maybe_fresh =
3262             fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
3263         if (maybe_fresh->ToObject(&fresh)) {
3264           ASSERT(memcmp(Map::cast(fresh)->address(),
3265                         Map::cast(result)->address(),
3266                         Map::kSize) == 0);
3267         }
3268       }
3269     }
3270 #endif
3271     return result;
3272   }
3273
3274   { MaybeObject* maybe_result =
3275         fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
3276     if (!maybe_result->ToObject(&result)) return maybe_result;
3277   }
3278   set(index, result);
3279   isolate->counters()->normalized_maps()->Increment();
3280
3281   return result;
3282 }
3283
3284
3285 void NormalizedMapCache::Clear() {
3286   int entries = length();
3287   for (int i = 0; i != entries; i++) {
3288     set_undefined(i);
3289   }
3290 }
3291
3292
3293 void JSObject::UpdateMapCodeCache(Handle<JSObject> object,
3294                                   Handle<String> name,
3295                                   Handle<Code> code) {
3296   Isolate* isolate = object->GetIsolate();
3297   CALL_HEAP_FUNCTION_VOID(isolate,
3298                           object->UpdateMapCodeCache(*name, *code));
3299 }
3300
3301
3302 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
3303   if (map()->is_shared()) {
3304     // Fast case maps are never marked as shared.
3305     ASSERT(!HasFastProperties());
3306     // Replace the map with an identical copy that can be safely modified.
3307     Object* obj;
3308     { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES,
3309                                                      UNIQUE_NORMALIZED_MAP);
3310       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3311     }
3312     GetIsolate()->counters()->normalized_maps()->Increment();
3313
3314     set_map(Map::cast(obj));
3315   }
3316   return map()->UpdateCodeCache(name, code);
3317 }
3318
3319
3320 void JSObject::NormalizeProperties(Handle<JSObject> object,
3321                                    PropertyNormalizationMode mode,
3322                                    int expected_additional_properties) {
3323   CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
3324                           object->NormalizeProperties(
3325                               mode, expected_additional_properties));
3326 }
3327
3328
3329 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
3330                                            int expected_additional_properties) {
3331   if (!HasFastProperties()) return this;
3332
3333   // The global object is always normalized.
3334   ASSERT(!IsGlobalObject());
3335   // JSGlobalProxy must never be normalized
3336   ASSERT(!IsJSGlobalProxy());
3337
3338   Map* map_of_this = map();
3339
3340   // Allocate new content.
3341   int property_count = map_of_this->NumberOfDescribedProperties();
3342   if (expected_additional_properties > 0) {
3343     property_count += expected_additional_properties;
3344   } else {
3345     property_count += 2;  // Make space for two more properties.
3346   }
3347   StringDictionary* dictionary;
3348   { MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
3349     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3350   }
3351
3352   DescriptorArray* descs = map_of_this->instance_descriptors();
3353   for (int i = 0; i < descs->number_of_descriptors(); i++) {
3354     PropertyDetails details = descs->GetDetails(i);
3355     switch (details.type()) {
3356       case CONSTANT_FUNCTION: {
3357         PropertyDetails d =
3358             PropertyDetails(details.attributes(), NORMAL, details.index());
3359         Object* value = descs->GetConstantFunction(i);
3360         MaybeObject* maybe_dictionary =
3361             dictionary->Add(descs->GetKey(i), value, d);
3362         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3363         break;
3364       }
3365       case FIELD: {
3366         PropertyDetails d =
3367             PropertyDetails(details.attributes(), NORMAL, details.index());
3368         Object* value = FastPropertyAt(descs->GetFieldIndex(i));
3369         MaybeObject* maybe_dictionary =
3370             dictionary->Add(descs->GetKey(i), value, d);
3371         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3372         break;
3373       }
3374       case CALLBACKS: {
3375         if (!descs->IsProperty(i)) break;
3376         Object* value = descs->GetCallbacksObject(i);
3377         if (value->IsAccessorPair()) {
3378           MaybeObject* maybe_copy =
3379               AccessorPair::cast(value)->CopyWithoutTransitions();
3380           if (!maybe_copy->To(&value)) return maybe_copy;
3381         }
3382         MaybeObject* maybe_dictionary =
3383             dictionary->Add(descs->GetKey(i), value, details);
3384         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3385         break;
3386       }
3387       case MAP_TRANSITION:
3388       case CONSTANT_TRANSITION:
3389       case NULL_DESCRIPTOR:
3390       case INTERCEPTOR:
3391       case ELEMENTS_TRANSITION:
3392         break;
3393       case HANDLER:
3394       case NORMAL:
3395         UNREACHABLE();
3396         break;
3397     }
3398   }
3399
3400   Heap* current_heap = GetHeap();
3401
3402   // Copy the next enumeration index from instance descriptor.
3403   int index = map_of_this->instance_descriptors()->NextEnumerationIndex();
3404   dictionary->SetNextEnumerationIndex(index);
3405
3406   Map* new_map;
3407   { MaybeObject* maybe_map =
3408         current_heap->isolate()->context()->global_context()->
3409         normalized_map_cache()->Get(this, mode);
3410     if (!maybe_map->To(&new_map)) return maybe_map;
3411   }
3412
3413   // We have now successfully allocated all the necessary objects.
3414   // Changes can now be made with the guarantee that all of them take effect.
3415
3416   // Resize the object in the heap if necessary.
3417   int new_instance_size = new_map->instance_size();
3418   int instance_size_delta = map_of_this->instance_size() - new_instance_size;
3419   ASSERT(instance_size_delta >= 0);
3420   current_heap->CreateFillerObjectAt(this->address() + new_instance_size,
3421                                      instance_size_delta);
3422   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
3423     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
3424                                                -instance_size_delta);
3425   }
3426
3427
3428   set_map(new_map);
3429   new_map->clear_instance_descriptors();
3430
3431   set_properties(dictionary);
3432
3433   current_heap->isolate()->counters()->props_to_dictionary()->Increment();
3434
3435 #ifdef DEBUG
3436   if (FLAG_trace_normalization) {
3437     PrintF("Object properties have been normalized:\n");
3438     Print();
3439   }
3440 #endif
3441   return this;
3442 }
3443
3444
3445 void JSObject::TransformToFastProperties(Handle<JSObject> object,
3446                                          int unused_property_fields) {
3447   CALL_HEAP_FUNCTION_VOID(
3448       object->GetIsolate(),
3449       object->TransformToFastProperties(unused_property_fields));
3450 }
3451
3452
3453 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
3454   if (HasFastProperties()) return this;
3455   ASSERT(!IsGlobalObject());
3456   return property_dictionary()->
3457       TransformPropertiesToFastFor(this, unused_property_fields);
3458 }
3459
3460
3461 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
3462     Handle<JSObject> object) {
3463   CALL_HEAP_FUNCTION(object->GetIsolate(),
3464                      object->NormalizeElements(),
3465                      SeededNumberDictionary);
3466 }
3467
3468
3469 MaybeObject* JSObject::NormalizeElements() {
3470   ASSERT(!HasExternalArrayElements());
3471
3472   // Find the backing store.
3473   FixedArrayBase* array = FixedArrayBase::cast(elements());
3474   Map* old_map = array->map();
3475   bool is_arguments =
3476       (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
3477   if (is_arguments) {
3478     array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
3479   }
3480   if (array->IsDictionary()) return array;
3481
3482   ASSERT(HasFastElements() ||
3483          HasFastSmiOnlyElements() ||
3484          HasFastDoubleElements() ||
3485          HasFastArgumentsElements());
3486   // Compute the effective length and allocate a new backing store.
3487   int length = IsJSArray()
3488       ? Smi::cast(JSArray::cast(this)->length())->value()
3489       : array->length();
3490   int old_capacity = 0;
3491   int used_elements = 0;
3492   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
3493   SeededNumberDictionary* dictionary = NULL;
3494   { Object* object;
3495     MaybeObject* maybe = SeededNumberDictionary::Allocate(used_elements);
3496     if (!maybe->ToObject(&object)) return maybe;
3497     dictionary = SeededNumberDictionary::cast(object);
3498   }
3499
3500   // Copy the elements to the new backing store.
3501   bool has_double_elements = array->IsFixedDoubleArray();
3502   for (int i = 0; i < length; i++) {
3503     Object* value = NULL;
3504     if (has_double_elements) {
3505       FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
3506       if (double_array->is_the_hole(i)) {
3507         value = GetIsolate()->heap()->the_hole_value();
3508       } else {
3509         // Objects must be allocated in the old object space, since the
3510         // overall number of HeapNumbers needed for the conversion might
3511         // exceed the capacity of new space, and we would fail repeatedly
3512         // trying to convert the FixedDoubleArray.
3513         MaybeObject* maybe_value_object =
3514             GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3515         if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3516       }
3517     } else {
3518       ASSERT(old_map->has_fast_elements() ||
3519              old_map->has_fast_smi_only_elements());
3520       value = FixedArray::cast(array)->get(i);
3521     }
3522     PropertyDetails details = PropertyDetails(NONE, NORMAL);
3523     if (!value->IsTheHole()) {
3524       Object* result;
3525       MaybeObject* maybe_result =
3526           dictionary->AddNumberEntry(i, value, details);
3527       if (!maybe_result->ToObject(&result)) return maybe_result;
3528       dictionary = SeededNumberDictionary::cast(result);
3529     }
3530   }
3531
3532   // Switch to using the dictionary as the backing storage for elements.
3533   if (is_arguments) {
3534     FixedArray::cast(elements())->set(1, dictionary);
3535   } else {
3536     // Set the new map first to satify the elements type assert in
3537     // set_elements().
3538     Object* new_map;
3539     MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
3540                                                   DICTIONARY_ELEMENTS);
3541     if (!maybe->ToObject(&new_map)) return maybe;
3542     set_map(Map::cast(new_map));
3543     set_elements(dictionary);
3544   }
3545
3546   old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
3547       Increment();
3548
3549 #ifdef DEBUG
3550   if (FLAG_trace_normalization) {
3551     PrintF("Object elements have been normalized:\n");
3552     Print();
3553   }
3554 #endif
3555
3556   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
3557   return dictionary;
3558 }
3559
3560
3561 Smi* JSReceiver::GenerateIdentityHash() {
3562   Isolate* isolate = GetIsolate();
3563
3564   int hash_value;
3565   int attempts = 0;
3566   do {
3567     // Generate a random 32-bit hash value but limit range to fit
3568     // within a smi.
3569     hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue;
3570     attempts++;
3571   } while (hash_value == 0 && attempts < 30);
3572   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
3573
3574   return Smi::FromInt(hash_value);
3575 }
3576
3577
3578 MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) {
3579   MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3580                                          hash);
3581   if (maybe->IsFailure()) return maybe;
3582   return this;
3583 }
3584
3585
3586 int JSObject::GetIdentityHash(Handle<JSObject> obj) {
3587   CALL_AND_RETRY(obj->GetIsolate(),
3588                  obj->GetIdentityHash(ALLOW_CREATION),
3589                  return Smi::cast(__object__)->value(),
3590                  return 0);
3591 }
3592
3593
3594 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) {
3595   Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol());
3596   if (stored_value->IsSmi()) return stored_value;
3597
3598   // Do not generate permanent identity hash code if not requested.
3599   if (flag == OMIT_CREATION) return GetHeap()->undefined_value();
3600
3601   Smi* hash = GenerateIdentityHash();
3602   MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3603                                           hash);
3604   if (result->IsFailure()) return result;
3605   if (result->ToObjectUnchecked()->IsUndefined()) {
3606     // Trying to get hash of detached proxy.
3607     return Smi::FromInt(0);
3608   }
3609   return hash;
3610 }
3611
3612
3613 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) {
3614   Object* hash = this->hash();
3615   if (!hash->IsSmi() && flag == ALLOW_CREATION) {
3616     hash = GenerateIdentityHash();
3617     set_hash(hash);
3618   }
3619   return hash;
3620 }
3621
3622
3623 Object* JSObject::GetHiddenProperty(String* key) {
3624   if (IsJSGlobalProxy()) {
3625     // For a proxy, use the prototype as target object.
3626     Object* proxy_parent = GetPrototype();
3627     // If the proxy is detached, return undefined.
3628     if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3629     ASSERT(proxy_parent->IsJSGlobalObject());
3630     return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
3631   }
3632   ASSERT(!IsJSGlobalProxy());
3633   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3634   ASSERT(!hidden_lookup->IsFailure());  // No failure when passing false as arg.
3635   if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) {
3636     return GetHeap()->undefined_value();
3637   }
3638   StringDictionary* dictionary =
3639       StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3640   int entry = dictionary->FindEntry(key);
3641   if (entry == StringDictionary::kNotFound) return GetHeap()->undefined_value();
3642   return dictionary->ValueAt(entry);
3643 }
3644
3645
3646 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj,
3647                                  Handle<String> key,
3648                                  Handle<Object> value) {
3649   CALL_HEAP_FUNCTION(obj->GetIsolate(),
3650                      obj->SetHiddenProperty(*key, *value),
3651                      Object);
3652 }
3653
3654
3655 MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
3656   if (IsJSGlobalProxy()) {
3657     // For a proxy, use the prototype as target object.
3658     Object* proxy_parent = GetPrototype();
3659     // If the proxy is detached, return undefined.
3660     if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3661     ASSERT(proxy_parent->IsJSGlobalObject());
3662     return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value);
3663   }
3664   ASSERT(!IsJSGlobalProxy());
3665   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(true);
3666   StringDictionary* dictionary;
3667   if (!hidden_lookup->To<StringDictionary>(&dictionary)) return hidden_lookup;
3668
3669   // If it was found, check if the key is already in the dictionary.
3670   int entry = dictionary->FindEntry(key);
3671   if (entry != StringDictionary::kNotFound) {
3672     // If key was found, just update the value.
3673     dictionary->ValueAtPut(entry, value);
3674     return this;
3675   }
3676   // Key was not already in the dictionary, so add the entry.
3677   MaybeObject* insert_result = dictionary->Add(key,
3678                                                value,
3679                                                PropertyDetails(NONE, NORMAL));
3680   StringDictionary* new_dict;
3681   if (!insert_result->To<StringDictionary>(&new_dict)) return insert_result;
3682   if (new_dict != dictionary) {
3683     // If adding the key expanded the dictionary (i.e., Add returned a new
3684     // dictionary), store it back to the object.
3685     MaybeObject* store_result = SetHiddenPropertiesDictionary(new_dict);
3686     if (store_result->IsFailure()) return store_result;
3687   }
3688   // Return this to mark success.
3689   return this;
3690 }
3691
3692
3693 void JSObject::DeleteHiddenProperty(String* key) {
3694   if (IsJSGlobalProxy()) {
3695     // For a proxy, use the prototype as target object.
3696     Object* proxy_parent = GetPrototype();
3697     // If the proxy is detached, return immediately.
3698     if (proxy_parent->IsNull()) return;
3699     ASSERT(proxy_parent->IsJSGlobalObject());
3700     JSObject::cast(proxy_parent)->DeleteHiddenProperty(key);
3701     return;
3702   }
3703   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3704   ASSERT(!hidden_lookup->IsFailure());  // No failure when passing false as arg.
3705   if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) return;
3706   StringDictionary* dictionary =
3707       StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3708   int entry = dictionary->FindEntry(key);
3709   if (entry == StringDictionary::kNotFound) {
3710     // Key wasn't in dictionary. Deletion is a success.
3711     return;
3712   }
3713   // Key was in the dictionary. Remove it.
3714   dictionary->DeleteProperty(entry, JSReceiver::FORCE_DELETION);
3715 }
3716
3717
3718 bool JSObject::HasHiddenProperties() {
3719   return GetPropertyAttributePostInterceptor(this,
3720                                              GetHeap()->hidden_symbol(),
3721                                              false) != ABSENT;
3722 }
3723
3724
3725 MaybeObject* JSObject::GetHiddenPropertiesDictionary(bool create_if_absent) {
3726   ASSERT(!IsJSGlobalProxy());
3727   if (HasFastProperties()) {
3728     // If the object has fast properties, check whether the first slot
3729     // in the descriptor array matches the hidden symbol. Since the
3730     // hidden symbols hash code is zero (and no other string has hash
3731     // code zero) it will always occupy the first entry if present.
3732     DescriptorArray* descriptors = this->map()->instance_descriptors();
3733     if ((descriptors->number_of_descriptors() > 0) &&
3734         (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
3735       if (descriptors->GetType(0) == FIELD) {
3736         Object* hidden_store =
3737             this->FastPropertyAt(descriptors->GetFieldIndex(0));
3738         return StringDictionary::cast(hidden_store);
3739       } else {
3740         ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR ||
3741                descriptors->GetType(0) == MAP_TRANSITION);
3742       }
3743     }
3744   } else {
3745     PropertyAttributes attributes;
3746     // You can't install a getter on a property indexed by the hidden symbol,
3747     // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3748     // object.
3749     Object* lookup =
3750         GetLocalPropertyPostInterceptor(this,
3751                                         GetHeap()->hidden_symbol(),
3752                                         &attributes)->ToObjectUnchecked();
3753     if (!lookup->IsUndefined()) {
3754       return StringDictionary::cast(lookup);
3755     }
3756   }
3757   if (!create_if_absent) return GetHeap()->undefined_value();
3758   const int kInitialSize = 5;
3759   MaybeObject* dict_alloc = StringDictionary::Allocate(kInitialSize);
3760   StringDictionary* dictionary;
3761   if (!dict_alloc->To<StringDictionary>(&dictionary)) return dict_alloc;
3762   // Using AddProperty or SetPropertyPostInterceptor here could fail, because
3763   // object might be non-extensible.
3764   return HasFastProperties()
3765       ? AddFastProperty(GetHeap()->hidden_symbol(), dictionary, DONT_ENUM)
3766       : AddSlowProperty(GetHeap()->hidden_symbol(), dictionary, DONT_ENUM);
3767 }
3768
3769
3770 MaybeObject* JSObject::SetHiddenPropertiesDictionary(
3771     StringDictionary* dictionary) {
3772   ASSERT(!IsJSGlobalProxy());
3773   ASSERT(HasHiddenProperties());
3774   if (HasFastProperties()) {
3775     // If the object has fast properties, check whether the first slot
3776     // in the descriptor array matches the hidden symbol. Since the
3777     // hidden symbols hash code is zero (and no other string has hash
3778     // code zero) it will always occupy the first entry if present.
3779     DescriptorArray* descriptors = this->map()->instance_descriptors();
3780     if ((descriptors->number_of_descriptors() > 0) &&
3781         (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
3782       if (descriptors->GetType(0) == FIELD) {
3783         this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary);
3784         return this;
3785       } else {
3786         ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR ||
3787                descriptors->GetType(0) == MAP_TRANSITION);
3788       }
3789     }
3790   }
3791   MaybeObject* store_result =
3792       SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3793                                  dictionary,
3794                                  DONT_ENUM,
3795                                  kNonStrictMode);
3796   if (store_result->IsFailure()) return store_result;
3797   return this;
3798 }
3799
3800
3801 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
3802                                                      DeleteMode mode) {
3803   // Check local property, ignore interceptor.
3804   LookupResult result(GetIsolate());
3805   LocalLookupRealNamedProperty(name, &result);
3806   if (!result.IsProperty()) return GetHeap()->true_value();
3807
3808   // Normalize object if needed.
3809   Object* obj;
3810   { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3811     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3812   }
3813
3814   return DeleteNormalizedProperty(name, mode);
3815 }
3816
3817
3818 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) {
3819   Isolate* isolate = GetIsolate();
3820   HandleScope scope(isolate);
3821   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
3822   Handle<String> name_handle(name);
3823   Handle<JSObject> this_handle(this);
3824   if (!interceptor->deleter()->IsUndefined()) {
3825     v8::NamedPropertyDeleter deleter =
3826         v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
3827     LOG(isolate,
3828         ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
3829     CustomArguments args(isolate, interceptor->data(), this, this);
3830     v8::AccessorInfo info(args.end());
3831     v8::Handle<v8::Boolean> result;
3832     {
3833       // Leaving JavaScript.
3834       VMState state(isolate, EXTERNAL);
3835       result = deleter(v8::Utils::ToLocal(name_handle), info);
3836     }
3837     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3838     if (!result.IsEmpty()) {
3839       ASSERT(result->IsBoolean());
3840       return *v8::Utils::OpenHandle(*result);
3841     }
3842   }
3843   MaybeObject* raw_result =
3844       this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
3845   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3846   return raw_result;
3847 }
3848
3849
3850 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
3851   Isolate* isolate = GetIsolate();
3852   Heap* heap = isolate->heap();
3853   // Make sure that the top context does not change when doing
3854   // callbacks or interceptor calls.
3855   AssertNoContextChange ncc;
3856   HandleScope scope(isolate);
3857   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
3858   if (interceptor->deleter()->IsUndefined()) return heap->false_value();
3859   v8::IndexedPropertyDeleter deleter =
3860       v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
3861   Handle<JSObject> this_handle(this);
3862   LOG(isolate,
3863       ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
3864   CustomArguments args(isolate, interceptor->data(), this, this);
3865   v8::AccessorInfo info(args.end());
3866   v8::Handle<v8::Boolean> result;
3867   {
3868     // Leaving JavaScript.
3869     VMState state(isolate, EXTERNAL);
3870     result = deleter(index, info);
3871   }
3872   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3873   if (!result.IsEmpty()) {
3874     ASSERT(result->IsBoolean());
3875     return *v8::Utils::OpenHandle(*result);
3876   }
3877   MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete(
3878       *this_handle,
3879       index,
3880       NORMAL_DELETION);
3881   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3882   return raw_result;
3883 }
3884
3885
3886 Handle<Object> JSObject::DeleteElement(Handle<JSObject> obj,
3887                                        uint32_t index) {
3888   CALL_HEAP_FUNCTION(obj->GetIsolate(),
3889                      obj->DeleteElement(index, JSObject::NORMAL_DELETION),
3890                      Object);
3891 }
3892
3893
3894 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
3895   Isolate* isolate = GetIsolate();
3896   // Check access rights if needed.
3897   if (IsAccessCheckNeeded() &&
3898       !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
3899     isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
3900     return isolate->heap()->false_value();
3901   }
3902
3903   if (IsJSGlobalProxy()) {
3904     Object* proto = GetPrototype();
3905     if (proto->IsNull()) return isolate->heap()->false_value();
3906     ASSERT(proto->IsJSGlobalObject());
3907     return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
3908   }
3909
3910   if (HasIndexedInterceptor()) {
3911     // Skip interceptor if forcing deletion.
3912     if (mode != FORCE_DELETION) {
3913       return DeleteElementWithInterceptor(index);
3914     }
3915     mode = JSReceiver::FORCE_DELETION;
3916   }
3917
3918   return GetElementsAccessor()->Delete(this, index, mode);
3919 }
3920
3921
3922 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj,
3923                               Handle<String> prop) {
3924   CALL_HEAP_FUNCTION(obj->GetIsolate(),
3925                      obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
3926                      Object);
3927 }
3928
3929
3930 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
3931   Isolate* isolate = GetIsolate();
3932   // ECMA-262, 3rd, 8.6.2.5
3933   ASSERT(name->IsString());
3934
3935   // Check access rights if needed.
3936   if (IsAccessCheckNeeded() &&
3937       !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
3938     isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
3939     return isolate->heap()->false_value();
3940   }
3941
3942   if (IsJSGlobalProxy()) {
3943     Object* proto = GetPrototype();
3944     if (proto->IsNull()) return isolate->heap()->false_value();
3945     ASSERT(proto->IsJSGlobalObject());
3946     return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
3947   }
3948
3949   uint32_t index = 0;
3950   if (name->AsArrayIndex(&index)) {
3951     return DeleteElement(index, mode);
3952   } else {
3953     LookupResult result(isolate);
3954     LocalLookup(name, &result);
3955     if (!result.IsProperty()) return isolate->heap()->true_value();
3956     // Ignore attributes if forcing a deletion.
3957     if (result.IsDontDelete() && mode != FORCE_DELETION) {
3958       if (mode == STRICT_DELETION) {
3959         // Deleting a non-configurable property in strict mode.
3960         HandleScope scope(isolate);
3961         Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
3962         return isolate->Throw(*isolate->factory()->NewTypeError(
3963             "strict_delete_property", HandleVector(args, 2)));
3964       }
3965       return isolate->heap()->false_value();
3966     }
3967     // Check for interceptor.
3968     if (result.type() == INTERCEPTOR) {
3969       // Skip interceptor if forcing a deletion.
3970       if (mode == FORCE_DELETION) {
3971         return DeletePropertyPostInterceptor(name, mode);
3972       }
3973       return DeletePropertyWithInterceptor(name);
3974     }
3975     // Normalize object if needed.
3976     Object* obj;
3977     { MaybeObject* maybe_obj =
3978           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3979       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3980     }
3981     // Make sure the properties are normalized before removing the entry.
3982     return DeleteNormalizedProperty(name, mode);
3983   }
3984 }
3985
3986
3987 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
3988   if (IsJSProxy()) {
3989     return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
3990   }
3991   return JSObject::cast(this)->DeleteElement(index, mode);
3992 }
3993
3994
3995 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
3996   if (IsJSProxy()) {
3997     return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
3998   }
3999   return JSObject::cast(this)->DeleteProperty(name, mode);
4000 }
4001
4002
4003 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
4004                                             ElementsKind kind,
4005                                             Object* object) {
4006   ASSERT(kind == FAST_ELEMENTS ||
4007          kind == DICTIONARY_ELEMENTS);
4008   if (kind == FAST_ELEMENTS) {
4009     int length = IsJSArray()
4010         ? Smi::cast(JSArray::cast(this)->length())->value()
4011         : elements->length();
4012     for (int i = 0; i < length; ++i) {
4013       Object* element = elements->get(i);
4014       if (!element->IsTheHole() && element == object) return true;
4015     }
4016   } else {
4017     Object* key =
4018         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
4019     if (!key->IsUndefined()) return true;
4020   }
4021   return false;
4022 }
4023
4024
4025 // Check whether this object references another object.
4026 bool JSObject::ReferencesObject(Object* obj) {
4027   Map* map_of_this = map();
4028   Heap* heap = GetHeap();
4029   AssertNoAllocation no_alloc;
4030
4031   // Is the object the constructor for this object?
4032   if (map_of_this->constructor() == obj) {
4033     return true;
4034   }
4035
4036   // Is the object the prototype for this object?
4037   if (map_of_this->prototype() == obj) {
4038     return true;
4039   }
4040
4041   // Check if the object is among the named properties.
4042   Object* key = SlowReverseLookup(obj);
4043   if (!key->IsUndefined()) {
4044     return true;
4045   }
4046
4047   // Check if the object is among the indexed properties.
4048   ElementsKind kind = GetElementsKind();
4049   switch (kind) {
4050     case EXTERNAL_PIXEL_ELEMENTS:
4051     case EXTERNAL_BYTE_ELEMENTS:
4052     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4053     case EXTERNAL_SHORT_ELEMENTS:
4054     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4055     case EXTERNAL_INT_ELEMENTS:
4056     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4057     case EXTERNAL_FLOAT_ELEMENTS:
4058     case EXTERNAL_DOUBLE_ELEMENTS:
4059     case FAST_DOUBLE_ELEMENTS:
4060       // Raw pixels and external arrays do not reference other
4061       // objects.
4062       break;
4063     case FAST_SMI_ONLY_ELEMENTS:
4064       break;
4065     case FAST_ELEMENTS:
4066     case DICTIONARY_ELEMENTS: {
4067       FixedArray* elements = FixedArray::cast(this->elements());
4068       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
4069       break;
4070     }
4071     case NON_STRICT_ARGUMENTS_ELEMENTS: {
4072       FixedArray* parameter_map = FixedArray::cast(elements());
4073       // Check the mapped parameters.
4074       int length = parameter_map->length();
4075       for (int i = 2; i < length; ++i) {
4076         Object* value = parameter_map->get(i);
4077         if (!value->IsTheHole() && value == obj) return true;
4078       }
4079       // Check the arguments.
4080       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4081       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
4082       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
4083       break;
4084     }
4085   }
4086
4087   // For functions check the context.
4088   if (IsJSFunction()) {
4089     // Get the constructor function for arguments array.
4090     JSObject* arguments_boilerplate =
4091         heap->isolate()->context()->global_context()->
4092             arguments_boilerplate();
4093     JSFunction* arguments_function =
4094         JSFunction::cast(arguments_boilerplate->map()->constructor());
4095
4096     // Get the context and don't check if it is the global context.
4097     JSFunction* f = JSFunction::cast(this);
4098     Context* context = f->context();
4099     if (context->IsGlobalContext()) {
4100       return false;
4101     }
4102
4103     // Check the non-special context slots.
4104     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
4105       // Only check JS objects.
4106       if (context->get(i)->IsJSObject()) {
4107         JSObject* ctxobj = JSObject::cast(context->get(i));
4108         // If it is an arguments array check the content.
4109         if (ctxobj->map()->constructor() == arguments_function) {
4110           if (ctxobj->ReferencesObject(obj)) {
4111             return true;
4112           }
4113         } else if (ctxobj == obj) {
4114           return true;
4115         }
4116       }
4117     }
4118
4119     // Check the context extension (if any) if it can have references.
4120     if (context->has_extension() && !context->IsCatchContext()) {
4121       return JSObject::cast(context->extension())->ReferencesObject(obj);
4122     }
4123   }
4124
4125   // No references to object.
4126   return false;
4127 }
4128
4129
4130 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
4131   CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object);
4132 }
4133
4134
4135 MaybeObject* JSObject::PreventExtensions() {
4136   Isolate* isolate = GetIsolate();
4137   if (IsAccessCheckNeeded() &&
4138       !isolate->MayNamedAccess(this,
4139                                isolate->heap()->undefined_value(),
4140                                v8::ACCESS_KEYS)) {
4141     isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
4142     return isolate->heap()->false_value();
4143   }
4144
4145   if (IsJSGlobalProxy()) {
4146     Object* proto = GetPrototype();
4147     if (proto->IsNull()) return this;
4148     ASSERT(proto->IsJSGlobalObject());
4149     return JSObject::cast(proto)->PreventExtensions();
4150   }
4151
4152   // It's not possible to seal objects with external array elements
4153   if (HasExternalArrayElements()) {
4154     HandleScope scope(isolate);
4155     Handle<Object> object(this);
4156     Handle<Object> error  =
4157         isolate->factory()->NewTypeError(
4158             "cant_prevent_ext_external_array_elements",
4159             HandleVector(&object, 1));
4160     return isolate->Throw(*error);
4161   }
4162
4163   // If there are fast elements we normalize.
4164   SeededNumberDictionary* dictionary = NULL;
4165   { MaybeObject* maybe = NormalizeElements();
4166     if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe;
4167   }
4168   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
4169   // Make sure that we never go back to fast case.
4170   dictionary->set_requires_slow_elements();
4171
4172   // Do a map transition, other objects with this map may still
4173   // be extensible.
4174   Map* new_map;
4175   { MaybeObject* maybe = map()->CopyDropTransitions();
4176     if (!maybe->To<Map>(&new_map)) return maybe;
4177   }
4178   new_map->set_is_extensible(false);
4179   set_map(new_map);
4180   ASSERT(!map()->is_extensible());
4181   return new_map;
4182 }
4183
4184
4185 // Tests for the fast common case for property enumeration:
4186 // - This object and all prototypes has an enum cache (which means that
4187 //   it is no proxy, has no interceptors and needs no access checks).
4188 // - This object has no elements.
4189 // - No prototype has enumerable properties/elements.
4190 bool JSReceiver::IsSimpleEnum() {
4191   Heap* heap = GetHeap();
4192   for (Object* o = this;
4193        o != heap->null_value();
4194        o = JSObject::cast(o)->GetPrototype()) {
4195     if (!o->IsJSObject()) return false;
4196     JSObject* curr = JSObject::cast(o);
4197     if (!curr->map()->instance_descriptors()->HasEnumCache()) return false;
4198     ASSERT(!curr->HasNamedInterceptor());
4199     ASSERT(!curr->HasIndexedInterceptor());
4200     ASSERT(!curr->IsAccessCheckNeeded());
4201     if (curr->NumberOfEnumElements() > 0) return false;
4202     if (curr != this) {
4203       FixedArray* curr_fixed_array =
4204           FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache());
4205       if (curr_fixed_array->length() > 0) return false;
4206     }
4207   }
4208   return true;
4209 }
4210
4211
4212 int Map::NumberOfDescribedProperties(PropertyAttributes filter) {
4213   int result = 0;
4214   DescriptorArray* descs = instance_descriptors();
4215   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4216     PropertyDetails details = descs->GetDetails(i);
4217     if (descs->IsProperty(i) && (details.attributes() & filter) == 0) {
4218       result++;
4219     }
4220   }
4221   return result;
4222 }
4223
4224
4225 int Map::PropertyIndexFor(String* name) {
4226   DescriptorArray* descs = instance_descriptors();
4227   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4228     if (name->Equals(descs->GetKey(i)) && !descs->IsNullDescriptor(i)) {
4229       return descs->GetFieldIndex(i);
4230     }
4231   }
4232   return -1;
4233 }
4234
4235
4236 int Map::NextFreePropertyIndex() {
4237   int max_index = -1;
4238   DescriptorArray* descs = instance_descriptors();
4239   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4240     if (descs->GetType(i) == FIELD) {
4241       int current_index = descs->GetFieldIndex(i);
4242       if (current_index > max_index) max_index = current_index;
4243     }
4244   }
4245   return max_index + 1;
4246 }
4247
4248
4249 AccessorDescriptor* Map::FindAccessor(String* name) {
4250   DescriptorArray* descs = instance_descriptors();
4251   for (int i = 0; i < descs->number_of_descriptors(); i++) {
4252     if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
4253       return descs->GetCallbacks(i);
4254     }
4255   }
4256   return NULL;
4257 }
4258
4259
4260 void JSReceiver::LocalLookup(String* name, LookupResult* result,
4261                              bool skip_fallback_interceptor) {
4262   ASSERT(name->IsString());
4263
4264   Heap* heap = GetHeap();
4265
4266   if (IsJSGlobalProxy()) {
4267     Object* proto = GetPrototype();
4268     if (proto->IsNull()) return result->NotFound();
4269     ASSERT(proto->IsJSGlobalObject());
4270     return JSReceiver::cast(proto)->LocalLookup(name, result);
4271   }
4272
4273   if (IsJSProxy()) {
4274     result->HandlerResult(JSProxy::cast(this));
4275     return;
4276   }
4277
4278   // Do not use inline caching if the object is a non-global object
4279   // that requires access checks.
4280   if (IsAccessCheckNeeded()) {
4281     result->DisallowCaching();
4282   }
4283
4284   JSObject* js_object = JSObject::cast(this);
4285
4286   // Check __proto__ before interceptor.
4287   if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) {
4288     result->ConstantResult(js_object);
4289     return;
4290   }
4291
4292   // Check for lookup interceptor except when bootstrapping.
4293   bool wouldIntercept = js_object->HasNamedInterceptor() &&
4294                         !heap->isolate()->bootstrapper()->IsActive();
4295   if (wouldIntercept && !map()->named_interceptor_is_fallback()) {
4296     result->InterceptorResult(js_object);
4297     return;
4298   }
4299
4300   js_object->LocalLookupRealNamedProperty(name, result);
4301
4302   if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() &&
4303       map()->named_interceptor_is_fallback()) {
4304     result->InterceptorResult(js_object);
4305     return;
4306   }
4307 }
4308
4309
4310 void JSReceiver::Lookup(String* name, LookupResult* result,
4311                         bool skip_fallback_interceptor) {
4312   // Ecma-262 3rd 8.6.2.4
4313   Heap* heap = GetHeap();
4314   for (Object* current = this;
4315        current != heap->null_value();
4316        current = JSObject::cast(current)->GetPrototype()) {
4317     JSReceiver::cast(current)->LocalLookup(name,
4318                                            result,
4319                                            skip_fallback_interceptor);
4320     if (result->IsProperty()) return;
4321   }
4322   result->NotFound();
4323 }
4324
4325
4326 // Search object and it's prototype chain for callback properties.
4327 void JSObject::LookupCallback(String* name, LookupResult* result) {
4328   Heap* heap = GetHeap();
4329   for (Object* current = this;
4330        current != heap->null_value() && current->IsJSObject();
4331        current = JSObject::cast(current)->GetPrototype()) {
4332     JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4333     if (result->IsFound() && result->type() == CALLBACKS) return;
4334   }
4335   result->NotFound();
4336 }
4337
4338
4339 // Try to update an accessor in an elements dictionary. Return true if the
4340 // update succeeded, and false otherwise.
4341 static bool UpdateGetterSetterInDictionary(
4342     SeededNumberDictionary* dictionary,
4343     uint32_t index,
4344     Object* getter,
4345     Object* setter,
4346     PropertyAttributes attributes) {
4347   int entry = dictionary->FindEntry(index);
4348   if (entry != SeededNumberDictionary::kNotFound) {
4349     Object* result = dictionary->ValueAt(entry);
4350     PropertyDetails details = dictionary->DetailsAt(entry);
4351     if (details.type() == CALLBACKS && result->IsAccessorPair()) {
4352       ASSERT(!details.IsDontDelete());
4353       if (details.attributes() != attributes) {
4354         dictionary->DetailsAtPut(entry,
4355                                  PropertyDetails(attributes, CALLBACKS, index));
4356       }
4357       AccessorPair::cast(result)->SetComponents(getter, setter);
4358       return true;
4359     }
4360   }
4361   return false;
4362 }
4363
4364
4365 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
4366                                              Object* getter,
4367                                              Object* setter,
4368                                              PropertyAttributes attributes) {
4369   switch (GetElementsKind()) {
4370     case FAST_SMI_ONLY_ELEMENTS:
4371     case FAST_ELEMENTS:
4372     case FAST_DOUBLE_ELEMENTS:
4373       break;
4374     case EXTERNAL_PIXEL_ELEMENTS:
4375     case EXTERNAL_BYTE_ELEMENTS:
4376     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4377     case EXTERNAL_SHORT_ELEMENTS:
4378     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4379     case EXTERNAL_INT_ELEMENTS:
4380     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4381     case EXTERNAL_FLOAT_ELEMENTS:
4382     case EXTERNAL_DOUBLE_ELEMENTS:
4383       // Ignore getters and setters on pixel and external array elements.
4384       return GetHeap()->undefined_value();
4385     case DICTIONARY_ELEMENTS:
4386       if (UpdateGetterSetterInDictionary(element_dictionary(),
4387                                          index,
4388                                          getter,
4389                                          setter,
4390                                          attributes)) {
4391         return GetHeap()->undefined_value();
4392       }
4393       break;
4394     case NON_STRICT_ARGUMENTS_ELEMENTS: {
4395       // Ascertain whether we have read-only properties or an existing
4396       // getter/setter pair in an arguments elements dictionary backing
4397       // store.
4398       FixedArray* parameter_map = FixedArray::cast(elements());
4399       uint32_t length = parameter_map->length();
4400       Object* probe =
4401           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
4402       if (probe == NULL || probe->IsTheHole()) {
4403         FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4404         if (arguments->IsDictionary()) {
4405           SeededNumberDictionary* dictionary =
4406               SeededNumberDictionary::cast(arguments);
4407           if (UpdateGetterSetterInDictionary(dictionary,
4408                                              index,
4409                                              getter,
4410                                              setter,
4411                                              attributes)) {
4412             return GetHeap()->undefined_value();
4413           }
4414         }
4415       }
4416       break;
4417     }
4418   }
4419
4420   AccessorPair* accessors;
4421   { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair();
4422     if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4423   }
4424   accessors->SetComponents(getter, setter);
4425
4426   return SetElementCallback(index, accessors, attributes);
4427 }
4428
4429
4430 MaybeObject* JSObject::CreateAccessorPairFor(String* name) {
4431   LookupResult result(GetHeap()->isolate());
4432   LocalLookupRealNamedProperty(name, &result);
4433   if (result.IsProperty() && result.type() == CALLBACKS) {
4434     ASSERT(!result.IsDontDelete());
4435     Object* obj = result.GetCallbackObject();
4436     if (obj->IsAccessorPair()) {
4437       return AccessorPair::cast(obj)->CopyWithoutTransitions();
4438     }
4439   }
4440   return GetHeap()->AllocateAccessorPair();
4441 }
4442
4443
4444 MaybeObject* JSObject::DefinePropertyAccessor(String* name,
4445                                               Object* getter,
4446                                               Object* setter,
4447                                               PropertyAttributes attributes) {
4448   AccessorPair* accessors;
4449   { MaybeObject* maybe_accessors = CreateAccessorPairFor(name);
4450     if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4451   }
4452   accessors->SetComponents(getter, setter);
4453   return SetPropertyCallback(name, accessors, attributes);
4454 }
4455
4456
4457 bool JSObject::CanSetCallback(String* name) {
4458   ASSERT(!IsAccessCheckNeeded() ||
4459          GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4460
4461   // Check if there is an API defined callback object which prohibits
4462   // callback overwriting in this object or it's prototype chain.
4463   // This mechanism is needed for instance in a browser setting, where
4464   // certain accessors such as window.location should not be allowed
4465   // to be overwritten because allowing overwriting could potentially
4466   // cause security problems.
4467   LookupResult callback_result(GetIsolate());
4468   LookupCallback(name, &callback_result);
4469   if (callback_result.IsProperty()) {
4470     Object* obj = callback_result.GetCallbackObject();
4471     if (obj->IsAccessorInfo() &&
4472         AccessorInfo::cast(obj)->prohibits_overwriting()) {
4473       return false;
4474     }
4475   }
4476
4477   return true;
4478 }
4479
4480
4481 MaybeObject* JSObject::SetElementCallback(uint32_t index,
4482                                           Object* structure,
4483                                           PropertyAttributes attributes) {
4484   PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4485
4486   // Normalize elements to make this operation simple.
4487   SeededNumberDictionary* dictionary;
4488   { MaybeObject* maybe_dictionary = NormalizeElements();
4489     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4490   }
4491   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
4492
4493   // Update the dictionary with the new CALLBACKS property.
4494   { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details);
4495     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4496   }
4497
4498   dictionary->set_requires_slow_elements();
4499   // Update the dictionary backing store on the object.
4500   if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
4501     // Also delete any parameter alias.
4502     //
4503     // TODO(kmillikin): when deleting the last parameter alias we could
4504     // switch to a direct backing store without the parameter map.  This
4505     // would allow GC of the context.
4506     FixedArray* parameter_map = FixedArray::cast(elements());
4507     if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
4508       parameter_map->set(index + 2, GetHeap()->the_hole_value());
4509     }
4510     parameter_map->set(1, dictionary);
4511   } else {
4512     set_elements(dictionary);
4513   }
4514
4515   return GetHeap()->undefined_value();
4516 }
4517
4518
4519 MaybeObject* JSObject::SetPropertyCallback(String* name,
4520                                            Object* structure,
4521                                            PropertyAttributes attributes) {
4522   // Normalize object to make this operation simple.
4523   { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4524     if (maybe_ok->IsFailure()) return maybe_ok;
4525   }
4526
4527   // For the global object allocate a new map to invalidate the global inline
4528   // caches which have a global property cell reference directly in the code.
4529   if (IsGlobalObject()) {
4530     Map* new_map;
4531     { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
4532       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4533     }
4534     set_map(new_map);
4535     // When running crankshaft, changing the map is not enough. We
4536     // need to deoptimize all functions that rely on this global
4537     // object.
4538     Deoptimizer::DeoptimizeGlobalObject(this);
4539   }
4540
4541   // Update the dictionary with the new CALLBACKS property.
4542   PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4543   { MaybeObject* maybe_ok = SetNormalizedProperty(name, structure, details);
4544     if (maybe_ok->IsFailure()) return maybe_ok;
4545   }
4546
4547   return GetHeap()->undefined_value();
4548 }
4549
4550
4551 void JSObject::DefineAccessor(Handle<JSObject> object,
4552                               Handle<String> name,
4553                               Handle<Object> getter,
4554                               Handle<Object> setter,
4555                               PropertyAttributes attributes) {
4556   CALL_HEAP_FUNCTION_VOID(
4557       object->GetIsolate(),
4558       object->DefineAccessor(*name, *getter, *setter, attributes));
4559 }
4560
4561 MaybeObject* JSObject::DefineAccessor(String* name,
4562                                       Object* getter,
4563                                       Object* setter,
4564                                       PropertyAttributes attributes) {
4565   Isolate* isolate = GetIsolate();
4566   // Check access rights if needed.
4567   if (IsAccessCheckNeeded() &&
4568       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4569     isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4570     return isolate->heap()->undefined_value();
4571   }
4572
4573   if (IsJSGlobalProxy()) {
4574     Object* proto = GetPrototype();
4575     if (proto->IsNull()) return this;
4576     ASSERT(proto->IsJSGlobalObject());
4577     return JSObject::cast(proto)->DefineAccessor(
4578         name, getter, setter, attributes);
4579   }
4580
4581   // Make sure that the top context does not change when doing callbacks or
4582   // interceptor calls.
4583   AssertNoContextChange ncc;
4584
4585   // Try to flatten before operating on the string.
4586   name->TryFlatten();
4587
4588   if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
4589
4590   uint32_t index = 0;
4591   return name->AsArrayIndex(&index) ?
4592       DefineElementAccessor(index, getter, setter, attributes) :
4593       DefinePropertyAccessor(name, getter, setter, attributes);
4594 }
4595
4596
4597 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
4598   Isolate* isolate = GetIsolate();
4599   String* name = String::cast(info->name());
4600   // Check access rights if needed.
4601   if (IsAccessCheckNeeded() &&
4602       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4603     isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4604     return isolate->heap()->undefined_value();
4605   }
4606
4607   if (IsJSGlobalProxy()) {
4608     Object* proto = GetPrototype();
4609     if (proto->IsNull()) return this;
4610     ASSERT(proto->IsJSGlobalObject());
4611     return JSObject::cast(proto)->DefineAccessor(info);
4612   }
4613
4614   // Make sure that the top context does not change when doing callbacks or
4615   // interceptor calls.
4616   AssertNoContextChange ncc;
4617
4618   // Try to flatten before operating on the string.
4619   name->TryFlatten();
4620
4621   if (!CanSetCallback(name)) {
4622     return isolate->heap()->undefined_value();
4623   }
4624
4625   uint32_t index = 0;
4626   bool is_element = name->AsArrayIndex(&index);
4627
4628   if (is_element) {
4629     if (IsJSArray()) return isolate->heap()->undefined_value();
4630
4631     // Accessors overwrite previous callbacks (cf. with getters/setters).
4632     switch (GetElementsKind()) {
4633       case FAST_SMI_ONLY_ELEMENTS:
4634       case FAST_ELEMENTS:
4635       case FAST_DOUBLE_ELEMENTS:
4636         break;
4637       case EXTERNAL_PIXEL_ELEMENTS:
4638       case EXTERNAL_BYTE_ELEMENTS:
4639       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4640       case EXTERNAL_SHORT_ELEMENTS:
4641       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4642       case EXTERNAL_INT_ELEMENTS:
4643       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4644       case EXTERNAL_FLOAT_ELEMENTS:
4645       case EXTERNAL_DOUBLE_ELEMENTS:
4646         // Ignore getters and setters on pixel and external array
4647         // elements.
4648         return isolate->heap()->undefined_value();
4649       case DICTIONARY_ELEMENTS:
4650         break;
4651       case NON_STRICT_ARGUMENTS_ELEMENTS:
4652         UNIMPLEMENTED();
4653         break;
4654     }
4655
4656     { MaybeObject* maybe_ok =
4657           SetElementCallback(index, info, info->property_attributes());
4658       if (maybe_ok->IsFailure()) return maybe_ok;
4659     }
4660   } else {
4661     // Lookup the name.
4662     LookupResult result(isolate);
4663     LocalLookup(name, &result);
4664     // ES5 forbids turning a property into an accessor if it's not
4665     // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
4666     if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) {
4667       return isolate->heap()->undefined_value();
4668     }
4669     { MaybeObject* maybe_ok =
4670           SetPropertyCallback(name, info, info->property_attributes());
4671       if (maybe_ok->IsFailure()) return maybe_ok;
4672     }
4673   }
4674
4675   return this;
4676 }
4677
4678
4679 Object* JSObject::LookupAccessor(String* name, AccessorComponent component) {
4680   Heap* heap = GetHeap();
4681
4682   // Make sure that the top context does not change when doing callbacks or
4683   // interceptor calls.
4684   AssertNoContextChange ncc;
4685
4686   // Check access rights if needed.
4687   if (IsAccessCheckNeeded() &&
4688       !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
4689     heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
4690     return heap->undefined_value();
4691   }
4692
4693   // Make the lookup and include prototypes.
4694   uint32_t index = 0;
4695   if (name->AsArrayIndex(&index)) {
4696     for (Object* obj = this;
4697          obj != heap->null_value();
4698          obj = JSObject::cast(obj)->GetPrototype()) {
4699       JSObject* js_object = JSObject::cast(obj);
4700       if (js_object->HasDictionaryElements()) {
4701         SeededNumberDictionary* dictionary = js_object->element_dictionary();
4702         int entry = dictionary->FindEntry(index);
4703         if (entry != SeededNumberDictionary::kNotFound) {
4704           Object* element = dictionary->ValueAt(entry);
4705           if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
4706               element->IsAccessorPair()) {
4707             return AccessorPair::cast(element)->GetComponent(component);
4708           }
4709         }
4710       }
4711     }
4712   } else {
4713     for (Object* obj = this;
4714          obj != heap->null_value();
4715          obj = JSObject::cast(obj)->GetPrototype()) {
4716       LookupResult result(heap->isolate());
4717       JSObject::cast(obj)->LocalLookup(name, &result);
4718       if (result.IsProperty()) {
4719         if (result.IsReadOnly()) return heap->undefined_value();
4720         if (result.type() == CALLBACKS) {
4721           Object* obj = result.GetCallbackObject();
4722           if (obj->IsAccessorPair()) {
4723             return AccessorPair::cast(obj)->GetComponent(component);
4724           }
4725         }
4726       }
4727     }
4728   }
4729   return heap->undefined_value();
4730 }
4731
4732
4733 Object* JSObject::SlowReverseLookup(Object* value) {
4734   if (HasFastProperties()) {
4735     DescriptorArray* descs = map()->instance_descriptors();
4736     for (int i = 0; i < descs->number_of_descriptors(); i++) {
4737       if (descs->GetType(i) == FIELD) {
4738         if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
4739           return descs->GetKey(i);
4740         }
4741       } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
4742         if (descs->GetConstantFunction(i) == value) {
4743           return descs->GetKey(i);
4744         }
4745       }
4746     }
4747     return GetHeap()->undefined_value();
4748   } else {
4749     return property_dictionary()->SlowReverseLookup(value);
4750   }
4751 }
4752
4753
4754 MaybeObject* Map::CopyDropDescriptors() {
4755   Heap* heap = GetHeap();
4756   Object* result;
4757   { MaybeObject* maybe_result =
4758         heap->AllocateMap(instance_type(), instance_size());
4759     if (!maybe_result->ToObject(&result)) return maybe_result;
4760   }
4761   Map::cast(result)->set_prototype(prototype());
4762   Map::cast(result)->set_constructor(constructor());
4763   // Don't copy descriptors, so map transitions always remain a forest.
4764   // If we retained the same descriptors we would have two maps
4765   // pointing to the same transition which is bad because the garbage
4766   // collector relies on being able to reverse pointers from transitions
4767   // to maps.  If properties need to be retained use CopyDropTransitions.
4768   Map::cast(result)->clear_instance_descriptors();
4769   // Please note instance_type and instance_size are set when allocated.
4770   Map::cast(result)->set_inobject_properties(inobject_properties());
4771   Map::cast(result)->set_unused_property_fields(unused_property_fields());
4772
4773   // If the map has pre-allocated properties always start out with a descriptor
4774   // array describing these properties.
4775   if (pre_allocated_property_fields() > 0) {
4776     ASSERT(constructor()->IsJSFunction());
4777     JSFunction* ctor = JSFunction::cast(constructor());
4778     Object* descriptors;
4779     { MaybeObject* maybe_descriptors =
4780           ctor->initial_map()->instance_descriptors()->RemoveTransitions();
4781       if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
4782     }
4783     Map::cast(result)->set_instance_descriptors(
4784         DescriptorArray::cast(descriptors));
4785     Map::cast(result)->set_pre_allocated_property_fields(
4786         pre_allocated_property_fields());
4787   }
4788   Map::cast(result)->set_bit_field(bit_field());
4789   Map::cast(result)->set_bit_field2(bit_field2());
4790   Map::cast(result)->set_bit_field3(bit_field3());
4791   Map::cast(result)->set_is_shared(false);
4792   Map::cast(result)->ClearCodeCache(heap);
4793   return result;
4794 }
4795
4796
4797 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
4798                                  NormalizedMapSharingMode sharing) {
4799   int new_instance_size = instance_size();
4800   if (mode == CLEAR_INOBJECT_PROPERTIES) {
4801     new_instance_size -= inobject_properties() * kPointerSize;
4802   }
4803
4804   Object* result;
4805   { MaybeObject* maybe_result =
4806         GetHeap()->AllocateMap(instance_type(), new_instance_size);
4807     if (!maybe_result->ToObject(&result)) return maybe_result;
4808   }
4809
4810   if (mode != CLEAR_INOBJECT_PROPERTIES) {
4811     Map::cast(result)->set_inobject_properties(inobject_properties());
4812   }
4813
4814   Map::cast(result)->set_prototype(prototype());
4815   Map::cast(result)->set_constructor(constructor());
4816
4817   Map::cast(result)->set_bit_field(bit_field());
4818   Map::cast(result)->set_bit_field2(bit_field2());
4819   Map::cast(result)->set_bit_field3(bit_field3());
4820
4821   Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
4822
4823 #ifdef DEBUG
4824   if (FLAG_verify_heap && Map::cast(result)->is_shared()) {
4825     Map::cast(result)->SharedMapVerify();
4826   }
4827 #endif
4828
4829   return result;
4830 }
4831
4832
4833 MaybeObject* Map::CopyDropTransitions() {
4834   Object* new_map;
4835   { MaybeObject* maybe_new_map = CopyDropDescriptors();
4836     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
4837   }
4838   Object* descriptors;
4839   { MaybeObject* maybe_descriptors =
4840         instance_descriptors()->RemoveTransitions();
4841     if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
4842   }
4843   cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
4844   return new_map;
4845 }
4846
4847 void Map::UpdateCodeCache(Handle<Map> map,
4848                           Handle<String> name,
4849                           Handle<Code> code) {
4850   Isolate* isolate = map->GetIsolate();
4851   CALL_HEAP_FUNCTION_VOID(isolate,
4852                           map->UpdateCodeCache(*name, *code));
4853 }
4854
4855 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
4856   // Allocate the code cache if not present.
4857   if (code_cache()->IsFixedArray()) {
4858     Object* result;
4859     { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
4860       if (!maybe_result->ToObject(&result)) return maybe_result;
4861     }
4862     set_code_cache(result);
4863   }
4864
4865   // Update the code cache.
4866   return CodeCache::cast(code_cache())->Update(name, code);
4867 }
4868
4869
4870 Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
4871   // Do a lookup if a code cache exists.
4872   if (!code_cache()->IsFixedArray()) {
4873     return CodeCache::cast(code_cache())->Lookup(name, flags);
4874   } else {
4875     return GetHeap()->undefined_value();
4876   }
4877 }
4878
4879
4880 int Map::IndexInCodeCache(Object* name, Code* code) {
4881   // Get the internal index if a code cache exists.
4882   if (!code_cache()->IsFixedArray()) {
4883     return CodeCache::cast(code_cache())->GetIndex(name, code);
4884   }
4885   return -1;
4886 }
4887
4888
4889 void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
4890   // No GC is supposed to happen between a call to IndexInCodeCache and
4891   // RemoveFromCodeCache so the code cache must be there.
4892   ASSERT(!code_cache()->IsFixedArray());
4893   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
4894 }
4895
4896
4897 // An iterator over all map transitions in an descriptor array, reusing the map
4898 // field of the contens array while it is running.
4899 class IntrusiveMapTransitionIterator {
4900  public:
4901   explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array)
4902       : descriptor_array_(descriptor_array) { }
4903
4904   void Start() {
4905     ASSERT(!IsIterating());
4906     if (HasContentArray()) *ContentHeader() = Smi::FromInt(0);
4907   }
4908
4909   bool IsIterating() {
4910     return HasContentArray() && (*ContentHeader())->IsSmi();
4911   }
4912
4913   Map* Next() {
4914     ASSERT(IsIterating());
4915     FixedArray* contents = ContentArray();
4916     // Attention, tricky index manipulation ahead: Every entry in the contents
4917     // array consists of a value/details pair, so the index is typically even.
4918     // An exception is made for CALLBACKS entries: An even index means we look
4919     // at its getter, and an odd index means we look at its setter.
4920     int index = Smi::cast(*ContentHeader())->value();
4921     while (index < contents->length()) {
4922       PropertyDetails details(Smi::cast(contents->get(index | 1)));
4923       switch (details.type()) {
4924         case MAP_TRANSITION:
4925         case CONSTANT_TRANSITION:
4926         case ELEMENTS_TRANSITION:
4927           // We definitely have a map transition.
4928           *ContentHeader() = Smi::FromInt(index + 2);
4929           return static_cast<Map*>(contents->get(index));
4930         case CALLBACKS: {
4931           // We might have a map transition in a getter or in a setter.
4932           AccessorPair* accessors =
4933               static_cast<AccessorPair*>(contents->get(index & ~1));
4934           Object* accessor =
4935               ((index & 1) == 0) ? accessors->getter() : accessors->setter();
4936           index++;
4937           if (accessor->IsMap()) {
4938             *ContentHeader() = Smi::FromInt(index);
4939             return static_cast<Map*>(accessor);
4940           }
4941           break;
4942         }
4943         case NORMAL:
4944         case FIELD:
4945         case CONSTANT_FUNCTION:
4946         case HANDLER:
4947         case INTERCEPTOR:
4948         case NULL_DESCRIPTOR:
4949           // We definitely have no map transition.
4950           index += 2;
4951           break;
4952       }
4953     }
4954     *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map();
4955     return NULL;
4956   }
4957
4958  private:
4959   bool HasContentArray() {
4960     return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex;
4961   }
4962
4963   FixedArray* ContentArray() {
4964     Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex);
4965     return static_cast<FixedArray*>(array);
4966   }
4967
4968   Object** ContentHeader() {
4969     return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset);
4970   }
4971
4972   DescriptorArray* descriptor_array_;
4973 };
4974
4975
4976 // An iterator over all prototype transitions, reusing the map field of the
4977 // underlying array while it is running.
4978 class IntrusivePrototypeTransitionIterator {
4979  public:
4980   explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans)
4981       : proto_trans_(proto_trans) { }
4982
4983   void Start() {
4984     ASSERT(!IsIterating());
4985     if (HasTransitions()) *Header() = Smi::FromInt(0);
4986   }
4987
4988   bool IsIterating() {
4989     return HasTransitions() && (*Header())->IsSmi();
4990   }
4991
4992   Map* Next() {
4993     ASSERT(IsIterating());
4994     int transitionNumber = Smi::cast(*Header())->value();
4995     if (transitionNumber < NumberOfTransitions()) {
4996       *Header() = Smi::FromInt(transitionNumber + 1);
4997       return GetTransition(transitionNumber);
4998     }
4999     *Header() = proto_trans_->GetHeap()->fixed_array_map();
5000     return NULL;
5001   }
5002
5003  private:
5004   bool HasTransitions() {
5005     return proto_trans_->map()->IsSmi() || proto_trans_->IsFixedArray();
5006   }
5007
5008   Object** Header() {
5009     return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
5010   }
5011
5012   int NumberOfTransitions() {
5013     ASSERT(HasTransitions());
5014     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
5015     Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
5016     return Smi::cast(num)->value();
5017   }
5018
5019   Map* GetTransition(int transitionNumber) {
5020     ASSERT(HasTransitions());
5021     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
5022     return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
5023   }
5024
5025   int IndexFor(int transitionNumber) {
5026     return Map::kProtoTransitionHeaderSize +
5027         Map::kProtoTransitionMapOffset +
5028         transitionNumber * Map::kProtoTransitionElementsPerEntry;
5029   }
5030
5031   HeapObject* proto_trans_;
5032 };
5033
5034
5035 // To traverse the transition tree iteratively, we have to store two kinds of
5036 // information in a map: The parent map in the traversal and which children of a
5037 // node have already been visited. To do this without additional memory, we
5038 // temporarily reuse two maps with known values:
5039 //
5040 //  (1) The map of the map temporarily holds the parent, and is restored to the
5041 //      meta map afterwards.
5042 //
5043 //  (2) The info which children have already been visited depends on which part
5044 //      of the map we currently iterate:
5045 //
5046 //    (a) If we currently follow normal map transitions, we temporarily store
5047 //        the current index in the map of the FixedArray of the desciptor
5048 //        array's contents, and restore it to the fixed array map afterwards.
5049 //        Note that a single descriptor can have 0, 1, or 2 transitions.
5050 //
5051 //    (b) If we currently follow prototype transitions, we temporarily store
5052 //        the current index in the map of the FixedArray holding the prototype
5053 //        transitions, and restore it to the fixed array map afterwards.
5054 //
5055 // Note that the child iterator is just a concatenation of two iterators: One
5056 // iterating over map transitions and one iterating over prototype transisitons.
5057 class TraversableMap : public Map {
5058  public:
5059   // Record the parent in the traversal within this map. Note that this destroys
5060   // this map's map!
5061   void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
5062
5063   // Reset the current map's map, returning the parent previously stored in it.
5064   TraversableMap* GetAndResetParent() {
5065     TraversableMap* old_parent = static_cast<TraversableMap*>(map());
5066     set_map_no_write_barrier(GetHeap()->meta_map());
5067     return old_parent;
5068   }
5069
5070   // Start iterating over this map's children, possibly destroying a FixedArray
5071   // map (see explanation above).
5072   void ChildIteratorStart() {
5073     IntrusiveMapTransitionIterator(instance_descriptors()).Start();
5074     IntrusivePrototypeTransitionIterator(
5075         unchecked_prototype_transitions()).Start();
5076   }
5077
5078   // If we have an unvisited child map, return that one and advance. If we have
5079   // none, return NULL and reset any destroyed FixedArray maps.
5080   TraversableMap* ChildIteratorNext() {
5081     IntrusiveMapTransitionIterator descriptor_iterator(instance_descriptors());
5082     if (descriptor_iterator.IsIterating()) {
5083       Map* next = descriptor_iterator.Next();
5084       if (next != NULL) return static_cast<TraversableMap*>(next);
5085     }
5086     IntrusivePrototypeTransitionIterator
5087         proto_iterator(unchecked_prototype_transitions());
5088     if (proto_iterator.IsIterating()) {
5089       Map* next = proto_iterator.Next();
5090       if (next != NULL) return static_cast<TraversableMap*>(next);
5091     }
5092     return NULL;
5093   }
5094 };
5095
5096
5097 // Traverse the transition tree in postorder without using the C++ stack by
5098 // doing pointer reversal.
5099 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
5100   TraversableMap* current = static_cast<TraversableMap*>(this);
5101   current->ChildIteratorStart();
5102   while (true) {
5103     TraversableMap* child = current->ChildIteratorNext();
5104     if (child != NULL) {
5105       child->ChildIteratorStart();
5106       child->SetParent(current);
5107       current = child;
5108     } else {
5109       TraversableMap* parent = current->GetAndResetParent();
5110       callback(current, data);
5111       if (current == this) break;
5112       current = parent;
5113     }
5114   }
5115 }
5116
5117
5118 MaybeObject* CodeCache::Update(String* name, Code* code) {
5119   // The number of monomorphic stubs for normal load/store/call IC's can grow to
5120   // a large number and therefore they need to go into a hash table. They are
5121   // used to load global properties from cells.
5122   if (code->type() == NORMAL) {
5123     // Make sure that a hash table is allocated for the normal load code cache.
5124     if (normal_type_cache()->IsUndefined()) {
5125       Object* result;
5126       { MaybeObject* maybe_result =
5127             CodeCacheHashTable::Allocate(CodeCacheHashTable::kInitialSize);
5128         if (!maybe_result->ToObject(&result)) return maybe_result;
5129       }
5130       set_normal_type_cache(result);
5131     }
5132     return UpdateNormalTypeCache(name, code);
5133   } else {
5134     ASSERT(default_cache()->IsFixedArray());
5135     return UpdateDefaultCache(name, code);
5136   }
5137 }
5138
5139
5140 MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) {
5141   // When updating the default code cache we disregard the type encoded in the
5142   // flags. This allows call constant stubs to overwrite call field
5143   // stubs, etc.
5144   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
5145
5146   // First check whether we can update existing code cache without
5147   // extending it.
5148   FixedArray* cache = default_cache();
5149   int length = cache->length();
5150   int deleted_index = -1;
5151   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
5152     Object* key = cache->get(i);
5153     if (key->IsNull()) {
5154       if (deleted_index < 0) deleted_index = i;
5155       continue;
5156     }
5157     if (key->IsUndefined()) {
5158       if (deleted_index >= 0) i = deleted_index;
5159       cache->set(i + kCodeCacheEntryNameOffset, name);
5160       cache->set(i + kCodeCacheEntryCodeOffset, code);
5161       return this;
5162     }
5163     if (name->Equals(String::cast(key))) {
5164       Code::Flags found =
5165           Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
5166       if (Code::RemoveTypeFromFlags(found) == flags) {
5167         cache->set(i + kCodeCacheEntryCodeOffset, code);
5168         return this;
5169       }
5170     }
5171   }
5172
5173   // Reached the end of the code cache.  If there were deleted
5174   // elements, reuse the space for the first of them.
5175   if (deleted_index >= 0) {
5176     cache->set(deleted_index + kCodeCacheEntryNameOffset, name);
5177     cache->set(deleted_index + kCodeCacheEntryCodeOffset, code);
5178     return this;
5179   }
5180
5181   // Extend the code cache with some new entries (at least one). Must be a
5182   // multiple of the entry size.
5183   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
5184   new_length = new_length - new_length % kCodeCacheEntrySize;
5185   ASSERT((new_length % kCodeCacheEntrySize) == 0);
5186   Object* result;
5187   { MaybeObject* maybe_result = cache->CopySize(new_length);
5188     if (!maybe_result->ToObject(&result)) return maybe_result;
5189   }
5190
5191   // Add the (name, code) pair to the new cache.
5192   cache = FixedArray::cast(result);
5193   cache->set(length + kCodeCacheEntryNameOffset, name);
5194   cache->set(length + kCodeCacheEntryCodeOffset, code);
5195   set_default_cache(cache);
5196   return this;
5197 }
5198
5199
5200 MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) {
5201   // Adding a new entry can cause a new cache to be allocated.
5202   CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5203   Object* new_cache;
5204   { MaybeObject* maybe_new_cache = cache->Put(name, code);
5205     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5206   }
5207   set_normal_type_cache(new_cache);
5208   return this;
5209 }
5210
5211
5212 Object* CodeCache::Lookup(String* name, Code::Flags flags) {
5213   if (Code::ExtractTypeFromFlags(flags) == NORMAL) {
5214     return LookupNormalTypeCache(name, flags);
5215   } else {
5216     return LookupDefaultCache(name, flags);
5217   }
5218 }
5219
5220
5221 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) {
5222   FixedArray* cache = default_cache();
5223   int length = cache->length();
5224   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
5225     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
5226     // Skip deleted elements.
5227     if (key->IsNull()) continue;
5228     if (key->IsUndefined()) return key;
5229     if (name->Equals(String::cast(key))) {
5230       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
5231       if (code->flags() == flags) {
5232         return code;
5233       }
5234     }
5235   }
5236   return GetHeap()->undefined_value();
5237 }
5238
5239
5240 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) {
5241   if (!normal_type_cache()->IsUndefined()) {
5242     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5243     return cache->Lookup(name, flags);
5244   } else {
5245     return GetHeap()->undefined_value();
5246   }
5247 }
5248
5249
5250 int CodeCache::GetIndex(Object* name, Code* code) {
5251   if (code->type() == NORMAL) {
5252     if (normal_type_cache()->IsUndefined()) return -1;
5253     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5254     return cache->GetIndex(String::cast(name), code->flags());
5255   }
5256
5257   FixedArray* array = default_cache();
5258   int len = array->length();
5259   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
5260     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
5261   }
5262   return -1;
5263 }
5264
5265
5266 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
5267   if (code->type() == NORMAL) {
5268     ASSERT(!normal_type_cache()->IsUndefined());
5269     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
5270     ASSERT(cache->GetIndex(String::cast(name), code->flags()) == index);
5271     cache->RemoveByIndex(index);
5272   } else {
5273     FixedArray* array = default_cache();
5274     ASSERT(array->length() >= index && array->get(index)->IsCode());
5275     // Use null instead of undefined for deleted elements to distinguish
5276     // deleted elements from unused elements.  This distinction is used
5277     // when looking up in the cache and when updating the cache.
5278     ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
5279     array->set_null(index - 1);  // Name.
5280     array->set_null(index);  // Code.
5281   }
5282 }
5283
5284
5285 // The key in the code cache hash table consists of the property name and the
5286 // code object. The actual match is on the name and the code flags. If a key
5287 // is created using the flags and not a code object it can only be used for
5288 // lookup not to create a new entry.
5289 class CodeCacheHashTableKey : public HashTableKey {
5290  public:
5291   CodeCacheHashTableKey(String* name, Code::Flags flags)
5292       : name_(name), flags_(flags), code_(NULL) { }
5293
5294   CodeCacheHashTableKey(String* name, Code* code)
5295       : name_(name),
5296         flags_(code->flags()),
5297         code_(code) { }
5298
5299
5300   bool IsMatch(Object* other) {
5301     if (!other->IsFixedArray()) return false;
5302     FixedArray* pair = FixedArray::cast(other);
5303     String* name = String::cast(pair->get(0));
5304     Code::Flags flags = Code::cast(pair->get(1))->flags();
5305     if (flags != flags_) {
5306       return false;
5307     }
5308     return name_->Equals(name);
5309   }
5310
5311   static uint32_t NameFlagsHashHelper(String* name, Code::Flags flags) {
5312     return name->Hash() ^ flags;
5313   }
5314
5315   uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); }
5316
5317   uint32_t HashForObject(Object* obj) {
5318     FixedArray* pair = FixedArray::cast(obj);
5319     String* name = String::cast(pair->get(0));
5320     Code* code = Code::cast(pair->get(1));
5321     return NameFlagsHashHelper(name, code->flags());
5322   }
5323
5324   MUST_USE_RESULT MaybeObject* AsObject() {
5325     ASSERT(code_ != NULL);
5326     Object* obj;
5327     { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2);
5328       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5329     }
5330     FixedArray* pair = FixedArray::cast(obj);
5331     pair->set(0, name_);
5332     pair->set(1, code_);
5333     return pair;
5334   }
5335
5336  private:
5337   String* name_;
5338   Code::Flags flags_;
5339   // TODO(jkummerow): We should be able to get by without this.
5340   Code* code_;
5341 };
5342
5343
5344 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) {
5345   CodeCacheHashTableKey key(name, flags);
5346   int entry = FindEntry(&key);
5347   if (entry == kNotFound) return GetHeap()->undefined_value();
5348   return get(EntryToIndex(entry) + 1);
5349 }
5350
5351
5352 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) {
5353   CodeCacheHashTableKey key(name, code);
5354   Object* obj;
5355   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5356     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5357   }
5358
5359   // Don't use |this|, as the table might have grown.
5360   CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
5361
5362   int entry = cache->FindInsertionEntry(key.Hash());
5363   Object* k;
5364   { MaybeObject* maybe_k = key.AsObject();
5365     if (!maybe_k->ToObject(&k)) return maybe_k;
5366   }
5367
5368   cache->set(EntryToIndex(entry), k);
5369   cache->set(EntryToIndex(entry) + 1, code);
5370   cache->ElementAdded();
5371   return cache;
5372 }
5373
5374
5375 int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) {
5376   CodeCacheHashTableKey key(name, flags);
5377   int entry = FindEntry(&key);
5378   return (entry == kNotFound) ? -1 : entry;
5379 }
5380
5381
5382 void CodeCacheHashTable::RemoveByIndex(int index) {
5383   ASSERT(index >= 0);
5384   Heap* heap = GetHeap();
5385   set(EntryToIndex(index), heap->the_hole_value());
5386   set(EntryToIndex(index) + 1, heap->the_hole_value());
5387   ElementRemoved();
5388 }
5389
5390
5391 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache,
5392                                   MapHandleList* maps,
5393                                   Code::Flags flags,
5394                                   Handle<Code> code) {
5395   Isolate* isolate = cache->GetIsolate();
5396   CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code));
5397 }
5398
5399
5400 MaybeObject* PolymorphicCodeCache::Update(MapHandleList* maps,
5401                                           Code::Flags flags,
5402                                           Code* code) {
5403   // Initialize cache if necessary.
5404   if (cache()->IsUndefined()) {
5405     Object* result;
5406     { MaybeObject* maybe_result =
5407           PolymorphicCodeCacheHashTable::Allocate(
5408               PolymorphicCodeCacheHashTable::kInitialSize);
5409       if (!maybe_result->ToObject(&result)) return maybe_result;
5410     }
5411     set_cache(result);
5412   } else {
5413     // This entry shouldn't be contained in the cache yet.
5414     ASSERT(PolymorphicCodeCacheHashTable::cast(cache())
5415                ->Lookup(maps, flags)->IsUndefined());
5416   }
5417   PolymorphicCodeCacheHashTable* hash_table =
5418       PolymorphicCodeCacheHashTable::cast(cache());
5419   Object* new_cache;
5420   { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
5421     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
5422   }
5423   set_cache(new_cache);
5424   return this;
5425 }
5426
5427
5428 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
5429                                             Code::Flags flags) {
5430   if (!cache()->IsUndefined()) {
5431     PolymorphicCodeCacheHashTable* hash_table =
5432         PolymorphicCodeCacheHashTable::cast(cache());
5433     return Handle<Object>(hash_table->Lookup(maps, flags));
5434   } else {
5435     return GetIsolate()->factory()->undefined_value();
5436   }
5437 }
5438
5439
5440 // Despite their name, object of this class are not stored in the actual
5441 // hash table; instead they're temporarily used for lookups. It is therefore
5442 // safe to have a weak (non-owning) pointer to a MapList as a member field.
5443 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
5444  public:
5445   // Callers must ensure that |maps| outlives the newly constructed object.
5446   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
5447       : maps_(maps),
5448         code_flags_(code_flags) {}
5449
5450   bool IsMatch(Object* other) {
5451     MapHandleList other_maps(kDefaultListAllocationSize);
5452     int other_flags;
5453     FromObject(other, &other_flags, &other_maps);
5454     if (code_flags_ != other_flags) return false;
5455     if (maps_->length() != other_maps.length()) return false;
5456     // Compare just the hashes first because it's faster.
5457     int this_hash = MapsHashHelper(maps_, code_flags_);
5458     int other_hash = MapsHashHelper(&other_maps, other_flags);
5459     if (this_hash != other_hash) return false;
5460
5461     // Full comparison: for each map in maps_, look for an equivalent map in
5462     // other_maps. This implementation is slow, but probably good enough for
5463     // now because the lists are short (<= 4 elements currently).
5464     for (int i = 0; i < maps_->length(); ++i) {
5465       bool match_found = false;
5466       for (int j = 0; j < other_maps.length(); ++j) {
5467         if (*(maps_->at(i)) == *(other_maps.at(j))) {
5468           match_found = true;
5469           break;
5470         }
5471       }
5472       if (!match_found) return false;
5473     }
5474     return true;
5475   }
5476
5477   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
5478     uint32_t hash = code_flags;
5479     for (int i = 0; i < maps->length(); ++i) {
5480       hash ^= maps->at(i)->Hash();
5481     }
5482     return hash;
5483   }
5484
5485   uint32_t Hash() {
5486     return MapsHashHelper(maps_, code_flags_);
5487   }
5488
5489   uint32_t HashForObject(Object* obj) {
5490     MapHandleList other_maps(kDefaultListAllocationSize);
5491     int other_flags;
5492     FromObject(obj, &other_flags, &other_maps);
5493     return MapsHashHelper(&other_maps, other_flags);
5494   }
5495
5496   MUST_USE_RESULT MaybeObject* AsObject() {
5497     Object* obj;
5498     // The maps in |maps_| must be copied to a newly allocated FixedArray,
5499     // both because the referenced MapList is short-lived, and because C++
5500     // objects can't be stored in the heap anyway.
5501     { MaybeObject* maybe_obj =
5502         HEAP->AllocateUninitializedFixedArray(maps_->length() + 1);
5503       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5504     }
5505     FixedArray* list = FixedArray::cast(obj);
5506     list->set(0, Smi::FromInt(code_flags_));
5507     for (int i = 0; i < maps_->length(); ++i) {
5508       list->set(i + 1, *maps_->at(i));
5509     }
5510     return list;
5511   }
5512
5513  private:
5514   static MapHandleList* FromObject(Object* obj,
5515                                    int* code_flags,
5516                                    MapHandleList* maps) {
5517     FixedArray* list = FixedArray::cast(obj);
5518     maps->Rewind(0);
5519     *code_flags = Smi::cast(list->get(0))->value();
5520     for (int i = 1; i < list->length(); ++i) {
5521       maps->Add(Handle<Map>(Map::cast(list->get(i))));
5522     }
5523     return maps;
5524   }
5525
5526   MapHandleList* maps_;  // weak.
5527   int code_flags_;
5528   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
5529 };
5530
5531
5532 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
5533                                               int code_flags) {
5534   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5535   int entry = FindEntry(&key);
5536   if (entry == kNotFound) return GetHeap()->undefined_value();
5537   return get(EntryToIndex(entry) + 1);
5538 }
5539
5540
5541 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps,
5542                                                 int code_flags,
5543                                                 Code* code) {
5544   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
5545   Object* obj;
5546   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
5547     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5548   }
5549   PolymorphicCodeCacheHashTable* cache =
5550       reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
5551   int entry = cache->FindInsertionEntry(key.Hash());
5552   { MaybeObject* maybe_obj = key.AsObject();
5553     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5554   }
5555   cache->set(EntryToIndex(entry), obj);
5556   cache->set(EntryToIndex(entry) + 1, code);
5557   cache->ElementAdded();
5558   return cache;
5559 }
5560
5561
5562 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
5563   ElementsAccessor* accessor = array->GetElementsAccessor();
5564   MaybeObject* maybe_result =
5565       accessor->AddElementsToFixedArray(array, array, this);
5566   FixedArray* result;
5567   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
5568 #ifdef DEBUG
5569   if (FLAG_enable_slow_asserts) {
5570     for (int i = 0; i < result->length(); i++) {
5571       Object* current = result->get(i);
5572       ASSERT(current->IsNumber() || current->IsString());
5573     }
5574   }
5575 #endif
5576   return result;
5577 }
5578
5579
5580 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
5581   ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
5582   MaybeObject* maybe_result =
5583       accessor->AddElementsToFixedArray(NULL, NULL, this, other);
5584   FixedArray* result;
5585   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
5586 #ifdef DEBUG
5587   if (FLAG_enable_slow_asserts) {
5588     for (int i = 0; i < result->length(); i++) {
5589       Object* current = result->get(i);
5590       ASSERT(current->IsNumber() || current->IsString());
5591     }
5592   }
5593 #endif
5594   return result;
5595 }
5596
5597
5598 MaybeObject* FixedArray::CopySize(int new_length) {
5599   Heap* heap = GetHeap();
5600   if (new_length == 0) return heap->empty_fixed_array();
5601   Object* obj;
5602   { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length);
5603     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5604   }
5605   FixedArray* result = FixedArray::cast(obj);
5606   // Copy the content
5607   AssertNoAllocation no_gc;
5608   int len = length();
5609   if (new_length < len) len = new_length;
5610   // We are taking the map from the old fixed array so the map is sure to
5611   // be an immortal immutable object.
5612   result->set_map_no_write_barrier(map());
5613   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
5614   for (int i = 0; i < len; i++) {
5615     result->set(i, get(i), mode);
5616   }
5617   return result;
5618 }
5619
5620
5621 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
5622   AssertNoAllocation no_gc;
5623   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
5624   for (int index = 0; index < len; index++) {
5625     dest->set(dest_pos+index, get(pos+index), mode);
5626   }
5627 }
5628
5629
5630 #ifdef DEBUG
5631 bool FixedArray::IsEqualTo(FixedArray* other) {
5632   if (length() != other->length()) return false;
5633   for (int i = 0 ; i < length(); ++i) {
5634     if (get(i) != other->get(i)) return false;
5635   }
5636   return true;
5637 }
5638 #endif
5639
5640
5641 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
5642   Heap* heap = Isolate::Current()->heap();
5643   if (number_of_descriptors == 0) {
5644     return heap->empty_descriptor_array();
5645   }
5646   // Allocate the array of keys.
5647   Object* array;
5648   { MaybeObject* maybe_array =
5649         heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
5650     if (!maybe_array->ToObject(&array)) return maybe_array;
5651   }
5652   // Do not use DescriptorArray::cast on incomplete object.
5653   FixedArray* result = FixedArray::cast(array);
5654
5655   // Allocate the content array and set it in the descriptor array.
5656   { MaybeObject* maybe_array =
5657         heap->AllocateFixedArray(number_of_descriptors << 1);
5658     if (!maybe_array->ToObject(&array)) return maybe_array;
5659   }
5660   result->set(kBitField3StorageIndex, Smi::FromInt(0));
5661   result->set(kContentArrayIndex, array);
5662   result->set(kEnumerationIndexIndex,
5663               Smi::FromInt(PropertyDetails::kInitialIndex));
5664   return result;
5665 }
5666
5667
5668 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
5669                                    FixedArray* new_cache,
5670                                    Object* new_index_cache) {
5671   ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
5672   ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
5673   if (HasEnumCache()) {
5674     FixedArray::cast(get(kEnumerationIndexIndex))->
5675       set(kEnumCacheBridgeCacheIndex, new_cache);
5676     FixedArray::cast(get(kEnumerationIndexIndex))->
5677       set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
5678   } else {
5679     if (IsEmpty()) return;  // Do nothing for empty descriptor array.
5680     FixedArray::cast(bridge_storage)->
5681       set(kEnumCacheBridgeCacheIndex, new_cache);
5682     FixedArray::cast(bridge_storage)->
5683       set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
5684     NoWriteBarrierSet(FixedArray::cast(bridge_storage),
5685                       kEnumCacheBridgeEnumIndex,
5686                       get(kEnumerationIndexIndex));
5687     set(kEnumerationIndexIndex, bridge_storage);
5688   }
5689 }
5690
5691
5692 static bool InsertionPointFound(String* key1, String* key2) {
5693   return key1->Hash() > key2->Hash() || key1 == key2;
5694 }
5695
5696
5697 void DescriptorArray::CopyFrom(Handle<DescriptorArray> dst,
5698                                int dst_index,
5699                                Handle<DescriptorArray> src,
5700                                int src_index,
5701                                const WhitenessWitness& witness) {
5702   CALL_HEAP_FUNCTION_VOID(dst->GetIsolate(),
5703                           dst->CopyFrom(dst_index, *src, src_index, witness));
5704 }
5705
5706
5707 MaybeObject* DescriptorArray::CopyFrom(int dst_index,
5708                                        DescriptorArray* src,
5709                                        int src_index,
5710                                        const WhitenessWitness& witness) {
5711   Object* value = src->GetValue(src_index);
5712   PropertyDetails details = src->GetDetails(src_index);
5713   if (details.type() == CALLBACKS && value->IsAccessorPair()) {
5714     MaybeObject* maybe_copy =
5715         AccessorPair::cast(value)->CopyWithoutTransitions();
5716     if (!maybe_copy->To(&value)) return maybe_copy;
5717   }
5718   Descriptor desc(src->GetKey(src_index), value, details);
5719   Set(dst_index, &desc, witness);
5720   return this;
5721 }
5722
5723
5724 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor,
5725                                          TransitionFlag transition_flag) {
5726   // Transitions are only kept when inserting another transition.
5727   // This precondition is not required by this function's implementation, but
5728   // is currently required by the semantics of maps, so we check it.
5729   // Conversely, we filter after replacing, so replacing a transition and
5730   // removing all other transitions is not supported.
5731   bool remove_transitions = transition_flag == REMOVE_TRANSITIONS;
5732   ASSERT(remove_transitions == !descriptor->ContainsTransition());
5733   ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR);
5734
5735   // Ensure the key is a symbol.
5736   { MaybeObject* maybe_result = descriptor->KeyToSymbol();
5737     if (maybe_result->IsFailure()) return maybe_result;
5738   }
5739
5740   int new_size = 0;
5741   for (int i = 0; i < number_of_descriptors(); i++) {
5742     if (IsNullDescriptor(i)) continue;
5743     if (remove_transitions && IsTransitionOnly(i)) continue;
5744     new_size++;
5745   }
5746
5747   // If key is in descriptor, we replace it in-place when filtering.
5748   // Count a null descriptor for key as inserted, not replaced.
5749   int index = Search(descriptor->GetKey());
5750   const bool replacing = (index != kNotFound);
5751   bool keep_enumeration_index = false;
5752   if (replacing) {
5753     // We are replacing an existing descriptor.  We keep the enumeration
5754     // index of a visible property.
5755     PropertyType t = GetDetails(index).type();
5756     if (t == CONSTANT_FUNCTION ||
5757         t == FIELD ||
5758         t == CALLBACKS ||
5759         t == INTERCEPTOR) {
5760       keep_enumeration_index = true;
5761     } else if (remove_transitions) {
5762      // Replaced descriptor has been counted as removed if it is
5763      // a transition that will be replaced.  Adjust count in this case.
5764       ++new_size;
5765     }
5766   } else {
5767     ++new_size;
5768   }
5769
5770   DescriptorArray* new_descriptors;
5771   { MaybeObject* maybe_result = Allocate(new_size);
5772     if (!maybe_result->To(&new_descriptors)) return maybe_result;
5773   }
5774
5775   DescriptorArray::WhitenessWitness witness(new_descriptors);
5776
5777   // Set the enumeration index in the descriptors and set the enumeration index
5778   // in the result.
5779   int enumeration_index = NextEnumerationIndex();
5780   if (!descriptor->ContainsTransition()) {
5781     if (keep_enumeration_index) {
5782       descriptor->SetEnumerationIndex(GetDetails(index).index());
5783     } else {
5784       descriptor->SetEnumerationIndex(enumeration_index);
5785       ++enumeration_index;
5786     }
5787   }
5788   new_descriptors->SetNextEnumerationIndex(enumeration_index);
5789
5790   // Copy the descriptors, filtering out transitions and null descriptors,
5791   // and inserting or replacing a descriptor.
5792   int to_index = 0;
5793   int insertion_index = -1;
5794   int from_index = 0;
5795   while (from_index < number_of_descriptors()) {
5796     if (insertion_index < 0 &&
5797         InsertionPointFound(GetKey(from_index), descriptor->GetKey())) {
5798       insertion_index = to_index++;
5799       if (replacing) from_index++;
5800     } else {
5801       if (!(IsNullDescriptor(from_index) ||
5802             (remove_transitions && IsTransitionOnly(from_index)))) {
5803         MaybeObject* copy_result =
5804             new_descriptors->CopyFrom(to_index++, this, from_index, witness);
5805         if (copy_result->IsFailure()) return copy_result;
5806       }
5807       from_index++;
5808     }
5809   }
5810   if (insertion_index < 0) insertion_index = to_index++;
5811   new_descriptors->Set(insertion_index, descriptor, witness);
5812
5813   ASSERT(to_index == new_descriptors->number_of_descriptors());
5814   SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5815
5816   return new_descriptors;
5817 }
5818
5819
5820 MaybeObject* DescriptorArray::RemoveTransitions() {
5821   // Allocate the new descriptor array.
5822   int new_number_of_descriptors = 0;
5823   for (int i = 0; i < number_of_descriptors(); i++) {
5824     if (IsProperty(i)) new_number_of_descriptors++;
5825   }
5826   DescriptorArray* new_descriptors;
5827   { MaybeObject* maybe_result = Allocate(new_number_of_descriptors);
5828     if (!maybe_result->To(&new_descriptors)) return maybe_result;
5829   }
5830
5831   // Copy the content.
5832   DescriptorArray::WhitenessWitness witness(new_descriptors);
5833   int next_descriptor = 0;
5834   for (int i = 0; i < number_of_descriptors(); i++) {
5835     if (IsProperty(i)) {
5836       MaybeObject* copy_result =
5837           new_descriptors->CopyFrom(next_descriptor++, this, i, witness);
5838       if (copy_result->IsFailure()) return copy_result;
5839     }
5840   }
5841   ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
5842
5843   return new_descriptors;
5844 }
5845
5846
5847 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
5848   // In-place heap sort.
5849   int len = number_of_descriptors();
5850
5851   // Bottom-up max-heap construction.
5852   // Index of the last node with children
5853   const int max_parent_index = (len / 2) - 1;
5854   for (int i = max_parent_index; i >= 0; --i) {
5855     int parent_index = i;
5856     const uint32_t parent_hash = GetKey(i)->Hash();
5857     while (parent_index <= max_parent_index) {
5858       int child_index = 2 * parent_index + 1;
5859       uint32_t child_hash = GetKey(child_index)->Hash();
5860       if (child_index + 1 < len) {
5861         uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
5862         if (right_child_hash > child_hash) {
5863           child_index++;
5864           child_hash = right_child_hash;
5865         }
5866       }
5867       if (child_hash <= parent_hash) break;
5868       NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
5869       // Now element at child_index could be < its children.
5870       parent_index = child_index;  // parent_hash remains correct.
5871     }
5872   }
5873
5874   // Extract elements and create sorted array.
5875   for (int i = len - 1; i > 0; --i) {
5876     // Put max element at the back of the array.
5877     NoIncrementalWriteBarrierSwapDescriptors(0, i);
5878     // Shift down the new top element.
5879     int parent_index = 0;
5880     const uint32_t parent_hash = GetKey(parent_index)->Hash();
5881     const int max_parent_index = (i / 2) - 1;
5882     while (parent_index <= max_parent_index) {
5883       int child_index = parent_index * 2 + 1;
5884       uint32_t child_hash = GetKey(child_index)->Hash();
5885       if (child_index + 1 < i) {
5886         uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
5887         if (right_child_hash > child_hash) {
5888           child_index++;
5889           child_hash = right_child_hash;
5890         }
5891       }
5892       if (child_hash <= parent_hash) break;
5893       NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
5894       parent_index = child_index;
5895     }
5896   }
5897 }
5898
5899
5900 void DescriptorArray::Sort(const WhitenessWitness& witness) {
5901   SortUnchecked(witness);
5902   SLOW_ASSERT(IsSortedNoDuplicates());
5903 }
5904
5905
5906 int DescriptorArray::BinarySearch(String* name, int low, int high) {
5907   uint32_t hash = name->Hash();
5908
5909   while (low <= high) {
5910     int mid = (low + high) / 2;
5911     String* mid_name = GetKey(mid);
5912     uint32_t mid_hash = mid_name->Hash();
5913
5914     if (mid_hash > hash) {
5915       high = mid - 1;
5916       continue;
5917     }
5918     if (mid_hash < hash) {
5919       low = mid + 1;
5920       continue;
5921     }
5922     // Found an element with the same hash-code.
5923     ASSERT(hash == mid_hash);
5924     // There might be more, so we find the first one and
5925     // check them all to see if we have a match.
5926     if (name == mid_name  && !IsNullDescriptor(mid)) return mid;
5927     while ((mid > low) && (GetKey(mid - 1)->Hash() == hash)) mid--;
5928     for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) {
5929       if (GetKey(mid)->Equals(name) && !IsNullDescriptor(mid)) return mid;
5930     }
5931     break;
5932   }
5933   return kNotFound;
5934 }
5935
5936
5937 int DescriptorArray::LinearSearch(String* name, int len) {
5938   uint32_t hash = name->Hash();
5939   for (int number = 0; number < len; number++) {
5940     String* entry = GetKey(number);
5941     if ((entry->Hash() == hash) &&
5942         name->Equals(entry) &&
5943         !IsNullDescriptor(number)) {
5944       return number;
5945     }
5946   }
5947   return kNotFound;
5948 }
5949
5950
5951 MaybeObject* AccessorPair::CopyWithoutTransitions() {
5952   Heap* heap = GetHeap();
5953   AccessorPair* copy;
5954   { MaybeObject* maybe_copy = heap->AllocateAccessorPair();
5955     if (!maybe_copy->To(&copy)) return maybe_copy;
5956   }
5957   copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter());
5958   copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter());
5959   return copy;
5960 }
5961
5962
5963 Object* AccessorPair::GetComponent(AccessorComponent component) {
5964     Object* accessor = (component == ACCESSOR_GETTER) ? getter() : setter();
5965     return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
5966 }
5967
5968
5969 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count,
5970                                                PretenureFlag pretenure) {
5971   ASSERT(deopt_entry_count > 0);
5972   return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count),
5973                                   pretenure);
5974 }
5975
5976
5977 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points,
5978                                                 PretenureFlag pretenure) {
5979   if (number_of_deopt_points == 0) return HEAP->empty_fixed_array();
5980   return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points),
5981                                   pretenure);
5982 }
5983
5984
5985 #ifdef DEBUG
5986 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
5987   if (IsEmpty()) return other->IsEmpty();
5988   if (other->IsEmpty()) return false;
5989   if (length() != other->length()) return false;
5990   for (int i = 0; i < length(); ++i) {
5991     if (get(i) != other->get(i) && i != kContentArrayIndex) return false;
5992   }
5993   return GetContentArray()->IsEqualTo(other->GetContentArray());
5994 }
5995 #endif
5996
5997
5998 bool String::LooksValid() {
5999   if (!Isolate::Current()->heap()->Contains(this)) return false;
6000   return true;
6001 }
6002
6003
6004 String::FlatContent String::GetFlatContent() {
6005   int length = this->length();
6006   StringShape shape(this);
6007   String* string = this;
6008   int offset = 0;
6009   if (shape.representation_tag() == kConsStringTag) {
6010     ConsString* cons = ConsString::cast(string);
6011     if (cons->second()->length() != 0) {
6012       return FlatContent();
6013     }
6014     string = cons->first();
6015     shape = StringShape(string);
6016   }
6017   if (shape.representation_tag() == kSlicedStringTag) {
6018     SlicedString* slice = SlicedString::cast(string);
6019     offset = slice->offset();
6020     string = slice->parent();
6021     shape = StringShape(string);
6022     ASSERT(shape.representation_tag() != kConsStringTag &&
6023            shape.representation_tag() != kSlicedStringTag);
6024   }
6025   if (shape.encoding_tag() == kAsciiStringTag) {
6026     const char* start;
6027     if (shape.representation_tag() == kSeqStringTag) {
6028       start = SeqAsciiString::cast(string)->GetChars();
6029     } else {
6030       start = ExternalAsciiString::cast(string)->GetChars();
6031     }
6032     return FlatContent(Vector<const char>(start + offset, length));
6033   } else {
6034     ASSERT(shape.encoding_tag() == kTwoByteStringTag);
6035     const uc16* start;
6036     if (shape.representation_tag() == kSeqStringTag) {
6037       start = SeqTwoByteString::cast(string)->GetChars();
6038     } else {
6039       start = ExternalTwoByteString::cast(string)->GetChars();
6040     }
6041     return FlatContent(Vector<const uc16>(start + offset, length));
6042   }
6043 }
6044
6045
6046 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
6047                                           RobustnessFlag robust_flag,
6048                                           int offset,
6049                                           int length,
6050                                           int* length_return) {
6051   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
6052     return SmartArrayPointer<char>(NULL);
6053   }
6054   Heap* heap = GetHeap();
6055
6056   // Negative length means the to the end of the string.
6057   if (length < 0) length = kMaxInt - offset;
6058
6059   // Compute the size of the UTF-8 string. Start at the specified offset.
6060   Access<StringInputBuffer> buffer(
6061       heap->isolate()->objects_string_input_buffer());
6062   buffer->Reset(offset, this);
6063   int character_position = offset;
6064   int utf8_bytes = 0;
6065   int last = unibrow::Utf16::kNoPreviousCharacter;
6066   while (buffer->has_more() && character_position++ < offset + length) {
6067     uint16_t character = buffer->GetNext();
6068     utf8_bytes += unibrow::Utf8::Length(character, last);
6069     last = character;
6070   }
6071
6072   if (length_return) {
6073     *length_return = utf8_bytes;
6074   }
6075
6076   char* result = NewArray<char>(utf8_bytes + 1);
6077
6078   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
6079   buffer->Rewind();
6080   buffer->Seek(offset);
6081   character_position = offset;
6082   int utf8_byte_position = 0;
6083   last = unibrow::Utf16::kNoPreviousCharacter;
6084   while (buffer->has_more() && character_position++ < offset + length) {
6085     uint16_t character = buffer->GetNext();
6086     if (allow_nulls == DISALLOW_NULLS && character == 0) {
6087       character = ' ';
6088     }
6089     utf8_byte_position +=
6090         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
6091     last = character;
6092   }
6093   result[utf8_byte_position] = 0;
6094   return SmartArrayPointer<char>(result);
6095 }
6096
6097
6098 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
6099                                           RobustnessFlag robust_flag,
6100                                           int* length_return) {
6101   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
6102 }
6103
6104
6105 const uc16* String::GetTwoByteData() {
6106   return GetTwoByteData(0);
6107 }
6108
6109
6110 const uc16* String::GetTwoByteData(unsigned start) {
6111   ASSERT(!IsAsciiRepresentationUnderneath());
6112   switch (StringShape(this).representation_tag()) {
6113     case kSeqStringTag:
6114       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
6115     case kExternalStringTag:
6116       return ExternalTwoByteString::cast(this)->
6117         ExternalTwoByteStringGetData(start);
6118     case kSlicedStringTag: {
6119       SlicedString* slice = SlicedString::cast(this);
6120       return slice->parent()->GetTwoByteData(start + slice->offset());
6121     }
6122     case kConsStringTag:
6123       UNREACHABLE();
6124       return NULL;
6125   }
6126   UNREACHABLE();
6127   return NULL;
6128 }
6129
6130
6131 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
6132   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
6133     return SmartArrayPointer<uc16>();
6134   }
6135   Heap* heap = GetHeap();
6136
6137   Access<StringInputBuffer> buffer(
6138       heap->isolate()->objects_string_input_buffer());
6139   buffer->Reset(this);
6140
6141   uc16* result = NewArray<uc16>(length() + 1);
6142
6143   int i = 0;
6144   while (buffer->has_more()) {
6145     uint16_t character = buffer->GetNext();
6146     result[i++] = character;
6147   }
6148   result[i] = 0;
6149   return SmartArrayPointer<uc16>(result);
6150 }
6151
6152
6153 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
6154   return reinterpret_cast<uc16*>(
6155       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
6156 }
6157
6158
6159 void SeqTwoByteString::SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
6160                                                            unsigned* offset_ptr,
6161                                                            unsigned max_chars) {
6162   unsigned chars_read = 0;
6163   unsigned offset = *offset_ptr;
6164   while (chars_read < max_chars) {
6165     uint16_t c = *reinterpret_cast<uint16_t*>(
6166         reinterpret_cast<char*>(this) -
6167             kHeapObjectTag + kHeaderSize + offset * kShortSize);
6168     if (c <= kMaxAsciiCharCode) {
6169       // Fast case for ASCII characters.   Cursor is an input output argument.
6170       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
6171                                                           rbb->util_buffer,
6172                                                           rbb->capacity,
6173                                                           rbb->cursor)) {
6174         break;
6175       }
6176     } else {
6177       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
6178                                                              rbb->util_buffer,
6179                                                              rbb->capacity,
6180                                                              rbb->cursor)) {
6181         break;
6182       }
6183     }
6184     offset++;
6185     chars_read++;
6186   }
6187   *offset_ptr = offset;
6188   rbb->remaining += chars_read;
6189 }
6190
6191
6192 const unibrow::byte* SeqAsciiString::SeqAsciiStringReadBlock(
6193     unsigned* remaining,
6194     unsigned* offset_ptr,
6195     unsigned max_chars) {
6196   const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
6197       kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
6198   *remaining = max_chars;
6199   *offset_ptr += max_chars;
6200   return b;
6201 }
6202
6203
6204 // This will iterate unless the block of string data spans two 'halves' of
6205 // a ConsString, in which case it will recurse.  Since the block of string
6206 // data to be read has a maximum size this limits the maximum recursion
6207 // depth to something sane.  Since C++ does not have tail call recursion
6208 // elimination, the iteration must be explicit. Since this is not an
6209 // -IntoBuffer method it can delegate to one of the efficient
6210 // *AsciiStringReadBlock routines.
6211 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
6212                                                      unsigned* offset_ptr,
6213                                                      unsigned max_chars) {
6214   ConsString* current = this;
6215   unsigned offset = *offset_ptr;
6216   int offset_correction = 0;
6217
6218   while (true) {
6219     String* left = current->first();
6220     unsigned left_length = (unsigned)left->length();
6221     if (left_length > offset &&
6222         (max_chars <= left_length - offset ||
6223          (rbb->capacity <= left_length - offset &&
6224           (max_chars = left_length - offset, true)))) {  // comma operator!
6225       // Left hand side only - iterate unless we have reached the bottom of
6226       // the cons tree.  The assignment on the left of the comma operator is
6227       // in order to make use of the fact that the -IntoBuffer routines can
6228       // produce at most 'capacity' characters.  This enables us to postpone
6229       // the point where we switch to the -IntoBuffer routines (below) in order
6230       // to maximize the chances of delegating a big chunk of work to the
6231       // efficient *AsciiStringReadBlock routines.
6232       if (StringShape(left).IsCons()) {
6233         current = ConsString::cast(left);
6234         continue;
6235       } else {
6236         const unibrow::byte* answer =
6237             String::ReadBlock(left, rbb, &offset, max_chars);
6238         *offset_ptr = offset + offset_correction;
6239         return answer;
6240       }
6241     } else if (left_length <= offset) {
6242       // Right hand side only - iterate unless we have reached the bottom of
6243       // the cons tree.
6244       String* right = current->second();
6245       offset -= left_length;
6246       offset_correction += left_length;
6247       if (StringShape(right).IsCons()) {
6248         current = ConsString::cast(right);
6249         continue;
6250       } else {
6251         const unibrow::byte* answer =
6252             String::ReadBlock(right, rbb, &offset, max_chars);
6253         *offset_ptr = offset + offset_correction;
6254         return answer;
6255       }
6256     } else {
6257       // The block to be read spans two sides of the ConsString, so we call the
6258       // -IntoBuffer version, which will recurse.  The -IntoBuffer methods
6259       // are able to assemble data from several part strings because they use
6260       // the util_buffer to store their data and never return direct pointers
6261       // to their storage.  We don't try to read more than the buffer capacity
6262       // here or we can get too much recursion.
6263       ASSERT(rbb->remaining == 0);
6264       ASSERT(rbb->cursor == 0);
6265       current->ConsStringReadBlockIntoBuffer(
6266           rbb,
6267           &offset,
6268           max_chars > rbb->capacity ? rbb->capacity : max_chars);
6269       *offset_ptr = offset + offset_correction;
6270       return rbb->util_buffer;
6271     }
6272   }
6273 }
6274
6275
6276 const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock(
6277       unsigned* remaining,
6278       unsigned* offset_ptr,
6279       unsigned max_chars) {
6280   // Cast const char* to unibrow::byte* (signedness difference).
6281   const unibrow::byte* b =
6282       reinterpret_cast<const unibrow::byte*>(GetChars()) + *offset_ptr;
6283   *remaining = max_chars;
6284   *offset_ptr += max_chars;
6285   return b;
6286 }
6287
6288
6289 void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer(
6290       ReadBlockBuffer* rbb,
6291       unsigned* offset_ptr,
6292       unsigned max_chars) {
6293   unsigned chars_read = 0;
6294   unsigned offset = *offset_ptr;
6295   const uint16_t* data = GetChars();
6296   while (chars_read < max_chars) {
6297     uint16_t c = data[offset];
6298     if (c <= kMaxAsciiCharCode) {
6299       // Fast case for ASCII characters. Cursor is an input output argument.
6300       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
6301                                                           rbb->util_buffer,
6302                                                           rbb->capacity,
6303                                                           rbb->cursor))
6304         break;
6305     } else {
6306       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
6307                                                              rbb->util_buffer,
6308                                                              rbb->capacity,
6309                                                              rbb->cursor))
6310         break;
6311     }
6312     offset++;
6313     chars_read++;
6314   }
6315   *offset_ptr = offset;
6316   rbb->remaining += chars_read;
6317 }
6318
6319
6320 void SeqAsciiString::SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
6321                                                  unsigned* offset_ptr,
6322                                                  unsigned max_chars) {
6323   unsigned capacity = rbb->capacity - rbb->cursor;
6324   if (max_chars > capacity) max_chars = capacity;
6325   memcpy(rbb->util_buffer + rbb->cursor,
6326          reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
6327              *offset_ptr * kCharSize,
6328          max_chars);
6329   rbb->remaining += max_chars;
6330   *offset_ptr += max_chars;
6331   rbb->cursor += max_chars;
6332 }
6333
6334
6335 void ExternalAsciiString::ExternalAsciiStringReadBlockIntoBuffer(
6336       ReadBlockBuffer* rbb,
6337       unsigned* offset_ptr,
6338       unsigned max_chars) {
6339   unsigned capacity = rbb->capacity - rbb->cursor;
6340   if (max_chars > capacity) max_chars = capacity;
6341   memcpy(rbb->util_buffer + rbb->cursor, GetChars() + *offset_ptr, max_chars);
6342   rbb->remaining += max_chars;
6343   *offset_ptr += max_chars;
6344   rbb->cursor += max_chars;
6345 }
6346
6347
6348 // This method determines the type of string involved and then copies
6349 // a whole chunk of characters into a buffer, or returns a pointer to a buffer
6350 // where they can be found.  The pointer is not necessarily valid across a GC
6351 // (see AsciiStringReadBlock).
6352 const unibrow::byte* String::ReadBlock(String* input,
6353                                        ReadBlockBuffer* rbb,
6354                                        unsigned* offset_ptr,
6355                                        unsigned max_chars) {
6356   ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
6357   if (max_chars == 0) {
6358     rbb->remaining = 0;
6359     return NULL;
6360   }
6361   switch (StringShape(input).representation_tag()) {
6362     case kSeqStringTag:
6363       if (input->IsAsciiRepresentation()) {
6364         SeqAsciiString* str = SeqAsciiString::cast(input);
6365         return str->SeqAsciiStringReadBlock(&rbb->remaining,
6366                                             offset_ptr,
6367                                             max_chars);
6368       } else {
6369         SeqTwoByteString* str = SeqTwoByteString::cast(input);
6370         str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
6371                                                  offset_ptr,
6372                                                  max_chars);
6373         return rbb->util_buffer;
6374       }
6375     case kConsStringTag:
6376       return ConsString::cast(input)->ConsStringReadBlock(rbb,
6377                                                           offset_ptr,
6378                                                           max_chars);
6379     case kExternalStringTag:
6380       if (input->IsAsciiRepresentation()) {
6381         return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
6382             &rbb->remaining,
6383             offset_ptr,
6384             max_chars);
6385       } else {
6386         ExternalTwoByteString::cast(input)->
6387             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6388                                                      offset_ptr,
6389                                                      max_chars);
6390         return rbb->util_buffer;
6391       }
6392     case kSlicedStringTag:
6393       return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
6394                                                               offset_ptr,
6395                                                               max_chars);
6396     default:
6397       break;
6398   }
6399
6400   UNREACHABLE();
6401   return 0;
6402 }
6403
6404
6405 void Relocatable::PostGarbageCollectionProcessing() {
6406   Isolate* isolate = Isolate::Current();
6407   Relocatable* current = isolate->relocatable_top();
6408   while (current != NULL) {
6409     current->PostGarbageCollection();
6410     current = current->prev_;
6411   }
6412 }
6413
6414
6415 // Reserve space for statics needing saving and restoring.
6416 int Relocatable::ArchiveSpacePerThread() {
6417   return sizeof(Isolate::Current()->relocatable_top());
6418 }
6419
6420
6421 // Archive statics that are thread local.
6422 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
6423   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
6424   isolate->set_relocatable_top(NULL);
6425   return to + ArchiveSpacePerThread();
6426 }
6427
6428
6429 // Restore statics that are thread local.
6430 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
6431   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
6432   return from + ArchiveSpacePerThread();
6433 }
6434
6435
6436 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
6437   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
6438   Iterate(v, top);
6439   return thread_storage + ArchiveSpacePerThread();
6440 }
6441
6442
6443 void Relocatable::Iterate(ObjectVisitor* v) {
6444   Isolate* isolate = Isolate::Current();
6445   Iterate(v, isolate->relocatable_top());
6446 }
6447
6448
6449 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
6450   Relocatable* current = top;
6451   while (current != NULL) {
6452     current->IterateInstance(v);
6453     current = current->prev_;
6454   }
6455 }
6456
6457
6458 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
6459     : Relocatable(isolate),
6460       str_(str.location()),
6461       length_(str->length()) {
6462   PostGarbageCollection();
6463 }
6464
6465
6466 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
6467     : Relocatable(isolate),
6468       str_(0),
6469       is_ascii_(true),
6470       length_(input.length()),
6471       start_(input.start()) { }
6472
6473
6474 void FlatStringReader::PostGarbageCollection() {
6475   if (str_ == NULL) return;
6476   Handle<String> str(str_);
6477   ASSERT(str->IsFlat());
6478   String::FlatContent content = str->GetFlatContent();
6479   ASSERT(content.IsFlat());
6480   is_ascii_ = content.IsAscii();
6481   if (is_ascii_) {
6482     start_ = content.ToAsciiVector().start();
6483   } else {
6484     start_ = content.ToUC16Vector().start();
6485   }
6486 }
6487
6488
6489 void StringInputBuffer::Seek(unsigned pos) {
6490   Reset(pos, input_);
6491 }
6492
6493
6494 void SafeStringInputBuffer::Seek(unsigned pos) {
6495   Reset(pos, input_);
6496 }
6497
6498
6499 // This method determines the type of string involved and then copies
6500 // a whole chunk of characters into a buffer.  It can be used with strings
6501 // that have been glued together to form a ConsString and which must cooperate
6502 // to fill up a buffer.
6503 void String::ReadBlockIntoBuffer(String* input,
6504                                  ReadBlockBuffer* rbb,
6505                                  unsigned* offset_ptr,
6506                                  unsigned max_chars) {
6507   ASSERT(*offset_ptr <= (unsigned)input->length());
6508   if (max_chars == 0) return;
6509
6510   switch (StringShape(input).representation_tag()) {
6511     case kSeqStringTag:
6512       if (input->IsAsciiRepresentation()) {
6513         SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
6514                                                                  offset_ptr,
6515                                                                  max_chars);
6516         return;
6517       } else {
6518         SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
6519                                                                      offset_ptr,
6520                                                                      max_chars);
6521         return;
6522       }
6523     case kConsStringTag:
6524       ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
6525                                                              offset_ptr,
6526                                                              max_chars);
6527       return;
6528     case kExternalStringTag:
6529       if (input->IsAsciiRepresentation()) {
6530         ExternalAsciiString::cast(input)->
6531             ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
6532       } else {
6533         ExternalTwoByteString::cast(input)->
6534             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
6535                                                      offset_ptr,
6536                                                      max_chars);
6537        }
6538        return;
6539     case kSlicedStringTag:
6540       SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
6541                                                                  offset_ptr,
6542                                                                  max_chars);
6543       return;
6544     default:
6545       break;
6546   }
6547
6548   UNREACHABLE();
6549   return;
6550 }
6551
6552
6553 const unibrow::byte* String::ReadBlock(String* input,
6554                                        unibrow::byte* util_buffer,
6555                                        unsigned capacity,
6556                                        unsigned* remaining,
6557                                        unsigned* offset_ptr) {
6558   ASSERT(*offset_ptr <= (unsigned)input->length());
6559   unsigned chars = input->length() - *offset_ptr;
6560   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6561   const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
6562   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6563   *remaining = rbb.remaining;
6564   return answer;
6565 }
6566
6567
6568 const unibrow::byte* String::ReadBlock(String** raw_input,
6569                                        unibrow::byte* util_buffer,
6570                                        unsigned capacity,
6571                                        unsigned* remaining,
6572                                        unsigned* offset_ptr) {
6573   Handle<String> input(raw_input);
6574   ASSERT(*offset_ptr <= (unsigned)input->length());
6575   unsigned chars = input->length() - *offset_ptr;
6576   if (chars > capacity) chars = capacity;
6577   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
6578   ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
6579   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
6580   *remaining = rbb.remaining;
6581   return rbb.util_buffer;
6582 }
6583
6584
6585 // This will iterate unless the block of string data spans two 'halves' of
6586 // a ConsString, in which case it will recurse.  Since the block of string
6587 // data to be read has a maximum size this limits the maximum recursion
6588 // depth to something sane.  Since C++ does not have tail call recursion
6589 // elimination, the iteration must be explicit.
6590 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
6591                                                unsigned* offset_ptr,
6592                                                unsigned max_chars) {
6593   ConsString* current = this;
6594   unsigned offset = *offset_ptr;
6595   int offset_correction = 0;
6596
6597   while (true) {
6598     String* left = current->first();
6599     unsigned left_length = (unsigned)left->length();
6600     if (left_length > offset &&
6601       max_chars <= left_length - offset) {
6602       // Left hand side only - iterate unless we have reached the bottom of
6603       // the cons tree.
6604       if (StringShape(left).IsCons()) {
6605         current = ConsString::cast(left);
6606         continue;
6607       } else {
6608         String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
6609         *offset_ptr = offset + offset_correction;
6610         return;
6611       }
6612     } else if (left_length <= offset) {
6613       // Right hand side only - iterate unless we have reached the bottom of
6614       // the cons tree.
6615       offset -= left_length;
6616       offset_correction += left_length;
6617       String* right = current->second();
6618       if (StringShape(right).IsCons()) {
6619         current = ConsString::cast(right);
6620         continue;
6621       } else {
6622         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6623         *offset_ptr = offset + offset_correction;
6624         return;
6625       }
6626     } else {
6627       // The block to be read spans two sides of the ConsString, so we recurse.
6628       // First recurse on the left.
6629       max_chars -= left_length - offset;
6630       String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
6631       // We may have reached the max or there may not have been enough space
6632       // in the buffer for the characters in the left hand side.
6633       if (offset == left_length) {
6634         // Recurse on the right.
6635         String* right = String::cast(current->second());
6636         offset -= left_length;
6637         offset_correction += left_length;
6638         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
6639       }
6640       *offset_ptr = offset + offset_correction;
6641       return;
6642     }
6643   }
6644 }
6645
6646
6647 uint16_t ConsString::ConsStringGet(int index) {
6648   ASSERT(index >= 0 && index < this->length());
6649
6650   // Check for a flattened cons string
6651   if (second()->length() == 0) {
6652     String* left = first();
6653     return left->Get(index);
6654   }
6655
6656   String* string = String::cast(this);
6657
6658   while (true) {
6659     if (StringShape(string).IsCons()) {
6660       ConsString* cons_string = ConsString::cast(string);
6661       String* left = cons_string->first();
6662       if (left->length() > index) {
6663         string = left;
6664       } else {
6665         index -= left->length();
6666         string = cons_string->second();
6667       }
6668     } else {
6669       return string->Get(index);
6670     }
6671   }
6672
6673   UNREACHABLE();
6674   return 0;
6675 }
6676
6677
6678 uint16_t SlicedString::SlicedStringGet(int index) {
6679   return parent()->Get(offset() + index);
6680 }
6681
6682
6683 const unibrow::byte* SlicedString::SlicedStringReadBlock(
6684     ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6685   unsigned offset = this->offset();
6686   *offset_ptr += offset;
6687   const unibrow::byte* answer = String::ReadBlock(String::cast(parent()),
6688                                                   buffer, offset_ptr, chars);
6689   *offset_ptr -= offset;
6690   return answer;
6691 }
6692
6693
6694 void SlicedString::SlicedStringReadBlockIntoBuffer(
6695     ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6696   unsigned offset = this->offset();
6697   *offset_ptr += offset;
6698   String::ReadBlockIntoBuffer(String::cast(parent()),
6699                               buffer, offset_ptr, chars);
6700   *offset_ptr -= offset;
6701 }
6702
6703 template <typename sinkchar>
6704 void String::WriteToFlat(String* src,
6705                          sinkchar* sink,
6706                          int f,
6707                          int t) {
6708   String* source = src;
6709   int from = f;
6710   int to = t;
6711   while (true) {
6712     ASSERT(0 <= from && from <= to && to <= source->length());
6713     switch (StringShape(source).full_representation_tag()) {
6714       case kAsciiStringTag | kExternalStringTag: {
6715         CopyChars(sink,
6716                   ExternalAsciiString::cast(source)->GetChars() + from,
6717                   to - from);
6718         return;
6719       }
6720       case kTwoByteStringTag | kExternalStringTag: {
6721         const uc16* data =
6722             ExternalTwoByteString::cast(source)->GetChars();
6723         CopyChars(sink,
6724                   data + from,
6725                   to - from);
6726         return;
6727       }
6728       case kAsciiStringTag | kSeqStringTag: {
6729         CopyChars(sink,
6730                   SeqAsciiString::cast(source)->GetChars() + from,
6731                   to - from);
6732         return;
6733       }
6734       case kTwoByteStringTag | kSeqStringTag: {
6735         CopyChars(sink,
6736                   SeqTwoByteString::cast(source)->GetChars() + from,
6737                   to - from);
6738         return;
6739       }
6740       case kAsciiStringTag | kConsStringTag:
6741       case kTwoByteStringTag | kConsStringTag: {
6742         ConsString* cons_string = ConsString::cast(source);
6743         String* first = cons_string->first();
6744         int boundary = first->length();
6745         if (to - boundary >= boundary - from) {
6746           // Right hand side is longer.  Recurse over left.
6747           if (from < boundary) {
6748             WriteToFlat(first, sink, from, boundary);
6749             sink += boundary - from;
6750             from = 0;
6751           } else {
6752             from -= boundary;
6753           }
6754           to -= boundary;
6755           source = cons_string->second();
6756         } else {
6757           // Left hand side is longer.  Recurse over right.
6758           if (to > boundary) {
6759             String* second = cons_string->second();
6760             // When repeatedly appending to a string, we get a cons string that
6761             // is unbalanced to the left, a list, essentially.  We inline the
6762             // common case of sequential ascii right child.
6763             if (to - boundary == 1) {
6764               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
6765             } else if (second->IsSeqAsciiString()) {
6766               CopyChars(sink + boundary - from,
6767                         SeqAsciiString::cast(second)->GetChars(),
6768                         to - boundary);
6769             } else {
6770               WriteToFlat(second,
6771                           sink + boundary - from,
6772                           0,
6773                           to - boundary);
6774             }
6775             to = boundary;
6776           }
6777           source = first;
6778         }
6779         break;
6780       }
6781       case kAsciiStringTag | kSlicedStringTag:
6782       case kTwoByteStringTag | kSlicedStringTag: {
6783         SlicedString* slice = SlicedString::cast(source);
6784         unsigned offset = slice->offset();
6785         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
6786         return;
6787       }
6788     }
6789   }
6790 }
6791
6792
6793 template <typename IteratorA, typename IteratorB>
6794 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
6795   // General slow case check.  We know that the ia and ib iterators
6796   // have the same length.
6797   while (ia->has_more()) {
6798     uint32_t ca = ia->GetNext();
6799     uint32_t cb = ib->GetNext();
6800     ASSERT(ca <= unibrow::Utf16::kMaxNonSurrogateCharCode);
6801     ASSERT(cb <= unibrow::Utf16::kMaxNonSurrogateCharCode);
6802     if (ca != cb)
6803       return false;
6804   }
6805   return true;
6806 }
6807
6808
6809 // Compares the contents of two strings by reading and comparing
6810 // int-sized blocks of characters.
6811 template <typename Char>
6812 static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
6813   int length = a.length();
6814   ASSERT_EQ(length, b.length());
6815   const Char* pa = a.start();
6816   const Char* pb = b.start();
6817   int i = 0;
6818 #ifndef V8_HOST_CAN_READ_UNALIGNED
6819   // If this architecture isn't comfortable reading unaligned ints
6820   // then we have to check that the strings are aligned before
6821   // comparing them blockwise.
6822   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
6823   uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
6824   uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
6825   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
6826 #endif
6827     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
6828     int endpoint = length - kStepSize;
6829     // Compare blocks until we reach near the end of the string.
6830     for (; i <= endpoint; i += kStepSize) {
6831       uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
6832       uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
6833       if (wa != wb) {
6834         return false;
6835       }
6836     }
6837 #ifndef V8_HOST_CAN_READ_UNALIGNED
6838   }
6839 #endif
6840   // Compare the remaining characters that didn't fit into a block.
6841   for (; i < length; i++) {
6842     if (a[i] != b[i]) {
6843       return false;
6844     }
6845   }
6846   return true;
6847 }
6848
6849
6850 template <typename IteratorA>
6851 static inline bool CompareStringContentsPartial(Isolate* isolate,
6852                                                 IteratorA* ia,
6853                                                 String* b) {
6854   String::FlatContent content = b->GetFlatContent();
6855   if (content.IsFlat()) {
6856     if (content.IsAscii()) {
6857       VectorIterator<char> ib(content.ToAsciiVector());
6858       return CompareStringContents(ia, &ib);
6859     } else {
6860       VectorIterator<uc16> ib(content.ToUC16Vector());
6861       return CompareStringContents(ia, &ib);
6862     }
6863   } else {
6864     isolate->objects_string_compare_buffer_b()->Reset(0, b);
6865     return CompareStringContents(ia,
6866                                  isolate->objects_string_compare_buffer_b());
6867   }
6868 }
6869
6870
6871 bool String::SlowEqualsExternal(uc16 *string, int length) {
6872   int len = this->length();
6873   if (len != length) return false;
6874   if (len == 0) return true;
6875
6876   // We know the strings are both non-empty. Compare the first chars
6877   // before we try to flatten the strings.
6878   if (this->Get(0) != string[0]) return false;
6879
6880   String* lhs = this->TryFlattenGetString();
6881
6882   if (lhs->IsFlat()) {
6883     String::FlatContent lhs_content = lhs->GetFlatContent();
6884     if (lhs->IsAsciiRepresentation()) {
6885       Vector<const char> vec1 = lhs_content.ToAsciiVector();
6886       VectorIterator<char> buf1(vec1);
6887       VectorIterator<uc16> ib(string, length);
6888       return CompareStringContents(&buf1, &ib);
6889     } else {
6890       Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
6891       Vector<const uc16> vec2(string, length);
6892       return CompareRawStringContents(vec1, vec2);
6893     }
6894   } else {
6895     Isolate* isolate = GetIsolate();
6896     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
6897     VectorIterator<uc16> ib(string, length);
6898     return CompareStringContents(isolate->objects_string_compare_buffer_a(),
6899                                  &ib);
6900   }
6901 }
6902
6903
6904 bool String::SlowEqualsExternal(char *string, int length) {
6905   int len = this->length();
6906   if (len != length) return false;
6907   if (len == 0) return true;
6908
6909   // We know the strings are both non-empty. Compare the first chars
6910   // before we try to flatten the strings.
6911   if (this->Get(0) != string[0]) return false;
6912
6913   String* lhs = this->TryFlattenGetString();
6914
6915   if (StringShape(lhs).IsSequentialAscii()) {
6916       const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
6917       return CompareRawStringContents(Vector<const char>(str1, len),
6918                                       Vector<const char>(string, len));
6919   }
6920
6921   if (lhs->IsFlat()) {
6922     String::FlatContent lhs_content = lhs->GetFlatContent();
6923     Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
6924     VectorIterator<const uc16> buf1(vec1);
6925     VectorIterator<char> buf2(string, length);
6926     return CompareStringContents(&buf1, &buf2);
6927   } else {
6928     Isolate* isolate = GetIsolate();
6929     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
6930     VectorIterator<char> ib(string, length);
6931     return CompareStringContents(isolate->objects_string_compare_buffer_a(),
6932                                  &ib);
6933   }
6934 }
6935
6936
6937 bool String::SlowEquals(String* other) {
6938   // Fast check: negative check with lengths.
6939   int len = length();
6940   if (len != other->length()) return false;
6941   if (len == 0) return true;
6942
6943   // Fast check: if hash code is computed for both strings
6944   // a fast negative check can be performed.
6945   if (HasHashCode() && other->HasHashCode()) {
6946 #ifdef DEBUG
6947     if (FLAG_enable_slow_asserts) {
6948       if (Hash() != other->Hash()) {
6949         bool found_difference = false;
6950         for (int i = 0; i < len; i++) {
6951           if (Get(i) != other->Get(i)) {
6952             found_difference = true;
6953             break;
6954           }
6955         }
6956         ASSERT(found_difference);
6957       }
6958     }
6959 #endif
6960     if (Hash() != other->Hash()) return false;
6961   }
6962
6963   // We know the strings are both non-empty. Compare the first chars
6964   // before we try to flatten the strings.
6965   if (this->Get(0) != other->Get(0)) return false;
6966
6967   String* lhs = this->TryFlattenGetString();
6968   String* rhs = other->TryFlattenGetString();
6969
6970   if (StringShape(lhs).IsSequentialAscii() &&
6971       StringShape(rhs).IsSequentialAscii()) {
6972     const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
6973     const char* str2 = SeqAsciiString::cast(rhs)->GetChars();
6974     return CompareRawStringContents(Vector<const char>(str1, len),
6975                                     Vector<const char>(str2, len));
6976   }
6977
6978   Isolate* isolate = GetIsolate();
6979   String::FlatContent lhs_content = lhs->GetFlatContent();
6980   String::FlatContent rhs_content = rhs->GetFlatContent();
6981   if (lhs_content.IsFlat()) {
6982     if (lhs_content.IsAscii()) {
6983       Vector<const char> vec1 = lhs_content.ToAsciiVector();
6984       if (rhs_content.IsFlat()) {
6985         if (rhs_content.IsAscii()) {
6986           Vector<const char> vec2 = rhs_content.ToAsciiVector();
6987           return CompareRawStringContents(vec1, vec2);
6988         } else {
6989           VectorIterator<char> buf1(vec1);
6990           VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
6991           return CompareStringContents(&buf1, &ib);
6992         }
6993       } else {
6994         VectorIterator<char> buf1(vec1);
6995         isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
6996         return CompareStringContents(&buf1,
6997             isolate->objects_string_compare_buffer_b());
6998       }
6999     } else {
7000       Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
7001       if (rhs_content.IsFlat()) {
7002         if (rhs_content.IsAscii()) {
7003           VectorIterator<uc16> buf1(vec1);
7004           VectorIterator<char> ib(rhs_content.ToAsciiVector());
7005           return CompareStringContents(&buf1, &ib);
7006         } else {
7007           Vector<const uc16> vec2(rhs_content.ToUC16Vector());
7008           return CompareRawStringContents(vec1, vec2);
7009         }
7010       } else {
7011         VectorIterator<uc16> buf1(vec1);
7012         isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
7013         return CompareStringContents(&buf1,
7014             isolate->objects_string_compare_buffer_b());
7015       }
7016     }
7017   } else {
7018     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
7019     return CompareStringContentsPartial(isolate,
7020         isolate->objects_string_compare_buffer_a(), rhs);
7021   }
7022 }
7023
7024
7025 bool String::MarkAsUndetectable() {
7026   if (StringShape(this).IsSymbol()) return false;
7027
7028   Map* map = this->map();
7029   Heap* heap = GetHeap();
7030   if (map == heap->string_map()) {
7031     this->set_map(heap->undetectable_string_map());
7032     return true;
7033   } else if (map == heap->ascii_string_map()) {
7034     this->set_map(heap->undetectable_ascii_string_map());
7035     return true;
7036   }
7037   // Rest cannot be marked as undetectable
7038   return false;
7039 }
7040
7041
7042 bool String::IsEqualTo(Vector<const char> str) {
7043   Isolate* isolate = GetIsolate();
7044   int slen = length();
7045   Access<UnicodeCache::Utf8Decoder>
7046       decoder(isolate->unicode_cache()->utf8_decoder());
7047   decoder->Reset(str.start(), str.length());
7048   int i;
7049   for (i = 0; i < slen && decoder->has_more(); i++) {
7050     uint32_t r = decoder->GetNext();
7051     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
7052       if (i > slen - 1) return false;
7053       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
7054       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
7055     } else {
7056       if (Get(i) != r) return false;
7057     }
7058   }
7059   return i == slen && !decoder->has_more();
7060 }
7061
7062
7063 bool String::IsAsciiEqualTo(Vector<const char> str) {
7064   int slen = length();
7065   if (str.length() != slen) return false;
7066   FlatContent content = GetFlatContent();
7067   if (content.IsAscii()) {
7068     return CompareChars(content.ToAsciiVector().start(),
7069                         str.start(), slen) == 0;
7070   }
7071   for (int i = 0; i < slen; i++) {
7072     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
7073   }
7074   return true;
7075 }
7076
7077
7078 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
7079   int slen = length();
7080   if (str.length() != slen) return false;
7081   FlatContent content = GetFlatContent();
7082   if (content.IsTwoByte()) {
7083     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
7084   }
7085   for (int i = 0; i < slen; i++) {
7086     if (Get(i) != str[i]) return false;
7087   }
7088   return true;
7089 }
7090
7091
7092 uint32_t String::ComputeAndSetHash() {
7093   // Should only be called if hash code has not yet been computed.
7094   ASSERT(!HasHashCode());
7095
7096   const int len = length();
7097
7098   // Compute the hash code.
7099   uint32_t field = 0;
7100   if (StringShape(this).IsSequentialAscii()) {
7101     field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(),
7102                                  len,
7103                                  GetHeap()->HashSeed());
7104   } else if (StringShape(this).IsSequentialTwoByte()) {
7105     field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(),
7106                                  len,
7107                                  GetHeap()->HashSeed());
7108   } else {
7109     StringInputBuffer buffer(this);
7110     field = ComputeHashField(&buffer, len, GetHeap()->HashSeed());
7111   }
7112
7113   // Store the hash code in the object.
7114   set_hash_field(field);
7115
7116   // Check the hash code is there.
7117   ASSERT(HasHashCode());
7118   uint32_t result = field >> kHashShift;
7119   ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
7120   return result;
7121 }
7122
7123
7124 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
7125                                uint32_t* index,
7126                                int length) {
7127   if (length == 0 || length > kMaxArrayIndexSize) return false;
7128   uc32 ch = buffer->GetNext();
7129
7130   // If the string begins with a '0' character, it must only consist
7131   // of it to be a legal array index.
7132   if (ch == '0') {
7133     *index = 0;
7134     return length == 1;
7135   }
7136
7137   // Convert string to uint32 array index; character by character.
7138   int d = ch - '0';
7139   if (d < 0 || d > 9) return false;
7140   uint32_t result = d;
7141   while (buffer->has_more()) {
7142     d = buffer->GetNext() - '0';
7143     if (d < 0 || d > 9) return false;
7144     // Check that the new result is below the 32 bit limit.
7145     if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
7146     result = (result * 10) + d;
7147   }
7148
7149   *index = result;
7150   return true;
7151 }
7152
7153
7154 bool String::SlowAsArrayIndex(uint32_t* index) {
7155   if (length() <= kMaxCachedArrayIndexLength) {
7156     Hash();  // force computation of hash code
7157     uint32_t field = hash_field();
7158     if ((field & kIsNotArrayIndexMask) != 0) return false;
7159     // Isolate the array index form the full hash field.
7160     *index = (kArrayIndexHashMask & field) >> kHashShift;
7161     return true;
7162   } else {
7163     StringInputBuffer buffer(this);
7164     return ComputeArrayIndex(&buffer, index, length());
7165   }
7166 }
7167
7168
7169 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
7170   // For array indexes mix the length into the hash as an array index could
7171   // be zero.
7172   ASSERT(length > 0);
7173   ASSERT(length <= String::kMaxArrayIndexSize);
7174   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
7175          (1 << String::kArrayIndexValueBits));
7176
7177   value <<= String::kHashShift;
7178   value |= length << String::kArrayIndexHashLengthShift;
7179
7180   ASSERT((value & String::kIsNotArrayIndexMask) == 0);
7181   ASSERT((length > String::kMaxCachedArrayIndexLength) ||
7182          (value & String::kContainsCachedArrayIndexMask) == 0);
7183   return value;
7184 }
7185
7186
7187 void StringHasher::AddSurrogatePair(uc32 c) {
7188   uint16_t lead = unibrow::Utf16::LeadSurrogate(c);
7189   AddCharacter(lead);
7190   uint16_t trail = unibrow::Utf16::TrailSurrogate(c);
7191   AddCharacter(trail);
7192 }
7193
7194
7195 void StringHasher::AddSurrogatePairNoIndex(uc32 c) {
7196   uint16_t lead = unibrow::Utf16::LeadSurrogate(c);
7197   AddCharacterNoIndex(lead);
7198   uint16_t trail = unibrow::Utf16::TrailSurrogate(c);
7199   AddCharacterNoIndex(trail);
7200 }
7201
7202
7203 uint32_t StringHasher::GetHashField() {
7204   ASSERT(is_valid());
7205   if (length_ <= String::kMaxHashCalcLength) {
7206     if (is_array_index()) {
7207       return MakeArrayIndexHash(array_index(), length_);
7208     }
7209     return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask;
7210   } else {
7211     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
7212   }
7213 }
7214
7215
7216 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer,
7217                                   int length,
7218                                   uint32_t seed) {
7219   StringHasher hasher(length, seed);
7220
7221   // Very long strings have a trivial hash that doesn't inspect the
7222   // string contents.
7223   if (hasher.has_trivial_hash()) {
7224     return hasher.GetHashField();
7225   }
7226
7227   // Do the iterative array index computation as long as there is a
7228   // chance this is an array index.
7229   while (buffer->has_more() && hasher.is_array_index()) {
7230     hasher.AddCharacter(buffer->GetNext());
7231   }
7232
7233   // Process the remaining characters without updating the array
7234   // index.
7235   while (buffer->has_more()) {
7236     hasher.AddCharacterNoIndex(buffer->GetNext());
7237   }
7238
7239   return hasher.GetHashField();
7240 }
7241
7242
7243 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
7244   Heap* heap = GetHeap();
7245   if (start == 0 && end == length()) return this;
7246   MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
7247   return result;
7248 }
7249
7250
7251 void String::PrintOn(FILE* file) {
7252   int length = this->length();
7253   for (int i = 0; i < length; i++) {
7254     fprintf(file, "%c", Get(i));
7255   }
7256 }
7257
7258
7259 // Clear a possible back pointer in case the transition leads to a dead map.
7260 // Return true in case a back pointer has been cleared and false otherwise.
7261 // Set *keep_entry to true when a live map transition has been found.
7262 static bool ClearBackPointer(Heap* heap, Object* target, bool* keep_entry) {
7263   if (!target->IsMap()) return false;
7264   Map* map = Map::cast(target);
7265   if (Marking::MarkBitFrom(map).Get()) {
7266     *keep_entry = true;
7267     return false;
7268   } else {
7269     map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
7270     return true;
7271   }
7272 }
7273
7274
7275 void Map::ClearNonLiveTransitions(Heap* heap) {
7276   DescriptorArray* d = DescriptorArray::cast(
7277       *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset));
7278   if (d->IsEmpty()) return;
7279   Smi* NullDescriptorDetails =
7280     PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
7281   FixedArray* contents = FixedArray::cast(
7282       d->get(DescriptorArray::kContentArrayIndex));
7283   ASSERT(contents->length() >= 2);
7284   for (int i = 0; i < contents->length(); i += 2) {
7285     // If the pair (value, details) is a map transition, check if the target is
7286     // live. If not, null the descriptor. Also drop the back pointer for that
7287     // map transition, so that this map is not reached again by following a back
7288     // pointer from that non-live map.
7289     bool keep_entry = false;
7290     PropertyDetails details(Smi::cast(contents->get(i + 1)));
7291     switch (details.type()) {
7292       case MAP_TRANSITION:
7293       case CONSTANT_TRANSITION:
7294         ClearBackPointer(heap, contents->get(i), &keep_entry);
7295         break;
7296       case ELEMENTS_TRANSITION: {
7297         Object* object = contents->get(i);
7298         if (object->IsMap()) {
7299           ClearBackPointer(heap, object, &keep_entry);
7300         } else {
7301           FixedArray* array = FixedArray::cast(object);
7302           for (int j = 0; j < array->length(); ++j) {
7303             if (ClearBackPointer(heap, array->get(j), &keep_entry)) {
7304               array->set_undefined(j);
7305             }
7306           }
7307         }
7308         break;
7309       }
7310       case CALLBACKS: {
7311         Object* object = contents->get(i);
7312         if (object->IsAccessorPair()) {
7313           AccessorPair* accessors = AccessorPair::cast(object);
7314           if (ClearBackPointer(heap, accessors->getter(), &keep_entry)) {
7315             accessors->set_getter(heap->the_hole_value());
7316           }
7317           if (ClearBackPointer(heap, accessors->setter(), &keep_entry)) {
7318             accessors->set_setter(heap->the_hole_value());
7319           }
7320         } else {
7321           keep_entry = true;
7322         }
7323         break;
7324       }
7325       case NORMAL:
7326       case FIELD:
7327       case CONSTANT_FUNCTION:
7328       case HANDLER:
7329       case INTERCEPTOR:
7330       case NULL_DESCRIPTOR:
7331         keep_entry = true;
7332         break;
7333     }
7334     // Make sure that an entry containing only dead transitions gets collected.
7335     // What we *really* want to do here is removing this entry completely, but
7336     // for technical reasons we can't do this, so we zero it out instead.
7337     if (!keep_entry) {
7338       contents->set_unchecked(i + 1, NullDescriptorDetails);
7339       contents->set_null_unchecked(heap, i);
7340     }
7341   }
7342 }
7343
7344
7345 int Map::Hash() {
7346   // For performance reasons we only hash the 3 most variable fields of a map:
7347   // constructor, prototype and bit_field2.
7348
7349   // Shift away the tag.
7350   int hash = (static_cast<uint32_t>(
7351         reinterpret_cast<uintptr_t>(constructor())) >> 2);
7352
7353   // XOR-ing the prototype and constructor directly yields too many zero bits
7354   // when the two pointers are close (which is fairly common).
7355   // To avoid this we shift the prototype 4 bits relatively to the constructor.
7356   hash ^= (static_cast<uint32_t>(
7357         reinterpret_cast<uintptr_t>(prototype())) << 2);
7358
7359   return hash ^ (hash >> 16) ^ bit_field2();
7360 }
7361
7362
7363 bool Map::EquivalentToForNormalization(Map* other,
7364                                        PropertyNormalizationMode mode) {
7365   return
7366     constructor() == other->constructor() &&
7367     prototype() == other->prototype() &&
7368     inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
7369                               0 :
7370                               other->inobject_properties()) &&
7371     instance_type() == other->instance_type() &&
7372     bit_field() == other->bit_field() &&
7373     bit_field2() == other->bit_field2() &&
7374     (bit_field3() & ~(1<<Map::kIsShared)) ==
7375         (other->bit_field3() & ~(1<<Map::kIsShared));
7376 }
7377
7378
7379 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
7380   // Iterate over all fields in the body but take care in dealing with
7381   // the code entry.
7382   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
7383   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
7384   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
7385 }
7386
7387
7388 void JSFunction::MarkForLazyRecompilation() {
7389   ASSERT(is_compiled() && !IsOptimized());
7390   ASSERT(shared()->allows_lazy_compilation() ||
7391          code()->optimizable());
7392   Builtins* builtins = GetIsolate()->builtins();
7393   ReplaceCode(builtins->builtin(Builtins::kLazyRecompile));
7394 }
7395
7396
7397 bool SharedFunctionInfo::EnsureCompiled(Handle<SharedFunctionInfo> shared,
7398                                         ClearExceptionFlag flag) {
7399   return shared->is_compiled() || CompileLazy(shared, flag);
7400 }
7401
7402
7403 static bool CompileLazyHelper(CompilationInfo* info,
7404                               ClearExceptionFlag flag) {
7405   // Compile the source information to a code object.
7406   ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
7407   ASSERT(!info->isolate()->has_pending_exception());
7408   bool result = Compiler::CompileLazy(info);
7409   ASSERT(result != Isolate::Current()->has_pending_exception());
7410   if (!result && flag == CLEAR_EXCEPTION) {
7411     info->isolate()->clear_pending_exception();
7412   }
7413   return result;
7414 }
7415
7416
7417 bool SharedFunctionInfo::CompileLazy(Handle<SharedFunctionInfo> shared,
7418                                      ClearExceptionFlag flag) {
7419   CompilationInfo info(shared);
7420   return CompileLazyHelper(&info, flag);
7421 }
7422
7423
7424 bool JSFunction::CompileLazy(Handle<JSFunction> function,
7425                              ClearExceptionFlag flag) {
7426   bool result = true;
7427   if (function->shared()->is_compiled()) {
7428     function->ReplaceCode(function->shared()->code());
7429     function->shared()->set_code_age(0);
7430   } else {
7431     CompilationInfo info(function);
7432     result = CompileLazyHelper(&info, flag);
7433     ASSERT(!result || function->is_compiled());
7434   }
7435   return result;
7436 }
7437
7438
7439 bool JSFunction::CompileOptimized(Handle<JSFunction> function,
7440                                   int osr_ast_id,
7441                                   ClearExceptionFlag flag) {
7442   CompilationInfo info(function);
7443   info.SetOptimizing(osr_ast_id);
7444   return CompileLazyHelper(&info, flag);
7445 }
7446
7447
7448 bool JSFunction::IsInlineable() {
7449   if (IsBuiltin()) return false;
7450   SharedFunctionInfo* shared_info = shared();
7451   // Check that the function has a script associated with it.
7452   if (!shared_info->script()->IsScript()) return false;
7453   if (shared_info->optimization_disabled()) return false;
7454   Code* code = shared_info->code();
7455   if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
7456   // If we never ran this (unlikely) then lets try to optimize it.
7457   if (code->kind() != Code::FUNCTION) return true;
7458   return code->optimizable();
7459 }
7460
7461
7462 MaybeObject* JSFunction::SetInstancePrototype(Object* value) {
7463   ASSERT(value->IsJSReceiver());
7464   Heap* heap = GetHeap();
7465   if (has_initial_map()) {
7466     // If the function has allocated the initial map
7467     // replace it with a copy containing the new prototype.
7468     Map* new_map;
7469     MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions();
7470     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7471     new_map->set_prototype(value);
7472     MaybeObject* maybe_object =
7473         set_initial_map_and_cache_transitions(new_map);
7474     if (maybe_object->IsFailure()) return maybe_object;
7475   } else {
7476     // Put the value in the initial map field until an initial map is
7477     // needed.  At that point, a new initial map is created and the
7478     // prototype is put into the initial map where it belongs.
7479     set_prototype_or_initial_map(value);
7480   }
7481   heap->ClearInstanceofCache();
7482   return value;
7483 }
7484
7485
7486 MaybeObject* JSFunction::SetPrototype(Object* value) {
7487   ASSERT(should_have_prototype());
7488   Object* construct_prototype = value;
7489
7490   // If the value is not a JSReceiver, store the value in the map's
7491   // constructor field so it can be accessed.  Also, set the prototype
7492   // used for constructing objects to the original object prototype.
7493   // See ECMA-262 13.2.2.
7494   if (!value->IsJSReceiver()) {
7495     // Copy the map so this does not affect unrelated functions.
7496     // Remove map transitions because they point to maps with a
7497     // different prototype.
7498     Map* new_map;
7499     { MaybeObject* maybe_new_map = map()->CopyDropTransitions();
7500       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7501     }
7502     Heap* heap = new_map->GetHeap();
7503     set_map(new_map);
7504     new_map->set_constructor(value);
7505     new_map->set_non_instance_prototype(true);
7506     construct_prototype =
7507         heap->isolate()->context()->global_context()->
7508             initial_object_prototype();
7509   } else {
7510     map()->set_non_instance_prototype(false);
7511   }
7512
7513   return SetInstancePrototype(construct_prototype);
7514 }
7515
7516
7517 Object* JSFunction::RemovePrototype() {
7518   Context* global_context = context()->global_context();
7519   Map* no_prototype_map = shared()->is_classic_mode()
7520       ? global_context->function_without_prototype_map()
7521       : global_context->strict_mode_function_without_prototype_map();
7522
7523   if (map() == no_prototype_map) {
7524     // Be idempotent.
7525     return this;
7526   }
7527
7528   ASSERT(map() == (shared()->is_classic_mode()
7529                    ? global_context->function_map()
7530                    : global_context->strict_mode_function_map()));
7531
7532   set_map(no_prototype_map);
7533   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
7534   return this;
7535 }
7536
7537
7538 Object* JSFunction::SetInstanceClassName(String* name) {
7539   shared()->set_instance_class_name(name);
7540   return this;
7541 }
7542
7543
7544 void JSFunction::PrintName(FILE* out) {
7545   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
7546   PrintF(out, "%s", *name);
7547 }
7548
7549
7550 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) {
7551   return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex));
7552 }
7553
7554
7555 MaybeObject* Oddball::Initialize(const char* to_string,
7556                                  Object* to_number,
7557                                  byte kind) {
7558   String* symbol;
7559   { MaybeObject* maybe_symbol =
7560         Isolate::Current()->heap()->LookupAsciiSymbol(to_string);
7561     if (!maybe_symbol->To(&symbol)) return maybe_symbol;
7562   }
7563   set_to_string(symbol);
7564   set_to_number(to_number);
7565   set_kind(kind);
7566   return this;
7567 }
7568
7569
7570 String* SharedFunctionInfo::DebugName() {
7571   Object* n = name();
7572   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
7573   return String::cast(n);
7574 }
7575
7576
7577 bool SharedFunctionInfo::HasSourceCode() {
7578   return !script()->IsUndefined() &&
7579          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
7580 }
7581
7582
7583 Handle<Object> SharedFunctionInfo::GetSourceCode() {
7584   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
7585   Handle<String> source(String::cast(Script::cast(script())->source()));
7586   return SubString(source, start_position(), end_position());
7587 }
7588
7589
7590 int SharedFunctionInfo::SourceSize() {
7591   return end_position() - start_position();
7592 }
7593
7594
7595 int SharedFunctionInfo::CalculateInstanceSize() {
7596   int instance_size =
7597       JSObject::kHeaderSize +
7598       expected_nof_properties() * kPointerSize;
7599   if (instance_size > JSObject::kMaxInstanceSize) {
7600     instance_size = JSObject::kMaxInstanceSize;
7601   }
7602   return instance_size;
7603 }
7604
7605
7606 int SharedFunctionInfo::CalculateInObjectProperties() {
7607   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
7608 }
7609
7610
7611 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
7612   // Check the basic conditions for generating inline constructor code.
7613   if (!FLAG_inline_new
7614       || !has_only_simple_this_property_assignments()
7615       || this_property_assignments_count() == 0) {
7616     return false;
7617   }
7618
7619   // If the prototype is null inline constructors cause no problems.
7620   if (!prototype->IsJSObject()) {
7621     ASSERT(prototype->IsNull());
7622     return true;
7623   }
7624
7625   Heap* heap = GetHeap();
7626
7627   // Traverse the proposed prototype chain looking for setters for properties of
7628   // the same names as are set by the inline constructor.
7629   for (Object* obj = prototype;
7630        obj != heap->null_value();
7631        obj = obj->GetPrototype()) {
7632     JSObject* js_object = JSObject::cast(obj);
7633     for (int i = 0; i < this_property_assignments_count(); i++) {
7634       LookupResult result(heap->isolate());
7635       String* name = GetThisPropertyAssignmentName(i);
7636       js_object->LocalLookupRealNamedProperty(name, &result);
7637       if (result.IsFound() && result.type() == CALLBACKS) {
7638         return false;
7639       }
7640     }
7641   }
7642
7643   return true;
7644 }
7645
7646
7647 void SharedFunctionInfo::ForbidInlineConstructor() {
7648   set_compiler_hints(BooleanBit::set(compiler_hints(),
7649                                      kHasOnlySimpleThisPropertyAssignments,
7650                                      false));
7651 }
7652
7653
7654 void SharedFunctionInfo::SetThisPropertyAssignmentsInfo(
7655     bool only_simple_this_property_assignments,
7656     FixedArray* assignments) {
7657   set_compiler_hints(BooleanBit::set(compiler_hints(),
7658                                      kHasOnlySimpleThisPropertyAssignments,
7659                                      only_simple_this_property_assignments));
7660   set_this_property_assignments(assignments);
7661   set_this_property_assignments_count(assignments->length() / 3);
7662 }
7663
7664
7665 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() {
7666   Heap* heap = GetHeap();
7667   set_compiler_hints(BooleanBit::set(compiler_hints(),
7668                                      kHasOnlySimpleThisPropertyAssignments,
7669                                      false));
7670   set_this_property_assignments(heap->undefined_value());
7671   set_this_property_assignments_count(0);
7672 }
7673
7674
7675 String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) {
7676   Object* obj = this_property_assignments();
7677   ASSERT(obj->IsFixedArray());
7678   ASSERT(index < this_property_assignments_count());
7679   obj = FixedArray::cast(obj)->get(index * 3);
7680   ASSERT(obj->IsString());
7681   return String::cast(obj);
7682 }
7683
7684
7685 bool SharedFunctionInfo::IsThisPropertyAssignmentArgument(int index) {
7686   Object* obj = this_property_assignments();
7687   ASSERT(obj->IsFixedArray());
7688   ASSERT(index < this_property_assignments_count());
7689   obj = FixedArray::cast(obj)->get(index * 3 + 1);
7690   return Smi::cast(obj)->value() != -1;
7691 }
7692
7693
7694 int SharedFunctionInfo::GetThisPropertyAssignmentArgument(int index) {
7695   ASSERT(IsThisPropertyAssignmentArgument(index));
7696   Object* obj =
7697       FixedArray::cast(this_property_assignments())->get(index * 3 + 1);
7698   return Smi::cast(obj)->value();
7699 }
7700
7701
7702 Object* SharedFunctionInfo::GetThisPropertyAssignmentConstant(int index) {
7703   ASSERT(!IsThisPropertyAssignmentArgument(index));
7704   Object* obj =
7705       FixedArray::cast(this_property_assignments())->get(index * 3 + 2);
7706   return obj;
7707 }
7708
7709
7710 // Support function for printing the source code to a StringStream
7711 // without any allocation in the heap.
7712 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
7713                                          int max_length) {
7714   // For some native functions there is no source.
7715   if (!HasSourceCode()) {
7716     accumulator->Add("<No Source>");
7717     return;
7718   }
7719
7720   // Get the source for the script which this function came from.
7721   // Don't use String::cast because we don't want more assertion errors while
7722   // we are already creating a stack dump.
7723   String* script_source =
7724       reinterpret_cast<String*>(Script::cast(script())->source());
7725
7726   if (!script_source->LooksValid()) {
7727     accumulator->Add("<Invalid Source>");
7728     return;
7729   }
7730
7731   if (!is_toplevel()) {
7732     accumulator->Add("function ");
7733     Object* name = this->name();
7734     if (name->IsString() && String::cast(name)->length() > 0) {
7735       accumulator->PrintName(name);
7736     }
7737   }
7738
7739   int len = end_position() - start_position();
7740   if (len <= max_length || max_length < 0) {
7741     accumulator->Put(script_source, start_position(), end_position());
7742   } else {
7743     accumulator->Put(script_source,
7744                      start_position(),
7745                      start_position() + max_length);
7746     accumulator->Add("...\n");
7747   }
7748 }
7749
7750
7751 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
7752   if (code->instruction_size() != recompiled->instruction_size()) return false;
7753   ByteArray* code_relocation = code->relocation_info();
7754   ByteArray* recompiled_relocation = recompiled->relocation_info();
7755   int length = code_relocation->length();
7756   if (length != recompiled_relocation->length()) return false;
7757   int compare = memcmp(code_relocation->GetDataStartAddress(),
7758                        recompiled_relocation->GetDataStartAddress(),
7759                        length);
7760   return compare == 0;
7761 }
7762
7763
7764 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
7765   ASSERT(!has_deoptimization_support());
7766   AssertNoAllocation no_allocation;
7767   Code* code = this->code();
7768   if (IsCodeEquivalent(code, recompiled)) {
7769     // Copy the deoptimization data from the recompiled code.
7770     code->set_deoptimization_data(recompiled->deoptimization_data());
7771     code->set_has_deoptimization_support(true);
7772   } else {
7773     // TODO(3025757): In case the recompiled isn't equivalent to the
7774     // old code, we have to replace it. We should try to avoid this
7775     // altogether because it flushes valuable type feedback by
7776     // effectively resetting all IC state.
7777     set_code(recompiled);
7778   }
7779   ASSERT(has_deoptimization_support());
7780 }
7781
7782
7783 void SharedFunctionInfo::DisableOptimization() {
7784   // Disable optimization for the shared function info and mark the
7785   // code as non-optimizable. The marker on the shared function info
7786   // is there because we flush non-optimized code thereby loosing the
7787   // non-optimizable information for the code. When the code is
7788   // regenerated and set on the shared function info it is marked as
7789   // non-optimizable if optimization is disabled for the shared
7790   // function info.
7791   set_optimization_disabled(true);
7792   // Code should be the lazy compilation stub or else unoptimized.  If the
7793   // latter, disable optimization for the code too.
7794   ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
7795   if (code()->kind() == Code::FUNCTION) {
7796     code()->set_optimizable(false);
7797   }
7798   if (FLAG_trace_opt) {
7799     PrintF("[disabled optimization for %s]\n", *DebugName()->ToCString());
7800   }
7801 }
7802
7803
7804 bool SharedFunctionInfo::VerifyBailoutId(int id) {
7805   ASSERT(id != AstNode::kNoNumber);
7806   Code* unoptimized = code();
7807   DeoptimizationOutputData* data =
7808       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
7809   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
7810   USE(ignore);
7811   return true;  // Return true if there was no ASSERT.
7812 }
7813
7814
7815 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) {
7816   ASSERT(!IsInobjectSlackTrackingInProgress());
7817
7818   if (!FLAG_clever_optimizations) return;
7819
7820   // Only initiate the tracking the first time.
7821   if (live_objects_may_exist()) return;
7822   set_live_objects_may_exist(true);
7823
7824   // No tracking during the snapshot construction phase.
7825   if (Serializer::enabled()) return;
7826
7827   if (map->unused_property_fields() == 0) return;
7828
7829   // Nonzero counter is a leftover from the previous attempt interrupted
7830   // by GC, keep it.
7831   if (construction_count() == 0) {
7832     set_construction_count(kGenerousAllocationCount);
7833   }
7834   set_initial_map(map);
7835   Builtins* builtins = map->GetHeap()->isolate()->builtins();
7836   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
7837             construct_stub());
7838   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
7839 }
7840
7841
7842 // Called from GC, hence reinterpret_cast and unchecked accessors.
7843 void SharedFunctionInfo::DetachInitialMap() {
7844   Map* map = reinterpret_cast<Map*>(initial_map());
7845
7846   // Make the map remember to restore the link if it survives the GC.
7847   map->set_bit_field3(
7848       map->bit_field3() | (1 << Map::kAttachedToSharedFunctionInfo));
7849
7850   // Undo state changes made by StartInobjectTracking (except the
7851   // construction_count). This way if the initial map does not survive the GC
7852   // then StartInobjectTracking will be called again the next time the
7853   // constructor is called. The countdown will continue and (possibly after
7854   // several more GCs) CompleteInobjectSlackTracking will eventually be called.
7855   Heap* heap = map->GetHeap();
7856   set_initial_map(heap->raw_unchecked_undefined_value());
7857   Builtins* builtins = heap->isolate()->builtins();
7858   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
7859             *RawField(this, kConstructStubOffset));
7860   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
7861   // It is safe to clear the flag: it will be set again if the map is live.
7862   set_live_objects_may_exist(false);
7863 }
7864
7865
7866 // Called from GC, hence reinterpret_cast and unchecked accessors.
7867 void SharedFunctionInfo::AttachInitialMap(Map* map) {
7868   map->set_bit_field3(
7869       map->bit_field3() & ~(1 << Map::kAttachedToSharedFunctionInfo));
7870
7871   // Resume inobject slack tracking.
7872   set_initial_map(map);
7873   Builtins* builtins = map->GetHeap()->isolate()->builtins();
7874   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
7875             *RawField(this, kConstructStubOffset));
7876   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
7877   // The map survived the gc, so there may be objects referencing it.
7878   set_live_objects_may_exist(true);
7879 }
7880
7881
7882 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
7883   code()->ClearInlineCaches();
7884   set_ic_age(new_ic_age);
7885   if (code()->kind() == Code::FUNCTION) {
7886     code()->set_profiler_ticks(0);
7887     if (optimization_disabled() &&
7888         opt_count() >= Compiler::kDefaultMaxOptCount) {
7889       // Re-enable optimizations if they were disabled due to opt_count limit.
7890       set_optimization_disabled(false);
7891       code()->set_optimizable(true);
7892     }
7893     set_opt_count(0);
7894   }
7895 }
7896
7897
7898 static void GetMinInobjectSlack(Map* map, void* data) {
7899   int slack = map->unused_property_fields();
7900   if (*reinterpret_cast<int*>(data) > slack) {
7901     *reinterpret_cast<int*>(data) = slack;
7902   }
7903 }
7904
7905
7906 static void ShrinkInstanceSize(Map* map, void* data) {
7907   int slack = *reinterpret_cast<int*>(data);
7908   map->set_inobject_properties(map->inobject_properties() - slack);
7909   map->set_unused_property_fields(map->unused_property_fields() - slack);
7910   map->set_instance_size(map->instance_size() - slack * kPointerSize);
7911
7912   // Visitor id might depend on the instance size, recalculate it.
7913   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
7914 }
7915
7916
7917 void SharedFunctionInfo::CompleteInobjectSlackTracking() {
7918   ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
7919   Map* map = Map::cast(initial_map());
7920
7921   Heap* heap = map->GetHeap();
7922   set_initial_map(heap->undefined_value());
7923   Builtins* builtins = heap->isolate()->builtins();
7924   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
7925             construct_stub());
7926   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
7927
7928   int slack = map->unused_property_fields();
7929   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
7930   if (slack != 0) {
7931     // Resize the initial map and all maps in its transition tree.
7932     map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
7933
7934     // Give the correct expected_nof_properties to initial maps created later.
7935     ASSERT(expected_nof_properties() >= slack);
7936     set_expected_nof_properties(expected_nof_properties() - slack);
7937   }
7938 }
7939
7940
7941 void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) {
7942   v->VisitSharedFunctionInfo(this);
7943   SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
7944 }
7945
7946
7947 #define DECLARE_TAG(ignore1, name, ignore2) name,
7948 const char* const VisitorSynchronization::kTags[
7949     VisitorSynchronization::kNumberOfSyncTags] = {
7950   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
7951 };
7952 #undef DECLARE_TAG
7953
7954
7955 #define DECLARE_TAG(ignore1, ignore2, name) name,
7956 const char* const VisitorSynchronization::kTagNames[
7957     VisitorSynchronization::kNumberOfSyncTags] = {
7958   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
7959 };
7960 #undef DECLARE_TAG
7961
7962
7963 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
7964   ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
7965   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
7966   Object* old_target = target;
7967   VisitPointer(&target);
7968   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
7969 }
7970
7971
7972 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
7973   Object* code = Code::GetObjectFromEntryAddress(entry_address);
7974   Object* old_code = code;
7975   VisitPointer(&code);
7976   if (code != old_code) {
7977     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
7978   }
7979 }
7980
7981
7982 void ObjectVisitor::VisitGlobalPropertyCell(RelocInfo* rinfo) {
7983   ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
7984   Object* cell = rinfo->target_cell();
7985   Object* old_cell = cell;
7986   VisitPointer(&cell);
7987   if (cell != old_cell) {
7988     rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
7989   }
7990 }
7991
7992
7993 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
7994   ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
7995           rinfo->IsPatchedReturnSequence()) ||
7996          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
7997           rinfo->IsPatchedDebugBreakSlotSequence()));
7998   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
7999   Object* old_target = target;
8000   VisitPointer(&target);
8001   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
8002 }
8003
8004 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
8005   ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
8006   VisitPointer(rinfo->target_object_address());
8007 }
8008
8009 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
8010   Address* p = rinfo->target_reference_address();
8011   VisitExternalReferences(p, p + 1);
8012 }
8013
8014 void Code::InvalidateRelocation() {
8015   set_relocation_info(GetHeap()->empty_byte_array());
8016 }
8017
8018
8019 void Code::Relocate(intptr_t delta) {
8020   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
8021     it.rinfo()->apply(delta);
8022   }
8023   CPU::FlushICache(instruction_start(), instruction_size());
8024 }
8025
8026
8027 void Code::CopyFrom(const CodeDesc& desc) {
8028   ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
8029
8030   // copy code
8031   memmove(instruction_start(), desc.buffer, desc.instr_size);
8032
8033   // copy reloc info
8034   memmove(relocation_start(),
8035           desc.buffer + desc.buffer_size - desc.reloc_size,
8036           desc.reloc_size);
8037
8038   // unbox handles and relocate
8039   intptr_t delta = instruction_start() - desc.buffer;
8040   int mode_mask = RelocInfo::kCodeTargetMask |
8041                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
8042                   RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
8043                   RelocInfo::kApplyMask;
8044   Assembler* origin = desc.origin;  // Needed to find target_object on X64.
8045   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
8046     RelocInfo::Mode mode = it.rinfo()->rmode();
8047     if (mode == RelocInfo::EMBEDDED_OBJECT) {
8048       Handle<Object> p = it.rinfo()->target_object_handle(origin);
8049       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
8050     } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
8051       Handle<JSGlobalPropertyCell> cell  = it.rinfo()->target_cell_handle();
8052       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
8053     } else if (RelocInfo::IsCodeTarget(mode)) {
8054       // rewrite code handles in inline cache targets to direct
8055       // pointers to the first instruction in the code object
8056       Handle<Object> p = it.rinfo()->target_object_handle(origin);
8057       Code* code = Code::cast(*p);
8058       it.rinfo()->set_target_address(code->instruction_start(),
8059                                      SKIP_WRITE_BARRIER);
8060     } else {
8061       it.rinfo()->apply(delta);
8062     }
8063   }
8064   CPU::FlushICache(instruction_start(), instruction_size());
8065 }
8066
8067
8068 // Locate the source position which is closest to the address in the code. This
8069 // is using the source position information embedded in the relocation info.
8070 // The position returned is relative to the beginning of the script where the
8071 // source for this function is found.
8072 int Code::SourcePosition(Address pc) {
8073   int distance = kMaxInt;
8074   int position = RelocInfo::kNoPosition;  // Initially no position found.
8075   // Run through all the relocation info to find the best matching source
8076   // position. All the code needs to be considered as the sequence of the
8077   // instructions in the code does not necessarily follow the same order as the
8078   // source.
8079   RelocIterator it(this, RelocInfo::kPositionMask);
8080   while (!it.done()) {
8081     // Only look at positions after the current pc.
8082     if (it.rinfo()->pc() < pc) {
8083       // Get position and distance.
8084
8085       int dist = static_cast<int>(pc - it.rinfo()->pc());
8086       int pos = static_cast<int>(it.rinfo()->data());
8087       // If this position is closer than the current candidate or if it has the
8088       // same distance as the current candidate and the position is higher then
8089       // this position is the new candidate.
8090       if ((dist < distance) ||
8091           (dist == distance && pos > position)) {
8092         position = pos;
8093         distance = dist;
8094       }
8095     }
8096     it.next();
8097   }
8098   return position;
8099 }
8100
8101
8102 // Same as Code::SourcePosition above except it only looks for statement
8103 // positions.
8104 int Code::SourceStatementPosition(Address pc) {
8105   // First find the position as close as possible using all position
8106   // information.
8107   int position = SourcePosition(pc);
8108   // Now find the closest statement position before the position.
8109   int statement_position = 0;
8110   RelocIterator it(this, RelocInfo::kPositionMask);
8111   while (!it.done()) {
8112     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
8113       int p = static_cast<int>(it.rinfo()->data());
8114       if (statement_position < p && p <= position) {
8115         statement_position = p;
8116       }
8117     }
8118     it.next();
8119   }
8120   return statement_position;
8121 }
8122
8123
8124 SafepointEntry Code::GetSafepointEntry(Address pc) {
8125   SafepointTable table(this);
8126   return table.FindEntry(pc);
8127 }
8128
8129
8130 void Code::SetNoStackCheckTable() {
8131   // Indicate the absence of a stack-check table by a table start after the
8132   // end of the instructions.  Table start must be aligned, so round up.
8133   set_stack_check_table_offset(RoundUp(instruction_size(), kIntSize));
8134 }
8135
8136
8137 Map* Code::FindFirstMap() {
8138   ASSERT(is_inline_cache_stub());
8139   AssertNoAllocation no_allocation;
8140   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
8141   for (RelocIterator it(this, mask); !it.done(); it.next()) {
8142     RelocInfo* info = it.rinfo();
8143     Object* object = info->target_object();
8144     if (object->IsMap()) return Map::cast(object);
8145   }
8146   return NULL;
8147 }
8148
8149
8150 void Code::ClearInlineCaches() {
8151   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
8152              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
8153              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
8154              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
8155   for (RelocIterator it(this, mask); !it.done(); it.next()) {
8156     RelocInfo* info = it.rinfo();
8157     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
8158     if (target->is_inline_cache_stub()) {
8159       IC::Clear(info->pc());
8160     }
8161   }
8162 }
8163
8164
8165 void Code::ClearTypeFeedbackCells(Heap* heap) {
8166   Object* raw_info = type_feedback_info();
8167   if (raw_info->IsTypeFeedbackInfo()) {
8168     TypeFeedbackCells* type_feedback_cells =
8169         TypeFeedbackInfo::cast(raw_info)->type_feedback_cells();
8170     for (int i = 0; i < type_feedback_cells->CellCount(); i++) {
8171       ASSERT(type_feedback_cells->AstId(i)->IsSmi());
8172       JSGlobalPropertyCell* cell = type_feedback_cells->Cell(i);
8173       cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap));
8174     }
8175   }
8176 }
8177
8178
8179 #ifdef ENABLE_DISASSEMBLER
8180
8181 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
8182   disasm::NameConverter converter;
8183   int deopt_count = DeoptCount();
8184   PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
8185   if (0 == deopt_count) return;
8186
8187   PrintF(out, "%6s  %6s  %6s %6s %12s\n", "index", "ast id", "argc", "pc",
8188          FLAG_print_code_verbose ? "commands" : "");
8189   for (int i = 0; i < deopt_count; i++) {
8190     PrintF(out, "%6d  %6d  %6d %6d",
8191            i,
8192            AstId(i)->value(),
8193            ArgumentsStackHeight(i)->value(),
8194            Pc(i)->value());
8195
8196     if (!FLAG_print_code_verbose) {
8197       PrintF(out, "\n");
8198       continue;
8199     }
8200     // Print details of the frame translation.
8201     int translation_index = TranslationIndex(i)->value();
8202     TranslationIterator iterator(TranslationByteArray(), translation_index);
8203     Translation::Opcode opcode =
8204         static_cast<Translation::Opcode>(iterator.Next());
8205     ASSERT(Translation::BEGIN == opcode);
8206     int frame_count = iterator.Next();
8207     int jsframe_count = iterator.Next();
8208     PrintF(out, "  %s {frame count=%d, js frame count=%d}\n",
8209            Translation::StringFor(opcode),
8210            frame_count,
8211            jsframe_count);
8212
8213     while (iterator.HasNext() &&
8214            Translation::BEGIN !=
8215            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
8216       PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
8217
8218       switch (opcode) {
8219         case Translation::BEGIN:
8220           UNREACHABLE();
8221           break;
8222
8223         case Translation::JS_FRAME: {
8224           int ast_id = iterator.Next();
8225           int function_id = iterator.Next();
8226           JSFunction* function =
8227               JSFunction::cast(LiteralArray()->get(function_id));
8228           unsigned height = iterator.Next();
8229           PrintF(out, "{ast_id=%d, function=", ast_id);
8230           function->PrintName(out);
8231           PrintF(out, ", height=%u}", height);
8232           break;
8233         }
8234
8235         case Translation::ARGUMENTS_ADAPTOR_FRAME:
8236         case Translation::CONSTRUCT_STUB_FRAME: {
8237           int function_id = iterator.Next();
8238           JSFunction* function =
8239               JSFunction::cast(LiteralArray()->get(function_id));
8240           unsigned height = iterator.Next();
8241           PrintF(out, "{function=");
8242           function->PrintName(out);
8243           PrintF(out, ", height=%u}", height);
8244           break;
8245         }
8246
8247         case Translation::DUPLICATE:
8248           break;
8249
8250         case Translation::REGISTER: {
8251           int reg_code = iterator.Next();
8252             PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
8253           break;
8254         }
8255
8256         case Translation::INT32_REGISTER: {
8257           int reg_code = iterator.Next();
8258           PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
8259           break;
8260         }
8261
8262         case Translation::DOUBLE_REGISTER: {
8263           int reg_code = iterator.Next();
8264           PrintF(out, "{input=%s}",
8265                  DoubleRegister::AllocationIndexToString(reg_code));
8266           break;
8267         }
8268
8269         case Translation::STACK_SLOT: {
8270           int input_slot_index = iterator.Next();
8271           PrintF(out, "{input=%d}", input_slot_index);
8272           break;
8273         }
8274
8275         case Translation::INT32_STACK_SLOT: {
8276           int input_slot_index = iterator.Next();
8277           PrintF(out, "{input=%d}", input_slot_index);
8278           break;
8279         }
8280
8281         case Translation::DOUBLE_STACK_SLOT: {
8282           int input_slot_index = iterator.Next();
8283           PrintF(out, "{input=%d}", input_slot_index);
8284           break;
8285         }
8286
8287         case Translation::LITERAL: {
8288           unsigned literal_index = iterator.Next();
8289           PrintF(out, "{literal_id=%u}", literal_index);
8290           break;
8291         }
8292
8293         case Translation::ARGUMENTS_OBJECT:
8294           break;
8295       }
8296       PrintF(out, "\n");
8297     }
8298   }
8299 }
8300
8301
8302 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
8303   PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
8304          this->DeoptPoints());
8305   if (this->DeoptPoints() == 0) return;
8306
8307   PrintF("%6s  %8s  %s\n", "ast id", "pc", "state");
8308   for (int i = 0; i < this->DeoptPoints(); i++) {
8309     int pc_and_state = this->PcAndState(i)->value();
8310     PrintF("%6d  %8d  %s\n",
8311            this->AstId(i)->value(),
8312            FullCodeGenerator::PcField::decode(pc_and_state),
8313            FullCodeGenerator::State2String(
8314                FullCodeGenerator::StateField::decode(pc_and_state)));
8315   }
8316 }
8317
8318
8319 // Identify kind of code.
8320 const char* Code::Kind2String(Kind kind) {
8321   switch (kind) {
8322     case FUNCTION: return "FUNCTION";
8323     case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION";
8324     case STUB: return "STUB";
8325     case BUILTIN: return "BUILTIN";
8326     case LOAD_IC: return "LOAD_IC";
8327     case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
8328     case STORE_IC: return "STORE_IC";
8329     case KEYED_STORE_IC: return "KEYED_STORE_IC";
8330     case CALL_IC: return "CALL_IC";
8331     case KEYED_CALL_IC: return "KEYED_CALL_IC";
8332     case UNARY_OP_IC: return "UNARY_OP_IC";
8333     case BINARY_OP_IC: return "BINARY_OP_IC";
8334     case COMPARE_IC: return "COMPARE_IC";
8335     case TO_BOOLEAN_IC: return "TO_BOOLEAN_IC";
8336   }
8337   UNREACHABLE();
8338   return NULL;
8339 }
8340
8341
8342 const char* Code::ICState2String(InlineCacheState state) {
8343   switch (state) {
8344     case UNINITIALIZED: return "UNINITIALIZED";
8345     case PREMONOMORPHIC: return "PREMONOMORPHIC";
8346     case MONOMORPHIC: return "MONOMORPHIC";
8347     case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
8348     case MEGAMORPHIC: return "MEGAMORPHIC";
8349     case DEBUG_BREAK: return "DEBUG_BREAK";
8350     case DEBUG_PREPARE_STEP_IN: return "DEBUG_PREPARE_STEP_IN";
8351   }
8352   UNREACHABLE();
8353   return NULL;
8354 }
8355
8356
8357 const char* Code::PropertyType2String(PropertyType type) {
8358   switch (type) {
8359     case NORMAL: return "NORMAL";
8360     case FIELD: return "FIELD";
8361     case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
8362     case CALLBACKS: return "CALLBACKS";
8363     case HANDLER: return "HANDLER";
8364     case INTERCEPTOR: return "INTERCEPTOR";
8365     case MAP_TRANSITION: return "MAP_TRANSITION";
8366     case ELEMENTS_TRANSITION: return "ELEMENTS_TRANSITION";
8367     case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
8368     case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
8369   }
8370   UNREACHABLE();  // keep the compiler happy
8371   return NULL;
8372 }
8373
8374
8375 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
8376   const char* name = NULL;
8377   switch (kind) {
8378     case CALL_IC:
8379       if (extra == STRING_INDEX_OUT_OF_BOUNDS) {
8380         name = "STRING_INDEX_OUT_OF_BOUNDS";
8381       }
8382       break;
8383     case STORE_IC:
8384     case KEYED_STORE_IC:
8385       if (extra == kStrictMode) {
8386         name = "STRICT";
8387       }
8388       break;
8389     default:
8390       break;
8391   }
8392   if (name != NULL) {
8393     PrintF(out, "extra_ic_state = %s\n", name);
8394   } else {
8395     PrintF(out, "extra_ic_state = %d\n", extra);
8396   }
8397 }
8398
8399
8400 void Code::Disassemble(const char* name, FILE* out) {
8401   PrintF(out, "kind = %s\n", Kind2String(kind()));
8402   if (is_inline_cache_stub()) {
8403     PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
8404     PrintExtraICState(out, kind(), extra_ic_state());
8405     if (ic_state() == MONOMORPHIC) {
8406       PrintF(out, "type = %s\n", PropertyType2String(type()));
8407     }
8408     if (is_call_stub() || is_keyed_call_stub()) {
8409       PrintF(out, "argc = %d\n", arguments_count());
8410     }
8411     if (is_compare_ic_stub()) {
8412       CompareIC::State state = CompareIC::ComputeState(this);
8413       PrintF(out, "compare_state = %s\n", CompareIC::GetStateName(state));
8414     }
8415     if (is_compare_ic_stub() && major_key() == CodeStub::CompareIC) {
8416       Token::Value op = CompareIC::ComputeOperation(this);
8417       PrintF(out, "compare_operation = %s\n", Token::Name(op));
8418     }
8419   }
8420   if ((name != NULL) && (name[0] != '\0')) {
8421     PrintF(out, "name = %s\n", name);
8422   }
8423   if (kind() == OPTIMIZED_FUNCTION) {
8424     PrintF(out, "stack_slots = %d\n", stack_slots());
8425   }
8426
8427   PrintF(out, "Instructions (size = %d)\n", instruction_size());
8428   Disassembler::Decode(out, this);
8429   PrintF(out, "\n");
8430
8431   if (kind() == FUNCTION) {
8432     DeoptimizationOutputData* data =
8433         DeoptimizationOutputData::cast(this->deoptimization_data());
8434     data->DeoptimizationOutputDataPrint(out);
8435   } else if (kind() == OPTIMIZED_FUNCTION) {
8436     DeoptimizationInputData* data =
8437         DeoptimizationInputData::cast(this->deoptimization_data());
8438     data->DeoptimizationInputDataPrint(out);
8439   }
8440   PrintF("\n");
8441
8442   if (kind() == OPTIMIZED_FUNCTION) {
8443     SafepointTable table(this);
8444     PrintF(out, "Safepoints (size = %u)\n", table.size());
8445     for (unsigned i = 0; i < table.length(); i++) {
8446       unsigned pc_offset = table.GetPcOffset(i);
8447       PrintF(out, "%p  %4d  ", (instruction_start() + pc_offset), pc_offset);
8448       table.PrintEntry(i);
8449       PrintF(out, " (sp -> fp)");
8450       SafepointEntry entry = table.GetEntry(i);
8451       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
8452         PrintF(out, "  %6d", entry.deoptimization_index());
8453       } else {
8454         PrintF(out, "  <none>");
8455       }
8456       if (entry.argument_count() > 0) {
8457         PrintF(out, " argc: %d", entry.argument_count());
8458       }
8459       PrintF(out, "\n");
8460     }
8461     PrintF(out, "\n");
8462   } else if (kind() == FUNCTION) {
8463     unsigned offset = stack_check_table_offset();
8464     // If there is no stack check table, the "table start" will at or after
8465     // (due to alignment) the end of the instruction stream.
8466     if (static_cast<int>(offset) < instruction_size()) {
8467       unsigned* address =
8468           reinterpret_cast<unsigned*>(instruction_start() + offset);
8469       unsigned length = address[0];
8470       PrintF(out, "Stack checks (size = %u)\n", length);
8471       PrintF(out, "ast_id  pc_offset\n");
8472       for (unsigned i = 0; i < length; ++i) {
8473         unsigned index = (2 * i) + 1;
8474         PrintF(out, "%6u  %9u\n", address[index], address[index + 1]);
8475       }
8476       PrintF(out, "\n");
8477     }
8478   }
8479
8480   PrintF("RelocInfo (size = %d)\n", relocation_size());
8481   for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
8482   PrintF(out, "\n");
8483 }
8484 #endif  // ENABLE_DISASSEMBLER
8485
8486
8487 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
8488     int capacity,
8489     int length,
8490     SetFastElementsCapacityMode set_capacity_mode) {
8491   Heap* heap = GetHeap();
8492   // We should never end in here with a pixel or external array.
8493   ASSERT(!HasExternalArrayElements());
8494
8495   // Allocate a new fast elements backing store.
8496   FixedArray* new_elements;
8497   { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
8498     if (!maybe->To(&new_elements)) return maybe;
8499   }
8500
8501   // Find the new map to use for this object if there is a map change.
8502   Map* new_map = NULL;
8503   if (elements()->map() != heap->non_strict_arguments_elements_map()) {
8504     // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces
8505     // it, or if it's allowed and the old elements array contained only SMIs.
8506     bool has_fast_smi_only_elements =
8507         (set_capacity_mode == kForceSmiOnlyElements) ||
8508         ((set_capacity_mode == kAllowSmiOnlyElements) &&
8509          (elements()->map()->has_fast_smi_only_elements() ||
8510           elements() == heap->empty_fixed_array()));
8511     ElementsKind elements_kind = has_fast_smi_only_elements
8512         ? FAST_SMI_ONLY_ELEMENTS
8513         : FAST_ELEMENTS;
8514     MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind);
8515     if (!maybe->To(&new_map)) return maybe;
8516   }
8517
8518   FixedArrayBase* old_elements = elements();
8519   ElementsKind elements_kind = GetElementsKind();
8520   ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8521   ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS)
8522       ? FAST_SMI_ONLY_ELEMENTS
8523       : FAST_ELEMENTS;
8524   { MaybeObject* maybe_obj =
8525         accessor->CopyElements(this, new_elements, to_kind);
8526     if (maybe_obj->IsFailure()) return maybe_obj;
8527   }
8528   if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8529     set_map_and_elements(new_map, new_elements);
8530   } else {
8531     FixedArray* parameter_map = FixedArray::cast(old_elements);
8532     parameter_map->set(1, new_elements);
8533   }
8534
8535   if (FLAG_trace_elements_transitions) {
8536     PrintElementsTransition(stdout, elements_kind, old_elements,
8537                             GetElementsKind(), new_elements);
8538   }
8539
8540   // Update the length if necessary.
8541   if (IsJSArray()) {
8542     JSArray::cast(this)->set_length(Smi::FromInt(length));
8543   }
8544
8545   return new_elements;
8546 }
8547
8548
8549 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
8550     int capacity,
8551     int length) {
8552   Heap* heap = GetHeap();
8553   // We should never end in here with a pixel or external array.
8554   ASSERT(!HasExternalArrayElements());
8555
8556   FixedArrayBase* elems;
8557   { MaybeObject* maybe_obj =
8558         heap->AllocateUninitializedFixedDoubleArray(capacity);
8559     if (!maybe_obj->To(&elems)) return maybe_obj;
8560   }
8561
8562   Map* new_map;
8563   { MaybeObject* maybe_obj =
8564         GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS);
8565     if (!maybe_obj->To(&new_map)) return maybe_obj;
8566   }
8567
8568   FixedArrayBase* old_elements = elements();
8569   ElementsKind elements_kind = GetElementsKind();
8570   ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8571   { MaybeObject* maybe_obj =
8572         accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
8573     if (maybe_obj->IsFailure()) return maybe_obj;
8574   }
8575   if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8576     set_map_and_elements(new_map, elems);
8577   } else {
8578     FixedArray* parameter_map = FixedArray::cast(old_elements);
8579     parameter_map->set(1, elems);
8580   }
8581
8582   if (FLAG_trace_elements_transitions) {
8583     PrintElementsTransition(stdout, elements_kind, old_elements,
8584                             FAST_DOUBLE_ELEMENTS, elems);
8585   }
8586
8587   if (IsJSArray()) {
8588     JSArray::cast(this)->set_length(Smi::FromInt(length));
8589   }
8590
8591   return this;
8592 }
8593
8594
8595 MaybeObject* JSArray::Initialize(int capacity) {
8596   Heap* heap = GetHeap();
8597   ASSERT(capacity >= 0);
8598   set_length(Smi::FromInt(0));
8599   FixedArray* new_elements;
8600   if (capacity == 0) {
8601     new_elements = heap->empty_fixed_array();
8602   } else {
8603     MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
8604     if (!maybe_obj->To(&new_elements)) return maybe_obj;
8605   }
8606   set_elements(new_elements);
8607   return this;
8608 }
8609
8610
8611 void JSArray::Expand(int required_size) {
8612   GetIsolate()->factory()->SetElementsCapacityAndLength(
8613       Handle<JSArray>(this), required_size, required_size);
8614 }
8615
8616
8617 MaybeObject* JSArray::SetElementsLength(Object* len) {
8618   // We should never end in here with a pixel or external array.
8619   ASSERT(AllowsSetElementsLength());
8620   return GetElementsAccessor()->SetLength(this, len);
8621 }
8622
8623
8624 Object* Map::GetPrototypeTransition(Object* prototype) {
8625   FixedArray* cache = prototype_transitions();
8626   int number_of_transitions = NumberOfProtoTransitions();
8627   const int proto_offset =
8628       kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
8629   const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
8630   const int step = kProtoTransitionElementsPerEntry;
8631   for (int i = 0; i < number_of_transitions; i++) {
8632     if (cache->get(proto_offset + i * step) == prototype) {
8633       Object* map = cache->get(map_offset + i * step);
8634       ASSERT(map->IsMap());
8635       return map;
8636     }
8637   }
8638   return NULL;
8639 }
8640
8641
8642 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
8643   ASSERT(map->IsMap());
8644   ASSERT(HeapObject::cast(prototype)->map()->IsMap());
8645   // Don't cache prototype transition if this map is shared.
8646   if (is_shared() || !FLAG_cache_prototype_transitions) return this;
8647
8648   FixedArray* cache = prototype_transitions();
8649
8650   const int step = kProtoTransitionElementsPerEntry;
8651   const int header = kProtoTransitionHeaderSize;
8652
8653   int capacity = (cache->length() - header) / step;
8654
8655   int transitions = NumberOfProtoTransitions() + 1;
8656
8657   if (transitions > capacity) {
8658     if (capacity > kMaxCachedPrototypeTransitions) return this;
8659
8660     FixedArray* new_cache;
8661     // Grow array by factor 2 over and above what we need.
8662     { MaybeObject* maybe_cache =
8663           GetHeap()->AllocateFixedArray(transitions * 2 * step + header);
8664       if (!maybe_cache->To(&new_cache)) return maybe_cache;
8665     }
8666
8667     for (int i = 0; i < capacity * step; i++) {
8668       new_cache->set(i + header, cache->get(i + header));
8669     }
8670     cache = new_cache;
8671     set_prototype_transitions(cache);
8672   }
8673
8674   int last = transitions - 1;
8675
8676   cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype);
8677   cache->set(header + last * step + kProtoTransitionMapOffset, map);
8678   SetNumberOfProtoTransitions(transitions);
8679
8680   return cache;
8681 }
8682
8683
8684 MaybeObject* JSReceiver::SetPrototype(Object* value,
8685                                       bool skip_hidden_prototypes) {
8686 #ifdef DEBUG
8687   int size = Size();
8688 #endif
8689
8690   Heap* heap = GetHeap();
8691   // Silently ignore the change if value is not a JSObject or null.
8692   // SpiderMonkey behaves this way.
8693   if (!value->IsJSReceiver() && !value->IsNull()) return value;
8694
8695   // From 8.6.2 Object Internal Methods
8696   // ...
8697   // In addition, if [[Extensible]] is false the value of the [[Class]] and
8698   // [[Prototype]] internal properties of the object may not be modified.
8699   // ...
8700   // Implementation specific extensions that modify [[Class]], [[Prototype]]
8701   // or [[Extensible]] must not violate the invariants defined in the preceding
8702   // paragraph.
8703   if (!this->map()->is_extensible()) {
8704     HandleScope scope(heap->isolate());
8705     Handle<Object> handle(this, heap->isolate());
8706     return heap->isolate()->Throw(
8707         *FACTORY->NewTypeError("non_extensible_proto",
8708                                HandleVector<Object>(&handle, 1)));
8709   }
8710
8711   // Before we can set the prototype we need to be sure
8712   // prototype cycles are prevented.
8713   // It is sufficient to validate that the receiver is not in the new prototype
8714   // chain.
8715   for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
8716     if (JSReceiver::cast(pt) == this) {
8717       // Cycle detected.
8718       HandleScope scope(heap->isolate());
8719       return heap->isolate()->Throw(
8720           *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
8721     }
8722   }
8723
8724   JSReceiver* real_receiver = this;
8725
8726   if (skip_hidden_prototypes) {
8727     // Find the first object in the chain whose prototype object is not
8728     // hidden and set the new prototype on that object.
8729     Object* current_proto = real_receiver->GetPrototype();
8730     while (current_proto->IsJSObject() &&
8731           JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) {
8732       real_receiver = JSReceiver::cast(current_proto);
8733       current_proto = current_proto->GetPrototype();
8734     }
8735   }
8736
8737   // Set the new prototype of the object.
8738   Map* map = real_receiver->map();
8739
8740   // Nothing to do if prototype is already set.
8741   if (map->prototype() == value) return value;
8742
8743   Object* new_map = map->GetPrototypeTransition(value);
8744   if (new_map == NULL) {
8745     { MaybeObject* maybe_new_map = map->CopyDropTransitions();
8746       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
8747     }
8748
8749     { MaybeObject* maybe_new_cache =
8750           map->PutPrototypeTransition(value, Map::cast(new_map));
8751       if (maybe_new_cache->IsFailure()) return maybe_new_cache;
8752     }
8753
8754     Map::cast(new_map)->set_prototype(value);
8755   }
8756   ASSERT(Map::cast(new_map)->prototype() == value);
8757   real_receiver->set_map(Map::cast(new_map));
8758
8759   heap->ClearInstanceofCache();
8760   ASSERT(size == Size());
8761   return value;
8762 }
8763
8764
8765 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args,
8766                                                 uint32_t first_arg,
8767                                                 uint32_t arg_count,
8768                                                 EnsureElementsMode mode) {
8769   // Elements in |Arguments| are ordered backwards (because they're on the
8770   // stack), but the method that's called here iterates over them in forward
8771   // direction.
8772   return EnsureCanContainElements(
8773       args->arguments() - first_arg - (arg_count - 1),
8774       arg_count, mode);
8775 }
8776
8777
8778 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) {
8779   Isolate* isolate = GetIsolate();
8780   // Make sure that the top context does not change when doing
8781   // callbacks or interceptor calls.
8782   AssertNoContextChange ncc;
8783   HandleScope scope(isolate);
8784   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
8785   Handle<JSReceiver> receiver_handle(receiver);
8786   Handle<JSObject> holder_handle(this);
8787   CustomArguments args(isolate, interceptor->data(), receiver, this);
8788   v8::AccessorInfo info(args.end());
8789   if (!interceptor->query()->IsUndefined()) {
8790     v8::IndexedPropertyQuery query =
8791         v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
8792     LOG(isolate,
8793         ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
8794     v8::Handle<v8::Integer> result;
8795     {
8796       // Leaving JavaScript.
8797       VMState state(isolate, EXTERNAL);
8798       result = query(index, info);
8799     }
8800     if (!result.IsEmpty()) {
8801       ASSERT(result->IsInt32());
8802       return true;  // absence of property is signaled by empty handle.
8803     }
8804   } else if (!interceptor->getter()->IsUndefined()) {
8805     v8::IndexedPropertyGetter getter =
8806         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
8807     LOG(isolate,
8808         ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
8809     v8::Handle<v8::Value> result;
8810     {
8811       // Leaving JavaScript.
8812       VMState state(isolate, EXTERNAL);
8813       result = getter(index, info);
8814     }
8815     if (!result.IsEmpty()) return true;
8816   }
8817
8818   if (holder_handle->GetElementsAccessor()->HasElement(
8819           *receiver_handle, *holder_handle, index)) {
8820     return true;
8821   }
8822
8823   if (holder_handle->IsStringObjectWithCharacterAt(index)) return true;
8824   Object* pt = holder_handle->GetPrototype();
8825   if (pt->IsJSProxy()) {
8826     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
8827     return JSProxy::cast(pt)->GetElementAttributeWithHandler(
8828         receiver, index) != ABSENT;
8829   }
8830   if (pt->IsNull()) return false;
8831   return JSObject::cast(pt)->HasElementWithReceiver(*receiver_handle, index);
8832 }
8833
8834
8835 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) {
8836   // Check access rights if needed.
8837   if (IsAccessCheckNeeded()) {
8838     Heap* heap = GetHeap();
8839     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
8840       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
8841       return UNDEFINED_ELEMENT;
8842     }
8843   }
8844
8845   if (IsJSGlobalProxy()) {
8846     Object* proto = GetPrototype();
8847     if (proto->IsNull()) return UNDEFINED_ELEMENT;
8848     ASSERT(proto->IsJSGlobalObject());
8849     return JSObject::cast(proto)->HasLocalElement(index);
8850   }
8851
8852   // Check for lookup interceptor
8853   if (HasIndexedInterceptor()) {
8854     return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
8855                                                   : UNDEFINED_ELEMENT;
8856   }
8857
8858   // Handle [] on String objects.
8859   if (this->IsStringObjectWithCharacterAt(index)) {
8860     return STRING_CHARACTER_ELEMENT;
8861   }
8862
8863   switch (GetElementsKind()) {
8864     case FAST_SMI_ONLY_ELEMENTS:
8865     case FAST_ELEMENTS: {
8866       uint32_t length = IsJSArray() ?
8867           static_cast<uint32_t>
8868               (Smi::cast(JSArray::cast(this)->length())->value()) :
8869           static_cast<uint32_t>(FixedArray::cast(elements())->length());
8870       if ((index < length) &&
8871           !FixedArray::cast(elements())->get(index)->IsTheHole()) {
8872         return FAST_ELEMENT;
8873       }
8874       break;
8875     }
8876     case FAST_DOUBLE_ELEMENTS: {
8877       uint32_t length = IsJSArray() ?
8878           static_cast<uint32_t>
8879               (Smi::cast(JSArray::cast(this)->length())->value()) :
8880           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
8881       if ((index < length) &&
8882           !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
8883         return FAST_ELEMENT;
8884       }
8885       break;
8886     }
8887     case EXTERNAL_PIXEL_ELEMENTS: {
8888       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
8889       if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT;
8890       break;
8891     }
8892     case EXTERNAL_BYTE_ELEMENTS:
8893     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8894     case EXTERNAL_SHORT_ELEMENTS:
8895     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8896     case EXTERNAL_INT_ELEMENTS:
8897     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8898     case EXTERNAL_FLOAT_ELEMENTS:
8899     case EXTERNAL_DOUBLE_ELEMENTS: {
8900       ExternalArray* array = ExternalArray::cast(elements());
8901       if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
8902       break;
8903     }
8904     case DICTIONARY_ELEMENTS: {
8905       if (element_dictionary()->FindEntry(index) !=
8906           SeededNumberDictionary::kNotFound) {
8907         return DICTIONARY_ELEMENT;
8908       }
8909       break;
8910     }
8911     case NON_STRICT_ARGUMENTS_ELEMENTS: {
8912       // Aliased parameters and non-aliased elements in a fast backing store
8913       // behave as FAST_ELEMENT.  Non-aliased elements in a dictionary
8914       // backing store behave as DICTIONARY_ELEMENT.
8915       FixedArray* parameter_map = FixedArray::cast(elements());
8916       uint32_t length = parameter_map->length();
8917       Object* probe =
8918           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
8919       if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
8920       // If not aliased, check the arguments.
8921       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
8922       if (arguments->IsDictionary()) {
8923         SeededNumberDictionary* dictionary =
8924             SeededNumberDictionary::cast(arguments);
8925         if (dictionary->FindEntry(index) != SeededNumberDictionary::kNotFound) {
8926           return DICTIONARY_ELEMENT;
8927         }
8928       } else {
8929         length = arguments->length();
8930         probe = (index < length) ? arguments->get(index) : NULL;
8931         if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
8932       }
8933       break;
8934     }
8935   }
8936
8937   return UNDEFINED_ELEMENT;
8938 }
8939
8940
8941 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
8942   // Check access rights if needed.
8943   if (IsAccessCheckNeeded()) {
8944     Heap* heap = GetHeap();
8945     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
8946       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
8947       return false;
8948     }
8949   }
8950
8951   // Check for lookup interceptor
8952   if (HasIndexedInterceptor()) {
8953     return HasElementWithInterceptor(receiver, index);
8954   }
8955
8956   ElementsAccessor* accessor = GetElementsAccessor();
8957   if (accessor->HasElement(receiver, this, index)) {
8958     return true;
8959   }
8960
8961   // Handle [] on String objects.
8962   if (this->IsStringObjectWithCharacterAt(index)) return true;
8963
8964   Object* pt = GetPrototype();
8965   if (pt->IsNull()) return false;
8966   if (pt->IsJSProxy()) {
8967     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
8968     return JSProxy::cast(pt)->GetElementAttributeWithHandler(
8969         receiver, index) != ABSENT;
8970   }
8971   return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
8972 }
8973
8974
8975 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
8976                                                  Object* value,
8977                                                  PropertyAttributes attributes,
8978                                                  StrictModeFlag strict_mode,
8979                                                  bool check_prototype,
8980                                                  SetPropertyMode set_mode) {
8981   Isolate* isolate = GetIsolate();
8982   // Make sure that the top context does not change when doing
8983   // callbacks or interceptor calls.
8984   AssertNoContextChange ncc;
8985   HandleScope scope(isolate);
8986   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
8987   Handle<JSObject> this_handle(this);
8988   Handle<Object> value_handle(value, isolate);
8989   if (!interceptor->setter()->IsUndefined()) {
8990     v8::IndexedPropertySetter setter =
8991         v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
8992     LOG(isolate,
8993         ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
8994     CustomArguments args(isolate, interceptor->data(), this, this);
8995     v8::AccessorInfo info(args.end());
8996     v8::Handle<v8::Value> result;
8997     {
8998       // Leaving JavaScript.
8999       VMState state(isolate, EXTERNAL);
9000       result = setter(index, v8::Utils::ToLocal(value_handle), info);
9001     }
9002     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9003     if (!result.IsEmpty()) return *value_handle;
9004   }
9005   MaybeObject* raw_result =
9006       this_handle->SetElementWithoutInterceptor(index,
9007                                                 *value_handle,
9008                                                 attributes,
9009                                                 strict_mode,
9010                                                 check_prototype,
9011                                                 set_mode);
9012   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9013   return raw_result;
9014 }
9015
9016
9017 MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
9018                                               Object* structure,
9019                                               uint32_t index,
9020                                               Object* holder) {
9021   Isolate* isolate = GetIsolate();
9022   ASSERT(!structure->IsForeign());
9023
9024   // api style callbacks.
9025   if (structure->IsAccessorInfo()) {
9026     Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9027     Object* fun_obj = data->getter();
9028     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
9029     HandleScope scope(isolate);
9030     Handle<JSObject> self(JSObject::cast(receiver));
9031     Handle<JSObject> holder_handle(JSObject::cast(holder));
9032     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9033     Handle<String> key = isolate->factory()->NumberToString(number);
9034     LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
9035     CustomArguments args(isolate, data->data(), *self, *holder_handle);
9036     v8::AccessorInfo info(args.end());
9037     v8::Handle<v8::Value> result;
9038     {
9039       // Leaving JavaScript.
9040       VMState state(isolate, EXTERNAL);
9041       result = call_fun(v8::Utils::ToLocal(key), info);
9042     }
9043     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9044     if (result.IsEmpty()) return isolate->heap()->undefined_value();
9045     return *v8::Utils::OpenHandle(*result);
9046   }
9047
9048   // __defineGetter__ callback
9049   if (structure->IsAccessorPair()) {
9050     Object* getter = AccessorPair::cast(structure)->getter();
9051     if (getter->IsSpecFunction()) {
9052       // TODO(rossberg): nicer would be to cast to some JSCallable here...
9053       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
9054     }
9055     // Getter is not a function.
9056     return isolate->heap()->undefined_value();
9057   }
9058
9059   UNREACHABLE();
9060   return NULL;
9061 }
9062
9063
9064 MaybeObject* JSObject::SetElementWithCallback(Object* structure,
9065                                               uint32_t index,
9066                                               Object* value,
9067                                               JSObject* holder,
9068                                               StrictModeFlag strict_mode) {
9069   Isolate* isolate = GetIsolate();
9070   HandleScope scope(isolate);
9071
9072   // We should never get here to initialize a const with the hole
9073   // value since a const declaration would conflict with the setter.
9074   ASSERT(!value->IsTheHole());
9075   Handle<Object> value_handle(value, isolate);
9076
9077   // To accommodate both the old and the new api we switch on the
9078   // data structure used to store the callbacks.  Eventually foreign
9079   // callbacks should be phased out.
9080   ASSERT(!structure->IsForeign());
9081
9082   if (structure->IsAccessorInfo()) {
9083     // api style callbacks
9084     Handle<JSObject> self(this);
9085     Handle<JSObject> holder_handle(JSObject::cast(holder));
9086     Handle<AccessorInfo> data(AccessorInfo::cast(structure));
9087     Object* call_obj = data->setter();
9088     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
9089     if (call_fun == NULL) return value;
9090     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9091     Handle<String> key(isolate->factory()->NumberToString(number));
9092     LOG(isolate, ApiNamedPropertyAccess("store", *self, *key));
9093     CustomArguments args(isolate, data->data(), *self, *holder_handle);
9094     v8::AccessorInfo info(args.end());
9095     {
9096       // Leaving JavaScript.
9097       VMState state(isolate, EXTERNAL);
9098       call_fun(v8::Utils::ToLocal(key),
9099                v8::Utils::ToLocal(value_handle),
9100                info);
9101     }
9102     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9103     return *value_handle;
9104   }
9105
9106   if (structure->IsAccessorPair()) {
9107     Handle<Object> setter(AccessorPair::cast(structure)->setter());
9108     if (setter->IsSpecFunction()) {
9109       // TODO(rossberg): nicer would be to cast to some JSCallable here...
9110       return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
9111     } else {
9112       if (strict_mode == kNonStrictMode) {
9113         return value;
9114       }
9115       Handle<Object> holder_handle(holder, isolate);
9116       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
9117       Handle<Object> args[2] = { key, holder_handle };
9118       return isolate->Throw(
9119           *isolate->factory()->NewTypeError("no_setter_in_callback",
9120                                             HandleVector(args, 2)));
9121     }
9122   }
9123
9124   UNREACHABLE();
9125   return NULL;
9126 }
9127
9128
9129 bool JSObject::HasFastArgumentsElements() {
9130   Heap* heap = GetHeap();
9131   if (!elements()->IsFixedArray()) return false;
9132   FixedArray* elements = FixedArray::cast(this->elements());
9133   if (elements->map() != heap->non_strict_arguments_elements_map()) {
9134     return false;
9135   }
9136   FixedArray* arguments = FixedArray::cast(elements->get(1));
9137   return !arguments->IsDictionary();
9138 }
9139
9140
9141 bool JSObject::HasDictionaryArgumentsElements() {
9142   Heap* heap = GetHeap();
9143   if (!elements()->IsFixedArray()) return false;
9144   FixedArray* elements = FixedArray::cast(this->elements());
9145   if (elements->map() != heap->non_strict_arguments_elements_map()) {
9146     return false;
9147   }
9148   FixedArray* arguments = FixedArray::cast(elements->get(1));
9149   return arguments->IsDictionary();
9150 }
9151
9152
9153 // Adding n elements in fast case is O(n*n).
9154 // Note: revisit design to have dual undefined values to capture absent
9155 // elements.
9156 MaybeObject* JSObject::SetFastElement(uint32_t index,
9157                                       Object* value,
9158                                       StrictModeFlag strict_mode,
9159                                       bool check_prototype) {
9160   ASSERT(HasFastTypeElements() ||
9161          HasFastArgumentsElements());
9162
9163   FixedArray* backing_store = FixedArray::cast(elements());
9164   if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
9165     backing_store = FixedArray::cast(backing_store->get(1));
9166   } else {
9167     MaybeObject* maybe = EnsureWritableFastElements();
9168     if (!maybe->To(&backing_store)) return maybe;
9169   }
9170   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
9171
9172   if (check_prototype &&
9173       (index >= capacity || backing_store->get(index)->IsTheHole())) {
9174     bool found;
9175     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9176                                                                    value,
9177                                                                    &found,
9178                                                                    strict_mode);
9179     if (found) return result;
9180   }
9181
9182   uint32_t new_capacity = capacity;
9183   // Check if the length property of this object needs to be updated.
9184   uint32_t array_length = 0;
9185   bool must_update_array_length = false;
9186   if (IsJSArray()) {
9187     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9188     if (index >= array_length) {
9189       must_update_array_length = true;
9190       array_length = index + 1;
9191     }
9192   }
9193   // Check if the capacity of the backing store needs to be increased, or if
9194   // a transition to slow elements is necessary.
9195   if (index >= capacity) {
9196     bool convert_to_slow = true;
9197     if ((index - capacity) < kMaxGap) {
9198       new_capacity = NewElementsCapacity(index + 1);
9199       ASSERT(new_capacity > index);
9200       if (!ShouldConvertToSlowElements(new_capacity)) {
9201         convert_to_slow = false;
9202       }
9203     }
9204     if (convert_to_slow) {
9205       MaybeObject* result = NormalizeElements();
9206       if (result->IsFailure()) return result;
9207       return SetDictionaryElement(index, value, NONE, strict_mode,
9208                                   check_prototype);
9209     }
9210   }
9211   // Convert to fast double elements if appropriate.
9212   if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) {
9213     MaybeObject* maybe =
9214         SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
9215     if (maybe->IsFailure()) return maybe;
9216     FixedDoubleArray::cast(elements())->set(index, value->Number());
9217     return value;
9218   }
9219   // Change elements kind from SMI_ONLY to generic FAST if necessary.
9220   if (HasFastSmiOnlyElements() && !value->IsSmi()) {
9221     Map* new_map;
9222     { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
9223                                                             FAST_ELEMENTS);
9224       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9225     }
9226     set_map(new_map);
9227     if (FLAG_trace_elements_transitions) {
9228       PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
9229                               FAST_ELEMENTS, elements());
9230     }
9231   }
9232   // Increase backing store capacity if that's been decided previously.
9233   if (new_capacity != capacity) {
9234     FixedArray* new_elements;
9235     SetFastElementsCapacityMode set_capacity_mode =
9236         value->IsSmi() && HasFastSmiOnlyElements()
9237             ? kAllowSmiOnlyElements
9238             : kDontAllowSmiOnlyElements;
9239     { MaybeObject* maybe =
9240           SetFastElementsCapacityAndLength(new_capacity,
9241                                            array_length,
9242                                            set_capacity_mode);
9243       if (!maybe->To(&new_elements)) return maybe;
9244     }
9245     new_elements->set(index, value);
9246     return value;
9247   }
9248   // Finally, set the new element and length.
9249   ASSERT(elements()->IsFixedArray());
9250   backing_store->set(index, value);
9251   if (must_update_array_length) {
9252     JSArray::cast(this)->set_length(Smi::FromInt(array_length));
9253   }
9254   return value;
9255 }
9256
9257
9258 MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
9259                                             Object* value,
9260                                             PropertyAttributes attributes,
9261                                             StrictModeFlag strict_mode,
9262                                             bool check_prototype,
9263                                             SetPropertyMode set_mode) {
9264   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
9265   Isolate* isolate = GetIsolate();
9266   Heap* heap = isolate->heap();
9267
9268   // Insert element in the dictionary.
9269   FixedArray* elements = FixedArray::cast(this->elements());
9270   bool is_arguments =
9271       (elements->map() == heap->non_strict_arguments_elements_map());
9272   SeededNumberDictionary* dictionary = NULL;
9273   if (is_arguments) {
9274     dictionary = SeededNumberDictionary::cast(elements->get(1));
9275   } else {
9276     dictionary = SeededNumberDictionary::cast(elements);
9277   }
9278
9279   int entry = dictionary->FindEntry(index);
9280   if (entry != SeededNumberDictionary::kNotFound) {
9281     Object* element = dictionary->ValueAt(entry);
9282     PropertyDetails details = dictionary->DetailsAt(entry);
9283     if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
9284       return SetElementWithCallback(element, index, value, this, strict_mode);
9285     } else {
9286       dictionary->UpdateMaxNumberKey(index);
9287       // If a value has not been initialized we allow writing to it even if it
9288       // is read-only (a declared const that has not been initialized).  If a
9289       // value is being defined we skip attribute checks completely.
9290       if (set_mode == DEFINE_PROPERTY) {
9291         details = PropertyDetails(attributes, NORMAL, details.index());
9292         dictionary->DetailsAtPut(entry, details);
9293       } else if (details.IsReadOnly() && !element->IsTheHole()) {
9294         if (strict_mode == kNonStrictMode) {
9295           return isolate->heap()->undefined_value();
9296         } else {
9297           Handle<Object> holder(this);
9298           Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9299           Handle<Object> args[2] = { number, holder };
9300           Handle<Object> error =
9301               isolate->factory()->NewTypeError("strict_read_only_property",
9302                                                HandleVector(args, 2));
9303           return isolate->Throw(*error);
9304         }
9305       }
9306       // Elements of the arguments object in slow mode might be slow aliases.
9307       if (is_arguments && element->IsAliasedArgumentsEntry()) {
9308         AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(element);
9309         Context* context = Context::cast(elements->get(0));
9310         int context_index = entry->aliased_context_slot();
9311         ASSERT(!context->get(context_index)->IsTheHole());
9312         context->set(context_index, value);
9313         // For elements that are still writable we keep slow aliasing.
9314         if (!details.IsReadOnly()) value = element;
9315       }
9316       dictionary->ValueAtPut(entry, value);
9317     }
9318   } else {
9319     // Index not already used. Look for an accessor in the prototype chain.
9320     if (check_prototype) {
9321       bool found;
9322       MaybeObject* result =
9323           SetElementWithCallbackSetterInPrototypes(
9324               index, value, &found, strict_mode);
9325       if (found) return result;
9326     }
9327     // When we set the is_extensible flag to false we always force the
9328     // element into dictionary mode (and force them to stay there).
9329     if (!map()->is_extensible()) {
9330       if (strict_mode == kNonStrictMode) {
9331         return isolate->heap()->undefined_value();
9332       } else {
9333         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9334         Handle<String> name = isolate->factory()->NumberToString(number);
9335         Handle<Object> args[1] = { name };
9336         Handle<Object> error =
9337             isolate->factory()->NewTypeError("object_not_extensible",
9338                                              HandleVector(args, 1));
9339         return isolate->Throw(*error);
9340       }
9341     }
9342     FixedArrayBase* new_dictionary;
9343     PropertyDetails details = PropertyDetails(attributes, NORMAL);
9344     MaybeObject* maybe = dictionary->AddNumberEntry(index, value, details);
9345     if (!maybe->To(&new_dictionary)) return maybe;
9346     if (dictionary != SeededNumberDictionary::cast(new_dictionary)) {
9347       if (is_arguments) {
9348         elements->set(1, new_dictionary);
9349       } else {
9350         set_elements(new_dictionary);
9351       }
9352       dictionary = SeededNumberDictionary::cast(new_dictionary);
9353     }
9354   }
9355
9356   // Update the array length if this JSObject is an array.
9357   if (IsJSArray()) {
9358     MaybeObject* result =
9359         JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
9360     if (result->IsFailure()) return result;
9361   }
9362
9363   // Attempt to put this object back in fast case.
9364   if (ShouldConvertToFastElements()) {
9365     uint32_t new_length = 0;
9366     if (IsJSArray()) {
9367       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
9368     } else {
9369       new_length = dictionary->max_number_key() + 1;
9370     }
9371     SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays
9372         ? kAllowSmiOnlyElements
9373         : kDontAllowSmiOnlyElements;
9374     bool has_smi_only_elements = false;
9375     bool should_convert_to_fast_double_elements =
9376         ShouldConvertToFastDoubleElements(&has_smi_only_elements);
9377     if (has_smi_only_elements) {
9378       set_capacity_mode = kForceSmiOnlyElements;
9379     }
9380     MaybeObject* result = should_convert_to_fast_double_elements
9381         ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
9382         : SetFastElementsCapacityAndLength(new_length,
9383                                            new_length,
9384                                            set_capacity_mode);
9385     if (result->IsFailure()) return result;
9386 #ifdef DEBUG
9387     if (FLAG_trace_normalization) {
9388       PrintF("Object elements are fast case again:\n");
9389       Print();
9390     }
9391 #endif
9392   }
9393   return value;
9394 }
9395
9396
9397 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
9398     uint32_t index,
9399     Object* value,
9400     StrictModeFlag strict_mode,
9401     bool check_prototype) {
9402   ASSERT(HasFastDoubleElements());
9403
9404   FixedArrayBase* base_elms = FixedArrayBase::cast(elements());
9405   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
9406
9407   // If storing to an element that isn't in the array, pass the store request
9408   // up the prototype chain before storing in the receiver's elements.
9409   if (check_prototype &&
9410       (index >= elms_length ||
9411        FixedDoubleArray::cast(base_elms)->is_the_hole(index))) {
9412     bool found;
9413     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9414                                                                    value,
9415                                                                    &found,
9416                                                                    strict_mode);
9417     if (found) return result;
9418   }
9419
9420   // If the value object is not a heap number, switch to fast elements and try
9421   // again.
9422   bool value_is_smi = value->IsSmi();
9423   if (!value->IsNumber()) {
9424     Object* obj;
9425     uint32_t length = elms_length;
9426     if (IsJSArray()) {
9427       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9428     }
9429     MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
9430         elms_length,
9431         length,
9432         kDontAllowSmiOnlyElements);
9433     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9434     return SetFastElement(index,
9435                           value,
9436                           strict_mode,
9437                           check_prototype);
9438   }
9439
9440   double double_value = value_is_smi
9441       ? static_cast<double>(Smi::cast(value)->value())
9442       : HeapNumber::cast(value)->value();
9443
9444   // Check whether there is extra space in the fixed array.
9445   if (index < elms_length) {
9446     FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9447     elms->set(index, double_value);
9448     if (IsJSArray()) {
9449       // Update the length of the array if needed.
9450       uint32_t array_length = 0;
9451       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9452       if (index >= array_length) {
9453         JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
9454       }
9455     }
9456     return value;
9457   }
9458
9459   // Allow gap in fast case.
9460   if ((index - elms_length) < kMaxGap) {
9461     // Try allocating extra space.
9462     int new_capacity = NewElementsCapacity(index+1);
9463     if (!ShouldConvertToSlowElements(new_capacity)) {
9464       ASSERT(static_cast<uint32_t>(new_capacity) > index);
9465       Object* obj;
9466       { MaybeObject* maybe_obj =
9467             SetFastDoubleElementsCapacityAndLength(new_capacity,
9468                                                    index + 1);
9469         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9470       }
9471       FixedDoubleArray::cast(elements())->set(index, double_value);
9472       return value;
9473     }
9474   }
9475
9476   // Otherwise default to slow case.
9477   ASSERT(HasFastDoubleElements());
9478   ASSERT(map()->has_fast_double_elements());
9479   ASSERT(elements()->IsFixedDoubleArray());
9480   Object* obj;
9481   { MaybeObject* maybe_obj = NormalizeElements();
9482     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9483   }
9484   ASSERT(HasDictionaryElements());
9485   return SetElement(index, value, NONE, strict_mode, check_prototype);
9486 }
9487
9488
9489 MaybeObject* JSReceiver::SetElement(uint32_t index,
9490                                     Object* value,
9491                                     PropertyAttributes attributes,
9492                                     StrictModeFlag strict_mode,
9493                                     bool check_proto) {
9494   if (IsJSProxy()) {
9495     return JSProxy::cast(this)->SetElementWithHandler(
9496         index, value, strict_mode);
9497   } else {
9498     return JSObject::cast(this)->SetElement(
9499         index, value, attributes, strict_mode, check_proto);
9500   }
9501 }
9502
9503
9504 Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
9505                                        uint32_t index,
9506                                        Handle<Object> value,
9507                                        StrictModeFlag strict_mode) {
9508   ASSERT(!object->HasExternalArrayElements());
9509   CALL_HEAP_FUNCTION(
9510       object->GetIsolate(),
9511       object->SetElement(index, *value, NONE, strict_mode, false),
9512       Object);
9513 }
9514
9515
9516 Handle<Object> JSObject::SetElement(Handle<JSObject> object,
9517                                     uint32_t index,
9518                                     Handle<Object> value,
9519                                     PropertyAttributes attr,
9520                                     StrictModeFlag strict_mode,
9521                                     SetPropertyMode set_mode) {
9522   if (object->HasExternalArrayElements()) {
9523     if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
9524       bool has_exception;
9525       Handle<Object> number = Execution::ToNumber(value, &has_exception);
9526       if (has_exception) return Handle<Object>();
9527       value = number;
9528     }
9529   }
9530   CALL_HEAP_FUNCTION(
9531       object->GetIsolate(),
9532       object->SetElement(index, *value, attr, strict_mode, true, set_mode),
9533       Object);
9534 }
9535
9536
9537 MaybeObject* JSObject::SetElement(uint32_t index,
9538                                   Object* value,
9539                                   PropertyAttributes attributes,
9540                                   StrictModeFlag strict_mode,
9541                                   bool check_prototype,
9542                                   SetPropertyMode set_mode) {
9543   // Check access rights if needed.
9544   if (IsAccessCheckNeeded()) {
9545     Heap* heap = GetHeap();
9546     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
9547       HandleScope scope(heap->isolate());
9548       Handle<Object> value_handle(value);
9549       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
9550       return *value_handle;
9551     }
9552   }
9553
9554   if (IsJSGlobalProxy()) {
9555     Object* proto = GetPrototype();
9556     if (proto->IsNull()) return value;
9557     ASSERT(proto->IsJSGlobalObject());
9558     return JSObject::cast(proto)->SetElement(index,
9559                                              value,
9560                                              attributes,
9561                                              strict_mode,
9562                                              check_prototype,
9563                                              set_mode);
9564   }
9565
9566   // Don't allow element properties to be redefined for external arrays.
9567   if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) {
9568     Isolate* isolate = GetHeap()->isolate();
9569     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
9570     Handle<Object> args[] = { Handle<Object>(this), number };
9571     Handle<Object> error = isolate->factory()->NewTypeError(
9572         "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
9573     return isolate->Throw(*error);
9574   }
9575
9576   // Normalize the elements to enable attributes on the property.
9577   if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
9578     SeededNumberDictionary* dictionary;
9579     MaybeObject* maybe_object = NormalizeElements();
9580     if (!maybe_object->To(&dictionary)) return maybe_object;
9581     // Make sure that we never go back to fast case.
9582     dictionary->set_requires_slow_elements();
9583   }
9584
9585   // Check for lookup interceptor
9586   if (HasIndexedInterceptor()) {
9587     return SetElementWithInterceptor(index,
9588                                      value,
9589                                      attributes,
9590                                      strict_mode,
9591                                      check_prototype,
9592                                      set_mode);
9593   }
9594
9595   return SetElementWithoutInterceptor(index,
9596                                       value,
9597                                       attributes,
9598                                       strict_mode,
9599                                       check_prototype,
9600                                       set_mode);
9601 }
9602
9603
9604 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
9605                                                     Object* value,
9606                                                     PropertyAttributes attr,
9607                                                     StrictModeFlag strict_mode,
9608                                                     bool check_prototype,
9609                                                     SetPropertyMode set_mode) {
9610   ASSERT(HasDictionaryElements() ||
9611          HasDictionaryArgumentsElements() ||
9612          (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
9613   Isolate* isolate = GetIsolate();
9614   switch (GetElementsKind()) {
9615     case FAST_SMI_ONLY_ELEMENTS:
9616     case FAST_ELEMENTS:
9617       return SetFastElement(index, value, strict_mode, check_prototype);
9618     case FAST_DOUBLE_ELEMENTS:
9619       return SetFastDoubleElement(index, value, strict_mode, check_prototype);
9620     case EXTERNAL_PIXEL_ELEMENTS: {
9621       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9622       return pixels->SetValue(index, value);
9623     }
9624     case EXTERNAL_BYTE_ELEMENTS: {
9625       ExternalByteArray* array = ExternalByteArray::cast(elements());
9626       return array->SetValue(index, value);
9627     }
9628     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
9629       ExternalUnsignedByteArray* array =
9630           ExternalUnsignedByteArray::cast(elements());
9631       return array->SetValue(index, value);
9632     }
9633     case EXTERNAL_SHORT_ELEMENTS: {
9634       ExternalShortArray* array = ExternalShortArray::cast(elements());
9635       return array->SetValue(index, value);
9636     }
9637     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
9638       ExternalUnsignedShortArray* array =
9639           ExternalUnsignedShortArray::cast(elements());
9640       return array->SetValue(index, value);
9641     }
9642     case EXTERNAL_INT_ELEMENTS: {
9643       ExternalIntArray* array = ExternalIntArray::cast(elements());
9644       return array->SetValue(index, value);
9645     }
9646     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
9647       ExternalUnsignedIntArray* array =
9648           ExternalUnsignedIntArray::cast(elements());
9649       return array->SetValue(index, value);
9650     }
9651     case EXTERNAL_FLOAT_ELEMENTS: {
9652       ExternalFloatArray* array = ExternalFloatArray::cast(elements());
9653       return array->SetValue(index, value);
9654     }
9655     case EXTERNAL_DOUBLE_ELEMENTS: {
9656       ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
9657       return array->SetValue(index, value);
9658     }
9659     case DICTIONARY_ELEMENTS:
9660       return SetDictionaryElement(index, value, attr, strict_mode,
9661                                   check_prototype, set_mode);
9662     case NON_STRICT_ARGUMENTS_ELEMENTS: {
9663       FixedArray* parameter_map = FixedArray::cast(elements());
9664       uint32_t length = parameter_map->length();
9665       Object* probe =
9666           (index < length - 2) ? parameter_map->get(index + 2) : NULL;
9667       if (probe != NULL && !probe->IsTheHole()) {
9668         Context* context = Context::cast(parameter_map->get(0));
9669         int context_index = Smi::cast(probe)->value();
9670         ASSERT(!context->get(context_index)->IsTheHole());
9671         context->set(context_index, value);
9672         // Redefining attributes of an aliased element destroys fast aliasing.
9673         if (set_mode == SET_PROPERTY || attr == NONE) return value;
9674         parameter_map->set_the_hole(index + 2);
9675         // For elements that are still writable we re-establish slow aliasing.
9676         if ((attr & READ_ONLY) == 0) {
9677           MaybeObject* maybe_entry =
9678               isolate->heap()->AllocateAliasedArgumentsEntry(context_index);
9679           if (!maybe_entry->ToObject(&value)) return maybe_entry;
9680         }
9681       }
9682       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9683       if (arguments->IsDictionary()) {
9684         return SetDictionaryElement(index, value, attr, strict_mode,
9685                                     check_prototype, set_mode);
9686       } else {
9687         return SetFastElement(index, value, strict_mode, check_prototype);
9688       }
9689     }
9690   }
9691   // All possible cases have been handled above. Add a return to avoid the
9692   // complaints from the compiler.
9693   UNREACHABLE();
9694   return isolate->heap()->null_value();
9695 }
9696
9697
9698 Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object,
9699                                                 ElementsKind to_kind) {
9700   CALL_HEAP_FUNCTION(object->GetIsolate(),
9701                      object->TransitionElementsKind(to_kind),
9702                      Object);
9703 }
9704
9705
9706 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
9707   ElementsKind from_kind = map()->elements_kind();
9708
9709   Isolate* isolate = GetIsolate();
9710   if ((from_kind == FAST_SMI_ONLY_ELEMENTS ||
9711       elements() == isolate->heap()->empty_fixed_array()) &&
9712       to_kind == FAST_ELEMENTS) {
9713     ASSERT(from_kind != FAST_ELEMENTS);
9714     MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
9715     Map* new_map;
9716     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9717     set_map(new_map);
9718     if (FLAG_trace_elements_transitions) {
9719       FixedArrayBase* elms = FixedArrayBase::cast(elements());
9720       PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
9721     }
9722     return this;
9723   }
9724
9725   FixedArrayBase* elms = FixedArrayBase::cast(elements());
9726   uint32_t capacity = static_cast<uint32_t>(elms->length());
9727   uint32_t length = capacity;
9728
9729   if (IsJSArray()) {
9730     Object* raw_length = JSArray::cast(this)->length();
9731     if (raw_length->IsUndefined()) {
9732       // If length is undefined, then JSArray is being initialized and has no
9733       // elements, assume a length of zero.
9734       length = 0;
9735     } else {
9736       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9737     }
9738   }
9739
9740   if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
9741       to_kind == FAST_DOUBLE_ELEMENTS) {
9742     MaybeObject* maybe_result =
9743         SetFastDoubleElementsCapacityAndLength(capacity, length);
9744     if (maybe_result->IsFailure()) return maybe_result;
9745     return this;
9746   }
9747
9748   if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
9749     MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
9750         capacity, length, kDontAllowSmiOnlyElements);
9751     if (maybe_result->IsFailure()) return maybe_result;
9752     return this;
9753   }
9754
9755   // This method should never be called for any other case than the ones
9756   // handled above.
9757   UNREACHABLE();
9758   return GetIsolate()->heap()->null_value();
9759 }
9760
9761
9762 // static
9763 bool Map::IsValidElementsTransition(ElementsKind from_kind,
9764                                     ElementsKind to_kind) {
9765   return
9766       (from_kind == FAST_SMI_ONLY_ELEMENTS &&
9767           (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) ||
9768       (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS);
9769 }
9770
9771
9772 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
9773                                                    Object* value) {
9774   uint32_t old_len = 0;
9775   CHECK(length()->ToArrayIndex(&old_len));
9776   // Check to see if we need to update the length. For now, we make
9777   // sure that the length stays within 32-bits (unsigned).
9778   if (index >= old_len && index != 0xffffffff) {
9779     Object* len;
9780     { MaybeObject* maybe_len =
9781           GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
9782       if (!maybe_len->ToObject(&len)) return maybe_len;
9783     }
9784     set_length(len);
9785   }
9786   return value;
9787 }
9788
9789
9790 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
9791                                                  uint32_t index) {
9792   Isolate* isolate = GetIsolate();
9793   // Make sure that the top context does not change when doing
9794   // callbacks or interceptor calls.
9795   AssertNoContextChange ncc;
9796   HandleScope scope(isolate);
9797   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
9798   Handle<Object> this_handle(receiver, isolate);
9799   Handle<JSObject> holder_handle(this, isolate);
9800   if (!interceptor->getter()->IsUndefined()) {
9801     v8::IndexedPropertyGetter getter =
9802         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
9803     LOG(isolate,
9804         ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
9805     CustomArguments args(isolate, interceptor->data(), receiver, this);
9806     v8::AccessorInfo info(args.end());
9807     v8::Handle<v8::Value> result;
9808     {
9809       // Leaving JavaScript.
9810       VMState state(isolate, EXTERNAL);
9811       result = getter(index, info);
9812     }
9813     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9814     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
9815   }
9816
9817   Heap* heap = holder_handle->GetHeap();
9818   ElementsAccessor* handler = holder_handle->GetElementsAccessor();
9819   MaybeObject* raw_result = handler->Get(*this_handle,
9820                                          *holder_handle,
9821                                          index);
9822   if (raw_result != heap->the_hole_value()) return raw_result;
9823
9824   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9825
9826   Object* pt = holder_handle->GetPrototype();
9827   if (pt == heap->null_value()) return heap->undefined_value();
9828   return pt->GetElementWithReceiver(*this_handle, index);
9829 }
9830
9831
9832 bool JSObject::HasDenseElements() {
9833   int capacity = 0;
9834   int used = 0;
9835   GetElementsCapacityAndUsage(&capacity, &used);
9836   return (capacity == 0) || (used > (capacity / 2));
9837 }
9838
9839
9840 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
9841   *capacity = 0;
9842   *used = 0;
9843
9844   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
9845   FixedArray* backing_store = NULL;
9846   switch (GetElementsKind()) {
9847     case NON_STRICT_ARGUMENTS_ELEMENTS:
9848       backing_store_base =
9849           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
9850       backing_store = FixedArray::cast(backing_store_base);
9851       if (backing_store->IsDictionary()) {
9852         SeededNumberDictionary* dictionary =
9853             SeededNumberDictionary::cast(backing_store);
9854         *capacity = dictionary->Capacity();
9855         *used = dictionary->NumberOfElements();
9856         break;
9857       }
9858       // Fall through.
9859     case FAST_SMI_ONLY_ELEMENTS:
9860     case FAST_ELEMENTS:
9861       backing_store = FixedArray::cast(backing_store_base);
9862       *capacity = backing_store->length();
9863       for (int i = 0; i < *capacity; ++i) {
9864         if (!backing_store->get(i)->IsTheHole()) ++(*used);
9865       }
9866       break;
9867     case DICTIONARY_ELEMENTS: {
9868       SeededNumberDictionary* dictionary =
9869           SeededNumberDictionary::cast(FixedArray::cast(elements()));
9870       *capacity = dictionary->Capacity();
9871       *used = dictionary->NumberOfElements();
9872       break;
9873     }
9874     case FAST_DOUBLE_ELEMENTS: {
9875       FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9876       *capacity = elms->length();
9877       for (int i = 0; i < *capacity; i++) {
9878         if (!elms->is_the_hole(i)) ++(*used);
9879       }
9880       break;
9881     }
9882     case EXTERNAL_BYTE_ELEMENTS:
9883     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9884     case EXTERNAL_SHORT_ELEMENTS:
9885     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9886     case EXTERNAL_INT_ELEMENTS:
9887     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9888     case EXTERNAL_FLOAT_ELEMENTS:
9889     case EXTERNAL_DOUBLE_ELEMENTS:
9890     case EXTERNAL_PIXEL_ELEMENTS:
9891       // External arrays are considered 100% used.
9892       ExternalArray* external_array = ExternalArray::cast(elements());
9893       *capacity = external_array->length();
9894       *used = external_array->length();
9895       break;
9896   }
9897 }
9898
9899
9900 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
9901   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
9902                 kMaxUncheckedFastElementsLength);
9903   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
9904       (new_capacity <= kMaxUncheckedFastElementsLength &&
9905        GetHeap()->InNewSpace(this))) {
9906     return false;
9907   }
9908   // If the fast-case backing storage takes up roughly three times as
9909   // much space (in machine words) as a dictionary backing storage
9910   // would, the object should have slow elements.
9911   int old_capacity = 0;
9912   int used_elements = 0;
9913   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
9914   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
9915       SeededNumberDictionary::kEntrySize;
9916   return 3 * dictionary_size <= new_capacity;
9917 }
9918
9919
9920 bool JSObject::ShouldConvertToFastElements() {
9921   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
9922   // If the elements are sparse, we should not go back to fast case.
9923   if (!HasDenseElements()) return false;
9924   // An object requiring access checks is never allowed to have fast
9925   // elements.  If it had fast elements we would skip security checks.
9926   if (IsAccessCheckNeeded()) return false;
9927
9928   FixedArray* elements = FixedArray::cast(this->elements());
9929   SeededNumberDictionary* dictionary = NULL;
9930   if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
9931     dictionary = SeededNumberDictionary::cast(elements->get(1));
9932   } else {
9933     dictionary = SeededNumberDictionary::cast(elements);
9934   }
9935   // If an element has been added at a very high index in the elements
9936   // dictionary, we cannot go back to fast case.
9937   if (dictionary->requires_slow_elements()) return false;
9938   // If the dictionary backing storage takes up roughly half as much
9939   // space (in machine words) as a fast-case backing storage would,
9940   // the object should have fast elements.
9941   uint32_t array_size = 0;
9942   if (IsJSArray()) {
9943     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
9944   } else {
9945     array_size = dictionary->max_number_key();
9946   }
9947   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
9948       SeededNumberDictionary::kEntrySize;
9949   return 2 * dictionary_size >= array_size;
9950 }
9951
9952
9953 bool JSObject::ShouldConvertToFastDoubleElements(
9954     bool* has_smi_only_elements) {
9955   *has_smi_only_elements = false;
9956   if (FLAG_unbox_double_arrays) {
9957     ASSERT(HasDictionaryElements());
9958     SeededNumberDictionary* dictionary =
9959         SeededNumberDictionary::cast(elements());
9960     bool found_double = false;
9961     for (int i = 0; i < dictionary->Capacity(); i++) {
9962       Object* key = dictionary->KeyAt(i);
9963       if (key->IsNumber()) {
9964         Object* value = dictionary->ValueAt(i);
9965         if (!value->IsNumber()) return false;
9966         if (!value->IsSmi()) {
9967           found_double = true;
9968         }
9969       }
9970     }
9971     *has_smi_only_elements = !found_double;
9972     return found_double;
9973   } else {
9974     return false;
9975   }
9976 }
9977
9978
9979 // Certain compilers request function template instantiation when they
9980 // see the definition of the other template functions in the
9981 // class. This requires us to have the template functions put
9982 // together, so even though this function belongs in objects-debug.cc,
9983 // we keep it here instead to satisfy certain compilers.
9984 #ifdef OBJECT_PRINT
9985 template<typename Shape, typename Key>
9986 void Dictionary<Shape, Key>::Print(FILE* out) {
9987   int capacity = HashTable<Shape, Key>::Capacity();
9988   for (int i = 0; i < capacity; i++) {
9989     Object* k = HashTable<Shape, Key>::KeyAt(i);
9990     if (HashTable<Shape, Key>::IsKey(k)) {
9991       PrintF(out, " ");
9992       if (k->IsString()) {
9993         String::cast(k)->StringPrint(out);
9994       } else {
9995         k->ShortPrint(out);
9996       }
9997       PrintF(out, ": ");
9998       ValueAt(i)->ShortPrint(out);
9999       PrintF(out, "\n");
10000     }
10001   }
10002 }
10003 #endif
10004
10005
10006 template<typename Shape, typename Key>
10007 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
10008   int pos = 0;
10009   int capacity = HashTable<Shape, Key>::Capacity();
10010   AssertNoAllocation no_gc;
10011   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
10012   for (int i = 0; i < capacity; i++) {
10013     Object* k =  Dictionary<Shape, Key>::KeyAt(i);
10014     if (Dictionary<Shape, Key>::IsKey(k)) {
10015       elements->set(pos++, ValueAt(i), mode);
10016     }
10017   }
10018   ASSERT(pos == elements->length());
10019 }
10020
10021
10022 InterceptorInfo* JSObject::GetNamedInterceptor() {
10023   ASSERT(map()->has_named_interceptor());
10024   JSFunction* constructor = JSFunction::cast(map()->constructor());
10025   ASSERT(constructor->shared()->IsApiFunction());
10026   Object* result =
10027       constructor->shared()->get_api_func_data()->named_property_handler();
10028   return InterceptorInfo::cast(result);
10029 }
10030
10031
10032 InterceptorInfo* JSObject::GetIndexedInterceptor() {
10033   ASSERT(map()->has_indexed_interceptor());
10034   JSFunction* constructor = JSFunction::cast(map()->constructor());
10035   ASSERT(constructor->shared()->IsApiFunction());
10036   Object* result =
10037       constructor->shared()->get_api_func_data()->indexed_property_handler();
10038   return InterceptorInfo::cast(result);
10039 }
10040
10041
10042 MaybeObject* JSObject::GetPropertyPostInterceptor(
10043     JSReceiver* receiver,
10044     String* name,
10045     PropertyAttributes* attributes) {
10046   // Check local property in holder, ignore interceptor.
10047   LookupResult result(GetIsolate());
10048   LocalLookupRealNamedProperty(name, &result);
10049   if (result.IsProperty()) {
10050     return GetProperty(receiver, &result, name, attributes);
10051   }
10052   // Continue searching via the prototype chain.
10053   Object* pt = GetPrototype();
10054   *attributes = ABSENT;
10055   if (pt->IsNull()) return GetHeap()->undefined_value();
10056   return pt->GetPropertyWithReceiver(receiver, name, attributes);
10057 }
10058
10059
10060 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
10061     JSReceiver* receiver,
10062     String* name,
10063     PropertyAttributes* attributes) {
10064   // Check local property in holder, ignore interceptor.
10065   LookupResult result(GetIsolate());
10066   LocalLookupRealNamedProperty(name, &result);
10067   if (result.IsProperty()) {
10068     return GetProperty(receiver, &result, name, attributes);
10069   }
10070   return GetHeap()->undefined_value();
10071 }
10072
10073
10074 MaybeObject* JSObject::GetPropertyWithInterceptor(
10075     JSReceiver* receiver,
10076     String* name,
10077     PropertyAttributes* attributes) {
10078   Isolate* isolate = GetIsolate();
10079   InterceptorInfo* interceptor = GetNamedInterceptor();
10080   HandleScope scope(isolate);
10081   Handle<JSReceiver> receiver_handle(receiver);
10082   Handle<JSObject> holder_handle(this);
10083   Handle<String> name_handle(name);
10084
10085   if (!interceptor->getter()->IsUndefined()) {
10086     v8::NamedPropertyGetter getter =
10087         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
10088     LOG(isolate,
10089         ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
10090     CustomArguments args(isolate, interceptor->data(), receiver, this);
10091     v8::AccessorInfo info(args.end());
10092     v8::Handle<v8::Value> result;
10093     {
10094       // Leaving JavaScript.
10095       VMState state(isolate, EXTERNAL);
10096       result = getter(v8::Utils::ToLocal(name_handle), info);
10097     }
10098     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
10099     if (!result.IsEmpty()) {
10100       *attributes = NONE;
10101       return *v8::Utils::OpenHandle(*result);
10102     }
10103   }
10104
10105   MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
10106       *receiver_handle,
10107       *name_handle,
10108       attributes);
10109   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
10110   return result;
10111 }
10112
10113
10114 bool JSObject::HasRealNamedProperty(String* key) {
10115   // Check access rights if needed.
10116   Isolate* isolate = GetIsolate();
10117   if (IsAccessCheckNeeded()) {
10118     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10119       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10120       return false;
10121     }
10122   }
10123
10124   LookupResult result(isolate);
10125   LocalLookupRealNamedProperty(key, &result);
10126   return result.IsProperty() && (result.type() != INTERCEPTOR);
10127 }
10128
10129
10130 bool JSObject::HasRealElementProperty(uint32_t index) {
10131   // Check access rights if needed.
10132   if (IsAccessCheckNeeded()) {
10133     Heap* heap = GetHeap();
10134     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
10135       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10136       return false;
10137     }
10138   }
10139
10140   // Handle [] on String objects.
10141   if (this->IsStringObjectWithCharacterAt(index)) return true;
10142
10143   switch (GetElementsKind()) {
10144     case FAST_SMI_ONLY_ELEMENTS:
10145     case FAST_ELEMENTS: {
10146       uint32_t length = IsJSArray() ?
10147           static_cast<uint32_t>(
10148               Smi::cast(JSArray::cast(this)->length())->value()) :
10149           static_cast<uint32_t>(FixedArray::cast(elements())->length());
10150       return (index < length) &&
10151           !FixedArray::cast(elements())->get(index)->IsTheHole();
10152     }
10153     case FAST_DOUBLE_ELEMENTS: {
10154       uint32_t length = IsJSArray() ?
10155           static_cast<uint32_t>(
10156               Smi::cast(JSArray::cast(this)->length())->value()) :
10157           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
10158       return (index < length) &&
10159           !FixedDoubleArray::cast(elements())->is_the_hole(index);
10160       break;
10161     }
10162     case EXTERNAL_PIXEL_ELEMENTS: {
10163       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
10164       return index < static_cast<uint32_t>(pixels->length());
10165     }
10166     case EXTERNAL_BYTE_ELEMENTS:
10167     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
10168     case EXTERNAL_SHORT_ELEMENTS:
10169     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
10170     case EXTERNAL_INT_ELEMENTS:
10171     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
10172     case EXTERNAL_FLOAT_ELEMENTS:
10173     case EXTERNAL_DOUBLE_ELEMENTS: {
10174       ExternalArray* array = ExternalArray::cast(elements());
10175       return index < static_cast<uint32_t>(array->length());
10176     }
10177     case DICTIONARY_ELEMENTS: {
10178       return element_dictionary()->FindEntry(index)
10179           != SeededNumberDictionary::kNotFound;
10180     }
10181     case NON_STRICT_ARGUMENTS_ELEMENTS:
10182       UNIMPLEMENTED();
10183       break;
10184   }
10185   // All possibilities have been handled above already.
10186   UNREACHABLE();
10187   return GetHeap()->null_value();
10188 }
10189
10190
10191 bool JSObject::HasRealNamedCallbackProperty(String* key) {
10192   // Check access rights if needed.
10193   Isolate* isolate = GetIsolate();
10194   if (IsAccessCheckNeeded()) {
10195     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10196       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10197       return false;
10198     }
10199   }
10200
10201   LookupResult result(isolate);
10202   LocalLookupRealNamedProperty(key, &result);
10203   return result.IsFound() && (result.type() == CALLBACKS);
10204 }
10205
10206
10207 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
10208   return HasFastProperties() ?
10209       map()->NumberOfDescribedProperties(filter) :
10210       property_dictionary()->NumberOfElementsFilterAttributes(filter);
10211 }
10212
10213
10214 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
10215   Object* temp = get(i);
10216   set(i, get(j));
10217   set(j, temp);
10218   if (this != numbers) {
10219     temp = numbers->get(i);
10220     numbers->set(i, Smi::cast(numbers->get(j)));
10221     numbers->set(j, Smi::cast(temp));
10222   }
10223 }
10224
10225
10226 static void InsertionSortPairs(FixedArray* content,
10227                                FixedArray* numbers,
10228                                int len) {
10229   for (int i = 1; i < len; i++) {
10230     int j = i;
10231     while (j > 0 &&
10232            (NumberToUint32(numbers->get(j - 1)) >
10233             NumberToUint32(numbers->get(j)))) {
10234       content->SwapPairs(numbers, j - 1, j);
10235       j--;
10236     }
10237   }
10238 }
10239
10240
10241 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
10242   // In-place heap sort.
10243   ASSERT(content->length() == numbers->length());
10244
10245   // Bottom-up max-heap construction.
10246   for (int i = 1; i < len; ++i) {
10247     int child_index = i;
10248     while (child_index > 0) {
10249       int parent_index = ((child_index + 1) >> 1) - 1;
10250       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10251       uint32_t child_value = NumberToUint32(numbers->get(child_index));
10252       if (parent_value < child_value) {
10253         content->SwapPairs(numbers, parent_index, child_index);
10254       } else {
10255         break;
10256       }
10257       child_index = parent_index;
10258     }
10259   }
10260
10261   // Extract elements and create sorted array.
10262   for (int i = len - 1; i > 0; --i) {
10263     // Put max element at the back of the array.
10264     content->SwapPairs(numbers, 0, i);
10265     // Sift down the new top element.
10266     int parent_index = 0;
10267     while (true) {
10268       int child_index = ((parent_index + 1) << 1) - 1;
10269       if (child_index >= i) break;
10270       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
10271       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
10272       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
10273       if (child_index + 1 >= i || child1_value > child2_value) {
10274         if (parent_value > child1_value) break;
10275         content->SwapPairs(numbers, parent_index, child_index);
10276         parent_index = child_index;
10277       } else {
10278         if (parent_value > child2_value) break;
10279         content->SwapPairs(numbers, parent_index, child_index + 1);
10280         parent_index = child_index + 1;
10281       }
10282     }
10283   }
10284 }
10285
10286
10287 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
10288 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
10289   ASSERT(this->length() == numbers->length());
10290   // For small arrays, simply use insertion sort.
10291   if (len <= 10) {
10292     InsertionSortPairs(this, numbers, len);
10293     return;
10294   }
10295   // Check the range of indices.
10296   uint32_t min_index = NumberToUint32(numbers->get(0));
10297   uint32_t max_index = min_index;
10298   uint32_t i;
10299   for (i = 1; i < len; i++) {
10300     if (NumberToUint32(numbers->get(i)) < min_index) {
10301       min_index = NumberToUint32(numbers->get(i));
10302     } else if (NumberToUint32(numbers->get(i)) > max_index) {
10303       max_index = NumberToUint32(numbers->get(i));
10304     }
10305   }
10306   if (max_index - min_index + 1 == len) {
10307     // Indices form a contiguous range, unless there are duplicates.
10308     // Do an in-place linear time sort assuming distinct numbers, but
10309     // avoid hanging in case they are not.
10310     for (i = 0; i < len; i++) {
10311       uint32_t p;
10312       uint32_t j = 0;
10313       // While the current element at i is not at its correct position p,
10314       // swap the elements at these two positions.
10315       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
10316              j++ < len) {
10317         SwapPairs(numbers, i, p);
10318       }
10319     }
10320   } else {
10321     HeapSortPairs(this, numbers, len);
10322     return;
10323   }
10324 }
10325
10326
10327 // Fill in the names of local properties into the supplied storage. The main
10328 // purpose of this function is to provide reflection information for the object
10329 // mirrors.
10330 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
10331   ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
10332   if (HasFastProperties()) {
10333     DescriptorArray* descs = map()->instance_descriptors();
10334     for (int i = 0; i < descs->number_of_descriptors(); i++) {
10335       if (descs->IsProperty(i)) storage->set(index++, descs->GetKey(i));
10336     }
10337     ASSERT(storage->length() >= index);
10338   } else {
10339     property_dictionary()->CopyKeysTo(storage,
10340                                       index,
10341                                       StringDictionary::UNSORTED);
10342   }
10343 }
10344
10345
10346 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
10347   return GetLocalElementKeys(NULL, filter);
10348 }
10349
10350
10351 int JSObject::NumberOfEnumElements() {
10352   // Fast case for objects with no elements.
10353   if (!IsJSValue() && HasFastElements()) {
10354     uint32_t length = IsJSArray() ?
10355         static_cast<uint32_t>(
10356             Smi::cast(JSArray::cast(this)->length())->value()) :
10357         static_cast<uint32_t>(FixedArray::cast(elements())->length());
10358     if (length == 0) return 0;
10359   }
10360   // Compute the number of enumerable elements.
10361   return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
10362 }
10363
10364
10365 int JSObject::GetLocalElementKeys(FixedArray* storage,
10366                                   PropertyAttributes filter) {
10367   int counter = 0;
10368   switch (GetElementsKind()) {
10369     case FAST_SMI_ONLY_ELEMENTS:
10370     case FAST_ELEMENTS: {
10371       int length = IsJSArray() ?
10372           Smi::cast(JSArray::cast(this)->length())->value() :
10373           FixedArray::cast(elements())->length();
10374       for (int i = 0; i < length; i++) {
10375         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
10376           if (storage != NULL) {
10377             storage->set(counter, Smi::FromInt(i));
10378           }
10379           counter++;
10380         }
10381       }
10382       ASSERT(!storage || storage->length() >= counter);
10383       break;
10384     }
10385     case FAST_DOUBLE_ELEMENTS: {
10386       int length = IsJSArray() ?
10387           Smi::cast(JSArray::cast(this)->length())->value() :
10388           FixedDoubleArray::cast(elements())->length();
10389       for (int i = 0; i < length; i++) {
10390         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
10391           if (storage != NULL) {
10392             storage->set(counter, Smi::FromInt(i));
10393           }
10394           counter++;
10395         }
10396       }
10397       ASSERT(!storage || storage->length() >= counter);
10398       break;
10399     }
10400     case EXTERNAL_PIXEL_ELEMENTS: {
10401       int length = ExternalPixelArray::cast(elements())->length();
10402       while (counter < length) {
10403         if (storage != NULL) {
10404           storage->set(counter, Smi::FromInt(counter));
10405         }
10406         counter++;
10407       }
10408       ASSERT(!storage || storage->length() >= counter);
10409       break;
10410     }
10411     case EXTERNAL_BYTE_ELEMENTS:
10412     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
10413     case EXTERNAL_SHORT_ELEMENTS:
10414     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
10415     case EXTERNAL_INT_ELEMENTS:
10416     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
10417     case EXTERNAL_FLOAT_ELEMENTS:
10418     case EXTERNAL_DOUBLE_ELEMENTS: {
10419       int length = ExternalArray::cast(elements())->length();
10420       while (counter < length) {
10421         if (storage != NULL) {
10422           storage->set(counter, Smi::FromInt(counter));
10423         }
10424         counter++;
10425       }
10426       ASSERT(!storage || storage->length() >= counter);
10427       break;
10428     }
10429     case DICTIONARY_ELEMENTS: {
10430       if (storage != NULL) {
10431         element_dictionary()->CopyKeysTo(storage,
10432                                          filter,
10433                                          SeededNumberDictionary::SORTED);
10434       }
10435       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
10436       break;
10437     }
10438     case NON_STRICT_ARGUMENTS_ELEMENTS: {
10439       FixedArray* parameter_map = FixedArray::cast(elements());
10440       int mapped_length = parameter_map->length() - 2;
10441       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
10442       if (arguments->IsDictionary()) {
10443         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
10444         // will insert in storage starting at index 0.
10445         SeededNumberDictionary* dictionary =
10446             SeededNumberDictionary::cast(arguments);
10447         if (storage != NULL) {
10448           dictionary->CopyKeysTo(
10449               storage, filter, SeededNumberDictionary::UNSORTED);
10450         }
10451         counter += dictionary->NumberOfElementsFilterAttributes(filter);
10452         for (int i = 0; i < mapped_length; ++i) {
10453           if (!parameter_map->get(i + 2)->IsTheHole()) {
10454             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10455             ++counter;
10456           }
10457         }
10458         if (storage != NULL) storage->SortPairs(storage, counter);
10459
10460       } else {
10461         int backing_length = arguments->length();
10462         int i = 0;
10463         for (; i < mapped_length; ++i) {
10464           if (!parameter_map->get(i + 2)->IsTheHole()) {
10465             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10466             ++counter;
10467           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
10468             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10469             ++counter;
10470           }
10471         }
10472         for (; i < backing_length; ++i) {
10473           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
10474           ++counter;
10475         }
10476       }
10477       break;
10478     }
10479   }
10480
10481   if (this->IsJSValue()) {
10482     Object* val = JSValue::cast(this)->value();
10483     if (val->IsString()) {
10484       String* str = String::cast(val);
10485       if (storage) {
10486         for (int i = 0; i < str->length(); i++) {
10487           storage->set(counter + i, Smi::FromInt(i));
10488         }
10489       }
10490       counter += str->length();
10491     }
10492   }
10493   ASSERT(!storage || storage->length() == counter);
10494   return counter;
10495 }
10496
10497
10498 int JSObject::GetEnumElementKeys(FixedArray* storage) {
10499   return GetLocalElementKeys(storage,
10500                              static_cast<PropertyAttributes>(DONT_ENUM));
10501 }
10502
10503
10504 // StringKey simply carries a string object as key.
10505 class StringKey : public HashTableKey {
10506  public:
10507   explicit StringKey(String* string) :
10508       string_(string),
10509       hash_(HashForObject(string)) { }
10510
10511   bool IsMatch(Object* string) {
10512     // We know that all entries in a hash table had their hash keys created.
10513     // Use that knowledge to have fast failure.
10514     if (hash_ != HashForObject(string)) {
10515       return false;
10516     }
10517     return string_->Equals(String::cast(string));
10518   }
10519
10520   uint32_t Hash() { return hash_; }
10521
10522   uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
10523
10524   Object* AsObject() { return string_; }
10525
10526   String* string_;
10527   uint32_t hash_;
10528 };
10529
10530
10531 // StringSharedKeys are used as keys in the eval cache.
10532 class StringSharedKey : public HashTableKey {
10533  public:
10534   StringSharedKey(String* source,
10535                   SharedFunctionInfo* shared,
10536                   LanguageMode language_mode,
10537                   int scope_position)
10538       : source_(source),
10539         shared_(shared),
10540         language_mode_(language_mode),
10541         scope_position_(scope_position) { }
10542
10543   bool IsMatch(Object* other) {
10544     if (!other->IsFixedArray()) return false;
10545     FixedArray* other_array = FixedArray::cast(other);
10546     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
10547     if (shared != shared_) return false;
10548     int language_unchecked = Smi::cast(other_array->get(2))->value();
10549     ASSERT(language_unchecked == CLASSIC_MODE ||
10550            language_unchecked == STRICT_MODE ||
10551            language_unchecked == EXTENDED_MODE);
10552     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
10553     if (language_mode != language_mode_) return false;
10554     int scope_position = Smi::cast(other_array->get(3))->value();
10555     if (scope_position != scope_position_) return false;
10556     String* source = String::cast(other_array->get(1));
10557     return source->Equals(source_);
10558   }
10559
10560   static uint32_t StringSharedHashHelper(String* source,
10561                                          SharedFunctionInfo* shared,
10562                                          LanguageMode language_mode,
10563                                          int scope_position) {
10564     uint32_t hash = source->Hash();
10565     if (shared->HasSourceCode()) {
10566       // Instead of using the SharedFunctionInfo pointer in the hash
10567       // code computation, we use a combination of the hash of the
10568       // script source code and the start position of the calling scope.
10569       // We do this to ensure that the cache entries can survive garbage
10570       // collection.
10571       Script* script = Script::cast(shared->script());
10572       hash ^= String::cast(script->source())->Hash();
10573       if (language_mode == STRICT_MODE) hash ^= 0x8000;
10574       if (language_mode == EXTENDED_MODE) hash ^= 0x0080;
10575       hash += scope_position;
10576     }
10577     return hash;
10578   }
10579
10580   uint32_t Hash() {
10581     return StringSharedHashHelper(
10582         source_, shared_, language_mode_, scope_position_);
10583   }
10584
10585   uint32_t HashForObject(Object* obj) {
10586     FixedArray* other_array = FixedArray::cast(obj);
10587     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
10588     String* source = String::cast(other_array->get(1));
10589     int language_unchecked = Smi::cast(other_array->get(2))->value();
10590     ASSERT(language_unchecked == CLASSIC_MODE ||
10591            language_unchecked == STRICT_MODE ||
10592            language_unchecked == EXTENDED_MODE);
10593     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
10594     int scope_position = Smi::cast(other_array->get(3))->value();
10595     return StringSharedHashHelper(
10596         source, shared, language_mode, scope_position);
10597   }
10598
10599   MUST_USE_RESULT MaybeObject* AsObject() {
10600     Object* obj;
10601     { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(4);
10602       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10603     }
10604     FixedArray* other_array = FixedArray::cast(obj);
10605     other_array->set(0, shared_);
10606     other_array->set(1, source_);
10607     other_array->set(2, Smi::FromInt(language_mode_));
10608     other_array->set(3, Smi::FromInt(scope_position_));
10609     return other_array;
10610   }
10611
10612  private:
10613   String* source_;
10614   SharedFunctionInfo* shared_;
10615   LanguageMode language_mode_;
10616   int scope_position_;
10617 };
10618
10619
10620 // RegExpKey carries the source and flags of a regular expression as key.
10621 class RegExpKey : public HashTableKey {
10622  public:
10623   RegExpKey(String* string, JSRegExp::Flags flags)
10624       : string_(string),
10625         flags_(Smi::FromInt(flags.value())) { }
10626
10627   // Rather than storing the key in the hash table, a pointer to the
10628   // stored value is stored where the key should be.  IsMatch then
10629   // compares the search key to the found object, rather than comparing
10630   // a key to a key.
10631   bool IsMatch(Object* obj) {
10632     FixedArray* val = FixedArray::cast(obj);
10633     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
10634         && (flags_ == val->get(JSRegExp::kFlagsIndex));
10635   }
10636
10637   uint32_t Hash() { return RegExpHash(string_, flags_); }
10638
10639   Object* AsObject() {
10640     // Plain hash maps, which is where regexp keys are used, don't
10641     // use this function.
10642     UNREACHABLE();
10643     return NULL;
10644   }
10645
10646   uint32_t HashForObject(Object* obj) {
10647     FixedArray* val = FixedArray::cast(obj);
10648     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
10649                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
10650   }
10651
10652   static uint32_t RegExpHash(String* string, Smi* flags) {
10653     return string->Hash() + flags->value();
10654   }
10655
10656   String* string_;
10657   Smi* flags_;
10658 };
10659
10660 // Utf8SymbolKey carries a vector of chars as key.
10661 class Utf8SymbolKey : public HashTableKey {
10662  public:
10663   explicit Utf8SymbolKey(Vector<const char> string, uint32_t seed)
10664       : string_(string), hash_field_(0), seed_(seed) { }
10665
10666   bool IsMatch(Object* string) {
10667     return String::cast(string)->IsEqualTo(string_);
10668   }
10669
10670   uint32_t Hash() {
10671     if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
10672     unibrow::Utf8InputBuffer<> buffer(string_.start(),
10673                                       static_cast<unsigned>(string_.length()));
10674     chars_ = buffer.Utf16Length();
10675     hash_field_ = String::ComputeHashField(&buffer, chars_, seed_);
10676     uint32_t result = hash_field_ >> String::kHashShift;
10677     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
10678     return result;
10679   }
10680
10681   uint32_t HashForObject(Object* other) {
10682     return String::cast(other)->Hash();
10683   }
10684
10685   MaybeObject* AsObject() {
10686     if (hash_field_ == 0) Hash();
10687     return Isolate::Current()->heap()->AllocateSymbol(
10688         string_, chars_, hash_field_);
10689   }
10690
10691   Vector<const char> string_;
10692   uint32_t hash_field_;
10693   int chars_;  // Caches the number of characters when computing the hash code.
10694   uint32_t seed_;
10695 };
10696
10697
10698 template <typename Char>
10699 class SequentialSymbolKey : public HashTableKey {
10700  public:
10701   explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed)
10702       : string_(string), hash_field_(0), seed_(seed) { }
10703
10704   uint32_t Hash() {
10705     StringHasher hasher(string_.length(), seed_);
10706
10707     // Very long strings have a trivial hash that doesn't inspect the
10708     // string contents.
10709     if (hasher.has_trivial_hash()) {
10710       hash_field_ = hasher.GetHashField();
10711     } else {
10712       int i = 0;
10713       // Do the iterative array index computation as long as there is a
10714       // chance this is an array index.
10715       while (i < string_.length() && hasher.is_array_index()) {
10716         hasher.AddCharacter(static_cast<uc32>(string_[i]));
10717         i++;
10718       }
10719
10720       // Process the remaining characters without updating the array
10721       // index.
10722       while (i < string_.length()) {
10723         hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i]));
10724         i++;
10725       }
10726       hash_field_ = hasher.GetHashField();
10727     }
10728
10729     uint32_t result = hash_field_ >> String::kHashShift;
10730     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
10731     return result;
10732   }
10733
10734
10735   uint32_t HashForObject(Object* other) {
10736     return String::cast(other)->Hash();
10737   }
10738
10739   Vector<const Char> string_;
10740   uint32_t hash_field_;
10741   uint32_t seed_;
10742 };
10743
10744
10745
10746 class AsciiSymbolKey : public SequentialSymbolKey<char> {
10747  public:
10748   AsciiSymbolKey(Vector<const char> str, uint32_t seed)
10749       : SequentialSymbolKey<char>(str, seed) { }
10750
10751   bool IsMatch(Object* string) {
10752     return String::cast(string)->IsAsciiEqualTo(string_);
10753   }
10754
10755   MaybeObject* AsObject() {
10756     if (hash_field_ == 0) Hash();
10757     MaybeObject *result = HEAP->AllocateAsciiSymbol(string_, hash_field_);
10758     if (!result->IsFailure() && result->ToObjectUnchecked()->IsSeqString()) {
10759         while (true) {
10760             Atomic32 my_symbol_id = next_symbol_id;
10761             if (my_symbol_id > Smi::kMaxValue)
10762                 break;
10763             if (my_symbol_id == NoBarrier_CompareAndSwap(&next_symbol_id,
10764                                                          my_symbol_id,
10765                                                          my_symbol_id + 1)) {
10766                 SeqString::cast(result->ToObjectUnchecked())->
10767                     set_symbol_id(my_symbol_id);
10768                 break;
10769             }
10770         }
10771     }
10772     return result;
10773   }
10774
10775   static Atomic32 next_symbol_id;
10776 };
10777 Atomic32 AsciiSymbolKey::next_symbol_id = 1;
10778
10779
10780 class SubStringAsciiSymbolKey : public HashTableKey {
10781  public:
10782   explicit SubStringAsciiSymbolKey(Handle<SeqAsciiString> string,
10783                                    int from,
10784                                    int length,
10785                                    uint32_t seed)
10786       : string_(string), from_(from), length_(length), seed_(seed) { }
10787
10788   uint32_t Hash() {
10789     ASSERT(length_ >= 0);
10790     ASSERT(from_ + length_ <= string_->length());
10791     StringHasher hasher(length_, string_->GetHeap()->HashSeed());
10792
10793     // Very long strings have a trivial hash that doesn't inspect the
10794     // string contents.
10795     if (hasher.has_trivial_hash()) {
10796       hash_field_ = hasher.GetHashField();
10797     } else {
10798       int i = 0;
10799       // Do the iterative array index computation as long as there is a
10800       // chance this is an array index.
10801       while (i < length_ && hasher.is_array_index()) {
10802         hasher.AddCharacter(static_cast<uc32>(
10803             string_->SeqAsciiStringGet(i + from_)));
10804         i++;
10805       }
10806
10807       // Process the remaining characters without updating the array
10808       // index.
10809       while (i < length_) {
10810         hasher.AddCharacterNoIndex(static_cast<uc32>(
10811             string_->SeqAsciiStringGet(i + from_)));
10812         i++;
10813       }
10814       hash_field_ = hasher.GetHashField();
10815     }
10816
10817     uint32_t result = hash_field_ >> String::kHashShift;
10818     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
10819     return result;
10820   }
10821
10822
10823   uint32_t HashForObject(Object* other) {
10824     return String::cast(other)->Hash();
10825   }
10826
10827   bool IsMatch(Object* string) {
10828     Vector<const char> chars(string_->GetChars() + from_, length_);
10829     return String::cast(string)->IsAsciiEqualTo(chars);
10830   }
10831
10832   MaybeObject* AsObject() {
10833     if (hash_field_ == 0) Hash();
10834     Vector<const char> chars(string_->GetChars() + from_, length_);
10835     return HEAP->AllocateAsciiSymbol(chars, hash_field_);
10836   }
10837
10838  private:
10839   Handle<SeqAsciiString> string_;
10840   int from_;
10841   int length_;
10842   uint32_t hash_field_;
10843   uint32_t seed_;
10844 };
10845
10846
10847 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
10848  public:
10849   explicit TwoByteSymbolKey(Vector<const uc16> str, uint32_t seed)
10850       : SequentialSymbolKey<uc16>(str, seed) { }
10851
10852   bool IsMatch(Object* string) {
10853     return String::cast(string)->IsTwoByteEqualTo(string_);
10854   }
10855
10856   MaybeObject* AsObject() {
10857     if (hash_field_ == 0) Hash();
10858     return HEAP->AllocateTwoByteSymbol(string_, hash_field_);
10859   }
10860 };
10861
10862
10863 // SymbolKey carries a string/symbol object as key.
10864 class SymbolKey : public HashTableKey {
10865  public:
10866   explicit SymbolKey(String* string)
10867       : string_(string) { }
10868
10869   bool IsMatch(Object* string) {
10870     return String::cast(string)->Equals(string_);
10871   }
10872
10873   uint32_t Hash() { return string_->Hash(); }
10874
10875   uint32_t HashForObject(Object* other) {
10876     return String::cast(other)->Hash();
10877   }
10878
10879   MaybeObject* AsObject() {
10880     // Attempt to flatten the string, so that symbols will most often
10881     // be flat strings.
10882     string_ = string_->TryFlattenGetString();
10883     Heap* heap = string_->GetHeap();
10884     // Transform string to symbol if possible.
10885     Map* map = heap->SymbolMapForString(string_);
10886     if (map != NULL) {
10887       string_->set_map_no_write_barrier(map);
10888       ASSERT(string_->IsSymbol());
10889       return string_;
10890     }
10891     // Otherwise allocate a new symbol.
10892     StringInputBuffer buffer(string_);
10893     return heap->AllocateInternalSymbol(&buffer,
10894                                         string_->length(),
10895                                         string_->hash_field());
10896   }
10897
10898   static uint32_t StringHash(Object* obj) {
10899     return String::cast(obj)->Hash();
10900   }
10901
10902   String* string_;
10903 };
10904
10905
10906 template<typename Shape, typename Key>
10907 void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
10908   IteratePointers(v, 0, kElementsStartOffset);
10909 }
10910
10911
10912 template<typename Shape, typename Key>
10913 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
10914   IteratePointers(v,
10915                   kElementsStartOffset,
10916                   kHeaderSize + length() * kPointerSize);
10917 }
10918
10919
10920 template<typename Shape, typename Key>
10921 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for,
10922                                              PretenureFlag pretenure) {
10923   int capacity = ComputeCapacity(at_least_space_for);
10924   if (capacity > HashTable::kMaxCapacity) {
10925     return Failure::OutOfMemoryException();
10926   }
10927
10928   Object* obj;
10929   { MaybeObject* maybe_obj = Isolate::Current()->heap()->
10930         AllocateHashTable(EntryToIndex(capacity), pretenure);
10931     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10932   }
10933   HashTable::cast(obj)->SetNumberOfElements(0);
10934   HashTable::cast(obj)->SetNumberOfDeletedElements(0);
10935   HashTable::cast(obj)->SetCapacity(capacity);
10936   return obj;
10937 }
10938
10939
10940 // Find entry for key otherwise return kNotFound.
10941 int StringDictionary::FindEntry(String* key) {
10942   if (!key->IsSymbol()) {
10943     return HashTable<StringDictionaryShape, String*>::FindEntry(key);
10944   }
10945
10946   // Optimized for symbol key. Knowledge of the key type allows:
10947   // 1. Move the check if the key is a symbol out of the loop.
10948   // 2. Avoid comparing hash codes in symbol to symbol comparison.
10949   // 3. Detect a case when a dictionary key is not a symbol but the key is.
10950   //    In case of positive result the dictionary key may be replaced by
10951   //    the symbol with minimal performance penalty. It gives a chance to
10952   //    perform further lookups in code stubs (and significant performance boost
10953   //    a certain style of code).
10954
10955   // EnsureCapacity will guarantee the hash table is never full.
10956   uint32_t capacity = Capacity();
10957   uint32_t entry = FirstProbe(key->Hash(), capacity);
10958   uint32_t count = 1;
10959
10960   while (true) {
10961     int index = EntryToIndex(entry);
10962     Object* element = get(index);
10963     if (element->IsUndefined()) break;  // Empty entry.
10964     if (key == element) return entry;
10965     if (!element->IsSymbol() &&
10966         !element->IsTheHole() &&
10967         String::cast(element)->Equals(key)) {
10968       // Replace a non-symbol key by the equivalent symbol for faster further
10969       // lookups.
10970       set(index, key);
10971       return entry;
10972     }
10973     ASSERT(element->IsTheHole() || !String::cast(element)->Equals(key));
10974     entry = NextProbe(entry, count++, capacity);
10975   }
10976   return kNotFound;
10977 }
10978
10979
10980 bool StringDictionary::ContainsTransition(int entry) {
10981   switch (DetailsAt(entry).type()) {
10982     case MAP_TRANSITION:
10983     case CONSTANT_TRANSITION:
10984     case ELEMENTS_TRANSITION:
10985       return true;
10986     case CALLBACKS: {
10987       Object* value = ValueAt(entry);
10988       if (!value->IsAccessorPair()) return false;
10989       AccessorPair* accessors = AccessorPair::cast(value);
10990       return accessors->getter()->IsMap() || accessors->setter()->IsMap();
10991     }
10992     case NORMAL:
10993     case FIELD:
10994     case CONSTANT_FUNCTION:
10995     case HANDLER:
10996     case INTERCEPTOR:
10997     case NULL_DESCRIPTOR:
10998       return false;
10999   }
11000   UNREACHABLE();  // Keep the compiler happy.
11001   return false;
11002 }
11003
11004
11005 template<typename Shape, typename Key>
11006 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
11007   ASSERT(NumberOfElements() < new_table->Capacity());
11008
11009   AssertNoAllocation no_gc;
11010   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
11011
11012   // Copy prefix to new array.
11013   for (int i = kPrefixStartIndex;
11014        i < kPrefixStartIndex + Shape::kPrefixSize;
11015        i++) {
11016     new_table->set(i, get(i), mode);
11017   }
11018
11019   // Rehash the elements.
11020   int capacity = Capacity();
11021   for (int i = 0; i < capacity; i++) {
11022     uint32_t from_index = EntryToIndex(i);
11023     Object* k = get(from_index);
11024     if (IsKey(k)) {
11025       uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k);
11026       uint32_t insertion_index =
11027           EntryToIndex(new_table->FindInsertionEntry(hash));
11028       for (int j = 0; j < Shape::kEntrySize; j++) {
11029         new_table->set(insertion_index + j, get(from_index + j), mode);
11030       }
11031     }
11032   }
11033   new_table->SetNumberOfElements(NumberOfElements());
11034   new_table->SetNumberOfDeletedElements(0);
11035   return new_table;
11036 }
11037
11038
11039 template<typename Shape, typename Key>
11040 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
11041   int capacity = Capacity();
11042   int nof = NumberOfElements() + n;
11043   int nod = NumberOfDeletedElements();
11044   // Return if:
11045   //   50% is still free after adding n elements and
11046   //   at most 50% of the free elements are deleted elements.
11047   if (nod <= (capacity - nof) >> 1) {
11048     int needed_free = nof >> 1;
11049     if (nof + needed_free <= capacity) return this;
11050   }
11051
11052   const int kMinCapacityForPretenure = 256;
11053   bool pretenure =
11054       (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this);
11055   Object* obj;
11056   { MaybeObject* maybe_obj =
11057         Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED);
11058     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11059   }
11060
11061   return Rehash(HashTable::cast(obj), key);
11062 }
11063
11064
11065 template<typename Shape, typename Key>
11066 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
11067   int capacity = Capacity();
11068   int nof = NumberOfElements();
11069
11070   // Shrink to fit the number of elements if only a quarter of the
11071   // capacity is filled with elements.
11072   if (nof > (capacity >> 2)) return this;
11073   // Allocate a new dictionary with room for at least the current
11074   // number of elements. The allocation method will make sure that
11075   // there is extra room in the dictionary for additions. Don't go
11076   // lower than room for 16 elements.
11077   int at_least_room_for = nof;
11078   if (at_least_room_for < 16) return this;
11079
11080   const int kMinCapacityForPretenure = 256;
11081   bool pretenure =
11082       (at_least_room_for > kMinCapacityForPretenure) &&
11083       !GetHeap()->InNewSpace(this);
11084   Object* obj;
11085   { MaybeObject* maybe_obj =
11086         Allocate(at_least_room_for, pretenure ? TENURED : NOT_TENURED);
11087     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11088   }
11089
11090   return Rehash(HashTable::cast(obj), key);
11091 }
11092
11093
11094 template<typename Shape, typename Key>
11095 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
11096   uint32_t capacity = Capacity();
11097   uint32_t entry = FirstProbe(hash, capacity);
11098   uint32_t count = 1;
11099   // EnsureCapacity will guarantee the hash table is never full.
11100   while (true) {
11101     Object* element = KeyAt(entry);
11102     if (element->IsUndefined() || element->IsTheHole()) break;
11103     entry = NextProbe(entry, count++, capacity);
11104   }
11105   return entry;
11106 }
11107
11108 // Force instantiation of template instances class.
11109 // Please note this list is compiler dependent.
11110
11111 template class HashTable<SymbolTableShape, HashTableKey*>;
11112
11113 template class HashTable<CompilationCacheShape, HashTableKey*>;
11114
11115 template class HashTable<MapCacheShape, HashTableKey*>;
11116
11117 template class HashTable<ObjectHashTableShape<1>, Object*>;
11118
11119 template class HashTable<ObjectHashTableShape<2>, Object*>;
11120
11121 template class Dictionary<StringDictionaryShape, String*>;
11122
11123 template class Dictionary<SeededNumberDictionaryShape, uint32_t>;
11124
11125 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>;
11126
11127 #ifndef __INTEL_COMPILER
11128 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11129     Allocate(int at_least_space_for);
11130
11131 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11132     Allocate(int at_least_space_for);
11133
11134 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate(
11135     int);
11136
11137 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut(
11138     uint32_t, Object*);
11139
11140 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11141     AtPut(uint32_t, Object*);
11142
11143 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11144     SlowReverseLookup(Object* value);
11145
11146 template Object* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11147     SlowReverseLookup(Object* value);
11148
11149 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
11150     Object*);
11151
11152 template void Dictionary<SeededNumberDictionaryShape, uint32_t>::CopyKeysTo(
11153     FixedArray*,
11154     PropertyAttributes,
11155     Dictionary<SeededNumberDictionaryShape, uint32_t>::SortMode);
11156
11157 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
11158     int, JSObject::DeleteMode);
11159
11160 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11161     DeleteProperty(int, JSObject::DeleteMode);
11162
11163 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink(
11164     String*);
11165
11166 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink(
11167     uint32_t);
11168
11169 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
11170     FixedArray*,
11171     int,
11172     Dictionary<StringDictionaryShape, String*>::SortMode);
11173
11174 template int
11175 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
11176     PropertyAttributes);
11177
11178 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add(
11179     String*, Object*, PropertyDetails);
11180
11181 template MaybeObject*
11182 Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
11183
11184 template int
11185 Dictionary<SeededNumberDictionaryShape, uint32_t>::
11186     NumberOfElementsFilterAttributes(PropertyAttributes);
11187
11188 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Add(
11189     uint32_t, Object*, PropertyDetails);
11190
11191 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::Add(
11192     uint32_t, Object*, PropertyDetails);
11193
11194 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11195     EnsureCapacity(int, uint32_t);
11196
11197 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11198     EnsureCapacity(int, uint32_t);
11199
11200 template MaybeObject* Dictionary<StringDictionaryShape, String*>::
11201     EnsureCapacity(int, String*);
11202
11203 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
11204     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
11205
11206 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
11207     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
11208
11209 template MaybeObject* Dictionary<StringDictionaryShape, String*>::AddEntry(
11210     String*, Object*, PropertyDetails, uint32_t);
11211
11212 template
11213 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements();
11214
11215 template
11216 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
11217
11218 template
11219 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
11220 #endif
11221
11222 // Collates undefined and unexisting elements below limit from position
11223 // zero of the elements. The object stays in Dictionary mode.
11224 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
11225   ASSERT(HasDictionaryElements());
11226   // Must stay in dictionary mode, either because of requires_slow_elements,
11227   // or because we are not going to sort (and therefore compact) all of the
11228   // elements.
11229   SeededNumberDictionary* dict = element_dictionary();
11230   HeapNumber* result_double = NULL;
11231   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11232     // Allocate space for result before we start mutating the object.
11233     Object* new_double;
11234     { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0);
11235       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11236     }
11237     result_double = HeapNumber::cast(new_double);
11238   }
11239
11240   Object* obj;
11241   { MaybeObject* maybe_obj =
11242         SeededNumberDictionary::Allocate(dict->NumberOfElements());
11243     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11244   }
11245   SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj);
11246
11247   AssertNoAllocation no_alloc;
11248
11249   uint32_t pos = 0;
11250   uint32_t undefs = 0;
11251   int capacity = dict->Capacity();
11252   for (int i = 0; i < capacity; i++) {
11253     Object* k = dict->KeyAt(i);
11254     if (dict->IsKey(k)) {
11255       ASSERT(k->IsNumber());
11256       ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
11257       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
11258       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
11259       Object* value = dict->ValueAt(i);
11260       PropertyDetails details = dict->DetailsAt(i);
11261       if (details.type() == CALLBACKS) {
11262         // Bail out and do the sorting of undefineds and array holes in JS.
11263         return Smi::FromInt(-1);
11264       }
11265       uint32_t key = NumberToUint32(k);
11266       // In the following we assert that adding the entry to the new dictionary
11267       // does not cause GC.  This is the case because we made sure to allocate
11268       // the dictionary big enough above, so it need not grow.
11269       if (key < limit) {
11270         if (value->IsUndefined()) {
11271           undefs++;
11272         } else {
11273           if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11274             // Adding an entry with the key beyond smi-range requires
11275             // allocation. Bailout.
11276             return Smi::FromInt(-1);
11277           }
11278           new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
11279           pos++;
11280         }
11281       } else {
11282         if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
11283           // Adding an entry with the key beyond smi-range requires
11284           // allocation. Bailout.
11285           return Smi::FromInt(-1);
11286         }
11287         new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
11288       }
11289     }
11290   }
11291
11292   uint32_t result = pos;
11293   PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
11294   Heap* heap = GetHeap();
11295   while (undefs > 0) {
11296     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
11297       // Adding an entry with the key beyond smi-range requires
11298       // allocation. Bailout.
11299       return Smi::FromInt(-1);
11300     }
11301     new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
11302         ToObjectUnchecked();
11303     pos++;
11304     undefs--;
11305   }
11306
11307   set_elements(new_dict);
11308
11309   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11310     return Smi::FromInt(static_cast<int>(result));
11311   }
11312
11313   ASSERT_NE(NULL, result_double);
11314   result_double->set_value(static_cast<double>(result));
11315   return result_double;
11316 }
11317
11318
11319 // Collects all defined (non-hole) and non-undefined (array) elements at
11320 // the start of the elements array.
11321 // If the object is in dictionary mode, it is converted to fast elements
11322 // mode.
11323 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
11324   Heap* heap = GetHeap();
11325
11326   if (HasDictionaryElements()) {
11327     // Convert to fast elements containing only the existing properties.
11328     // Ordering is irrelevant, since we are going to sort anyway.
11329     SeededNumberDictionary* dict = element_dictionary();
11330     if (IsJSArray() || dict->requires_slow_elements() ||
11331         dict->max_number_key() >= limit) {
11332       return PrepareSlowElementsForSort(limit);
11333     }
11334     // Convert to fast elements.
11335
11336     Object* obj;
11337     { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
11338                                                         FAST_ELEMENTS);
11339       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11340     }
11341     Map* new_map = Map::cast(obj);
11342
11343     PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
11344     Object* new_array;
11345     { MaybeObject* maybe_new_array =
11346           heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
11347       if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
11348     }
11349     FixedArray* fast_elements = FixedArray::cast(new_array);
11350     dict->CopyValuesTo(fast_elements);
11351
11352     set_map(new_map);
11353     set_elements(fast_elements);
11354   } else if (HasExternalArrayElements()) {
11355     // External arrays cannot have holes or undefined elements.
11356     return Smi::FromInt(ExternalArray::cast(elements())->length());
11357   } else if (!HasFastDoubleElements()) {
11358     Object* obj;
11359     { MaybeObject* maybe_obj = EnsureWritableFastElements();
11360       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11361     }
11362   }
11363   ASSERT(HasFastTypeElements() || HasFastDoubleElements());
11364
11365   // Collect holes at the end, undefined before that and the rest at the
11366   // start, and return the number of non-hole, non-undefined values.
11367
11368   FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
11369   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
11370   if (limit > elements_length) {
11371     limit = elements_length ;
11372   }
11373   if (limit == 0) {
11374     return Smi::FromInt(0);
11375   }
11376
11377   HeapNumber* result_double = NULL;
11378   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
11379     // Pessimistically allocate space for return value before
11380     // we start mutating the array.
11381     Object* new_double;
11382     { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0);
11383       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
11384     }
11385     result_double = HeapNumber::cast(new_double);
11386   }
11387
11388   uint32_t result = 0;
11389   if (elements_base->map() == heap->fixed_double_array_map()) {
11390     FixedDoubleArray* elements = FixedDoubleArray::cast(elements_base);
11391     // Split elements into defined and the_hole, in that order.
11392     unsigned int holes = limit;
11393     // Assume most arrays contain no holes and undefined values, so minimize the
11394     // number of stores of non-undefined, non-the-hole values.
11395     for (unsigned int i = 0; i < holes; i++) {
11396       if (elements->is_the_hole(i)) {
11397         holes--;
11398       } else {
11399         continue;
11400       }
11401       // Position i needs to be filled.
11402       while (holes > i) {
11403         if (elements->is_the_hole(holes)) {
11404           holes--;
11405         } else {
11406           elements->set(i, elements->get_scalar(holes));
11407           break;
11408         }
11409       }
11410     }
11411     result = holes;
11412     while (holes < limit) {
11413       elements->set_the_hole(holes);
11414       holes++;
11415     }
11416   } else {
11417     FixedArray* elements = FixedArray::cast(elements_base);
11418     AssertNoAllocation no_alloc;
11419
11420     // Split elements into defined, undefined and the_hole, in that order.  Only
11421     // count locations for undefined and the hole, and fill them afterwards.
11422     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
11423     unsigned int undefs = limit;
11424     unsigned int holes = limit;
11425     // Assume most arrays contain no holes and undefined values, so minimize the
11426     // number of stores of non-undefined, non-the-hole values.
11427     for (unsigned int i = 0; i < undefs; i++) {
11428       Object* current = elements->get(i);
11429       if (current->IsTheHole()) {
11430         holes--;
11431         undefs--;
11432       } else if (current->IsUndefined()) {
11433         undefs--;
11434       } else {
11435         continue;
11436       }
11437       // Position i needs to be filled.
11438       while (undefs > i) {
11439         current = elements->get(undefs);
11440         if (current->IsTheHole()) {
11441           holes--;
11442           undefs--;
11443         } else if (current->IsUndefined()) {
11444           undefs--;
11445         } else {
11446           elements->set(i, current, write_barrier);
11447           break;
11448         }
11449       }
11450     }
11451     result = undefs;
11452     while (undefs < holes) {
11453       elements->set_undefined(undefs);
11454       undefs++;
11455     }
11456     while (holes < limit) {
11457       elements->set_the_hole(holes);
11458       holes++;
11459     }
11460   }
11461
11462   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
11463     return Smi::FromInt(static_cast<int>(result));
11464   }
11465   ASSERT_NE(NULL, result_double);
11466   result_double->set_value(static_cast<double>(result));
11467   return result_double;
11468 }
11469
11470
11471 Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
11472   uint8_t clamped_value = 0;
11473   if (index < static_cast<uint32_t>(length())) {
11474     if (value->IsSmi()) {
11475       int int_value = Smi::cast(value)->value();
11476       if (int_value < 0) {
11477         clamped_value = 0;
11478       } else if (int_value > 255) {
11479         clamped_value = 255;
11480       } else {
11481         clamped_value = static_cast<uint8_t>(int_value);
11482       }
11483     } else if (value->IsHeapNumber()) {
11484       double double_value = HeapNumber::cast(value)->value();
11485       if (!(double_value > 0)) {
11486         // NaN and less than zero clamp to zero.
11487         clamped_value = 0;
11488       } else if (double_value > 255) {
11489         // Greater than 255 clamp to 255.
11490         clamped_value = 255;
11491       } else {
11492         // Other doubles are rounded to the nearest integer.
11493         clamped_value = static_cast<uint8_t>(double_value + 0.5);
11494       }
11495     } else {
11496       // Clamp undefined to zero (default). All other types have been
11497       // converted to a number type further up in the call chain.
11498       ASSERT(value->IsUndefined());
11499     }
11500     set(index, clamped_value);
11501   }
11502   return Smi::FromInt(clamped_value);
11503 }
11504
11505
11506 template<typename ExternalArrayClass, typename ValueType>
11507 static MaybeObject* ExternalArrayIntSetter(Heap* heap,
11508                                            ExternalArrayClass* receiver,
11509                                            uint32_t index,
11510                                            Object* value) {
11511   ValueType cast_value = 0;
11512   if (index < static_cast<uint32_t>(receiver->length())) {
11513     if (value->IsSmi()) {
11514       int int_value = Smi::cast(value)->value();
11515       cast_value = static_cast<ValueType>(int_value);
11516     } else if (value->IsHeapNumber()) {
11517       double double_value = HeapNumber::cast(value)->value();
11518       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
11519     } else {
11520       // Clamp undefined to zero (default). All other types have been
11521       // converted to a number type further up in the call chain.
11522       ASSERT(value->IsUndefined());
11523     }
11524     receiver->set(index, cast_value);
11525   }
11526   return heap->NumberFromInt32(cast_value);
11527 }
11528
11529
11530 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) {
11531   return ExternalArrayIntSetter<ExternalByteArray, int8_t>
11532       (GetHeap(), this, index, value);
11533 }
11534
11535
11536 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index,
11537                                                  Object* value) {
11538   return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
11539       (GetHeap(), this, index, value);
11540 }
11541
11542
11543 MaybeObject* ExternalShortArray::SetValue(uint32_t index,
11544                                           Object* value) {
11545   return ExternalArrayIntSetter<ExternalShortArray, int16_t>
11546       (GetHeap(), this, index, value);
11547 }
11548
11549
11550 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index,
11551                                                   Object* value) {
11552   return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
11553       (GetHeap(), this, index, value);
11554 }
11555
11556
11557 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) {
11558   return ExternalArrayIntSetter<ExternalIntArray, int32_t>
11559       (GetHeap(), this, index, value);
11560 }
11561
11562
11563 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
11564   uint32_t cast_value = 0;
11565   Heap* heap = GetHeap();
11566   if (index < static_cast<uint32_t>(length())) {
11567     if (value->IsSmi()) {
11568       int int_value = Smi::cast(value)->value();
11569       cast_value = static_cast<uint32_t>(int_value);
11570     } else if (value->IsHeapNumber()) {
11571       double double_value = HeapNumber::cast(value)->value();
11572       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
11573     } else {
11574       // Clamp undefined to zero (default). All other types have been
11575       // converted to a number type further up in the call chain.
11576       ASSERT(value->IsUndefined());
11577     }
11578     set(index, cast_value);
11579   }
11580   return heap->NumberFromUint32(cast_value);
11581 }
11582
11583
11584 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
11585   float cast_value = static_cast<float>(OS::nan_value());
11586   Heap* heap = GetHeap();
11587   if (index < static_cast<uint32_t>(length())) {
11588     if (value->IsSmi()) {
11589       int int_value = Smi::cast(value)->value();
11590       cast_value = static_cast<float>(int_value);
11591     } else if (value->IsHeapNumber()) {
11592       double double_value = HeapNumber::cast(value)->value();
11593       cast_value = static_cast<float>(double_value);
11594     } else {
11595       // Clamp undefined to NaN (default). All other types have been
11596       // converted to a number type further up in the call chain.
11597       ASSERT(value->IsUndefined());
11598     }
11599     set(index, cast_value);
11600   }
11601   return heap->AllocateHeapNumber(cast_value);
11602 }
11603
11604
11605 MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) {
11606   double double_value = OS::nan_value();
11607   Heap* heap = GetHeap();
11608   if (index < static_cast<uint32_t>(length())) {
11609     if (value->IsSmi()) {
11610       int int_value = Smi::cast(value)->value();
11611       double_value = static_cast<double>(int_value);
11612     } else if (value->IsHeapNumber()) {
11613       double_value = HeapNumber::cast(value)->value();
11614     } else {
11615       // Clamp undefined to NaN (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, double_value);
11620   }
11621   return heap->AllocateHeapNumber(double_value);
11622 }
11623
11624
11625 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
11626   ASSERT(!HasFastProperties());
11627   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
11628   return JSGlobalPropertyCell::cast(value);
11629 }
11630
11631
11632 Handle<JSGlobalPropertyCell> GlobalObject::EnsurePropertyCell(
11633     Handle<GlobalObject> global,
11634     Handle<String> name) {
11635   Isolate* isolate = global->GetIsolate();
11636   CALL_HEAP_FUNCTION(isolate,
11637                      global->EnsurePropertyCell(*name),
11638                      JSGlobalPropertyCell);
11639 }
11640
11641
11642 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) {
11643   ASSERT(!HasFastProperties());
11644   int entry = property_dictionary()->FindEntry(name);
11645   if (entry == StringDictionary::kNotFound) {
11646     Heap* heap = GetHeap();
11647     Object* cell;
11648     { MaybeObject* maybe_cell =
11649           heap->AllocateJSGlobalPropertyCell(heap->the_hole_value());
11650       if (!maybe_cell->ToObject(&cell)) return maybe_cell;
11651     }
11652     PropertyDetails details(NONE, NORMAL);
11653     details = details.AsDeleted();
11654     Object* dictionary;
11655     { MaybeObject* maybe_dictionary =
11656           property_dictionary()->Add(name, cell, details);
11657       if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
11658     }
11659     set_properties(StringDictionary::cast(dictionary));
11660     return cell;
11661   } else {
11662     Object* value = property_dictionary()->ValueAt(entry);
11663     ASSERT(value->IsJSGlobalPropertyCell());
11664     return value;
11665   }
11666 }
11667
11668
11669 MaybeObject* SymbolTable::LookupString(String* string, Object** s) {
11670   SymbolKey key(string);
11671   return LookupKey(&key, s);
11672 }
11673
11674
11675 // This class is used for looking up two character strings in the symbol table.
11676 // If we don't have a hit we don't want to waste much time so we unroll the
11677 // string hash calculation loop here for speed.  Doesn't work if the two
11678 // characters form a decimal integer, since such strings have a different hash
11679 // algorithm.
11680 class TwoCharHashTableKey : public HashTableKey {
11681  public:
11682   TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed)
11683     : c1_(c1), c2_(c2) {
11684     // Char 1.
11685     uint32_t hash = seed;
11686     hash += c1;
11687     hash += hash << 10;
11688     hash ^= hash >> 6;
11689     // Char 2.
11690     hash += c2;
11691     hash += hash << 10;
11692     hash ^= hash >> 6;
11693     // GetHash.
11694     hash += hash << 3;
11695     hash ^= hash >> 11;
11696     hash += hash << 15;
11697     if ((hash & String::kHashBitMask) == 0) hash = String::kZeroHash;
11698 #ifdef DEBUG
11699     StringHasher hasher(2, seed);
11700     hasher.AddCharacter(c1);
11701     hasher.AddCharacter(c2);
11702     // If this assert fails then we failed to reproduce the two-character
11703     // version of the string hashing algorithm above.  One reason could be
11704     // that we were passed two digits as characters, since the hash
11705     // algorithm is different in that case.
11706     ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
11707 #endif
11708     hash_ = hash;
11709   }
11710
11711   bool IsMatch(Object* o) {
11712     if (!o->IsString()) return false;
11713     String* other = String::cast(o);
11714     if (other->length() != 2) return false;
11715     if (other->Get(0) != c1_) return false;
11716     return other->Get(1) == c2_;
11717   }
11718
11719   uint32_t Hash() { return hash_; }
11720   uint32_t HashForObject(Object* key) {
11721     if (!key->IsString()) return 0;
11722     return String::cast(key)->Hash();
11723   }
11724
11725   Object* AsObject() {
11726     // The TwoCharHashTableKey is only used for looking in the symbol
11727     // table, not for adding to it.
11728     UNREACHABLE();
11729     return NULL;
11730   }
11731
11732  private:
11733   uint32_t c1_;
11734   uint32_t c2_;
11735   uint32_t hash_;
11736 };
11737
11738
11739 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
11740   SymbolKey key(string);
11741   int entry = FindEntry(&key);
11742   if (entry == kNotFound) {
11743     return false;
11744   } else {
11745     String* result = String::cast(KeyAt(entry));
11746     ASSERT(StringShape(result).IsSymbol());
11747     *symbol = result;
11748     return true;
11749   }
11750 }
11751
11752
11753 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
11754                                                uint32_t c2,
11755                                                String** symbol) {
11756   TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed());
11757   int entry = FindEntry(&key);
11758   if (entry == kNotFound) {
11759     return false;
11760   } else {
11761     String* result = String::cast(KeyAt(entry));
11762     ASSERT(StringShape(result).IsSymbol());
11763     *symbol = result;
11764     return true;
11765   }
11766 }
11767
11768
11769 MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str,
11770                                        Object** s) {
11771   Utf8SymbolKey key(str, GetHeap()->HashSeed());
11772   return LookupKey(&key, s);
11773 }
11774
11775
11776 MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str,
11777                                             Object** s) {
11778   AsciiSymbolKey key(str, GetHeap()->HashSeed());
11779   return LookupKey(&key, s);
11780 }
11781
11782
11783 MaybeObject* SymbolTable::LookupSubStringAsciiSymbol(Handle<SeqAsciiString> str,
11784                                                      int from,
11785                                                      int length,
11786                                                      Object** s) {
11787   SubStringAsciiSymbolKey key(str, from, length, GetHeap()->HashSeed());
11788   return LookupKey(&key, s);
11789 }
11790
11791
11792 MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
11793                                               Object** s) {
11794   TwoByteSymbolKey key(str, GetHeap()->HashSeed());
11795   return LookupKey(&key, s);
11796 }
11797
11798 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
11799   int entry = FindEntry(key);
11800
11801   // Symbol already in table.
11802   if (entry != kNotFound) {
11803     *s = KeyAt(entry);
11804     return this;
11805   }
11806
11807   // Adding new symbol. Grow table if needed.
11808   Object* obj;
11809   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
11810     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11811   }
11812
11813   // Create symbol object.
11814   Object* symbol;
11815   { MaybeObject* maybe_symbol = key->AsObject();
11816     if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol;
11817   }
11818
11819   // If the symbol table grew as part of EnsureCapacity, obj is not
11820   // the current symbol table and therefore we cannot use
11821   // SymbolTable::cast here.
11822   SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
11823
11824   // Add the new symbol and return it along with the symbol table.
11825   entry = table->FindInsertionEntry(key->Hash());
11826   table->set(EntryToIndex(entry), symbol);
11827   table->ElementAdded();
11828   *s = symbol;
11829   return table;
11830 }
11831
11832
11833 Object* CompilationCacheTable::Lookup(String* src) {
11834   StringKey key(src);
11835   int entry = FindEntry(&key);
11836   if (entry == kNotFound) return GetHeap()->undefined_value();
11837   return get(EntryToIndex(entry) + 1);
11838 }
11839
11840
11841 Object* CompilationCacheTable::LookupEval(String* src,
11842                                           Context* context,
11843                                           LanguageMode language_mode,
11844                                           int scope_position) {
11845   StringSharedKey key(src,
11846                       context->closure()->shared(),
11847                       language_mode,
11848                       scope_position);
11849   int entry = FindEntry(&key);
11850   if (entry == kNotFound) return GetHeap()->undefined_value();
11851   return get(EntryToIndex(entry) + 1);
11852 }
11853
11854
11855 Object* CompilationCacheTable::LookupRegExp(String* src,
11856                                             JSRegExp::Flags flags) {
11857   RegExpKey key(src, flags);
11858   int entry = FindEntry(&key);
11859   if (entry == kNotFound) return GetHeap()->undefined_value();
11860   return get(EntryToIndex(entry) + 1);
11861 }
11862
11863
11864 MaybeObject* CompilationCacheTable::Put(String* src, Object* value) {
11865   StringKey key(src);
11866   Object* obj;
11867   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11868     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11869   }
11870
11871   CompilationCacheTable* cache =
11872       reinterpret_cast<CompilationCacheTable*>(obj);
11873   int entry = cache->FindInsertionEntry(key.Hash());
11874   cache->set(EntryToIndex(entry), src);
11875   cache->set(EntryToIndex(entry) + 1, value);
11876   cache->ElementAdded();
11877   return cache;
11878 }
11879
11880
11881 MaybeObject* CompilationCacheTable::PutEval(String* src,
11882                                             Context* context,
11883                                             SharedFunctionInfo* value,
11884                                             int scope_position) {
11885   StringSharedKey key(src,
11886                       context->closure()->shared(),
11887                       value->language_mode(),
11888                       scope_position);
11889   Object* obj;
11890   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11891     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11892   }
11893
11894   CompilationCacheTable* cache =
11895       reinterpret_cast<CompilationCacheTable*>(obj);
11896   int entry = cache->FindInsertionEntry(key.Hash());
11897
11898   Object* k;
11899   { MaybeObject* maybe_k = key.AsObject();
11900     if (!maybe_k->ToObject(&k)) return maybe_k;
11901   }
11902
11903   cache->set(EntryToIndex(entry), k);
11904   cache->set(EntryToIndex(entry) + 1, value);
11905   cache->ElementAdded();
11906   return cache;
11907 }
11908
11909
11910 MaybeObject* CompilationCacheTable::PutRegExp(String* src,
11911                                               JSRegExp::Flags flags,
11912                                               FixedArray* value) {
11913   RegExpKey key(src, flags);
11914   Object* obj;
11915   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11916     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11917   }
11918
11919   CompilationCacheTable* cache =
11920       reinterpret_cast<CompilationCacheTable*>(obj);
11921   int entry = cache->FindInsertionEntry(key.Hash());
11922   // We store the value in the key slot, and compare the search key
11923   // to the stored value with a custon IsMatch function during lookups.
11924   cache->set(EntryToIndex(entry), value);
11925   cache->set(EntryToIndex(entry) + 1, value);
11926   cache->ElementAdded();
11927   return cache;
11928 }
11929
11930
11931 void CompilationCacheTable::Remove(Object* value) {
11932   Object* the_hole_value = GetHeap()->the_hole_value();
11933   for (int entry = 0, size = Capacity(); entry < size; entry++) {
11934     int entry_index = EntryToIndex(entry);
11935     int value_index = entry_index + 1;
11936     if (get(value_index) == value) {
11937       NoWriteBarrierSet(this, entry_index, the_hole_value);
11938       NoWriteBarrierSet(this, value_index, the_hole_value);
11939       ElementRemoved();
11940     }
11941   }
11942   return;
11943 }
11944
11945
11946 // SymbolsKey used for HashTable where key is array of symbols.
11947 class SymbolsKey : public HashTableKey {
11948  public:
11949   explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
11950
11951   bool IsMatch(Object* symbols) {
11952     FixedArray* o = FixedArray::cast(symbols);
11953     int len = symbols_->length();
11954     if (o->length() != len) return false;
11955     for (int i = 0; i < len; i++) {
11956       if (o->get(i) != symbols_->get(i)) return false;
11957     }
11958     return true;
11959   }
11960
11961   uint32_t Hash() { return HashForObject(symbols_); }
11962
11963   uint32_t HashForObject(Object* obj) {
11964     FixedArray* symbols = FixedArray::cast(obj);
11965     int len = symbols->length();
11966     uint32_t hash = 0;
11967     for (int i = 0; i < len; i++) {
11968       hash ^= String::cast(symbols->get(i))->Hash();
11969     }
11970     return hash;
11971   }
11972
11973   Object* AsObject() { return symbols_; }
11974
11975  private:
11976   FixedArray* symbols_;
11977 };
11978
11979
11980 Object* MapCache::Lookup(FixedArray* array) {
11981   SymbolsKey key(array);
11982   int entry = FindEntry(&key);
11983   if (entry == kNotFound) return GetHeap()->undefined_value();
11984   return get(EntryToIndex(entry) + 1);
11985 }
11986
11987
11988 MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
11989   SymbolsKey key(array);
11990   Object* obj;
11991   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
11992     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11993   }
11994
11995   MapCache* cache = reinterpret_cast<MapCache*>(obj);
11996   int entry = cache->FindInsertionEntry(key.Hash());
11997   cache->set(EntryToIndex(entry), array);
11998   cache->set(EntryToIndex(entry) + 1, value);
11999   cache->ElementAdded();
12000   return cache;
12001 }
12002
12003
12004 template<typename Shape, typename Key>
12005 MaybeObject* Dictionary<Shape, Key>::Allocate(int at_least_space_for) {
12006   Object* obj;
12007   { MaybeObject* maybe_obj =
12008         HashTable<Shape, Key>::Allocate(at_least_space_for);
12009     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12010   }
12011   // Initialize the next enumeration index.
12012   Dictionary<Shape, Key>::cast(obj)->
12013       SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
12014   return obj;
12015 }
12016
12017
12018 template<typename Shape, typename Key>
12019 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
12020   Heap* heap = Dictionary<Shape, Key>::GetHeap();
12021   int length = HashTable<Shape, Key>::NumberOfElements();
12022
12023   // Allocate and initialize iteration order array.
12024   Object* obj;
12025   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12026     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12027   }
12028   FixedArray* iteration_order = FixedArray::cast(obj);
12029   for (int i = 0; i < length; i++) {
12030     iteration_order->set(i, Smi::FromInt(i));
12031   }
12032
12033   // Allocate array with enumeration order.
12034   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
12035     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12036   }
12037   FixedArray* enumeration_order = FixedArray::cast(obj);
12038
12039   // Fill the enumeration order array with property details.
12040   int capacity = HashTable<Shape, Key>::Capacity();
12041   int pos = 0;
12042   for (int i = 0; i < capacity; i++) {
12043     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
12044       enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
12045     }
12046   }
12047
12048   // Sort the arrays wrt. enumeration order.
12049   iteration_order->SortPairs(enumeration_order, enumeration_order->length());
12050
12051   // Overwrite the enumeration_order with the enumeration indices.
12052   for (int i = 0; i < length; i++) {
12053     int index = Smi::cast(iteration_order->get(i))->value();
12054     int enum_index = PropertyDetails::kInitialIndex + i;
12055     enumeration_order->set(index, Smi::FromInt(enum_index));
12056   }
12057
12058   // Update the dictionary with new indices.
12059   capacity = HashTable<Shape, Key>::Capacity();
12060   pos = 0;
12061   for (int i = 0; i < capacity; i++) {
12062     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
12063       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
12064       PropertyDetails details = DetailsAt(i);
12065       PropertyDetails new_details =
12066           PropertyDetails(details.attributes(), details.type(), enum_index);
12067       DetailsAtPut(i, new_details);
12068     }
12069   }
12070
12071   // Set the next enumeration index.
12072   SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
12073   return this;
12074 }
12075
12076 template<typename Shape, typename Key>
12077 MaybeObject* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
12078   // Check whether there are enough enumeration indices to add n elements.
12079   if (Shape::kIsEnumerable &&
12080       !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
12081     // If not, we generate new indices for the properties.
12082     Object* result;
12083     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12084       if (!maybe_result->ToObject(&result)) return maybe_result;
12085     }
12086   }
12087   return HashTable<Shape, Key>::EnsureCapacity(n, key);
12088 }
12089
12090
12091 template<typename Shape, typename Key>
12092 Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
12093                                                JSReceiver::DeleteMode mode) {
12094   Heap* heap = Dictionary<Shape, Key>::GetHeap();
12095   PropertyDetails details = DetailsAt(entry);
12096   // Ignore attributes if forcing a deletion.
12097   if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
12098     return heap->false_value();
12099   }
12100   SetEntry(entry, heap->the_hole_value(), heap->the_hole_value());
12101   HashTable<Shape, Key>::ElementRemoved();
12102   return heap->true_value();
12103 }
12104
12105
12106 template<typename Shape, typename Key>
12107 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
12108   return HashTable<Shape, Key>::Shrink(key);
12109 }
12110
12111
12112 template<typename Shape, typename Key>
12113 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
12114   int entry = this->FindEntry(key);
12115
12116   // If the entry is present set the value;
12117   if (entry != Dictionary<Shape, Key>::kNotFound) {
12118     ValueAtPut(entry, value);
12119     return this;
12120   }
12121
12122   // Check whether the dictionary should be extended.
12123   Object* obj;
12124   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12125     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12126   }
12127
12128   Object* k;
12129   { MaybeObject* maybe_k = Shape::AsObject(key);
12130     if (!maybe_k->ToObject(&k)) return maybe_k;
12131   }
12132   PropertyDetails details = PropertyDetails(NONE, NORMAL);
12133
12134   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
12135       Dictionary<Shape, Key>::Hash(key));
12136 }
12137
12138
12139 template<typename Shape, typename Key>
12140 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
12141                                          Object* value,
12142                                          PropertyDetails details) {
12143   // Valdate key is absent.
12144   SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
12145   // Check whether the dictionary should be extended.
12146   Object* obj;
12147   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12148     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12149   }
12150
12151   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
12152       Dictionary<Shape, Key>::Hash(key));
12153 }
12154
12155
12156 // Add a key, value pair to the dictionary.
12157 template<typename Shape, typename Key>
12158 MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key,
12159                                               Object* value,
12160                                               PropertyDetails details,
12161                                               uint32_t hash) {
12162   // Compute the key object.
12163   Object* k;
12164   { MaybeObject* maybe_k = Shape::AsObject(key);
12165     if (!maybe_k->ToObject(&k)) return maybe_k;
12166   }
12167
12168   uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
12169   // Insert element at empty or deleted entry
12170   if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
12171     // Assign an enumeration index to the property and update
12172     // SetNextEnumerationIndex.
12173     int index = NextEnumerationIndex();
12174     details = PropertyDetails(details.attributes(), details.type(), index);
12175     SetNextEnumerationIndex(index + 1);
12176   }
12177   SetEntry(entry, k, value, details);
12178   ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
12179           || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
12180   HashTable<Shape, Key>::ElementAdded();
12181   return this;
12182 }
12183
12184
12185 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
12186   // If the dictionary requires slow elements an element has already
12187   // been added at a high index.
12188   if (requires_slow_elements()) return;
12189   // Check if this index is high enough that we should require slow
12190   // elements.
12191   if (key > kRequiresSlowElementsLimit) {
12192     set_requires_slow_elements();
12193     return;
12194   }
12195   // Update max key value.
12196   Object* max_index_object = get(kMaxNumberKeyIndex);
12197   if (!max_index_object->IsSmi() || max_number_key() < key) {
12198     FixedArray::set(kMaxNumberKeyIndex,
12199                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
12200   }
12201 }
12202
12203
12204 MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key,
12205                                                     Object* value,
12206                                                     PropertyDetails details) {
12207   UpdateMaxNumberKey(key);
12208   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
12209   return Add(key, value, details);
12210 }
12211
12212
12213 MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key,
12214                                                       Object* value) {
12215   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
12216   return Add(key, value, PropertyDetails(NONE, NORMAL));
12217 }
12218
12219
12220 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) {
12221   UpdateMaxNumberKey(key);
12222   return AtPut(key, value);
12223 }
12224
12225
12226 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key,
12227                                                    Object* value) {
12228   return AtPut(key, value);
12229 }
12230
12231
12232 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
12233     Handle<SeededNumberDictionary> dictionary,
12234     uint32_t index,
12235     Handle<Object> value,
12236     PropertyDetails details) {
12237   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
12238                      dictionary->Set(index, *value, details),
12239                      SeededNumberDictionary);
12240 }
12241
12242
12243 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
12244     Handle<UnseededNumberDictionary> dictionary,
12245     uint32_t index,
12246     Handle<Object> value) {
12247   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
12248                      dictionary->Set(index, *value),
12249                      UnseededNumberDictionary);
12250 }
12251
12252
12253 MaybeObject* SeededNumberDictionary::Set(uint32_t key,
12254                                          Object* value,
12255                                          PropertyDetails details) {
12256   int entry = FindEntry(key);
12257   if (entry == kNotFound) return AddNumberEntry(key, value, details);
12258   // Preserve enumeration index.
12259   details = PropertyDetails(details.attributes(),
12260                             details.type(),
12261                             DetailsAt(entry).index());
12262   MaybeObject* maybe_object_key = SeededNumberDictionaryShape::AsObject(key);
12263   Object* object_key;
12264   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
12265   SetEntry(entry, object_key, value, details);
12266   return this;
12267 }
12268
12269
12270 MaybeObject* UnseededNumberDictionary::Set(uint32_t key,
12271                                            Object* value) {
12272   int entry = FindEntry(key);
12273   if (entry == kNotFound) return AddNumberEntry(key, value);
12274   MaybeObject* maybe_object_key = UnseededNumberDictionaryShape::AsObject(key);
12275   Object* object_key;
12276   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
12277   SetEntry(entry, object_key, value);
12278   return this;
12279 }
12280
12281
12282
12283 template<typename Shape, typename Key>
12284 int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
12285     PropertyAttributes filter) {
12286   int capacity = HashTable<Shape, Key>::Capacity();
12287   int result = 0;
12288   for (int i = 0; i < capacity; i++) {
12289     Object* k = HashTable<Shape, Key>::KeyAt(i);
12290     if (HashTable<Shape, Key>::IsKey(k)) {
12291       PropertyDetails details = DetailsAt(i);
12292       if (details.IsDeleted()) continue;
12293       PropertyAttributes attr = details.attributes();
12294       if ((attr & filter) == 0) result++;
12295     }
12296   }
12297   return result;
12298 }
12299
12300
12301 template<typename Shape, typename Key>
12302 int Dictionary<Shape, Key>::NumberOfEnumElements() {
12303   return NumberOfElementsFilterAttributes(
12304       static_cast<PropertyAttributes>(DONT_ENUM));
12305 }
12306
12307
12308 template<typename Shape, typename Key>
12309 void Dictionary<Shape, Key>::CopyKeysTo(
12310     FixedArray* storage,
12311     PropertyAttributes filter,
12312     typename Dictionary<Shape, Key>::SortMode sort_mode) {
12313   ASSERT(storage->length() >= NumberOfEnumElements());
12314   int capacity = HashTable<Shape, Key>::Capacity();
12315   int index = 0;
12316   for (int i = 0; i < capacity; i++) {
12317      Object* k = HashTable<Shape, Key>::KeyAt(i);
12318      if (HashTable<Shape, Key>::IsKey(k)) {
12319        PropertyDetails details = DetailsAt(i);
12320        if (details.IsDeleted()) continue;
12321        PropertyAttributes attr = details.attributes();
12322        if ((attr & filter) == 0) storage->set(index++, k);
12323      }
12324   }
12325   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12326     storage->SortPairs(storage, index);
12327   }
12328   ASSERT(storage->length() >= index);
12329 }
12330
12331
12332 void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
12333                                       FixedArray* sort_array) {
12334   ASSERT(storage->length() >= NumberOfEnumElements());
12335   int capacity = Capacity();
12336   int index = 0;
12337   for (int i = 0; i < capacity; i++) {
12338      Object* k = KeyAt(i);
12339      if (IsKey(k)) {
12340        PropertyDetails details = DetailsAt(i);
12341        if (details.IsDeleted() || details.IsDontEnum()) continue;
12342        storage->set(index, k);
12343        sort_array->set(index, Smi::FromInt(details.index()));
12344        index++;
12345      }
12346   }
12347   storage->SortPairs(sort_array, sort_array->length());
12348   ASSERT(storage->length() >= index);
12349 }
12350
12351
12352 template<typename Shape, typename Key>
12353 void Dictionary<Shape, Key>::CopyKeysTo(
12354     FixedArray* storage,
12355     int index,
12356     typename Dictionary<Shape, Key>::SortMode sort_mode) {
12357   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
12358       static_cast<PropertyAttributes>(NONE)));
12359   int capacity = HashTable<Shape, Key>::Capacity();
12360   for (int i = 0; i < capacity; i++) {
12361     Object* k = HashTable<Shape, Key>::KeyAt(i);
12362     if (HashTable<Shape, Key>::IsKey(k)) {
12363       PropertyDetails details = DetailsAt(i);
12364       if (details.IsDeleted()) continue;
12365       storage->set(index++, k);
12366     }
12367   }
12368   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
12369     storage->SortPairs(storage, index);
12370   }
12371   ASSERT(storage->length() >= index);
12372 }
12373
12374
12375 // Backwards lookup (slow).
12376 template<typename Shape, typename Key>
12377 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
12378   int capacity = HashTable<Shape, Key>::Capacity();
12379   for (int i = 0; i < capacity; i++) {
12380     Object* k =  HashTable<Shape, Key>::KeyAt(i);
12381     if (Dictionary<Shape, Key>::IsKey(k)) {
12382       Object* e = ValueAt(i);
12383       if (e->IsJSGlobalPropertyCell()) {
12384         e = JSGlobalPropertyCell::cast(e)->value();
12385       }
12386       if (e == value) return k;
12387     }
12388   }
12389   Heap* heap = Dictionary<Shape, Key>::GetHeap();
12390   return heap->undefined_value();
12391 }
12392
12393
12394 MaybeObject* StringDictionary::TransformPropertiesToFastFor(
12395     JSObject* obj, int unused_property_fields) {
12396   // Make sure we preserve dictionary representation if there are too many
12397   // descriptors.
12398   if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
12399
12400   // Figure out if it is necessary to generate new enumeration indices.
12401   int max_enumeration_index =
12402       NextEnumerationIndex() +
12403           (DescriptorArray::kMaxNumberOfDescriptors -
12404            NumberOfElements());
12405   if (!PropertyDetails::IsValidIndex(max_enumeration_index)) {
12406     Object* result;
12407     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
12408       if (!maybe_result->ToObject(&result)) return maybe_result;
12409     }
12410   }
12411
12412   int instance_descriptor_length = 0;
12413   int number_of_fields = 0;
12414
12415   Heap* heap = GetHeap();
12416
12417   // Compute the length of the instance descriptor.
12418   int capacity = Capacity();
12419   for (int i = 0; i < capacity; i++) {
12420     Object* k = KeyAt(i);
12421     if (IsKey(k)) {
12422       Object* value = ValueAt(i);
12423       PropertyType type = DetailsAt(i).type();
12424       ASSERT(type != FIELD);
12425       instance_descriptor_length++;
12426       if (type == NORMAL &&
12427           (!value->IsJSFunction() || heap->InNewSpace(value))) {
12428         number_of_fields += 1;
12429       }
12430     }
12431   }
12432
12433   // Allocate the instance descriptor.
12434   DescriptorArray* descriptors;
12435   { MaybeObject* maybe_descriptors =
12436         DescriptorArray::Allocate(instance_descriptor_length);
12437     if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) {
12438       return maybe_descriptors;
12439     }
12440   }
12441
12442   DescriptorArray::WhitenessWitness witness(descriptors);
12443
12444   int inobject_props = obj->map()->inobject_properties();
12445   int number_of_allocated_fields =
12446       number_of_fields + unused_property_fields - inobject_props;
12447   if (number_of_allocated_fields < 0) {
12448     // There is enough inobject space for all fields (including unused).
12449     number_of_allocated_fields = 0;
12450     unused_property_fields = inobject_props - number_of_fields;
12451   }
12452
12453   // Allocate the fixed array for the fields.
12454   Object* fields;
12455   { MaybeObject* maybe_fields =
12456         heap->AllocateFixedArray(number_of_allocated_fields);
12457     if (!maybe_fields->ToObject(&fields)) return maybe_fields;
12458   }
12459
12460   // Fill in the instance descriptor and the fields.
12461   int next_descriptor = 0;
12462   int current_offset = 0;
12463   for (int i = 0; i < capacity; i++) {
12464     Object* k = KeyAt(i);
12465     if (IsKey(k)) {
12466       Object* value = ValueAt(i);
12467       // Ensure the key is a symbol before writing into the instance descriptor.
12468       Object* key;
12469       { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
12470         if (!maybe_key->ToObject(&key)) return maybe_key;
12471       }
12472       PropertyDetails details = DetailsAt(i);
12473       PropertyType type = details.type();
12474
12475       if (value->IsJSFunction() && !heap->InNewSpace(value)) {
12476         ConstantFunctionDescriptor d(String::cast(key),
12477                                      JSFunction::cast(value),
12478                                      details.attributes(),
12479                                      details.index());
12480         descriptors->Set(next_descriptor++, &d, witness);
12481       } else if (type == NORMAL) {
12482         if (current_offset < inobject_props) {
12483           obj->InObjectPropertyAtPut(current_offset,
12484                                      value,
12485                                      UPDATE_WRITE_BARRIER);
12486         } else {
12487           int offset = current_offset - inobject_props;
12488           FixedArray::cast(fields)->set(offset, value);
12489         }
12490         FieldDescriptor d(String::cast(key),
12491                           current_offset++,
12492                           details.attributes(),
12493                           details.index());
12494         descriptors->Set(next_descriptor++, &d, witness);
12495       } else if (type == CALLBACKS) {
12496         if (value->IsAccessorPair()) {
12497           MaybeObject* maybe_copy =
12498               AccessorPair::cast(value)->CopyWithoutTransitions();
12499           if (!maybe_copy->To(&value)) return maybe_copy;
12500         }
12501         CallbacksDescriptor d(String::cast(key),
12502                               value,
12503                               details.attributes(),
12504                               details.index());
12505         descriptors->Set(next_descriptor++, &d, witness);
12506       } else {
12507         UNREACHABLE();
12508       }
12509     }
12510   }
12511   ASSERT(current_offset == number_of_fields);
12512
12513   descriptors->Sort(witness);
12514   // Allocate new map.
12515   Object* new_map;
12516   { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
12517     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
12518   }
12519
12520   // Transform the object.
12521   obj->set_map(Map::cast(new_map));
12522   obj->map()->set_instance_descriptors(descriptors);
12523   obj->map()->set_unused_property_fields(unused_property_fields);
12524
12525   obj->set_properties(FixedArray::cast(fields));
12526   ASSERT(obj->IsJSObject());
12527
12528   descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
12529   // Check that it really works.
12530   ASSERT(obj->HasFastProperties());
12531
12532   return obj;
12533 }
12534
12535
12536 bool ObjectHashSet::Contains(Object* key) {
12537   ASSERT(IsKey(key));
12538
12539   // If the object does not have an identity hash, it was never used as a key.
12540   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12541     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false;
12542   }
12543   return (FindEntry(key) != kNotFound);
12544 }
12545
12546
12547 MaybeObject* ObjectHashSet::Add(Object* key) {
12548   ASSERT(IsKey(key));
12549
12550   // Make sure the key object has an identity hash code.
12551   int hash;
12552   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
12553     if (maybe_hash->IsFailure()) return maybe_hash;
12554     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
12555   }
12556   int entry = FindEntry(key);
12557
12558   // Check whether key is already present.
12559   if (entry != kNotFound) return this;
12560
12561   // Check whether the hash set should be extended and add entry.
12562   Object* obj;
12563   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12564     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12565   }
12566   ObjectHashSet* table = ObjectHashSet::cast(obj);
12567   entry = table->FindInsertionEntry(hash);
12568   table->set(EntryToIndex(entry), key);
12569   table->ElementAdded();
12570   return table;
12571 }
12572
12573
12574 MaybeObject* ObjectHashSet::Remove(Object* key) {
12575   ASSERT(IsKey(key));
12576
12577   // If the object does not have an identity hash, it was never used as a key.
12578   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12579     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this;
12580   }
12581   int entry = FindEntry(key);
12582
12583   // Check whether key is actually present.
12584   if (entry == kNotFound) return this;
12585
12586   // Remove entry and try to shrink this hash set.
12587   set_the_hole(EntryToIndex(entry));
12588   ElementRemoved();
12589   return Shrink(key);
12590 }
12591
12592
12593 Object* ObjectHashTable::Lookup(Object* key) {
12594   ASSERT(IsKey(key));
12595
12596   // If the object does not have an identity hash, it was never used as a key.
12597   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
12598     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) {
12599       return GetHeap()->undefined_value();
12600     }
12601   }
12602   int entry = FindEntry(key);
12603   if (entry == kNotFound) return GetHeap()->undefined_value();
12604   return get(EntryToIndex(entry) + 1);
12605 }
12606
12607
12608 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) {
12609   ASSERT(IsKey(key));
12610
12611   // Make sure the key object has an identity hash code.
12612   int hash;
12613   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
12614     if (maybe_hash->IsFailure()) return maybe_hash;
12615     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
12616   }
12617   int entry = FindEntry(key);
12618
12619   // Check whether to perform removal operation.
12620   if (value->IsUndefined()) {
12621     if (entry == kNotFound) return this;
12622     RemoveEntry(entry);
12623     return Shrink(key);
12624   }
12625
12626   // Key is already in table, just overwrite value.
12627   if (entry != kNotFound) {
12628     set(EntryToIndex(entry) + 1, value);
12629     return this;
12630   }
12631
12632   // Check whether the hash table should be extended.
12633   Object* obj;
12634   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
12635     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
12636   }
12637   ObjectHashTable* table = ObjectHashTable::cast(obj);
12638   table->AddEntry(table->FindInsertionEntry(hash), key, value);
12639   return table;
12640 }
12641
12642
12643 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
12644   set(EntryToIndex(entry), key);
12645   set(EntryToIndex(entry) + 1, value);
12646   ElementAdded();
12647 }
12648
12649
12650 void ObjectHashTable::RemoveEntry(int entry) {
12651   set_the_hole(EntryToIndex(entry));
12652   set_the_hole(EntryToIndex(entry) + 1);
12653   ElementRemoved();
12654 }
12655
12656
12657 #ifdef ENABLE_DEBUGGER_SUPPORT
12658 // Check if there is a break point at this code position.
12659 bool DebugInfo::HasBreakPoint(int code_position) {
12660   // Get the break point info object for this code position.
12661   Object* break_point_info = GetBreakPointInfo(code_position);
12662
12663   // If there is no break point info object or no break points in the break
12664   // point info object there is no break point at this code position.
12665   if (break_point_info->IsUndefined()) return false;
12666   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
12667 }
12668
12669
12670 // Get the break point info object for this code position.
12671 Object* DebugInfo::GetBreakPointInfo(int code_position) {
12672   // Find the index of the break point info object for this code position.
12673   int index = GetBreakPointInfoIndex(code_position);
12674
12675   // Return the break point info object if any.
12676   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
12677   return BreakPointInfo::cast(break_points()->get(index));
12678 }
12679
12680
12681 // Clear a break point at the specified code position.
12682 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
12683                                 int code_position,
12684                                 Handle<Object> break_point_object) {
12685   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
12686   if (break_point_info->IsUndefined()) return;
12687   BreakPointInfo::ClearBreakPoint(
12688       Handle<BreakPointInfo>::cast(break_point_info),
12689       break_point_object);
12690 }
12691
12692
12693 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
12694                               int code_position,
12695                               int source_position,
12696                               int statement_position,
12697                               Handle<Object> break_point_object) {
12698   Isolate* isolate = Isolate::Current();
12699   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
12700   if (!break_point_info->IsUndefined()) {
12701     BreakPointInfo::SetBreakPoint(
12702         Handle<BreakPointInfo>::cast(break_point_info),
12703         break_point_object);
12704     return;
12705   }
12706
12707   // Adding a new break point for a code position which did not have any
12708   // break points before. Try to find a free slot.
12709   int index = kNoBreakPointInfo;
12710   for (int i = 0; i < debug_info->break_points()->length(); i++) {
12711     if (debug_info->break_points()->get(i)->IsUndefined()) {
12712       index = i;
12713       break;
12714     }
12715   }
12716   if (index == kNoBreakPointInfo) {
12717     // No free slot - extend break point info array.
12718     Handle<FixedArray> old_break_points =
12719         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
12720     Handle<FixedArray> new_break_points =
12721         isolate->factory()->NewFixedArray(
12722             old_break_points->length() +
12723             Debug::kEstimatedNofBreakPointsInFunction);
12724
12725     debug_info->set_break_points(*new_break_points);
12726     for (int i = 0; i < old_break_points->length(); i++) {
12727       new_break_points->set(i, old_break_points->get(i));
12728     }
12729     index = old_break_points->length();
12730   }
12731   ASSERT(index != kNoBreakPointInfo);
12732
12733   // Allocate new BreakPointInfo object and set the break point.
12734   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
12735       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
12736   new_break_point_info->set_code_position(Smi::FromInt(code_position));
12737   new_break_point_info->set_source_position(Smi::FromInt(source_position));
12738   new_break_point_info->
12739       set_statement_position(Smi::FromInt(statement_position));
12740   new_break_point_info->set_break_point_objects(
12741       isolate->heap()->undefined_value());
12742   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
12743   debug_info->break_points()->set(index, *new_break_point_info);
12744 }
12745
12746
12747 // Get the break point objects for a code position.
12748 Object* DebugInfo::GetBreakPointObjects(int code_position) {
12749   Object* break_point_info = GetBreakPointInfo(code_position);
12750   if (break_point_info->IsUndefined()) {
12751     return GetHeap()->undefined_value();
12752   }
12753   return BreakPointInfo::cast(break_point_info)->break_point_objects();
12754 }
12755
12756
12757 // Get the total number of break points.
12758 int DebugInfo::GetBreakPointCount() {
12759   if (break_points()->IsUndefined()) return 0;
12760   int count = 0;
12761   for (int i = 0; i < break_points()->length(); i++) {
12762     if (!break_points()->get(i)->IsUndefined()) {
12763       BreakPointInfo* break_point_info =
12764           BreakPointInfo::cast(break_points()->get(i));
12765       count += break_point_info->GetBreakPointCount();
12766     }
12767   }
12768   return count;
12769 }
12770
12771
12772 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
12773                                       Handle<Object> break_point_object) {
12774   Heap* heap = debug_info->GetHeap();
12775   if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
12776   for (int i = 0; i < debug_info->break_points()->length(); i++) {
12777     if (!debug_info->break_points()->get(i)->IsUndefined()) {
12778       Handle<BreakPointInfo> break_point_info =
12779           Handle<BreakPointInfo>(BreakPointInfo::cast(
12780               debug_info->break_points()->get(i)));
12781       if (BreakPointInfo::HasBreakPointObject(break_point_info,
12782                                               break_point_object)) {
12783         return *break_point_info;
12784       }
12785     }
12786   }
12787   return heap->undefined_value();
12788 }
12789
12790
12791 // Find the index of the break point info object for the specified code
12792 // position.
12793 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
12794   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
12795   for (int i = 0; i < break_points()->length(); i++) {
12796     if (!break_points()->get(i)->IsUndefined()) {
12797       BreakPointInfo* break_point_info =
12798           BreakPointInfo::cast(break_points()->get(i));
12799       if (break_point_info->code_position()->value() == code_position) {
12800         return i;
12801       }
12802     }
12803   }
12804   return kNoBreakPointInfo;
12805 }
12806
12807
12808 // Remove the specified break point object.
12809 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
12810                                      Handle<Object> break_point_object) {
12811   Isolate* isolate = Isolate::Current();
12812   // If there are no break points just ignore.
12813   if (break_point_info->break_point_objects()->IsUndefined()) return;
12814   // If there is a single break point clear it if it is the same.
12815   if (!break_point_info->break_point_objects()->IsFixedArray()) {
12816     if (break_point_info->break_point_objects() == *break_point_object) {
12817       break_point_info->set_break_point_objects(
12818           isolate->heap()->undefined_value());
12819     }
12820     return;
12821   }
12822   // If there are multiple break points shrink the array
12823   ASSERT(break_point_info->break_point_objects()->IsFixedArray());
12824   Handle<FixedArray> old_array =
12825       Handle<FixedArray>(
12826           FixedArray::cast(break_point_info->break_point_objects()));
12827   Handle<FixedArray> new_array =
12828       isolate->factory()->NewFixedArray(old_array->length() - 1);
12829   int found_count = 0;
12830   for (int i = 0; i < old_array->length(); i++) {
12831     if (old_array->get(i) == *break_point_object) {
12832       ASSERT(found_count == 0);
12833       found_count++;
12834     } else {
12835       new_array->set(i - found_count, old_array->get(i));
12836     }
12837   }
12838   // If the break point was found in the list change it.
12839   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
12840 }
12841
12842
12843 // Add the specified break point object.
12844 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
12845                                    Handle<Object> break_point_object) {
12846   // If there was no break point objects before just set it.
12847   if (break_point_info->break_point_objects()->IsUndefined()) {
12848     break_point_info->set_break_point_objects(*break_point_object);
12849     return;
12850   }
12851   // If the break point object is the same as before just ignore.
12852   if (break_point_info->break_point_objects() == *break_point_object) return;
12853   // If there was one break point object before replace with array.
12854   if (!break_point_info->break_point_objects()->IsFixedArray()) {
12855     Handle<FixedArray> array = FACTORY->NewFixedArray(2);
12856     array->set(0, break_point_info->break_point_objects());
12857     array->set(1, *break_point_object);
12858     break_point_info->set_break_point_objects(*array);
12859     return;
12860   }
12861   // If there was more than one break point before extend array.
12862   Handle<FixedArray> old_array =
12863       Handle<FixedArray>(
12864           FixedArray::cast(break_point_info->break_point_objects()));
12865   Handle<FixedArray> new_array =
12866       FACTORY->NewFixedArray(old_array->length() + 1);
12867   for (int i = 0; i < old_array->length(); i++) {
12868     // If the break point was there before just ignore.
12869     if (old_array->get(i) == *break_point_object) return;
12870     new_array->set(i, old_array->get(i));
12871   }
12872   // Add the new break point.
12873   new_array->set(old_array->length(), *break_point_object);
12874   break_point_info->set_break_point_objects(*new_array);
12875 }
12876
12877
12878 bool BreakPointInfo::HasBreakPointObject(
12879     Handle<BreakPointInfo> break_point_info,
12880     Handle<Object> break_point_object) {
12881   // No break point.
12882   if (break_point_info->break_point_objects()->IsUndefined()) return false;
12883   // Single break point.
12884   if (!break_point_info->break_point_objects()->IsFixedArray()) {
12885     return break_point_info->break_point_objects() == *break_point_object;
12886   }
12887   // Multiple break points.
12888   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
12889   for (int i = 0; i < array->length(); i++) {
12890     if (array->get(i) == *break_point_object) {
12891       return true;
12892     }
12893   }
12894   return false;
12895 }
12896
12897
12898 // Get the number of break points.
12899 int BreakPointInfo::GetBreakPointCount() {
12900   // No break point.
12901   if (break_point_objects()->IsUndefined()) return 0;
12902   // Single break point.
12903   if (!break_point_objects()->IsFixedArray()) return 1;
12904   // Multiple break points.
12905   return FixedArray::cast(break_point_objects())->length();
12906 }
12907 #endif  // ENABLE_DEBUGGER_SUPPORT
12908
12909
12910 Object* JSDate::GetField(Object* object, Smi* index) {
12911   return JSDate::cast(object)->DoGetField(
12912       static_cast<FieldIndex>(index->value()));
12913 }
12914
12915
12916 Object* JSDate::DoGetField(FieldIndex index) {
12917   ASSERT(index != kDateValue);
12918
12919   DateCache* date_cache = GetIsolate()->date_cache();
12920
12921   if (index < kFirstUncachedField) {
12922     Object* stamp = cache_stamp();
12923     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
12924       // Since the stamp is not NaN, the value is also not NaN.
12925       int64_t local_time_ms =
12926           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
12927       SetLocalFields(local_time_ms, date_cache);
12928     }
12929     switch (index) {
12930       case kYear: return year();
12931       case kMonth: return month();
12932       case kDay: return day();
12933       case kWeekday: return weekday();
12934       case kHour: return hour();
12935       case kMinute: return min();
12936       case kSecond: return sec();
12937       default: UNREACHABLE();
12938     }
12939   }
12940
12941   if (index >= kFirstUTCField) {
12942     return GetUTCField(index, value()->Number(), date_cache);
12943   }
12944
12945   double time = value()->Number();
12946   if (isnan(time)) return GetIsolate()->heap()->nan_value();
12947
12948   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
12949   int days = DateCache::DaysFromTime(local_time_ms);
12950
12951   if (index == kDays) return Smi::FromInt(days);
12952
12953   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
12954   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
12955   ASSERT(index == kTimeInDay);
12956   return Smi::FromInt(time_in_day_ms);
12957 }
12958
12959
12960 Object* JSDate::GetUTCField(FieldIndex index,
12961                             double value,
12962                             DateCache* date_cache) {
12963   ASSERT(index >= kFirstUTCField);
12964
12965   if (isnan(value)) return GetIsolate()->heap()->nan_value();
12966
12967   int64_t time_ms = static_cast<int64_t>(value);
12968
12969   if (index == kTimezoneOffset) {
12970     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
12971   }
12972
12973   int days = DateCache::DaysFromTime(time_ms);
12974
12975   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
12976
12977   if (index <= kDayUTC) {
12978     int year, month, day;
12979     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
12980     if (index == kYearUTC) return Smi::FromInt(year);
12981     if (index == kMonthUTC) return Smi::FromInt(month);
12982     ASSERT(index == kDayUTC);
12983     return Smi::FromInt(day);
12984   }
12985
12986   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
12987   switch (index) {
12988     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
12989     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
12990     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
12991     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
12992     case kDaysUTC: return Smi::FromInt(days);
12993     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
12994     default: UNREACHABLE();
12995   }
12996
12997   UNREACHABLE();
12998   return NULL;
12999 }
13000
13001
13002 void JSDate::SetValue(Object* value, bool is_value_nan) {
13003   set_value(value);
13004   if (is_value_nan) {
13005     HeapNumber* nan = GetIsolate()->heap()->nan_value();
13006     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
13007     set_year(nan, SKIP_WRITE_BARRIER);
13008     set_month(nan, SKIP_WRITE_BARRIER);
13009     set_day(nan, SKIP_WRITE_BARRIER);
13010     set_hour(nan, SKIP_WRITE_BARRIER);
13011     set_min(nan, SKIP_WRITE_BARRIER);
13012     set_sec(nan, SKIP_WRITE_BARRIER);
13013     set_weekday(nan, SKIP_WRITE_BARRIER);
13014   } else {
13015     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
13016   }
13017 }
13018
13019
13020 void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) {
13021   int days = DateCache::DaysFromTime(local_time_ms);
13022   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
13023   int year, month, day;
13024   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
13025   int weekday = date_cache->Weekday(days);
13026   int hour = time_in_day_ms / (60 * 60 * 1000);
13027   int min = (time_in_day_ms / (60 * 1000)) % 60;
13028   int sec = (time_in_day_ms / 1000) % 60;
13029   set_cache_stamp(date_cache->stamp());
13030   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13031   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13032   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13033   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13034   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13035   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13036   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13037 }
13038
13039 } }  // namespace v8::internal