1// Copyright 2006-2009 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 "debug.h"
34#include "execution.h"
35#include "objects-inl.h"
36#include "macro-assembler.h"
37#include "scanner.h"
38#include "scopeinfo.h"
39#include "string-stream.h"
40#include "utils.h"
41
42#ifdef ENABLE_DISASSEMBLER
43#include "disassembler.h"
44#endif
45
46
47namespace v8 {
48namespace internal {
49
50// Getters and setters are stored in a fixed array property.  These are
51// constants for their indices.
52const int kGetterIndex = 0;
53const int kSetterIndex = 1;
54
55
56static Object* CreateJSValue(JSFunction* constructor, Object* value) {
57  Object* result = Heap::AllocateJSObject(constructor);
58  if (result->IsFailure()) return result;
59  JSValue::cast(result)->set_value(value);
60  return result;
61}
62
63
64Object* Object::ToObject(Context* global_context) {
65  if (IsNumber()) {
66    return CreateJSValue(global_context->number_function(), this);
67  } else if (IsBoolean()) {
68    return CreateJSValue(global_context->boolean_function(), this);
69  } else if (IsString()) {
70    return CreateJSValue(global_context->string_function(), this);
71  }
72  ASSERT(IsJSObject());
73  return this;
74}
75
76
77Object* Object::ToObject() {
78  Context* global_context = Top::context()->global_context();
79  if (IsJSObject()) {
80    return this;
81  } else if (IsNumber()) {
82    return CreateJSValue(global_context->number_function(), this);
83  } else if (IsBoolean()) {
84    return CreateJSValue(global_context->boolean_function(), this);
85  } else if (IsString()) {
86    return CreateJSValue(global_context->string_function(), this);
87  }
88
89  // Throw a type error.
90  return Failure::InternalError();
91}
92
93
94Object* Object::ToBoolean() {
95  if (IsTrue()) return Heap::true_value();
96  if (IsFalse()) return Heap::false_value();
97  if (IsSmi()) {
98    return Heap::ToBoolean(Smi::cast(this)->value() != 0);
99  }
100  if (IsUndefined() || IsNull()) return Heap::false_value();
101  // Undetectable object is false
102  if (IsUndetectableObject()) {
103    return Heap::false_value();
104  }
105  if (IsString()) {
106    return Heap::ToBoolean(String::cast(this)->length() != 0);
107  }
108  if (IsHeapNumber()) {
109    return HeapNumber::cast(this)->HeapNumberToBoolean();
110  }
111  return Heap::true_value();
112}
113
114
115void Object::Lookup(String* name, LookupResult* result) {
116  if (IsJSObject()) return JSObject::cast(this)->Lookup(name, result);
117  Object* holder = NULL;
118  Context* global_context = Top::context()->global_context();
119  if (IsString()) {
120    holder = global_context->string_function()->instance_prototype();
121  } else if (IsNumber()) {
122    holder = global_context->number_function()->instance_prototype();
123  } else if (IsBoolean()) {
124    holder = global_context->boolean_function()->instance_prototype();
125  }
126  ASSERT(holder != NULL);  // Cannot handle null or undefined.
127  JSObject::cast(holder)->Lookup(name, result);
128}
129
130
131Object* Object::GetPropertyWithReceiver(Object* receiver,
132                                        String* name,
133                                        PropertyAttributes* attributes) {
134  LookupResult result;
135  Lookup(name, &result);
136  Object* value = GetProperty(receiver, &result, name, attributes);
137  ASSERT(*attributes <= ABSENT);
138  return value;
139}
140
141
142Object* Object::GetPropertyWithCallback(Object* receiver,
143                                        Object* structure,
144                                        String* name,
145                                        Object* holder) {
146  // To accommodate both the old and the new api we switch on the
147  // data structure used to store the callbacks.  Eventually proxy
148  // callbacks should be phased out.
149  if (structure->IsProxy()) {
150    AccessorDescriptor* callback =
151        reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy());
152    Object* value = (callback->getter)(receiver, callback->data);
153    RETURN_IF_SCHEDULED_EXCEPTION();
154    return value;
155  }
156
157  // api style callbacks.
158  if (structure->IsAccessorInfo()) {
159    AccessorInfo* data = AccessorInfo::cast(structure);
160    Object* fun_obj = data->getter();
161    v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
162    HandleScope scope;
163    JSObject* self = JSObject::cast(receiver);
164    JSObject* holder_handle = JSObject::cast(holder);
165    Handle<String> key(name);
166    LOG(ApiNamedPropertyAccess("load", self, name));
167    CustomArguments args(data->data(), self, holder_handle);
168    v8::AccessorInfo info(args.end());
169    v8::Handle<v8::Value> result;
170    {
171      // Leaving JavaScript.
172      VMState state(EXTERNAL);
173      result = call_fun(v8::Utils::ToLocal(key), info);
174    }
175    RETURN_IF_SCHEDULED_EXCEPTION();
176    if (result.IsEmpty()) return Heap::undefined_value();
177    return *v8::Utils::OpenHandle(*result);
178  }
179
180  // __defineGetter__ callback
181  if (structure->IsFixedArray()) {
182    Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
183    if (getter->IsJSFunction()) {
184      return Object::GetPropertyWithDefinedGetter(receiver,
185                                                  JSFunction::cast(getter));
186    }
187    // Getter is not a function.
188    return Heap::undefined_value();
189  }
190
191  UNREACHABLE();
192  return 0;
193}
194
195
196Object* Object::GetPropertyWithDefinedGetter(Object* receiver,
197                                             JSFunction* getter) {
198  HandleScope scope;
199  Handle<JSFunction> fun(JSFunction::cast(getter));
200  Handle<Object> self(receiver);
201#ifdef ENABLE_DEBUGGER_SUPPORT
202  // Handle stepping into a getter if step into is active.
203  if (Debug::StepInActive()) {
204    Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false);
205  }
206#endif
207  bool has_pending_exception;
208  Handle<Object> result =
209      Execution::Call(fun, self, 0, NULL, &has_pending_exception);
210  // Check for pending exception and return the result.
211  if (has_pending_exception) return Failure::Exception();
212  return *result;
213}
214
215
216// Only deal with CALLBACKS and INTERCEPTOR
217Object* JSObject::GetPropertyWithFailedAccessCheck(
218    Object* receiver,
219    LookupResult* result,
220    String* name,
221    PropertyAttributes* attributes) {
222  if (result->IsProperty()) {
223    switch (result->type()) {
224      case CALLBACKS: {
225        // Only allow API accessors.
226        Object* obj = result->GetCallbackObject();
227        if (obj->IsAccessorInfo()) {
228          AccessorInfo* info = AccessorInfo::cast(obj);
229          if (info->all_can_read()) {
230            *attributes = result->GetAttributes();
231            return GetPropertyWithCallback(receiver,
232                                           result->GetCallbackObject(),
233                                           name,
234                                           result->holder());
235          }
236        }
237        break;
238      }
239      case NORMAL:
240      case FIELD:
241      case CONSTANT_FUNCTION: {
242        // Search ALL_CAN_READ accessors in prototype chain.
243        LookupResult r;
244        result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
245        if (r.IsProperty()) {
246          return GetPropertyWithFailedAccessCheck(receiver,
247                                                  &r,
248                                                  name,
249                                                  attributes);
250        }
251        break;
252      }
253      case INTERCEPTOR: {
254        // If the object has an interceptor, try real named properties.
255        // No access check in GetPropertyAttributeWithInterceptor.
256        LookupResult r;
257        result->holder()->LookupRealNamedProperty(name, &r);
258        if (r.IsProperty()) {
259          return GetPropertyWithFailedAccessCheck(receiver,
260                                                  &r,
261                                                  name,
262                                                  attributes);
263        }
264        break;
265      }
266      default:
267        UNREACHABLE();
268    }
269  }
270
271  // No accessible property found.
272  *attributes = ABSENT;
273  Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
274  return Heap::undefined_value();
275}
276
277
278PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
279    Object* receiver,
280    LookupResult* result,
281    String* name,
282    bool continue_search) {
283  if (result->IsProperty()) {
284    switch (result->type()) {
285      case CALLBACKS: {
286        // Only allow API accessors.
287        Object* obj = result->GetCallbackObject();
288        if (obj->IsAccessorInfo()) {
289          AccessorInfo* info = AccessorInfo::cast(obj);
290          if (info->all_can_read()) {
291            return result->GetAttributes();
292          }
293        }
294        break;
295      }
296
297      case NORMAL:
298      case FIELD:
299      case CONSTANT_FUNCTION: {
300        if (!continue_search) break;
301        // Search ALL_CAN_READ accessors in prototype chain.
302        LookupResult r;
303        result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
304        if (r.IsProperty()) {
305          return GetPropertyAttributeWithFailedAccessCheck(receiver,
306                                                           &r,
307                                                           name,
308                                                           continue_search);
309        }
310        break;
311      }
312
313      case INTERCEPTOR: {
314        // If the object has an interceptor, try real named properties.
315        // No access check in GetPropertyAttributeWithInterceptor.
316        LookupResult r;
317        if (continue_search) {
318          result->holder()->LookupRealNamedProperty(name, &r);
319        } else {
320          result->holder()->LocalLookupRealNamedProperty(name, &r);
321        }
322        if (r.IsProperty()) {
323          return GetPropertyAttributeWithFailedAccessCheck(receiver,
324                                                           &r,
325                                                           name,
326                                                           continue_search);
327        }
328        break;
329      }
330
331      default:
332        UNREACHABLE();
333    }
334  }
335
336  Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
337  return ABSENT;
338}
339
340
341Object* JSObject::GetNormalizedProperty(LookupResult* result) {
342  ASSERT(!HasFastProperties());
343  Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
344  if (IsGlobalObject()) {
345    value = JSGlobalPropertyCell::cast(value)->value();
346  }
347  ASSERT(!value->IsJSGlobalPropertyCell());
348  return value;
349}
350
351
352Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
353  ASSERT(!HasFastProperties());
354  if (IsGlobalObject()) {
355    JSGlobalPropertyCell* cell =
356        JSGlobalPropertyCell::cast(
357            property_dictionary()->ValueAt(result->GetDictionaryEntry()));
358    cell->set_value(value);
359  } else {
360    property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
361  }
362  return value;
363}
364
365
366Object* JSObject::SetNormalizedProperty(String* name,
367                                        Object* value,
368                                        PropertyDetails details) {
369  ASSERT(!HasFastProperties());
370  int entry = property_dictionary()->FindEntry(name);
371  if (entry == StringDictionary::kNotFound) {
372    Object* store_value = value;
373    if (IsGlobalObject()) {
374      store_value = Heap::AllocateJSGlobalPropertyCell(value);
375      if (store_value->IsFailure()) return store_value;
376    }
377    Object* dict = property_dictionary()->Add(name, store_value, details);
378    if (dict->IsFailure()) return dict;
379    set_properties(StringDictionary::cast(dict));
380    return value;
381  }
382  // Preserve enumeration index.
383  details = PropertyDetails(details.attributes(),
384                            details.type(),
385                            property_dictionary()->DetailsAt(entry).index());
386  if (IsGlobalObject()) {
387    JSGlobalPropertyCell* cell =
388        JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
389    cell->set_value(value);
390    // Please note we have to update the property details.
391    property_dictionary()->DetailsAtPut(entry, details);
392  } else {
393    property_dictionary()->SetEntry(entry, name, value, details);
394  }
395  return value;
396}
397
398
399Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
400  ASSERT(!HasFastProperties());
401  StringDictionary* dictionary = property_dictionary();
402  int entry = dictionary->FindEntry(name);
403  if (entry != StringDictionary::kNotFound) {
404    // If we have a global object set the cell to the hole.
405    if (IsGlobalObject()) {
406      PropertyDetails details = dictionary->DetailsAt(entry);
407      if (details.IsDontDelete()) {
408        if (mode != FORCE_DELETION) return Heap::false_value();
409        // When forced to delete global properties, we have to make a
410        // map change to invalidate any ICs that think they can load
411        // from the DontDelete cell without checking if it contains
412        // the hole value.
413        Object* new_map = map()->CopyDropDescriptors();
414        if (new_map->IsFailure()) return new_map;
415        set_map(Map::cast(new_map));
416      }
417      JSGlobalPropertyCell* cell =
418          JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
419      cell->set_value(Heap::the_hole_value());
420      dictionary->DetailsAtPut(entry, details.AsDeleted());
421    } else {
422      return dictionary->DeleteProperty(entry, mode);
423    }
424  }
425  return Heap::true_value();
426}
427
428
429bool JSObject::IsDirty() {
430  Object* cons_obj = map()->constructor();
431  if (!cons_obj->IsJSFunction())
432    return true;
433  JSFunction* fun = JSFunction::cast(cons_obj);
434  if (!fun->shared()->function_data()->IsFunctionTemplateInfo())
435    return true;
436  // If the object is fully fast case and has the same map it was
437  // created with then no changes can have been made to it.
438  return map() != fun->initial_map()
439      || !HasFastElements()
440      || !HasFastProperties();
441}
442
443
444Object* Object::GetProperty(Object* receiver,
445                            LookupResult* result,
446                            String* name,
447                            PropertyAttributes* attributes) {
448  // Make sure that the top context does not change when doing
449  // callbacks or interceptor calls.
450  AssertNoContextChange ncc;
451
452  // Traverse the prototype chain from the current object (this) to
453  // the holder and check for access rights. This avoid traversing the
454  // objects more than once in case of interceptors, because the
455  // holder will always be the interceptor holder and the search may
456  // only continue with a current object just after the interceptor
457  // holder in the prototype chain.
458  Object* last = result->IsProperty() ? result->holder() : Heap::null_value();
459  for (Object* current = this; true; current = current->GetPrototype()) {
460    if (current->IsAccessCheckNeeded()) {
461      // Check if we're allowed to read from the current object. Note
462      // that even though we may not actually end up loading the named
463      // property from the current object, we still check that we have
464      // access to it.
465      JSObject* checked = JSObject::cast(current);
466      if (!Top::MayNamedAccess(checked, name, v8::ACCESS_GET)) {
467        return checked->GetPropertyWithFailedAccessCheck(receiver,
468                                                         result,
469                                                         name,
470                                                         attributes);
471      }
472    }
473    // Stop traversing the chain once we reach the last object in the
474    // chain; either the holder of the result or null in case of an
475    // absent property.
476    if (current == last) break;
477  }
478
479  if (!result->IsProperty()) {
480    *attributes = ABSENT;
481    return Heap::undefined_value();
482  }
483  *attributes = result->GetAttributes();
484  Object* value;
485  JSObject* holder = result->holder();
486  switch (result->type()) {
487    case NORMAL:
488      value = holder->GetNormalizedProperty(result);
489      ASSERT(!value->IsTheHole() || result->IsReadOnly());
490      return value->IsTheHole() ? Heap::undefined_value() : value;
491    case FIELD:
492      value = holder->FastPropertyAt(result->GetFieldIndex());
493      ASSERT(!value->IsTheHole() || result->IsReadOnly());
494      return value->IsTheHole() ? Heap::undefined_value() : value;
495    case CONSTANT_FUNCTION:
496      return result->GetConstantFunction();
497    case CALLBACKS:
498      return GetPropertyWithCallback(receiver,
499                                     result->GetCallbackObject(),
500                                     name,
501                                     holder);
502    case INTERCEPTOR: {
503      JSObject* recvr = JSObject::cast(receiver);
504      return holder->GetPropertyWithInterceptor(recvr, name, attributes);
505    }
506    default:
507      UNREACHABLE();
508      return NULL;
509  }
510}
511
512
513Object* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
514  // Non-JS objects do not have integer indexed properties.
515  if (!IsJSObject()) return Heap::undefined_value();
516  return JSObject::cast(this)->GetElementWithReceiver(JSObject::cast(receiver),
517                                                      index);
518}
519
520
521Object* Object::GetPrototype() {
522  // The object is either a number, a string, a boolean, or a real JS object.
523  if (IsJSObject()) return JSObject::cast(this)->map()->prototype();
524  Context* context = Top::context()->global_context();
525
526  if (IsNumber()) return context->number_function()->instance_prototype();
527  if (IsString()) return context->string_function()->instance_prototype();
528  if (IsBoolean()) {
529    return context->boolean_function()->instance_prototype();
530  } else {
531    return Heap::null_value();
532  }
533}
534
535
536void Object::ShortPrint() {
537  HeapStringAllocator allocator;
538  StringStream accumulator(&allocator);
539  ShortPrint(&accumulator);
540  accumulator.OutputToStdOut();
541}
542
543
544void Object::ShortPrint(StringStream* accumulator) {
545  if (IsSmi()) {
546    Smi::cast(this)->SmiPrint(accumulator);
547  } else if (IsFailure()) {
548    Failure::cast(this)->FailurePrint(accumulator);
549  } else {
550    HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
551  }
552}
553
554
555void Smi::SmiPrint() {
556  PrintF("%d", value());
557}
558
559
560void Smi::SmiPrint(StringStream* accumulator) {
561  accumulator->Add("%d", value());
562}
563
564
565void Failure::FailurePrint(StringStream* accumulator) {
566  accumulator->Add("Failure(%p)", reinterpret_cast<void*>(value()));
567}
568
569
570void Failure::FailurePrint() {
571  PrintF("Failure(%p)", reinterpret_cast<void*>(value()));
572}
573
574
575Failure* Failure::RetryAfterGC(int requested_bytes, AllocationSpace space) {
576  ASSERT((space & ~kSpaceTagMask) == 0);
577  // TODO(X64): Stop using Smi validation for non-smi checks, even if they
578  // happen to be identical at the moment.
579
580  int requested = requested_bytes >> kObjectAlignmentBits;
581  int value = (requested << kSpaceTagSize) | space;
582  // We can't very well allocate a heap number in this situation, and if the
583  // requested memory is so large it seems reasonable to say that this is an
584  // out of memory situation.  This fixes a crash in
585  // js1_5/Regress/regress-303213.js.
586  if (value >> kSpaceTagSize != requested ||
587      !Smi::IsValid(value) ||
588      value != ((value << kFailureTypeTagSize) >> kFailureTypeTagSize) ||
589      !Smi::IsValid(value << kFailureTypeTagSize)) {
590    Top::context()->mark_out_of_memory();
591    return Failure::OutOfMemoryException();
592  }
593  return Construct(RETRY_AFTER_GC, value);
594}
595
596
597// Should a word be prefixed by 'a' or 'an' in order to read naturally in
598// English?  Returns false for non-ASCII or words that don't start with
599// a capital letter.  The a/an rule follows pronunciation in English.
600// We don't use the BBC's overcorrect "an historic occasion" though if
601// you speak a dialect you may well say "an 'istoric occasion".
602static bool AnWord(String* str) {
603  if (str->length() == 0) return false;  // A nothing.
604  int c0 = str->Get(0);
605  int c1 = str->length() > 1 ? str->Get(1) : 0;
606  if (c0 == 'U') {
607    if (c1 > 'Z') {
608      return true;  // An Umpire, but a UTF8String, a U.
609    }
610  } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
611    return true;    // An Ape, an ABCBook.
612  } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
613           (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
614            c0 == 'S' || c0 == 'X')) {
615    return true;    // An MP3File, an M.
616  }
617  return false;
618}
619
620
621Object* String::TryFlatten() {
622#ifdef DEBUG
623  // Do not attempt to flatten in debug mode when allocation is not
624  // allowed.  This is to avoid an assertion failure when allocating.
625  // Flattening strings is the only case where we always allow
626  // allocation because no GC is performed if the allocation fails.
627  if (!Heap::IsAllocationAllowed()) return this;
628#endif
629
630  switch (StringShape(this).representation_tag()) {
631    case kConsStringTag: {
632      ConsString* cs = ConsString::cast(this);
633      if (cs->second()->length() == 0) {
634        return this;
635      }
636      // There's little point in putting the flat string in new space if the
637      // cons string is in old space.  It can never get GCed until there is
638      // an old space GC.
639      PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
640      int len = length();
641      Object* object;
642      String* result;
643      if (IsAsciiRepresentation()) {
644        object = Heap::AllocateRawAsciiString(len, tenure);
645        if (object->IsFailure()) return object;
646        result = String::cast(object);
647        String* first = cs->first();
648        int first_length = first->length();
649        char* dest = SeqAsciiString::cast(result)->GetChars();
650        WriteToFlat(first, dest, 0, first_length);
651        String* second = cs->second();
652        WriteToFlat(second,
653                    dest + first_length,
654                    0,
655                    len - first_length);
656      } else {
657        object = Heap::AllocateRawTwoByteString(len, tenure);
658        if (object->IsFailure()) return object;
659        result = String::cast(object);
660        uc16* dest = SeqTwoByteString::cast(result)->GetChars();
661        String* first = cs->first();
662        int first_length = first->length();
663        WriteToFlat(first, dest, 0, first_length);
664        String* second = cs->second();
665        WriteToFlat(second,
666                    dest + first_length,
667                    0,
668                    len - first_length);
669      }
670      cs->set_first(result);
671      cs->set_second(Heap::empty_string());
672      return this;
673    }
674    default:
675      return this;
676  }
677}
678
679
680bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
681#ifdef DEBUG
682  if (FLAG_enable_slow_asserts) {
683    // Assert that the resource and the string are equivalent.
684    ASSERT(static_cast<size_t>(this->length()) == resource->length());
685    SmartPointer<uc16> smart_chars(NewArray<uc16>(this->length()));
686    String::WriteToFlat(this, *smart_chars, 0, this->length());
687    ASSERT(memcmp(*smart_chars,
688                  resource->data(),
689                  resource->length() * sizeof(**smart_chars)) == 0);
690  }
691#endif  // DEBUG
692
693  int size = this->Size();  // Byte size of the original string.
694  if (size < ExternalString::kSize) {
695    // The string is too small to fit an external String in its place. This can
696    // only happen for zero length strings.
697    return false;
698  }
699  ASSERT(size >= ExternalString::kSize);
700  bool is_symbol = this->IsSymbol();
701  int length = this->length();
702  int hash_field = this->hash_field();
703
704  // Morph the object to an external string by adjusting the map and
705  // reinitializing the fields.
706  this->set_map(Heap::external_string_map());
707  ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
708  self->set_length(length);
709  self->set_hash_field(hash_field);
710  self->set_resource(resource);
711  // Additionally make the object into an external symbol if the original string
712  // was a symbol to start with.
713  if (is_symbol) {
714    self->Hash();  // Force regeneration of the hash value.
715    // Now morph this external string into a external symbol.
716    this->set_map(Heap::external_symbol_map());
717  }
718
719  // Fill the remainder of the string with dead wood.
720  int new_size = this->Size();  // Byte size of the external String object.
721  Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size);
722  return true;
723}
724
725
726bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
727#ifdef DEBUG
728  if (FLAG_enable_slow_asserts) {
729    // Assert that the resource and the string are equivalent.
730    ASSERT(static_cast<size_t>(this->length()) == resource->length());
731    SmartPointer<char> smart_chars(NewArray<char>(this->length()));
732    String::WriteToFlat(this, *smart_chars, 0, this->length());
733    ASSERT(memcmp(*smart_chars,
734                  resource->data(),
735                  resource->length()*sizeof(**smart_chars)) == 0);
736  }
737#endif  // DEBUG
738
739  int size = this->Size();  // Byte size of the original string.
740  if (size < ExternalString::kSize) {
741    // The string is too small to fit an external String in its place. This can
742    // only happen for zero length strings.
743    return false;
744  }
745  ASSERT(size >= ExternalString::kSize);
746  bool is_symbol = this->IsSymbol();
747  int length = this->length();
748  int hash_field = this->hash_field();
749
750  // Morph the object to an external string by adjusting the map and
751  // reinitializing the fields.
752  this->set_map(Heap::external_ascii_string_map());
753  ExternalAsciiString* self = ExternalAsciiString::cast(this);
754  self->set_length(length);
755  self->set_hash_field(hash_field);
756  self->set_resource(resource);
757  // Additionally make the object into an external symbol if the original string
758  // was a symbol to start with.
759  if (is_symbol) {
760    self->Hash();  // Force regeneration of the hash value.
761    // Now morph this external string into a external symbol.
762    this->set_map(Heap::external_ascii_symbol_map());
763  }
764
765  // Fill the remainder of the string with dead wood.
766  int new_size = this->Size();  // Byte size of the external String object.
767  Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size);
768  return true;
769}
770
771
772void String::StringShortPrint(StringStream* accumulator) {
773  int len = length();
774  if (len > kMaxShortPrintLength) {
775    accumulator->Add("<Very long string[%u]>", len);
776    return;
777  }
778
779  if (!LooksValid()) {
780    accumulator->Add("<Invalid String>");
781    return;
782  }
783
784  StringInputBuffer buf(this);
785
786  bool truncated = false;
787  if (len > kMaxShortPrintLength) {
788    len = kMaxShortPrintLength;
789    truncated = true;
790  }
791  bool ascii = true;
792  for (int i = 0; i < len; i++) {
793    int c = buf.GetNext();
794
795    if (c < 32 || c >= 127) {
796      ascii = false;
797    }
798  }
799  buf.Reset(this);
800  if (ascii) {
801    accumulator->Add("<String[%u]: ", length());
802    for (int i = 0; i < len; i++) {
803      accumulator->Put(buf.GetNext());
804    }
805    accumulator->Put('>');
806  } else {
807    // Backslash indicates that the string contains control
808    // characters and that backslashes are therefore escaped.
809    accumulator->Add("<String[%u]\\: ", length());
810    for (int i = 0; i < len; i++) {
811      int c = buf.GetNext();
812      if (c == '\n') {
813        accumulator->Add("\\n");
814      } else if (c == '\r') {
815        accumulator->Add("\\r");
816      } else if (c == '\\') {
817        accumulator->Add("\\\\");
818      } else if (c < 32 || c > 126) {
819        accumulator->Add("\\x%02x", c);
820      } else {
821        accumulator->Put(c);
822      }
823    }
824    if (truncated) {
825      accumulator->Put('.');
826      accumulator->Put('.');
827      accumulator->Put('.');
828    }
829    accumulator->Put('>');
830  }
831  return;
832}
833
834
835void JSObject::JSObjectShortPrint(StringStream* accumulator) {
836  switch (map()->instance_type()) {
837    case JS_ARRAY_TYPE: {
838      double length = JSArray::cast(this)->length()->Number();
839      accumulator->Add("<JS array[%u]>", static_cast<uint32_t>(length));
840      break;
841    }
842    case JS_REGEXP_TYPE: {
843      accumulator->Add("<JS RegExp>");
844      break;
845    }
846    case JS_FUNCTION_TYPE: {
847      Object* fun_name = JSFunction::cast(this)->shared()->name();
848      bool printed = false;
849      if (fun_name->IsString()) {
850        String* str = String::cast(fun_name);
851        if (str->length() > 0) {
852          accumulator->Add("<JS Function ");
853          accumulator->Put(str);
854          accumulator->Put('>');
855          printed = true;
856        }
857      }
858      if (!printed) {
859        accumulator->Add("<JS Function>");
860      }
861      break;
862    }
863    // All other JSObjects are rather similar to each other (JSObject,
864    // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
865    default: {
866      Object* constructor = map()->constructor();
867      bool printed = false;
868      if (constructor->IsHeapObject() &&
869          !Heap::Contains(HeapObject::cast(constructor))) {
870        accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
871      } else {
872        bool global_object = IsJSGlobalProxy();
873        if (constructor->IsJSFunction()) {
874          if (!Heap::Contains(JSFunction::cast(constructor)->shared())) {
875            accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
876          } else {
877            Object* constructor_name =
878                JSFunction::cast(constructor)->shared()->name();
879            if (constructor_name->IsString()) {
880              String* str = String::cast(constructor_name);
881              if (str->length() > 0) {
882                bool vowel = AnWord(str);
883                accumulator->Add("<%sa%s ",
884                       global_object ? "Global Object: " : "",
885                       vowel ? "n" : "");
886                accumulator->Put(str);
887                accumulator->Put('>');
888                printed = true;
889              }
890            }
891          }
892        }
893        if (!printed) {
894          accumulator->Add("<JS %sObject", global_object ? "Global " : "");
895        }
896      }
897      if (IsJSValue()) {
898        accumulator->Add(" value = ");
899        JSValue::cast(this)->value()->ShortPrint(accumulator);
900      }
901      accumulator->Put('>');
902      break;
903    }
904  }
905}
906
907
908void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
909  // if (!Heap::InNewSpace(this)) PrintF("*", this);
910  if (!Heap::Contains(this)) {
911    accumulator->Add("!!!INVALID POINTER!!!");
912    return;
913  }
914  if (!Heap::Contains(map())) {
915    accumulator->Add("!!!INVALID MAP!!!");
916    return;
917  }
918
919  accumulator->Add("%p ", this);
920
921  if (IsString()) {
922    String::cast(this)->StringShortPrint(accumulator);
923    return;
924  }
925  if (IsJSObject()) {
926    JSObject::cast(this)->JSObjectShortPrint(accumulator);
927    return;
928  }
929  switch (map()->instance_type()) {
930    case MAP_TYPE:
931      accumulator->Add("<Map>");
932      break;
933    case FIXED_ARRAY_TYPE:
934      accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
935      break;
936    case BYTE_ARRAY_TYPE:
937      accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
938      break;
939    case PIXEL_ARRAY_TYPE:
940      accumulator->Add("<PixelArray[%u]>", PixelArray::cast(this)->length());
941      break;
942    case EXTERNAL_BYTE_ARRAY_TYPE:
943      accumulator->Add("<ExternalByteArray[%u]>",
944                       ExternalByteArray::cast(this)->length());
945      break;
946    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
947      accumulator->Add("<ExternalUnsignedByteArray[%u]>",
948                       ExternalUnsignedByteArray::cast(this)->length());
949      break;
950    case EXTERNAL_SHORT_ARRAY_TYPE:
951      accumulator->Add("<ExternalShortArray[%u]>",
952                       ExternalShortArray::cast(this)->length());
953      break;
954    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
955      accumulator->Add("<ExternalUnsignedShortArray[%u]>",
956                       ExternalUnsignedShortArray::cast(this)->length());
957      break;
958    case EXTERNAL_INT_ARRAY_TYPE:
959      accumulator->Add("<ExternalIntArray[%u]>",
960                       ExternalIntArray::cast(this)->length());
961      break;
962    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
963      accumulator->Add("<ExternalUnsignedIntArray[%u]>",
964                       ExternalUnsignedIntArray::cast(this)->length());
965      break;
966    case EXTERNAL_FLOAT_ARRAY_TYPE:
967      accumulator->Add("<ExternalFloatArray[%u]>",
968                       ExternalFloatArray::cast(this)->length());
969      break;
970    case SHARED_FUNCTION_INFO_TYPE:
971      accumulator->Add("<SharedFunctionInfo>");
972      break;
973#define MAKE_STRUCT_CASE(NAME, Name, name) \
974  case NAME##_TYPE:                        \
975    accumulator->Put('<');                 \
976    accumulator->Add(#Name);               \
977    accumulator->Put('>');                 \
978    break;
979  STRUCT_LIST(MAKE_STRUCT_CASE)
980#undef MAKE_STRUCT_CASE
981    case CODE_TYPE:
982      accumulator->Add("<Code>");
983      break;
984    case ODDBALL_TYPE: {
985      if (IsUndefined())
986        accumulator->Add("<undefined>");
987      else if (IsTheHole())
988        accumulator->Add("<the hole>");
989      else if (IsNull())
990        accumulator->Add("<null>");
991      else if (IsTrue())
992        accumulator->Add("<true>");
993      else if (IsFalse())
994        accumulator->Add("<false>");
995      else
996        accumulator->Add("<Odd Oddball>");
997      break;
998    }
999    case HEAP_NUMBER_TYPE:
1000      accumulator->Add("<Number: ");
1001      HeapNumber::cast(this)->HeapNumberPrint(accumulator);
1002      accumulator->Put('>');
1003      break;
1004    case PROXY_TYPE:
1005      accumulator->Add("<Proxy>");
1006      break;
1007    case JS_GLOBAL_PROPERTY_CELL_TYPE:
1008      accumulator->Add("Cell for ");
1009      JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
1010      break;
1011    default:
1012      accumulator->Add("<Other heap object (%d)>", map()->instance_type());
1013      break;
1014  }
1015}
1016
1017
1018int HeapObject::SlowSizeFromMap(Map* map) {
1019  // Avoid calling functions such as FixedArray::cast during GC, which
1020  // read map pointer of this object again.
1021  InstanceType instance_type = map->instance_type();
1022  uint32_t type = static_cast<uint32_t>(instance_type);
1023
1024  if (instance_type < FIRST_NONSTRING_TYPE
1025      && (StringShape(instance_type).IsSequential())) {
1026    if ((type & kStringEncodingMask) == kAsciiStringTag) {
1027      SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
1028      return seq_ascii_this->SeqAsciiStringSize(instance_type);
1029    } else {
1030      SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
1031      return self->SeqTwoByteStringSize(instance_type);
1032    }
1033  }
1034
1035  switch (instance_type) {
1036    case FIXED_ARRAY_TYPE:
1037      return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1038    case BYTE_ARRAY_TYPE:
1039      return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
1040    case CODE_TYPE:
1041      return reinterpret_cast<Code*>(this)->CodeSize();
1042    case MAP_TYPE:
1043      return Map::kSize;
1044    default:
1045      return map->instance_size();
1046  }
1047}
1048
1049
1050void HeapObject::Iterate(ObjectVisitor* v) {
1051  // Handle header
1052  IteratePointer(v, kMapOffset);
1053  // Handle object body
1054  Map* m = map();
1055  IterateBody(m->instance_type(), SizeFromMap(m), v);
1056}
1057
1058
1059void HeapObject::IterateBody(InstanceType type, int object_size,
1060                             ObjectVisitor* v) {
1061  // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1062  // During GC, the map pointer field is encoded.
1063  if (type < FIRST_NONSTRING_TYPE) {
1064    switch (type & kStringRepresentationMask) {
1065      case kSeqStringTag:
1066        break;
1067      case kConsStringTag:
1068        reinterpret_cast<ConsString*>(this)->ConsStringIterateBody(v);
1069        break;
1070      case kExternalStringTag:
1071        if ((type & kStringEncodingMask) == kAsciiStringTag) {
1072          reinterpret_cast<ExternalAsciiString*>(this)->
1073              ExternalAsciiStringIterateBody(v);
1074        } else {
1075          reinterpret_cast<ExternalTwoByteString*>(this)->
1076              ExternalTwoByteStringIterateBody(v);
1077        }
1078        break;
1079    }
1080    return;
1081  }
1082
1083  switch (type) {
1084    case FIXED_ARRAY_TYPE:
1085      reinterpret_cast<FixedArray*>(this)->FixedArrayIterateBody(v);
1086      break;
1087    case JS_OBJECT_TYPE:
1088    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1089    case JS_VALUE_TYPE:
1090    case JS_ARRAY_TYPE:
1091    case JS_REGEXP_TYPE:
1092    case JS_FUNCTION_TYPE:
1093    case JS_GLOBAL_PROXY_TYPE:
1094    case JS_GLOBAL_OBJECT_TYPE:
1095    case JS_BUILTINS_OBJECT_TYPE:
1096      reinterpret_cast<JSObject*>(this)->JSObjectIterateBody(object_size, v);
1097      break;
1098    case ODDBALL_TYPE:
1099      reinterpret_cast<Oddball*>(this)->OddballIterateBody(v);
1100      break;
1101    case PROXY_TYPE:
1102      reinterpret_cast<Proxy*>(this)->ProxyIterateBody(v);
1103      break;
1104    case MAP_TYPE:
1105      reinterpret_cast<Map*>(this)->MapIterateBody(v);
1106      break;
1107    case CODE_TYPE:
1108      reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1109      break;
1110    case JS_GLOBAL_PROPERTY_CELL_TYPE:
1111      reinterpret_cast<JSGlobalPropertyCell*>(this)
1112          ->JSGlobalPropertyCellIterateBody(v);
1113      break;
1114    case HEAP_NUMBER_TYPE:
1115    case FILLER_TYPE:
1116    case BYTE_ARRAY_TYPE:
1117    case PIXEL_ARRAY_TYPE:
1118    case EXTERNAL_BYTE_ARRAY_TYPE:
1119    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1120    case EXTERNAL_SHORT_ARRAY_TYPE:
1121    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1122    case EXTERNAL_INT_ARRAY_TYPE:
1123    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1124    case EXTERNAL_FLOAT_ARRAY_TYPE:
1125      break;
1126    case SHARED_FUNCTION_INFO_TYPE: {
1127      SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this);
1128      shared->SharedFunctionInfoIterateBody(v);
1129      break;
1130    }
1131#define MAKE_STRUCT_CASE(NAME, Name, name) \
1132        case NAME##_TYPE:
1133      STRUCT_LIST(MAKE_STRUCT_CASE)
1134#undef MAKE_STRUCT_CASE
1135      IterateStructBody(object_size, v);
1136      break;
1137    default:
1138      PrintF("Unknown type: %d\n", type);
1139      UNREACHABLE();
1140  }
1141}
1142
1143
1144void HeapObject::IterateStructBody(int object_size, ObjectVisitor* v) {
1145  IteratePointers(v, HeapObject::kHeaderSize, object_size);
1146}
1147
1148
1149Object* HeapNumber::HeapNumberToBoolean() {
1150  // NaN, +0, and -0 should return the false object
1151  switch (fpclassify(value())) {
1152    case FP_NAN:  // fall through
1153    case FP_ZERO: return Heap::false_value();
1154    default: return Heap::true_value();
1155  }
1156}
1157
1158
1159void HeapNumber::HeapNumberPrint() {
1160  PrintF("%.16g", Number());
1161}
1162
1163
1164void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
1165  // The Windows version of vsnprintf can allocate when printing a %g string
1166  // into a buffer that may not be big enough.  We don't want random memory
1167  // allocation when producing post-crash stack traces, so we print into a
1168  // buffer that is plenty big enough for any floating point number, then
1169  // print that using vsnprintf (which may truncate but never allocate if
1170  // there is no more space in the buffer).
1171  EmbeddedVector<char, 100> buffer;
1172  OS::SNPrintF(buffer, "%.16g", Number());
1173  accumulator->Add("%s", buffer.start());
1174}
1175
1176
1177String* JSObject::class_name() {
1178  if (IsJSFunction()) {
1179    return Heap::function_class_symbol();
1180  }
1181  if (map()->constructor()->IsJSFunction()) {
1182    JSFunction* constructor = JSFunction::cast(map()->constructor());
1183    return String::cast(constructor->shared()->instance_class_name());
1184  }
1185  // If the constructor is not present, return "Object".
1186  return Heap::Object_symbol();
1187}
1188
1189
1190String* JSObject::constructor_name() {
1191  if (IsJSFunction()) {
1192    return JSFunction::cast(this)->IsBoilerplate() ?
1193      Heap::function_class_symbol() : Heap::closure_symbol();
1194  }
1195  if (map()->constructor()->IsJSFunction()) {
1196    JSFunction* constructor = JSFunction::cast(map()->constructor());
1197    String* name = String::cast(constructor->shared()->name());
1198    return name->length() > 0 ? name : constructor->shared()->inferred_name();
1199  }
1200  // If the constructor is not present, return "Object".
1201  return Heap::Object_symbol();
1202}
1203
1204
1205void JSObject::JSObjectIterateBody(int object_size, ObjectVisitor* v) {
1206  // Iterate over all fields in the body. Assumes all are Object*.
1207  IteratePointers(v, kPropertiesOffset, object_size);
1208}
1209
1210
1211Object* JSObject::AddFastPropertyUsingMap(Map* new_map,
1212                                          String* name,
1213                                          Object* value) {
1214  int index = new_map->PropertyIndexFor(name);
1215  if (map()->unused_property_fields() == 0) {
1216    ASSERT(map()->unused_property_fields() == 0);
1217    int new_unused = new_map->unused_property_fields();
1218    Object* values =
1219        properties()->CopySize(properties()->length() + new_unused + 1);
1220    if (values->IsFailure()) return values;
1221    set_properties(FixedArray::cast(values));
1222  }
1223  set_map(new_map);
1224  return FastPropertyAtPut(index, value);
1225}
1226
1227
1228Object* JSObject::AddFastProperty(String* name,
1229                                  Object* value,
1230                                  PropertyAttributes attributes) {
1231  // Normalize the object if the name is an actual string (not the
1232  // hidden symbols) and is not a real identifier.
1233  StringInputBuffer buffer(name);
1234  if (!Scanner::IsIdentifier(&buffer) && name != Heap::hidden_symbol()) {
1235    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1236    if (obj->IsFailure()) return obj;
1237    return AddSlowProperty(name, value, attributes);
1238  }
1239
1240  DescriptorArray* old_descriptors = map()->instance_descriptors();
1241  // Compute the new index for new field.
1242  int index = map()->NextFreePropertyIndex();
1243
1244  // Allocate new instance descriptors with (name, index) added
1245  FieldDescriptor new_field(name, index, attributes);
1246  Object* new_descriptors =
1247      old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
1248  if (new_descriptors->IsFailure()) return new_descriptors;
1249
1250  // Only allow map transition if the object's map is NOT equal to the
1251  // global object_function's map and there is not a transition for name.
1252  bool allow_map_transition =
1253        !old_descriptors->Contains(name) &&
1254        (Top::context()->global_context()->object_function()->map() != map());
1255
1256  ASSERT(index < map()->inobject_properties() ||
1257         (index - map()->inobject_properties()) < properties()->length() ||
1258         map()->unused_property_fields() == 0);
1259  // Allocate a new map for the object.
1260  Object* r = map()->CopyDropDescriptors();
1261  if (r->IsFailure()) return r;
1262  Map* new_map = Map::cast(r);
1263  if (allow_map_transition) {
1264    // Allocate new instance descriptors for the old map with map transition.
1265    MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
1266    Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
1267    if (r->IsFailure()) return r;
1268    old_descriptors = DescriptorArray::cast(r);
1269  }
1270
1271  if (map()->unused_property_fields() == 0) {
1272    if (properties()->length() > kMaxFastProperties) {
1273      Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1274      if (obj->IsFailure()) return obj;
1275      return AddSlowProperty(name, value, attributes);
1276    }
1277    // Make room for the new value
1278    Object* values =
1279        properties()->CopySize(properties()->length() + kFieldsAdded);
1280    if (values->IsFailure()) return values;
1281    set_properties(FixedArray::cast(values));
1282    new_map->set_unused_property_fields(kFieldsAdded - 1);
1283  } else {
1284    new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
1285  }
1286  // We have now allocated all the necessary objects.
1287  // All the changes can be applied at once, so they are atomic.
1288  map()->set_instance_descriptors(old_descriptors);
1289  new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1290  set_map(new_map);
1291  return FastPropertyAtPut(index, value);
1292}
1293
1294
1295Object* JSObject::AddConstantFunctionProperty(String* name,
1296                                              JSFunction* function,
1297                                              PropertyAttributes attributes) {
1298  ASSERT(!Heap::InNewSpace(function));
1299
1300  // Allocate new instance descriptors with (name, function) added
1301  ConstantFunctionDescriptor d(name, function, attributes);
1302  Object* new_descriptors =
1303      map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS);
1304  if (new_descriptors->IsFailure()) return new_descriptors;
1305
1306  // Allocate a new map for the object.
1307  Object* new_map = map()->CopyDropDescriptors();
1308  if (new_map->IsFailure()) return new_map;
1309
1310  DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
1311  Map::cast(new_map)->set_instance_descriptors(descriptors);
1312  Map* old_map = map();
1313  set_map(Map::cast(new_map));
1314
1315  // If the old map is the global object map (from new Object()),
1316  // then transitions are not added to it, so we are done.
1317  if (old_map == Top::context()->global_context()->object_function()->map()) {
1318    return function;
1319  }
1320
1321  // Do not add CONSTANT_TRANSITIONS to global objects
1322  if (IsGlobalObject()) {
1323    return function;
1324  }
1325
1326  // Add a CONSTANT_TRANSITION descriptor to the old map,
1327  // so future assignments to this property on other objects
1328  // of the same type will create a normal field, not a constant function.
1329  // Don't do this for special properties, with non-trival attributes.
1330  if (attributes != NONE) {
1331    return function;
1332  }
1333  ConstTransitionDescriptor mark(name);
1334  new_descriptors =
1335      old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS);
1336  if (new_descriptors->IsFailure()) {
1337    return function;  // We have accomplished the main goal, so return success.
1338  }
1339  old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1340
1341  return function;
1342}
1343
1344
1345// Add property in slow mode
1346Object* JSObject::AddSlowProperty(String* name,
1347                                  Object* value,
1348                                  PropertyAttributes attributes) {
1349  ASSERT(!HasFastProperties());
1350  StringDictionary* dict = property_dictionary();
1351  Object* store_value = value;
1352  if (IsGlobalObject()) {
1353    // In case name is an orphaned property reuse the cell.
1354    int entry = dict->FindEntry(name);
1355    if (entry != StringDictionary::kNotFound) {
1356      store_value = dict->ValueAt(entry);
1357      JSGlobalPropertyCell::cast(store_value)->set_value(value);
1358      // Assign an enumeration index to the property and update
1359      // SetNextEnumerationIndex.
1360      int index = dict->NextEnumerationIndex();
1361      PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
1362      dict->SetNextEnumerationIndex(index + 1);
1363      dict->SetEntry(entry, name, store_value, details);
1364      return value;
1365    }
1366    store_value = Heap::AllocateJSGlobalPropertyCell(value);
1367    if (store_value->IsFailure()) return store_value;
1368    JSGlobalPropertyCell::cast(store_value)->set_value(value);
1369  }
1370  PropertyDetails details = PropertyDetails(attributes, NORMAL);
1371  Object* result = dict->Add(name, store_value, details);
1372  if (result->IsFailure()) return result;
1373  if (dict != result) set_properties(StringDictionary::cast(result));
1374  return value;
1375}
1376
1377
1378Object* JSObject::AddProperty(String* name,
1379                              Object* value,
1380                              PropertyAttributes attributes) {
1381  ASSERT(!IsJSGlobalProxy());
1382  if (HasFastProperties()) {
1383    // Ensure the descriptor array does not get too big.
1384    if (map()->instance_descriptors()->number_of_descriptors() <
1385        DescriptorArray::kMaxNumberOfDescriptors) {
1386      if (value->IsJSFunction() && !Heap::InNewSpace(value)) {
1387        return AddConstantFunctionProperty(name,
1388                                           JSFunction::cast(value),
1389                                           attributes);
1390      } else {
1391        return AddFastProperty(name, value, attributes);
1392      }
1393    } else {
1394      // Normalize the object to prevent very large instance descriptors.
1395      // This eliminates unwanted N^2 allocation and lookup behavior.
1396      Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1397      if (obj->IsFailure()) return obj;
1398    }
1399  }
1400  return AddSlowProperty(name, value, attributes);
1401}
1402
1403
1404Object* JSObject::SetPropertyPostInterceptor(String* name,
1405                                             Object* value,
1406                                             PropertyAttributes attributes) {
1407  // Check local property, ignore interceptor.
1408  LookupResult result;
1409  LocalLookupRealNamedProperty(name, &result);
1410  if (result.IsFound()) {
1411    // An existing property, a map transition or a null descriptor was
1412    // found.  Use set property to handle all these cases.
1413    return SetProperty(&result, name, value, attributes);
1414  }
1415  // Add a new real property.
1416  return AddProperty(name, value, attributes);
1417}
1418
1419
1420Object* JSObject::ReplaceSlowProperty(String* name,
1421                                      Object* value,
1422                                      PropertyAttributes attributes) {
1423  StringDictionary* dictionary = property_dictionary();
1424  int old_index = dictionary->FindEntry(name);
1425  int new_enumeration_index = 0;  // 0 means "Use the next available index."
1426  if (old_index != -1) {
1427    // All calls to ReplaceSlowProperty have had all transitions removed.
1428    ASSERT(!dictionary->DetailsAt(old_index).IsTransition());
1429    new_enumeration_index = dictionary->DetailsAt(old_index).index();
1430  }
1431
1432  PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
1433  return SetNormalizedProperty(name, value, new_details);
1434}
1435
1436
1437Object* JSObject::ConvertDescriptorToFieldAndMapTransition(
1438    String* name,
1439    Object* new_value,
1440    PropertyAttributes attributes) {
1441  Map* old_map = map();
1442  Object* result = ConvertDescriptorToField(name, new_value, attributes);
1443  if (result->IsFailure()) return result;
1444  // If we get to this point we have succeeded - do not return failure
1445  // after this point.  Later stuff is optional.
1446  if (!HasFastProperties()) {
1447    return result;
1448  }
1449  // Do not add transitions to the map of "new Object()".
1450  if (map() == Top::context()->global_context()->object_function()->map()) {
1451    return result;
1452  }
1453
1454  MapTransitionDescriptor transition(name,
1455                                     map(),
1456                                     attributes);
1457  Object* new_descriptors =
1458      old_map->instance_descriptors()->
1459          CopyInsert(&transition, KEEP_TRANSITIONS);
1460  if (new_descriptors->IsFailure()) return result;  // Yes, return _result_.
1461  old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1462  return result;
1463}
1464
1465
1466Object* JSObject::ConvertDescriptorToField(String* name,
1467                                           Object* new_value,
1468                                           PropertyAttributes attributes) {
1469  if (map()->unused_property_fields() == 0 &&
1470      properties()->length() > kMaxFastProperties) {
1471    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1472    if (obj->IsFailure()) return obj;
1473    return ReplaceSlowProperty(name, new_value, attributes);
1474  }
1475
1476  int index = map()->NextFreePropertyIndex();
1477  FieldDescriptor new_field(name, index, attributes);
1478  // Make a new DescriptorArray replacing an entry with FieldDescriptor.
1479  Object* descriptors_unchecked = map()->instance_descriptors()->
1480      CopyInsert(&new_field, REMOVE_TRANSITIONS);
1481  if (descriptors_unchecked->IsFailure()) return descriptors_unchecked;
1482  DescriptorArray* new_descriptors =
1483      DescriptorArray::cast(descriptors_unchecked);
1484
1485  // Make a new map for the object.
1486  Object* new_map_unchecked = map()->CopyDropDescriptors();
1487  if (new_map_unchecked->IsFailure()) return new_map_unchecked;
1488  Map* new_map = Map::cast(new_map_unchecked);
1489  new_map->set_instance_descriptors(new_descriptors);
1490
1491  // Make new properties array if necessary.
1492  FixedArray* new_properties = 0;  // Will always be NULL or a valid pointer.
1493  int new_unused_property_fields = map()->unused_property_fields() - 1;
1494  if (map()->unused_property_fields() == 0) {
1495     new_unused_property_fields = kFieldsAdded - 1;
1496     Object* new_properties_unchecked =
1497        properties()->CopySize(properties()->length() + kFieldsAdded);
1498    if (new_properties_unchecked->IsFailure()) return new_properties_unchecked;
1499    new_properties = FixedArray::cast(new_properties_unchecked);
1500  }
1501
1502  // Update pointers to commit changes.
1503  // Object points to the new map.
1504  new_map->set_unused_property_fields(new_unused_property_fields);
1505  set_map(new_map);
1506  if (new_properties) {
1507    set_properties(FixedArray::cast(new_properties));
1508  }
1509  return FastPropertyAtPut(index, new_value);
1510}
1511
1512
1513
1514Object* JSObject::SetPropertyWithInterceptor(String* name,
1515                                             Object* value,
1516                                             PropertyAttributes attributes) {
1517  HandleScope scope;
1518  Handle<JSObject> this_handle(this);
1519  Handle<String> name_handle(name);
1520  Handle<Object> value_handle(value);
1521  Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
1522  if (!interceptor->setter()->IsUndefined()) {
1523    LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name));
1524    CustomArguments args(interceptor->data(), this, this);
1525    v8::AccessorInfo info(args.end());
1526    v8::NamedPropertySetter setter =
1527        v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
1528    v8::Handle<v8::Value> result;
1529    {
1530      // Leaving JavaScript.
1531      VMState state(EXTERNAL);
1532      Handle<Object> value_unhole(value->IsTheHole() ?
1533                                  Heap::undefined_value() :
1534                                  value);
1535      result = setter(v8::Utils::ToLocal(name_handle),
1536                      v8::Utils::ToLocal(value_unhole),
1537                      info);
1538    }
1539    RETURN_IF_SCHEDULED_EXCEPTION();
1540    if (!result.IsEmpty()) return *value_handle;
1541  }
1542  Object* raw_result = this_handle->SetPropertyPostInterceptor(*name_handle,
1543                                                               *value_handle,
1544                                                               attributes);
1545  RETURN_IF_SCHEDULED_EXCEPTION();
1546  return raw_result;
1547}
1548
1549
1550Object* JSObject::SetProperty(String* name,
1551                              Object* value,
1552                              PropertyAttributes attributes) {
1553  LookupResult result;
1554  LocalLookup(name, &result);
1555  return SetProperty(&result, name, value, attributes);
1556}
1557
1558
1559Object* JSObject::SetPropertyWithCallback(Object* structure,
1560                                          String* name,
1561                                          Object* value,
1562                                          JSObject* holder) {
1563  HandleScope scope;
1564
1565  // We should never get here to initialize a const with the hole
1566  // value since a const declaration would conflict with the setter.
1567  ASSERT(!value->IsTheHole());
1568  Handle<Object> value_handle(value);
1569
1570  // To accommodate both the old and the new api we switch on the
1571  // data structure used to store the callbacks.  Eventually proxy
1572  // callbacks should be phased out.
1573  if (structure->IsProxy()) {
1574    AccessorDescriptor* callback =
1575        reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy());
1576    Object* obj = (callback->setter)(this,  value, callback->data);
1577    RETURN_IF_SCHEDULED_EXCEPTION();
1578    if (obj->IsFailure()) return obj;
1579    return *value_handle;
1580  }
1581
1582  if (structure->IsAccessorInfo()) {
1583    // api style callbacks
1584    AccessorInfo* data = AccessorInfo::cast(structure);
1585    Object* call_obj = data->setter();
1586    v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
1587    if (call_fun == NULL) return value;
1588    Handle<String> key(name);
1589    LOG(ApiNamedPropertyAccess("store", this, name));
1590    CustomArguments args(data->data(), this, JSObject::cast(holder));
1591    v8::AccessorInfo info(args.end());
1592    {
1593      // Leaving JavaScript.
1594      VMState state(EXTERNAL);
1595      call_fun(v8::Utils::ToLocal(key),
1596               v8::Utils::ToLocal(value_handle),
1597               info);
1598    }
1599    RETURN_IF_SCHEDULED_EXCEPTION();
1600    return *value_handle;
1601  }
1602
1603  if (structure->IsFixedArray()) {
1604    Object* setter = FixedArray::cast(structure)->get(kSetterIndex);
1605    if (setter->IsJSFunction()) {
1606     return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
1607    } else {
1608      Handle<String> key(name);
1609      Handle<Object> holder_handle(holder);
1610      Handle<Object> args[2] = { key, holder_handle };
1611      return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
1612                                               HandleVector(args, 2)));
1613    }
1614  }
1615
1616  UNREACHABLE();
1617  return 0;
1618}
1619
1620
1621Object* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter,
1622                                               Object* value) {
1623  Handle<Object> value_handle(value);
1624  Handle<JSFunction> fun(JSFunction::cast(setter));
1625  Handle<JSObject> self(this);
1626#ifdef ENABLE_DEBUGGER_SUPPORT
1627  // Handle stepping into a setter if step into is active.
1628  if (Debug::StepInActive()) {
1629    Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false);
1630  }
1631#endif
1632  bool has_pending_exception;
1633  Object** argv[] = { value_handle.location() };
1634  Execution::Call(fun, self, 1, argv, &has_pending_exception);
1635  // Check for pending exception and return the result.
1636  if (has_pending_exception) return Failure::Exception();
1637  return *value_handle;
1638}
1639
1640
1641void JSObject::LookupCallbackSetterInPrototypes(String* name,
1642                                                LookupResult* result) {
1643  for (Object* pt = GetPrototype();
1644       pt != Heap::null_value();
1645       pt = pt->GetPrototype()) {
1646    JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
1647    if (result->IsProperty()) {
1648      if (result->IsReadOnly()) {
1649        result->NotFound();
1650        return;
1651      }
1652      if (result->type() == CALLBACKS) {
1653        return;
1654      }
1655    }
1656  }
1657  result->NotFound();
1658}
1659
1660
1661Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) {
1662  for (Object* pt = GetPrototype();
1663       pt != Heap::null_value();
1664       pt = pt->GetPrototype()) {
1665    if (!JSObject::cast(pt)->HasDictionaryElements()) {
1666        continue;
1667    }
1668    NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
1669    int entry = dictionary->FindEntry(index);
1670    if (entry != NumberDictionary::kNotFound) {
1671      Object* element = dictionary->ValueAt(entry);
1672      PropertyDetails details = dictionary->DetailsAt(entry);
1673      if (details.type() == CALLBACKS) {
1674        // Only accessors allowed as elements.
1675        return FixedArray::cast(element)->get(kSetterIndex);
1676      }
1677    }
1678  }
1679  return Heap::undefined_value();
1680}
1681
1682
1683void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
1684  DescriptorArray* descriptors = map()->instance_descriptors();
1685  int number = DescriptorLookupCache::Lookup(descriptors, name);
1686  if (number == DescriptorLookupCache::kAbsent) {
1687    number = descriptors->Search(name);
1688    DescriptorLookupCache::Update(descriptors, name, number);
1689  }
1690  if (number != DescriptorArray::kNotFound) {
1691    result->DescriptorResult(this, descriptors->GetDetails(number), number);
1692  } else {
1693    result->NotFound();
1694  }
1695}
1696
1697
1698void JSObject::LocalLookupRealNamedProperty(String* name,
1699                                            LookupResult* result) {
1700  if (IsJSGlobalProxy()) {
1701    Object* proto = GetPrototype();
1702    if (proto->IsNull()) return result->NotFound();
1703    ASSERT(proto->IsJSGlobalObject());
1704    return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
1705  }
1706
1707  if (HasFastProperties()) {
1708    LookupInDescriptor(name, result);
1709    if (result->IsFound()) {
1710      // A property, a map transition or a null descriptor was found.
1711      // We return all of these result types because
1712      // LocalLookupRealNamedProperty is used when setting properties
1713      // where map transitions and null descriptors are handled.
1714      ASSERT(result->holder() == this && result->type() != NORMAL);
1715      // Disallow caching for uninitialized constants. These can only
1716      // occur as fields.
1717      if (result->IsReadOnly() && result->type() == FIELD &&
1718          FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
1719        result->DisallowCaching();
1720      }
1721      return;
1722    }
1723  } else {
1724    int entry = property_dictionary()->FindEntry(name);
1725    if (entry != StringDictionary::kNotFound) {
1726      Object* value = property_dictionary()->ValueAt(entry);
1727      if (IsGlobalObject()) {
1728        PropertyDetails d = property_dictionary()->DetailsAt(entry);
1729        if (d.IsDeleted()) {
1730          result->NotFound();
1731          return;
1732        }
1733        value = JSGlobalPropertyCell::cast(value)->value();
1734      }
1735      // Make sure to disallow caching for uninitialized constants
1736      // found in the dictionary-mode objects.
1737      if (value->IsTheHole()) result->DisallowCaching();
1738      result->DictionaryResult(this, entry);
1739      return;
1740    }
1741    // Slow case object skipped during lookup. Do not use inline caching.
1742    if (!IsGlobalObject()) result->DisallowCaching();
1743  }
1744  result->NotFound();
1745}
1746
1747
1748void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
1749  LocalLookupRealNamedProperty(name, result);
1750  if (result->IsProperty()) return;
1751
1752  LookupRealNamedPropertyInPrototypes(name, result);
1753}
1754
1755
1756void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
1757                                                   LookupResult* result) {
1758  for (Object* pt = GetPrototype();
1759       pt != Heap::null_value();
1760       pt = JSObject::cast(pt)->GetPrototype()) {
1761    JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
1762    if (result->IsProperty() && (result->type() != INTERCEPTOR)) return;
1763  }
1764  result->NotFound();
1765}
1766
1767
1768// We only need to deal with CALLBACKS and INTERCEPTORS
1769Object* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result,
1770                                                   String* name,
1771                                                   Object* value) {
1772  if (!result->IsProperty()) {
1773    LookupCallbackSetterInPrototypes(name, result);
1774  }
1775
1776  if (result->IsProperty()) {
1777    if (!result->IsReadOnly()) {
1778      switch (result->type()) {
1779        case CALLBACKS: {
1780          Object* obj = result->GetCallbackObject();
1781          if (obj->IsAccessorInfo()) {
1782            AccessorInfo* info = AccessorInfo::cast(obj);
1783            if (info->all_can_write()) {
1784              return SetPropertyWithCallback(result->GetCallbackObject(),
1785                                             name,
1786                                             value,
1787                                             result->holder());
1788            }
1789          }
1790          break;
1791        }
1792        case INTERCEPTOR: {
1793          // Try lookup real named properties. Note that only property can be
1794          // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
1795          LookupResult r;
1796          LookupRealNamedProperty(name, &r);
1797          if (r.IsProperty()) {
1798            return SetPropertyWithFailedAccessCheck(&r, name, value);
1799          }
1800          break;
1801        }
1802        default: {
1803          break;
1804        }
1805      }
1806    }
1807  }
1808
1809  Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
1810  return value;
1811}
1812
1813
1814Object* JSObject::SetProperty(LookupResult* result,
1815                              String* name,
1816                              Object* value,
1817                              PropertyAttributes attributes) {
1818  // Make sure that the top context does not change when doing callbacks or
1819  // interceptor calls.
1820  AssertNoContextChange ncc;
1821
1822  // Optimization for 2-byte strings often used as keys in a decompression
1823  // dictionary.  We make these short keys into symbols to avoid constantly
1824  // reallocating them.
1825  if (!name->IsSymbol() && name->length() <= 2) {
1826    Object* symbol_version = Heap::LookupSymbol(name);
1827    if (!symbol_version->IsFailure()) name = String::cast(symbol_version);
1828  }
1829
1830  // Check access rights if needed.
1831  if (IsAccessCheckNeeded()
1832      && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
1833    return SetPropertyWithFailedAccessCheck(result, name, value);
1834  }
1835
1836  if (IsJSGlobalProxy()) {
1837    Object* proto = GetPrototype();
1838    if (proto->IsNull()) return value;
1839    ASSERT(proto->IsJSGlobalObject());
1840    return JSObject::cast(proto)->SetProperty(result, name, value, attributes);
1841  }
1842
1843  if (!result->IsProperty() && !IsJSContextExtensionObject()) {
1844    // We could not find a local property so let's check whether there is an
1845    // accessor that wants to handle the property.
1846    LookupResult accessor_result;
1847    LookupCallbackSetterInPrototypes(name, &accessor_result);
1848    if (accessor_result.IsProperty()) {
1849      return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
1850                                     name,
1851                                     value,
1852                                     accessor_result.holder());
1853    }
1854  }
1855  if (!result->IsFound()) {
1856    // Neither properties nor transitions found.
1857    return AddProperty(name, value, attributes);
1858  }
1859  if (result->IsReadOnly() && result->IsProperty()) return value;
1860  // This is a real property that is not read-only, or it is a
1861  // transition or null descriptor and there are no setters in the prototypes.
1862  switch (result->type()) {
1863    case NORMAL:
1864      return SetNormalizedProperty(result, value);
1865    case FIELD:
1866      return FastPropertyAtPut(result->GetFieldIndex(), value);
1867    case MAP_TRANSITION:
1868      if (attributes == result->GetAttributes()) {
1869        // Only use map transition if the attributes match.
1870        return AddFastPropertyUsingMap(result->GetTransitionMap(),
1871                                       name,
1872                                       value);
1873      }
1874      return ConvertDescriptorToField(name, value, attributes);
1875    case CONSTANT_FUNCTION:
1876      // Only replace the function if necessary.
1877      if (value == result->GetConstantFunction()) return value;
1878      // Preserve the attributes of this existing property.
1879      attributes = result->GetAttributes();
1880      return ConvertDescriptorToField(name, value, attributes);
1881    case CALLBACKS:
1882      return SetPropertyWithCallback(result->GetCallbackObject(),
1883                                     name,
1884                                     value,
1885                                     result->holder());
1886    case INTERCEPTOR:
1887      return SetPropertyWithInterceptor(name, value, attributes);
1888    case CONSTANT_TRANSITION:
1889      // Replace with a MAP_TRANSITION to a new map with a FIELD, even
1890      // if the value is a function.
1891      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
1892    case NULL_DESCRIPTOR:
1893      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
1894    default:
1895      UNREACHABLE();
1896  }
1897  UNREACHABLE();
1898  return value;
1899}
1900
1901
1902// Set a real local property, even if it is READ_ONLY.  If the property is not
1903// present, add it with attributes NONE.  This code is an exact clone of
1904// SetProperty, with the check for IsReadOnly and the check for a
1905// callback setter removed.  The two lines looking up the LookupResult
1906// result are also added.  If one of the functions is changed, the other
1907// should be.
1908Object* JSObject::IgnoreAttributesAndSetLocalProperty(
1909    String* name,
1910    Object* value,
1911    PropertyAttributes attributes) {
1912  // Make sure that the top context does not change when doing callbacks or
1913  // interceptor calls.
1914  AssertNoContextChange ncc;
1915  LookupResult result;
1916  LocalLookup(name, &result);
1917  // Check access rights if needed.
1918  if (IsAccessCheckNeeded()
1919      && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
1920    return SetPropertyWithFailedAccessCheck(&result, name, value);
1921  }
1922
1923  if (IsJSGlobalProxy()) {
1924    Object* proto = GetPrototype();
1925    if (proto->IsNull()) return value;
1926    ASSERT(proto->IsJSGlobalObject());
1927    return JSObject::cast(proto)->IgnoreAttributesAndSetLocalProperty(
1928        name,
1929        value,
1930        attributes);
1931  }
1932
1933  // Check for accessor in prototype chain removed here in clone.
1934  if (!result.IsFound()) {
1935    // Neither properties nor transitions found.
1936    return AddProperty(name, value, attributes);
1937  }
1938  PropertyDetails details = PropertyDetails(attributes, NORMAL);
1939
1940  // Check of IsReadOnly removed from here in clone.
1941  switch (result.type()) {
1942    case NORMAL:
1943      return SetNormalizedProperty(name, value, details);
1944    case FIELD:
1945      return FastPropertyAtPut(result.GetFieldIndex(), value);
1946    case MAP_TRANSITION:
1947      if (attributes == result.GetAttributes()) {
1948        // Only use map transition if the attributes match.
1949        return AddFastPropertyUsingMap(result.GetTransitionMap(),
1950                                       name,
1951                                       value);
1952      }
1953      return ConvertDescriptorToField(name, value, attributes);
1954    case CONSTANT_FUNCTION:
1955      // Only replace the function if necessary.
1956      if (value == result.GetConstantFunction()) return value;
1957      // Preserve the attributes of this existing property.
1958      attributes = result.GetAttributes();
1959      return ConvertDescriptorToField(name, value, attributes);
1960    case CALLBACKS:
1961    case INTERCEPTOR:
1962      // Override callback in clone
1963      return ConvertDescriptorToField(name, value, attributes);
1964    case CONSTANT_TRANSITION:
1965      // Replace with a MAP_TRANSITION to a new map with a FIELD, even
1966      // if the value is a function.
1967      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
1968    case NULL_DESCRIPTOR:
1969      return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
1970    default:
1971      UNREACHABLE();
1972  }
1973  UNREACHABLE();
1974  return value;
1975}
1976
1977
1978PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
1979      JSObject* receiver,
1980      String* name,
1981      bool continue_search) {
1982  // Check local property, ignore interceptor.
1983  LookupResult result;
1984  LocalLookupRealNamedProperty(name, &result);
1985  if (result.IsProperty()) return result.GetAttributes();
1986
1987  if (continue_search) {
1988    // Continue searching via the prototype chain.
1989    Object* pt = GetPrototype();
1990    if (pt != Heap::null_value()) {
1991      return JSObject::cast(pt)->
1992        GetPropertyAttributeWithReceiver(receiver, name);
1993    }
1994  }
1995  return ABSENT;
1996}
1997
1998
1999PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
2000      JSObject* receiver,
2001      String* name,
2002      bool continue_search) {
2003  // Make sure that the top context does not change when doing
2004  // callbacks or interceptor calls.
2005  AssertNoContextChange ncc;
2006
2007  HandleScope scope;
2008  Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
2009  Handle<JSObject> receiver_handle(receiver);
2010  Handle<JSObject> holder_handle(this);
2011  Handle<String> name_handle(name);
2012  CustomArguments args(interceptor->data(), receiver, this);
2013  v8::AccessorInfo info(args.end());
2014  if (!interceptor->query()->IsUndefined()) {
2015    v8::NamedPropertyQuery query =
2016        v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
2017    LOG(ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
2018    v8::Handle<v8::Boolean> result;
2019    {
2020      // Leaving JavaScript.
2021      VMState state(EXTERNAL);
2022      result = query(v8::Utils::ToLocal(name_handle), info);
2023    }
2024    if (!result.IsEmpty()) {
2025      // Convert the boolean result to a property attribute
2026      // specification.
2027      return result->IsTrue() ? NONE : ABSENT;
2028    }
2029  } else if (!interceptor->getter()->IsUndefined()) {
2030    v8::NamedPropertyGetter getter =
2031        v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
2032    LOG(ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
2033    v8::Handle<v8::Value> result;
2034    {
2035      // Leaving JavaScript.
2036      VMState state(EXTERNAL);
2037      result = getter(v8::Utils::ToLocal(name_handle), info);
2038    }
2039    if (!result.IsEmpty()) return NONE;
2040  }
2041  return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
2042                                                            *name_handle,
2043                                                            continue_search);
2044}
2045
2046
2047PropertyAttributes JSObject::GetPropertyAttributeWithReceiver(
2048      JSObject* receiver,
2049      String* key) {
2050  uint32_t index = 0;
2051  if (key->AsArrayIndex(&index)) {
2052    if (HasElementWithReceiver(receiver, index)) return NONE;
2053    return ABSENT;
2054  }
2055  // Named property.
2056  LookupResult result;
2057  Lookup(key, &result);
2058  return GetPropertyAttribute(receiver, &result, key, true);
2059}
2060
2061
2062PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver,
2063                                                  LookupResult* result,
2064                                                  String* name,
2065                                                  bool continue_search) {
2066  // Check access rights if needed.
2067  if (IsAccessCheckNeeded() &&
2068      !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
2069    return GetPropertyAttributeWithFailedAccessCheck(receiver,
2070                                                     result,
2071                                                     name,
2072                                                     continue_search);
2073  }
2074  if (result->IsProperty()) {
2075    switch (result->type()) {
2076      case NORMAL:  // fall through
2077      case FIELD:
2078      case CONSTANT_FUNCTION:
2079      case CALLBACKS:
2080        return result->GetAttributes();
2081      case INTERCEPTOR:
2082        return result->holder()->
2083          GetPropertyAttributeWithInterceptor(receiver, name, continue_search);
2084      default:
2085        UNREACHABLE();
2086    }
2087  }
2088  return ABSENT;
2089}
2090
2091
2092PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) {
2093  // Check whether the name is an array index.
2094  uint32_t index = 0;
2095  if (name->AsArrayIndex(&index)) {
2096    if (HasLocalElement(index)) return NONE;
2097    return ABSENT;
2098  }
2099  // Named property.
2100  LookupResult result;
2101  LocalLookup(name, &result);
2102  return GetPropertyAttribute(this, &result, name, false);
2103}
2104
2105
2106Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
2107                                      int expected_additional_properties) {
2108  if (!HasFastProperties()) return this;
2109
2110  // The global object is always normalized.
2111  ASSERT(!IsGlobalObject());
2112
2113  // Allocate new content.
2114  int property_count = map()->NumberOfDescribedProperties();
2115  if (expected_additional_properties > 0) {
2116    property_count += expected_additional_properties;
2117  } else {
2118    property_count += 2;  // Make space for two more properties.
2119  }
2120  Object* obj =
2121      StringDictionary::Allocate(property_count * 2);
2122  if (obj->IsFailure()) return obj;
2123  StringDictionary* dictionary = StringDictionary::cast(obj);
2124
2125  DescriptorArray* descs = map()->instance_descriptors();
2126  for (int i = 0; i < descs->number_of_descriptors(); i++) {
2127    PropertyDetails details = descs->GetDetails(i);
2128    switch (details.type()) {
2129      case CONSTANT_FUNCTION: {
2130        PropertyDetails d =
2131            PropertyDetails(details.attributes(), NORMAL, details.index());
2132        Object* value = descs->GetConstantFunction(i);
2133        Object* result = dictionary->Add(descs->GetKey(i), value, d);
2134        if (result->IsFailure()) return result;
2135        dictionary = StringDictionary::cast(result);
2136        break;
2137      }
2138      case FIELD: {
2139        PropertyDetails d =
2140            PropertyDetails(details.attributes(), NORMAL, details.index());
2141        Object* value = FastPropertyAt(descs->GetFieldIndex(i));
2142        Object* result = dictionary->Add(descs->GetKey(i), value, d);
2143        if (result->IsFailure()) return result;
2144        dictionary = StringDictionary::cast(result);
2145        break;
2146      }
2147      case CALLBACKS: {
2148        PropertyDetails d =
2149            PropertyDetails(details.attributes(), CALLBACKS, details.index());
2150        Object* value = descs->GetCallbacksObject(i);
2151        Object* result = dictionary->Add(descs->GetKey(i), value, d);
2152        if (result->IsFailure()) return result;
2153        dictionary = StringDictionary::cast(result);
2154        break;
2155      }
2156      case MAP_TRANSITION:
2157      case CONSTANT_TRANSITION:
2158      case NULL_DESCRIPTOR:
2159      case INTERCEPTOR:
2160        break;
2161      default:
2162        UNREACHABLE();
2163    }
2164  }
2165
2166  // Copy the next enumeration index from instance descriptor.
2167  int index = map()->instance_descriptors()->NextEnumerationIndex();
2168  dictionary->SetNextEnumerationIndex(index);
2169
2170  // Allocate new map.
2171  obj = map()->CopyDropDescriptors();
2172  if (obj->IsFailure()) return obj;
2173  Map* new_map = Map::cast(obj);
2174
2175  // Clear inobject properties if needed by adjusting the instance size and
2176  // putting in a filler object instead of the inobject properties.
2177  if (mode == CLEAR_INOBJECT_PROPERTIES && map()->inobject_properties() > 0) {
2178    int instance_size_delta = map()->inobject_properties() * kPointerSize;
2179    int new_instance_size = map()->instance_size() - instance_size_delta;
2180    new_map->set_inobject_properties(0);
2181    new_map->set_instance_size(new_instance_size);
2182    Heap::CreateFillerObjectAt(this->address() + new_instance_size,
2183                               instance_size_delta);
2184  }
2185  new_map->set_unused_property_fields(0);
2186
2187  // We have now successfully allocated all the necessary objects.
2188  // Changes can now be made with the guarantee that all of them take effect.
2189  set_map(new_map);
2190  map()->set_instance_descriptors(Heap::empty_descriptor_array());
2191
2192  set_properties(dictionary);
2193
2194  Counters::props_to_dictionary.Increment();
2195
2196#ifdef DEBUG
2197  if (FLAG_trace_normalization) {
2198    PrintF("Object properties have been normalized:\n");
2199    Print();
2200  }
2201#endif
2202  return this;
2203}
2204
2205
2206Object* JSObject::TransformToFastProperties(int unused_property_fields) {
2207  if (HasFastProperties()) return this;
2208  ASSERT(!IsGlobalObject());
2209  return property_dictionary()->
2210      TransformPropertiesToFastFor(this, unused_property_fields);
2211}
2212
2213
2214Object* JSObject::NormalizeElements() {
2215  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
2216  if (HasDictionaryElements()) return this;
2217
2218  // Get number of entries.
2219  FixedArray* array = FixedArray::cast(elements());
2220
2221  // Compute the effective length.
2222  int length = IsJSArray() ?
2223               Smi::cast(JSArray::cast(this)->length())->value() :
2224               array->length();
2225  Object* obj = NumberDictionary::Allocate(length);
2226  if (obj->IsFailure()) return obj;
2227  NumberDictionary* dictionary = NumberDictionary::cast(obj);
2228  // Copy entries.
2229  for (int i = 0; i < length; i++) {
2230    Object* value = array->get(i);
2231    if (!value->IsTheHole()) {
2232      PropertyDetails details = PropertyDetails(NONE, NORMAL);
2233      Object* result = dictionary->AddNumberEntry(i, array->get(i), details);
2234      if (result->IsFailure()) return result;
2235      dictionary = NumberDictionary::cast(result);
2236    }
2237  }
2238  // Switch to using the dictionary as the backing storage for elements.
2239  set_elements(dictionary);
2240
2241  Counters::elements_to_dictionary.Increment();
2242
2243#ifdef DEBUG
2244  if (FLAG_trace_normalization) {
2245    PrintF("Object elements have been normalized:\n");
2246    Print();
2247  }
2248#endif
2249
2250  return this;
2251}
2252
2253
2254Object* JSObject::DeletePropertyPostInterceptor(String* name, DeleteMode mode) {
2255  // Check local property, ignore interceptor.
2256  LookupResult result;
2257  LocalLookupRealNamedProperty(name, &result);
2258  if (!result.IsProperty()) return Heap::true_value();
2259
2260  // Normalize object if needed.
2261  Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
2262  if (obj->IsFailure()) return obj;
2263
2264  return DeleteNormalizedProperty(name, mode);
2265}
2266
2267
2268Object* JSObject::DeletePropertyWithInterceptor(String* name) {
2269  HandleScope scope;
2270  Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
2271  Handle<String> name_handle(name);
2272  Handle<JSObject> this_handle(this);
2273  if (!interceptor->deleter()->IsUndefined()) {
2274    v8::NamedPropertyDeleter deleter =
2275        v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
2276    LOG(ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
2277    CustomArguments args(interceptor->data(), this, this);
2278    v8::AccessorInfo info(args.end());
2279    v8::Handle<v8::Boolean> result;
2280    {
2281      // Leaving JavaScript.
2282      VMState state(EXTERNAL);
2283      result = deleter(v8::Utils::ToLocal(name_handle), info);
2284    }
2285    RETURN_IF_SCHEDULED_EXCEPTION();
2286    if (!result.IsEmpty()) {
2287      ASSERT(result->IsBoolean());
2288      return *v8::Utils::OpenHandle(*result);
2289    }
2290  }
2291  Object* raw_result =
2292      this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
2293  RETURN_IF_SCHEDULED_EXCEPTION();
2294  return raw_result;
2295}
2296
2297
2298Object* JSObject::DeleteElementPostInterceptor(uint32_t index,
2299                                               DeleteMode mode) {
2300  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
2301  switch (GetElementsKind()) {
2302    case FAST_ELEMENTS: {
2303      uint32_t length = IsJSArray() ?
2304      static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
2305      static_cast<uint32_t>(FixedArray::cast(elements())->length());
2306      if (index < length) {
2307        FixedArray::cast(elements())->set_the_hole(index);
2308      }
2309      break;
2310    }
2311    case DICTIONARY_ELEMENTS: {
2312      NumberDictionary* dictionary = element_dictionary();
2313      int entry = dictionary->FindEntry(index);
2314      if (entry != NumberDictionary::kNotFound) {
2315        return dictionary->DeleteProperty(entry, mode);
2316      }
2317      break;
2318    }
2319    default:
2320      UNREACHABLE();
2321      break;
2322  }
2323  return Heap::true_value();
2324}
2325
2326
2327Object* JSObject::DeleteElementWithInterceptor(uint32_t index) {
2328  // Make sure that the top context does not change when doing
2329  // callbacks or interceptor calls.
2330  AssertNoContextChange ncc;
2331  HandleScope scope;
2332  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
2333  if (interceptor->deleter()->IsUndefined()) return Heap::false_value();
2334  v8::IndexedPropertyDeleter deleter =
2335      v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
2336  Handle<JSObject> this_handle(this);
2337  LOG(ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
2338  CustomArguments args(interceptor->data(), this, this);
2339  v8::AccessorInfo info(args.end());
2340  v8::Handle<v8::Boolean> result;
2341  {
2342    // Leaving JavaScript.
2343    VMState state(EXTERNAL);
2344    result = deleter(index, info);
2345  }
2346  RETURN_IF_SCHEDULED_EXCEPTION();
2347  if (!result.IsEmpty()) {
2348    ASSERT(result->IsBoolean());
2349    return *v8::Utils::OpenHandle(*result);
2350  }
2351  Object* raw_result =
2352      this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION);
2353  RETURN_IF_SCHEDULED_EXCEPTION();
2354  return raw_result;
2355}
2356
2357
2358Object* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
2359  // Check access rights if needed.
2360  if (IsAccessCheckNeeded() &&
2361      !Top::MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
2362    Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
2363    return Heap::false_value();
2364  }
2365
2366  if (IsJSGlobalProxy()) {
2367    Object* proto = GetPrototype();
2368    if (proto->IsNull()) return Heap::false_value();
2369    ASSERT(proto->IsJSGlobalObject());
2370    return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
2371  }
2372
2373  if (HasIndexedInterceptor()) {
2374    // Skip interceptor if forcing deletion.
2375    if (mode == FORCE_DELETION) {
2376      return DeleteElementPostInterceptor(index, mode);
2377    }
2378    return DeleteElementWithInterceptor(index);
2379  }
2380
2381  switch (GetElementsKind()) {
2382    case FAST_ELEMENTS: {
2383      uint32_t length = IsJSArray() ?
2384      static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
2385      static_cast<uint32_t>(FixedArray::cast(elements())->length());
2386      if (index < length) {
2387        FixedArray::cast(elements())->set_the_hole(index);
2388      }
2389      break;
2390    }
2391    case PIXEL_ELEMENTS:
2392    case EXTERNAL_BYTE_ELEMENTS:
2393    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
2394    case EXTERNAL_SHORT_ELEMENTS:
2395    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
2396    case EXTERNAL_INT_ELEMENTS:
2397    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
2398    case EXTERNAL_FLOAT_ELEMENTS:
2399      // Pixel and external array elements cannot be deleted. Just
2400      // silently ignore here.
2401      break;
2402    case DICTIONARY_ELEMENTS: {
2403      NumberDictionary* dictionary = element_dictionary();
2404      int entry = dictionary->FindEntry(index);
2405      if (entry != NumberDictionary::kNotFound) {
2406        return dictionary->DeleteProperty(entry, mode);
2407      }
2408      break;
2409    }
2410    default:
2411      UNREACHABLE();
2412      break;
2413  }
2414  return Heap::true_value();
2415}
2416
2417
2418Object* JSObject::DeleteProperty(String* name, DeleteMode mode) {
2419  // ECMA-262, 3rd, 8.6.2.5
2420  ASSERT(name->IsString());
2421
2422  // Check access rights if needed.
2423  if (IsAccessCheckNeeded() &&
2424      !Top::MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
2425    Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
2426    return Heap::false_value();
2427  }
2428
2429  if (IsJSGlobalProxy()) {
2430    Object* proto = GetPrototype();
2431    if (proto->IsNull()) return Heap::false_value();
2432    ASSERT(proto->IsJSGlobalObject());
2433    return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
2434  }
2435
2436  uint32_t index = 0;
2437  if (name->AsArrayIndex(&index)) {
2438    return DeleteElement(index, mode);
2439  } else {
2440    LookupResult result;
2441    LocalLookup(name, &result);
2442    if (!result.IsProperty()) return Heap::true_value();
2443    // Ignore attributes if forcing a deletion.
2444    if (result.IsDontDelete() && mode != FORCE_DELETION) {
2445      return Heap::false_value();
2446    }
2447    // Check for interceptor.
2448    if (result.type() == INTERCEPTOR) {
2449      // Skip interceptor if forcing a deletion.
2450      if (mode == FORCE_DELETION) {
2451        return DeletePropertyPostInterceptor(name, mode);
2452      }
2453      return DeletePropertyWithInterceptor(name);
2454    }
2455    // Normalize object if needed.
2456    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
2457    if (obj->IsFailure()) return obj;
2458    // Make sure the properties are normalized before removing the entry.
2459    return DeleteNormalizedProperty(name, mode);
2460  }
2461}
2462
2463
2464// Check whether this object references another object.
2465bool JSObject::ReferencesObject(Object* obj) {
2466  AssertNoAllocation no_alloc;
2467
2468  // Is the object the constructor for this object?
2469  if (map()->constructor() == obj) {
2470    return true;
2471  }
2472
2473  // Is the object the prototype for this object?
2474  if (map()->prototype() == obj) {
2475    return true;
2476  }
2477
2478  // Check if the object is among the named properties.
2479  Object* key = SlowReverseLookup(obj);
2480  if (key != Heap::undefined_value()) {
2481    return true;
2482  }
2483
2484  // Check if the object is among the indexed properties.
2485  switch (GetElementsKind()) {
2486    case PIXEL_ELEMENTS:
2487    case EXTERNAL_BYTE_ELEMENTS:
2488    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
2489    case EXTERNAL_SHORT_ELEMENTS:
2490    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
2491    case EXTERNAL_INT_ELEMENTS:
2492    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
2493    case EXTERNAL_FLOAT_ELEMENTS:
2494      // Raw pixels and external arrays do not reference other
2495      // objects.
2496      break;
2497    case FAST_ELEMENTS: {
2498      int length = IsJSArray() ?
2499          Smi::cast(JSArray::cast(this)->length())->value() :
2500          FixedArray::cast(elements())->length();
2501      for (int i = 0; i < length; i++) {
2502        Object* element = FixedArray::cast(elements())->get(i);
2503        if (!element->IsTheHole() && element == obj) {
2504          return true;
2505        }
2506      }
2507      break;
2508    }
2509    case DICTIONARY_ELEMENTS: {
2510      key = element_dictionary()->SlowReverseLookup(obj);
2511      if (key != Heap::undefined_value()) {
2512        return true;
2513      }
2514      break;
2515    }
2516    default:
2517      UNREACHABLE();
2518      break;
2519  }
2520
2521  // For functions check the context. Boilerplate functions do
2522  // not have to be traversed since they have no real context.
2523  if (IsJSFunction() && !JSFunction::cast(this)->IsBoilerplate()) {
2524    // Get the constructor function for arguments array.
2525    JSObject* arguments_boilerplate =
2526        Top::context()->global_context()->arguments_boilerplate();
2527    JSFunction* arguments_function =
2528        JSFunction::cast(arguments_boilerplate->map()->constructor());
2529
2530    // Get the context and don't check if it is the global context.
2531    JSFunction* f = JSFunction::cast(this);
2532    Context* context = f->context();
2533    if (context->IsGlobalContext()) {
2534      return false;
2535    }
2536
2537    // Check the non-special context slots.
2538    for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
2539      // Only check JS objects.
2540      if (context->get(i)->IsJSObject()) {
2541        JSObject* ctxobj = JSObject::cast(context->get(i));
2542        // If it is an arguments array check the content.
2543        if (ctxobj->map()->constructor() == arguments_function) {
2544          if (ctxobj->ReferencesObject(obj)) {
2545            return true;
2546          }
2547        } else if (ctxobj == obj) {
2548          return true;
2549        }
2550      }
2551    }
2552
2553    // Check the context extension if any.
2554    if (context->has_extension()) {
2555      return context->extension()->ReferencesObject(obj);
2556    }
2557  }
2558
2559  // No references to object.
2560  return false;
2561}
2562
2563
2564// Tests for the fast common case for property enumeration:
2565// - This object and all prototypes has an enum cache (which means that it has
2566//   no interceptors and needs no access checks).
2567// - This object has no elements.
2568// - No prototype has enumerable properties/elements.
2569bool JSObject::IsSimpleEnum() {
2570  for (Object* o = this;
2571       o != Heap::null_value();
2572       o = JSObject::cast(o)->GetPrototype()) {
2573    JSObject* curr = JSObject::cast(o);
2574    if (!curr->map()->instance_descriptors()->HasEnumCache()) return false;
2575    ASSERT(!curr->HasNamedInterceptor());
2576    ASSERT(!curr->HasIndexedInterceptor());
2577    ASSERT(!curr->IsAccessCheckNeeded());
2578    if (curr->NumberOfEnumElements() > 0) return false;
2579    if (curr != this) {
2580      FixedArray* curr_fixed_array =
2581          FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache());
2582      if (curr_fixed_array->length() > 0) return false;
2583    }
2584  }
2585  return true;
2586}
2587
2588
2589int Map::NumberOfDescribedProperties() {
2590  int result = 0;
2591  DescriptorArray* descs = instance_descriptors();
2592  for (int i = 0; i < descs->number_of_descriptors(); i++) {
2593    if (descs->IsProperty(i)) result++;
2594  }
2595  return result;
2596}
2597
2598
2599int Map::PropertyIndexFor(String* name) {
2600  DescriptorArray* descs = instance_descriptors();
2601  for (int i = 0; i < descs->number_of_descriptors(); i++) {
2602    if (name->Equals(descs->GetKey(i)) && !descs->IsNullDescriptor(i)) {
2603      return descs->GetFieldIndex(i);
2604    }
2605  }
2606  return -1;
2607}
2608
2609
2610int Map::NextFreePropertyIndex() {
2611  int max_index = -1;
2612  DescriptorArray* descs = instance_descriptors();
2613  for (int i = 0; i < descs->number_of_descriptors(); i++) {
2614    if (descs->GetType(i) == FIELD) {
2615      int current_index = descs->GetFieldIndex(i);
2616      if (current_index > max_index) max_index = current_index;
2617    }
2618  }
2619  return max_index + 1;
2620}
2621
2622
2623AccessorDescriptor* Map::FindAccessor(String* name) {
2624  DescriptorArray* descs = instance_descriptors();
2625  for (int i = 0; i < descs->number_of_descriptors(); i++) {
2626    if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
2627      return descs->GetCallbacks(i);
2628    }
2629  }
2630  return NULL;
2631}
2632
2633
2634void JSObject::LocalLookup(String* name, LookupResult* result) {
2635  ASSERT(name->IsString());
2636
2637  if (IsJSGlobalProxy()) {
2638    Object* proto = GetPrototype();
2639    if (proto->IsNull()) return result->NotFound();
2640    ASSERT(proto->IsJSGlobalObject());
2641    return JSObject::cast(proto)->LocalLookup(name, result);
2642  }
2643
2644  // Do not use inline caching if the object is a non-global object
2645  // that requires access checks.
2646  if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) {
2647    result->DisallowCaching();
2648  }
2649
2650  // Check __proto__ before interceptor.
2651  if (name->Equals(Heap::Proto_symbol()) && !IsJSContextExtensionObject()) {
2652    result->ConstantResult(this);
2653    return;
2654  }
2655
2656  // Check for lookup interceptor except when bootstrapping.
2657  if (HasNamedInterceptor() && !Bootstrapper::IsActive()) {
2658    result->InterceptorResult(this);
2659    return;
2660  }
2661
2662  LocalLookupRealNamedProperty(name, result);
2663}
2664
2665
2666void JSObject::Lookup(String* name, LookupResult* result) {
2667  // Ecma-262 3rd 8.6.2.4
2668  for (Object* current = this;
2669       current != Heap::null_value();
2670       current = JSObject::cast(current)->GetPrototype()) {
2671    JSObject::cast(current)->LocalLookup(name, result);
2672    if (result->IsProperty()) return;
2673  }
2674  result->NotFound();
2675}
2676
2677
2678// Search object and it's prototype chain for callback properties.
2679void JSObject::LookupCallback(String* name, LookupResult* result) {
2680  for (Object* current = this;
2681       current != Heap::null_value();
2682       current = JSObject::cast(current)->GetPrototype()) {
2683    JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
2684    if (result->IsProperty() && result->type() == CALLBACKS) return;
2685  }
2686  result->NotFound();
2687}
2688
2689
2690Object* JSObject::DefineGetterSetter(String* name,
2691                                     PropertyAttributes attributes) {
2692  // Make sure that the top context does not change when doing callbacks or
2693  // interceptor calls.
2694  AssertNoContextChange ncc;
2695
2696  // Check access rights if needed.
2697  if (IsAccessCheckNeeded() &&
2698      !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
2699    Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
2700    return Heap::undefined_value();
2701  }
2702
2703  // Try to flatten before operating on the string.
2704  name->TryFlattenIfNotFlat();
2705
2706  // Check if there is an API defined callback object which prohibits
2707  // callback overwriting in this object or it's prototype chain.
2708  // This mechanism is needed for instance in a browser setting, where
2709  // certain accessors such as window.location should not be allowed
2710  // to be overwritten because allowing overwriting could potentially
2711  // cause security problems.
2712  LookupResult callback_result;
2713  LookupCallback(name, &callback_result);
2714  if (callback_result.IsFound()) {
2715    Object* obj = callback_result.GetCallbackObject();
2716    if (obj->IsAccessorInfo() &&
2717        AccessorInfo::cast(obj)->prohibits_overwriting()) {
2718      return Heap::undefined_value();
2719    }
2720  }
2721
2722  uint32_t index;
2723  bool is_element = name->AsArrayIndex(&index);
2724  if (is_element && IsJSArray()) return Heap::undefined_value();
2725
2726  if (is_element) {
2727    switch (GetElementsKind()) {
2728      case FAST_ELEMENTS:
2729        break;
2730      case PIXEL_ELEMENTS:
2731      case EXTERNAL_BYTE_ELEMENTS:
2732      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
2733      case EXTERNAL_SHORT_ELEMENTS:
2734      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
2735      case EXTERNAL_INT_ELEMENTS:
2736      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
2737      case EXTERNAL_FLOAT_ELEMENTS:
2738        // Ignore getters and setters on pixel and external array
2739        // elements.
2740        return Heap::undefined_value();
2741      case DICTIONARY_ELEMENTS: {
2742        // Lookup the index.
2743        NumberDictionary* dictionary = element_dictionary();
2744        int entry = dictionary->FindEntry(index);
2745        if (entry != NumberDictionary::kNotFound) {
2746          Object* result = dictionary->ValueAt(entry);
2747          PropertyDetails details = dictionary->DetailsAt(entry);
2748          if (details.IsReadOnly()) return Heap::undefined_value();
2749          if (details.type() == CALLBACKS) {
2750            // Only accessors allowed as elements.
2751            ASSERT(result->IsFixedArray());
2752            return result;
2753          }
2754        }
2755        break;
2756      }
2757      default:
2758        UNREACHABLE();
2759        break;
2760    }
2761  } else {
2762    // Lookup the name.
2763    LookupResult result;
2764    LocalLookup(name, &result);
2765    if (result.IsProperty()) {
2766      if (result.IsReadOnly()) return Heap::undefined_value();
2767      if (result.type() == CALLBACKS) {
2768        Object* obj = result.GetCallbackObject();
2769        if (obj->IsFixedArray()) {
2770          // The object might be in fast mode even though it has
2771          // a getter/setter.
2772          Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
2773          if (ok->IsFailure()) return ok;
2774
2775          PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
2776          SetNormalizedProperty(name, obj, details);
2777          return obj;
2778        }
2779      }
2780    }
2781  }
2782
2783  // Allocate the fixed array to hold getter and setter.
2784  Object* structure = Heap::AllocateFixedArray(2, TENURED);
2785  if (structure->IsFailure()) return structure;
2786  PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
2787
2788  if (is_element) {
2789    // Normalize object to make this operation simple.
2790    Object* ok = NormalizeElements();
2791    if (ok->IsFailure()) return ok;
2792
2793    // Update the dictionary with the new CALLBACKS property.
2794    Object* dict =
2795        element_dictionary()->Set(index, structure, details);
2796    if (dict->IsFailure()) return dict;
2797
2798    // If name is an index we need to stay in slow case.
2799    NumberDictionary* elements = NumberDictionary::cast(dict);
2800    elements->set_requires_slow_elements();
2801    // Set the potential new dictionary on the object.
2802    set_elements(NumberDictionary::cast(dict));
2803  } else {
2804    // Normalize object to make this operation simple.
2805    Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
2806    if (ok->IsFailure()) return ok;
2807
2808    // For the global object allocate a new map to invalidate the global inline
2809    // caches which have a global property cell reference directly in the code.
2810    if (IsGlobalObject()) {
2811      Object* new_map = map()->CopyDropDescriptors();
2812      if (new_map->IsFailure()) return new_map;
2813      set_map(Map::cast(new_map));
2814    }
2815
2816    // Update the dictionary with the new CALLBACKS property.
2817    return SetNormalizedProperty(name, structure, details);
2818  }
2819
2820  return structure;
2821}
2822
2823
2824Object* JSObject::DefineAccessor(String* name, bool is_getter, JSFunction* fun,
2825                                 PropertyAttributes attributes) {
2826  // Check access rights if needed.
2827  if (IsAccessCheckNeeded() &&
2828      !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
2829    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
2830    return Heap::undefined_value();
2831  }
2832
2833  if (IsJSGlobalProxy()) {
2834    Object* proto = GetPrototype();
2835    if (proto->IsNull()) return this;
2836    ASSERT(proto->IsJSGlobalObject());
2837    return JSObject::cast(proto)->DefineAccessor(name, is_getter,
2838                                                 fun, attributes);
2839  }
2840
2841  Object* array = DefineGetterSetter(name, attributes);
2842  if (array->IsFailure() || array->IsUndefined()) return array;
2843  FixedArray::cast(array)->set(is_getter ? 0 : 1, fun);
2844  return this;
2845}
2846
2847
2848Object* JSObject::LookupAccessor(String* name, bool is_getter) {
2849  // Make sure that the top context does not change when doing callbacks or
2850  // interceptor calls.
2851  AssertNoContextChange ncc;
2852
2853  // Check access rights if needed.
2854  if (IsAccessCheckNeeded() &&
2855      !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
2856    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
2857    return Heap::undefined_value();
2858  }
2859
2860  // Make the lookup and include prototypes.
2861  int accessor_index = is_getter ? kGetterIndex : kSetterIndex;
2862  uint32_t index;
2863  if (name->AsArrayIndex(&index)) {
2864    for (Object* obj = this;
2865         obj != Heap::null_value();
2866         obj = JSObject::cast(obj)->GetPrototype()) {
2867      JSObject* js_object = JSObject::cast(obj);
2868      if (js_object->HasDictionaryElements()) {
2869        NumberDictionary* dictionary = js_object->element_dictionary();
2870        int entry = dictionary->FindEntry(index);
2871        if (entry != NumberDictionary::kNotFound) {
2872          Object* element = dictionary->ValueAt(entry);
2873          PropertyDetails details = dictionary->DetailsAt(entry);
2874          if (details.type() == CALLBACKS) {
2875            // Only accessors allowed as elements.
2876            return FixedArray::cast(element)->get(accessor_index);
2877          }
2878        }
2879      }
2880    }
2881  } else {
2882    for (Object* obj = this;
2883         obj != Heap::null_value();
2884         obj = JSObject::cast(obj)->GetPrototype()) {
2885      LookupResult result;
2886      JSObject::cast(obj)->LocalLookup(name, &result);
2887      if (result.IsProperty()) {
2888        if (result.IsReadOnly()) return Heap::undefined_value();
2889        if (result.type() == CALLBACKS) {
2890          Object* obj = result.GetCallbackObject();
2891          if (obj->IsFixedArray()) {
2892            return FixedArray::cast(obj)->get(accessor_index);
2893          }
2894        }
2895      }
2896    }
2897  }
2898  return Heap::undefined_value();
2899}
2900
2901
2902Object* JSObject::SlowReverseLookup(Object* value) {
2903  if (HasFastProperties()) {
2904    DescriptorArray* descs = map()->instance_descriptors();
2905    for (int i = 0; i < descs->number_of_descriptors(); i++) {
2906      if (descs->GetType(i) == FIELD) {
2907        if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
2908          return descs->GetKey(i);
2909        }
2910      } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
2911        if (descs->GetConstantFunction(i) == value) {
2912          return descs->GetKey(i);
2913        }
2914      }
2915    }
2916    return Heap::undefined_value();
2917  } else {
2918    return property_dictionary()->SlowReverseLookup(value);
2919  }
2920}
2921
2922
2923Object* Map::CopyDropDescriptors() {
2924  Object* result = Heap::AllocateMap(instance_type(), instance_size());
2925  if (result->IsFailure()) return result;
2926  Map::cast(result)->set_prototype(prototype());
2927  Map::cast(result)->set_constructor(constructor());
2928  // Don't copy descriptors, so map transitions always remain a forest.
2929  // If we retained the same descriptors we would have two maps
2930  // pointing to the same transition which is bad because the garbage
2931  // collector relies on being able to reverse pointers from transitions
2932  // to maps.  If properties need to be retained use CopyDropTransitions.
2933  Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array());
2934  // Please note instance_type and instance_size are set when allocated.
2935  Map::cast(result)->set_inobject_properties(inobject_properties());
2936  Map::cast(result)->set_unused_property_fields(unused_property_fields());
2937
2938  // If the map has pre-allocated properties always start out with a descriptor
2939  // array describing these properties.
2940  if (pre_allocated_property_fields() > 0) {
2941    ASSERT(constructor()->IsJSFunction());
2942    JSFunction* ctor = JSFunction::cast(constructor());
2943    Object* descriptors =
2944        ctor->initial_map()->instance_descriptors()->RemoveTransitions();
2945    if (descriptors->IsFailure()) return descriptors;
2946    Map::cast(result)->set_instance_descriptors(
2947        DescriptorArray::cast(descriptors));
2948    Map::cast(result)->set_pre_allocated_property_fields(
2949        pre_allocated_property_fields());
2950  }
2951  Map::cast(result)->set_bit_field(bit_field());
2952  Map::cast(result)->set_bit_field2(bit_field2());
2953  Map::cast(result)->ClearCodeCache();
2954  return result;
2955}
2956
2957
2958Object* Map::CopyDropTransitions() {
2959  Object* new_map = CopyDropDescriptors();
2960  if (new_map->IsFailure()) return new_map;
2961  Object* descriptors = instance_descriptors()->RemoveTransitions();
2962  if (descriptors->IsFailure()) return descriptors;
2963  cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
2964  return cast(new_map);
2965}
2966
2967
2968Object* Map::UpdateCodeCache(String* name, Code* code) {
2969  ASSERT(code->ic_state() == MONOMORPHIC);
2970  FixedArray* cache = code_cache();
2971
2972  // When updating the code cache we disregard the type encoded in the
2973  // flags. This allows call constant stubs to overwrite call field
2974  // stubs, etc.
2975  Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
2976
2977  // First check whether we can update existing code cache without
2978  // extending it.
2979  int length = cache->length();
2980  int deleted_index = -1;
2981  for (int i = 0; i < length; i += 2) {
2982    Object* key = cache->get(i);
2983    if (key->IsNull()) {
2984      if (deleted_index < 0) deleted_index = i;
2985      continue;
2986    }
2987    if (key->IsUndefined()) {
2988      if (deleted_index >= 0) i = deleted_index;
2989      cache->set(i + 0, name);
2990      cache->set(i + 1, code);
2991      return this;
2992    }
2993    if (name->Equals(String::cast(key))) {
2994      Code::Flags found = Code::cast(cache->get(i + 1))->flags();
2995      if (Code::RemoveTypeFromFlags(found) == flags) {
2996        cache->set(i + 1, code);
2997        return this;
2998      }
2999    }
3000  }
3001
3002  // Reached the end of the code cache.  If there were deleted
3003  // elements, reuse the space for the first of them.
3004  if (deleted_index >= 0) {
3005    cache->set(deleted_index + 0, name);
3006    cache->set(deleted_index + 1, code);
3007    return this;
3008  }
3009
3010  // Extend the code cache with some new entries (at least one).
3011  int new_length = length + ((length >> 1) & ~1) + 2;
3012  ASSERT((new_length & 1) == 0);  // must be a multiple of two
3013  Object* result = cache->CopySize(new_length);
3014  if (result->IsFailure()) return result;
3015
3016  // Add the (name, code) pair to the new cache.
3017  cache = FixedArray::cast(result);
3018  cache->set(length + 0, name);
3019  cache->set(length + 1, code);
3020  set_code_cache(cache);
3021  return this;
3022}
3023
3024
3025Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
3026  FixedArray* cache = code_cache();
3027  int length = cache->length();
3028  for (int i = 0; i < length; i += 2) {
3029    Object* key = cache->get(i);
3030    // Skip deleted elements.
3031    if (key->IsNull()) continue;
3032    if (key->IsUndefined()) return key;
3033    if (name->Equals(String::cast(key))) {
3034      Code* code = Code::cast(cache->get(i + 1));
3035      if (code->flags() == flags) return code;
3036    }
3037  }
3038  return Heap::undefined_value();
3039}
3040
3041
3042int Map::IndexInCodeCache(Code* code) {
3043  FixedArray* array = code_cache();
3044  int len = array->length();
3045  for (int i = 0; i < len; i += 2) {
3046    if (array->get(i + 1) == code) return i + 1;
3047  }
3048  return -1;
3049}
3050
3051
3052void Map::RemoveFromCodeCache(int index) {
3053  FixedArray* array = code_cache();
3054  ASSERT(array->length() >= index && array->get(index)->IsCode());
3055  // Use null instead of undefined for deleted elements to distinguish
3056  // deleted elements from unused elements.  This distinction is used
3057  // when looking up in the cache and when updating the cache.
3058  array->set_null(index - 1);  // key
3059  array->set_null(index);  // code
3060}
3061
3062
3063void FixedArray::FixedArrayIterateBody(ObjectVisitor* v) {
3064  IteratePointers(v, kHeaderSize, kHeaderSize + length() * kPointerSize);
3065}
3066
3067
3068static bool HasKey(FixedArray* array, Object* key) {
3069  int len0 = array->length();
3070  for (int i = 0; i < len0; i++) {
3071    Object* element = array->get(i);
3072    if (element->IsSmi() && key->IsSmi() && (element == key)) return true;
3073    if (element->IsString() &&
3074        key->IsString() && String::cast(element)->Equals(String::cast(key))) {
3075      return true;
3076    }
3077  }
3078  return false;
3079}
3080
3081
3082Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
3083  ASSERT(!array->HasPixelElements() && !array->HasExternalArrayElements());
3084  switch (array->GetElementsKind()) {
3085    case JSObject::FAST_ELEMENTS:
3086      return UnionOfKeys(FixedArray::cast(array->elements()));
3087    case JSObject::DICTIONARY_ELEMENTS: {
3088      NumberDictionary* dict = array->element_dictionary();
3089      int size = dict->NumberOfElements();
3090
3091      // Allocate a temporary fixed array.
3092      Object* object = Heap::AllocateFixedArray(size);
3093      if (object->IsFailure()) return object;
3094      FixedArray* key_array = FixedArray::cast(object);
3095
3096      int capacity = dict->Capacity();
3097      int pos = 0;
3098      // Copy the elements from the JSArray to the temporary fixed array.
3099      for (int i = 0; i < capacity; i++) {
3100        if (dict->IsKey(dict->KeyAt(i))) {
3101          key_array->set(pos++, dict->ValueAt(i));
3102        }
3103      }
3104      // Compute the union of this and the temporary fixed array.
3105      return UnionOfKeys(key_array);
3106    }
3107    default:
3108      UNREACHABLE();
3109  }
3110  UNREACHABLE();
3111  return Heap::null_value();  // Failure case needs to "return" a value.
3112}
3113
3114
3115Object* FixedArray::UnionOfKeys(FixedArray* other) {
3116  int len0 = length();
3117  int len1 = other->length();
3118  // Optimize if either is empty.
3119  if (len0 == 0) return other;
3120  if (len1 == 0) return this;
3121
3122  // Compute how many elements are not in this.
3123  int extra = 0;
3124  for (int y = 0; y < len1; y++) {
3125    Object* value = other->get(y);
3126    if (!value->IsTheHole() && !HasKey(this, value)) extra++;
3127  }
3128
3129  if (extra == 0) return this;
3130
3131  // Allocate the result
3132  Object* obj = Heap::AllocateFixedArray(len0 + extra);
3133  if (obj->IsFailure()) return obj;
3134  // Fill in the content
3135  AssertNoAllocation no_gc;
3136  FixedArray* result = FixedArray::cast(obj);
3137  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
3138  for (int i = 0; i < len0; i++) {
3139    result->set(i, get(i), mode);
3140  }
3141  // Fill in the extra keys.
3142  int index = 0;
3143  for (int y = 0; y < len1; y++) {
3144    Object* value = other->get(y);
3145    if (!value->IsTheHole() && !HasKey(this, value)) {
3146      result->set(len0 + index, other->get(y), mode);
3147      index++;
3148    }
3149  }
3150  ASSERT(extra == index);
3151  return result;
3152}
3153
3154
3155Object* FixedArray::CopySize(int new_length) {
3156  if (new_length == 0) return Heap::empty_fixed_array();
3157  Object* obj = Heap::AllocateFixedArray(new_length);
3158  if (obj->IsFailure()) return obj;
3159  FixedArray* result = FixedArray::cast(obj);
3160  // Copy the content
3161  AssertNoAllocation no_gc;
3162  int len = length();
3163  if (new_length < len) len = new_length;
3164  result->set_map(map());
3165  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
3166  for (int i = 0; i < len; i++) {
3167    result->set(i, get(i), mode);
3168  }
3169  return result;
3170}
3171
3172
3173void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
3174  AssertNoAllocation no_gc;
3175  WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
3176  for (int index = 0; index < len; index++) {
3177    dest->set(dest_pos+index, get(pos+index), mode);
3178  }
3179}
3180
3181
3182#ifdef DEBUG
3183bool FixedArray::IsEqualTo(FixedArray* other) {
3184  if (length() != other->length()) return false;
3185  for (int i = 0 ; i < length(); ++i) {
3186    if (get(i) != other->get(i)) return false;
3187  }
3188  return true;
3189}
3190#endif
3191
3192
3193Object* DescriptorArray::Allocate(int number_of_descriptors) {
3194  if (number_of_descriptors == 0) {
3195    return Heap::empty_descriptor_array();
3196  }
3197  // Allocate the array of keys.
3198  Object* array =
3199      Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors));
3200  if (array->IsFailure()) return array;
3201  // Do not use DescriptorArray::cast on incomplete object.
3202  FixedArray* result = FixedArray::cast(array);
3203
3204  // Allocate the content array and set it in the descriptor array.
3205  array = Heap::AllocateFixedArray(number_of_descriptors << 1);
3206  if (array->IsFailure()) return array;
3207  result->set(kContentArrayIndex, array);
3208  result->set(kEnumerationIndexIndex,
3209              Smi::FromInt(PropertyDetails::kInitialIndex));
3210  return result;
3211}
3212
3213
3214void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
3215                                   FixedArray* new_cache) {
3216  ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
3217  if (HasEnumCache()) {
3218    FixedArray::cast(get(kEnumerationIndexIndex))->
3219      set(kEnumCacheBridgeCacheIndex, new_cache);
3220  } else {
3221    if (IsEmpty()) return;  // Do nothing for empty descriptor array.
3222    FixedArray::cast(bridge_storage)->
3223      set(kEnumCacheBridgeCacheIndex, new_cache);
3224    fast_set(FixedArray::cast(bridge_storage),
3225             kEnumCacheBridgeEnumIndex,
3226             get(kEnumerationIndexIndex));
3227    set(kEnumerationIndexIndex, bridge_storage);
3228  }
3229}
3230
3231
3232Object* DescriptorArray::CopyInsert(Descriptor* descriptor,
3233                                    TransitionFlag transition_flag) {
3234  // Transitions are only kept when inserting another transition.
3235  // This precondition is not required by this function's implementation, but
3236  // is currently required by the semantics of maps, so we check it.
3237  // Conversely, we filter after replacing, so replacing a transition and
3238  // removing all other transitions is not supported.
3239  bool remove_transitions = transition_flag == REMOVE_TRANSITIONS;
3240  ASSERT(remove_transitions == !descriptor->GetDetails().IsTransition());
3241  ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR);
3242
3243  // Ensure the key is a symbol.
3244  Object* result = descriptor->KeyToSymbol();
3245  if (result->IsFailure()) return result;
3246
3247  int transitions = 0;
3248  int null_descriptors = 0;
3249  if (remove_transitions) {
3250    for (int i = 0; i < number_of_descriptors(); i++) {
3251      if (IsTransition(i)) transitions++;
3252      if (IsNullDescriptor(i)) null_descriptors++;
3253    }
3254  } else {
3255    for (int i = 0; i < number_of_descriptors(); i++) {
3256      if (IsNullDescriptor(i)) null_descriptors++;
3257    }
3258  }
3259  int new_size = number_of_descriptors() - transitions - null_descriptors;
3260
3261  // If key is in descriptor, we replace it in-place when filtering.
3262  // Count a null descriptor for key as inserted, not replaced.
3263  int index = Search(descriptor->GetKey());
3264  const bool inserting = (index == kNotFound);
3265  const bool replacing = !inserting;
3266  bool keep_enumeration_index = false;
3267  if (inserting) {
3268    ++new_size;
3269  }
3270  if (replacing) {
3271    // We are replacing an existing descriptor.  We keep the enumeration
3272    // index of a visible property.
3273    PropertyType t = PropertyDetails(GetDetails(index)).type();
3274    if (t == CONSTANT_FUNCTION ||
3275        t == FIELD ||
3276        t == CALLBACKS ||
3277        t == INTERCEPTOR) {
3278      keep_enumeration_index = true;
3279    } else if (remove_transitions) {
3280     // Replaced descriptor has been counted as removed if it is
3281     // a transition that will be replaced.  Adjust count in this case.
3282      ++new_size;
3283    }
3284  }
3285  result = Allocate(new_size);
3286  if (result->IsFailure()) return result;
3287  DescriptorArray* new_descriptors = DescriptorArray::cast(result);
3288  // Set the enumeration index in the descriptors and set the enumeration index
3289  // in the result.
3290  int enumeration_index = NextEnumerationIndex();
3291  if (!descriptor->GetDetails().IsTransition()) {
3292    if (keep_enumeration_index) {
3293      descriptor->SetEnumerationIndex(
3294          PropertyDetails(GetDetails(index)).index());
3295    } else {
3296      descriptor->SetEnumerationIndex(enumeration_index);
3297      ++enumeration_index;
3298    }
3299  }
3300  new_descriptors->SetNextEnumerationIndex(enumeration_index);
3301
3302  // Copy the descriptors, filtering out transitions and null descriptors,
3303  // and inserting or replacing a descriptor.
3304  uint32_t descriptor_hash = descriptor->GetKey()->Hash();
3305  int from_index = 0;
3306  int to_index = 0;
3307
3308  for (; from_index < number_of_descriptors(); from_index++) {
3309    String* key = GetKey(from_index);
3310    if (key->Hash() > descriptor_hash || key == descriptor->GetKey()) {
3311      break;
3312    }
3313    if (IsNullDescriptor(from_index)) continue;
3314    if (remove_transitions && IsTransition(from_index)) continue;
3315    new_descriptors->CopyFrom(to_index++, this, from_index);
3316  }
3317
3318  new_descriptors->Set(to_index++, descriptor);
3319  if (replacing) from_index++;
3320
3321  for (; from_index < number_of_descriptors(); from_index++) {
3322    if (IsNullDescriptor(from_index)) continue;
3323    if (remove_transitions && IsTransition(from_index)) continue;
3324    new_descriptors->CopyFrom(to_index++, this, from_index);
3325  }
3326
3327  ASSERT(to_index == new_descriptors->number_of_descriptors());
3328  SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
3329
3330  return new_descriptors;
3331}
3332
3333
3334Object* DescriptorArray::RemoveTransitions() {
3335  // Remove all transitions and null descriptors. Return a copy of the array
3336  // with all transitions removed, or a Failure object if the new array could
3337  // not be allocated.
3338
3339  // Compute the size of the map transition entries to be removed.
3340  int num_removed = 0;
3341  for (int i = 0; i < number_of_descriptors(); i++) {
3342    if (!IsProperty(i)) num_removed++;
3343  }
3344
3345  // Allocate the new descriptor array.
3346  Object* result = Allocate(number_of_descriptors() - num_removed);
3347  if (result->IsFailure()) return result;
3348  DescriptorArray* new_descriptors = DescriptorArray::cast(result);
3349
3350  // Copy the content.
3351  int next_descriptor = 0;
3352  for (int i = 0; i < number_of_descriptors(); i++) {
3353    if (IsProperty(i)) new_descriptors->CopyFrom(next_descriptor++, this, i);
3354  }
3355  ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
3356
3357  return new_descriptors;
3358}
3359
3360
3361void DescriptorArray::Sort() {
3362  // In-place heap sort.
3363  int len = number_of_descriptors();
3364
3365  // Bottom-up max-heap construction.
3366  for (int i = 1; i < len; ++i) {
3367    int child_index = i;
3368    while (child_index > 0) {
3369      int parent_index = ((child_index + 1) >> 1) - 1;
3370      uint32_t parent_hash = GetKey(parent_index)->Hash();
3371      uint32_t child_hash = GetKey(child_index)->Hash();
3372      if (parent_hash < child_hash) {
3373        Swap(parent_index, child_index);
3374      } else {
3375        break;
3376      }
3377      child_index = parent_index;
3378    }
3379  }
3380
3381  // Extract elements and create sorted array.
3382  for (int i = len - 1; i > 0; --i) {
3383    // Put max element at the back of the array.
3384    Swap(0, i);
3385    // Sift down the new top element.
3386    int parent_index = 0;
3387    while (true) {
3388      int child_index = ((parent_index + 1) << 1) - 1;
3389      if (child_index >= i) break;
3390      uint32_t child1_hash = GetKey(child_index)->Hash();
3391      uint32_t child2_hash = GetKey(child_index + 1)->Hash();
3392      uint32_t parent_hash = GetKey(parent_index)->Hash();
3393      if (child_index + 1 >= i || child1_hash > child2_hash) {
3394        if (parent_hash > child1_hash) break;
3395        Swap(parent_index, child_index);
3396        parent_index = child_index;
3397      } else {
3398        if (parent_hash > child2_hash) break;
3399        Swap(parent_index, child_index + 1);
3400        parent_index = child_index + 1;
3401      }
3402    }
3403  }
3404
3405  SLOW_ASSERT(IsSortedNoDuplicates());
3406}
3407
3408
3409int DescriptorArray::BinarySearch(String* name, int low, int high) {
3410  uint32_t hash = name->Hash();
3411
3412  while (low <= high) {
3413    int mid = (low + high) / 2;
3414    String* mid_name = GetKey(mid);
3415    uint32_t mid_hash = mid_name->Hash();
3416
3417    if (mid_hash > hash) {
3418      high = mid - 1;
3419      continue;
3420    }
3421    if (mid_hash < hash) {
3422      low = mid + 1;
3423      continue;
3424    }
3425    // Found an element with the same hash-code.
3426    ASSERT(hash == mid_hash);
3427    // There might be more, so we find the first one and
3428    // check them all to see if we have a match.
3429    if (name == mid_name  && !is_null_descriptor(mid)) return mid;
3430    while ((mid > low) && (GetKey(mid - 1)->Hash() == hash)) mid--;
3431    for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) {
3432      if (GetKey(mid)->Equals(name) && !is_null_descriptor(mid)) return mid;
3433    }
3434    break;
3435  }
3436  return kNotFound;
3437}
3438
3439
3440int DescriptorArray::LinearSearch(String* name, int len) {
3441  uint32_t hash = name->Hash();
3442  for (int number = 0; number < len; number++) {
3443    String* entry = GetKey(number);
3444    if ((entry->Hash() == hash) &&
3445        name->Equals(entry) &&
3446        !is_null_descriptor(number)) {
3447      return number;
3448    }
3449  }
3450  return kNotFound;
3451}
3452
3453
3454#ifdef DEBUG
3455bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
3456  if (IsEmpty()) return other->IsEmpty();
3457  if (other->IsEmpty()) return false;
3458  if (length() != other->length()) return false;
3459  for (int i = 0; i < length(); ++i) {
3460    if (get(i) != other->get(i) && i != kContentArrayIndex) return false;
3461  }
3462  return GetContentArray()->IsEqualTo(other->GetContentArray());
3463}
3464#endif
3465
3466
3467static StaticResource<StringInputBuffer> string_input_buffer;
3468
3469
3470bool String::LooksValid() {
3471  if (!Heap::Contains(this)) return false;
3472  return true;
3473}
3474
3475
3476int String::Utf8Length() {
3477  if (IsAsciiRepresentation()) return length();
3478  // Attempt to flatten before accessing the string.  It probably
3479  // doesn't make Utf8Length faster, but it is very likely that
3480  // the string will be accessed later (for example by WriteUtf8)
3481  // so it's still a good idea.
3482  TryFlattenIfNotFlat();
3483  Access<StringInputBuffer> buffer(&string_input_buffer);
3484  buffer->Reset(0, this);
3485  int result = 0;
3486  while (buffer->has_more())
3487    result += unibrow::Utf8::Length(buffer->GetNext());
3488  return result;
3489}
3490
3491
3492Vector<const char> String::ToAsciiVector() {
3493  ASSERT(IsAsciiRepresentation());
3494  ASSERT(IsFlat());
3495
3496  int offset = 0;
3497  int length = this->length();
3498  StringRepresentationTag string_tag = StringShape(this).representation_tag();
3499  String* string = this;
3500  if (string_tag == kConsStringTag) {
3501    ConsString* cons = ConsString::cast(string);
3502    ASSERT(cons->second()->length() == 0);
3503    string = cons->first();
3504    string_tag = StringShape(string).representation_tag();
3505  }
3506  if (string_tag == kSeqStringTag) {
3507    SeqAsciiString* seq = SeqAsciiString::cast(string);
3508    char* start = seq->GetChars();
3509    return Vector<const char>(start + offset, length);
3510  }
3511  ASSERT(string_tag == kExternalStringTag);
3512  ExternalAsciiString* ext = ExternalAsciiString::cast(string);
3513  const char* start = ext->resource()->data();
3514  return Vector<const char>(start + offset, length);
3515}
3516
3517
3518Vector<const uc16> String::ToUC16Vector() {
3519  ASSERT(IsTwoByteRepresentation());
3520  ASSERT(IsFlat());
3521
3522  int offset = 0;
3523  int length = this->length();
3524  StringRepresentationTag string_tag = StringShape(this).representation_tag();
3525  String* string = this;
3526  if (string_tag == kConsStringTag) {
3527    ConsString* cons = ConsString::cast(string);
3528    ASSERT(cons->second()->length() == 0);
3529    string = cons->first();
3530    string_tag = StringShape(string).representation_tag();
3531  }
3532  if (string_tag == kSeqStringTag) {
3533    SeqTwoByteString* seq = SeqTwoByteString::cast(string);
3534    return Vector<const uc16>(seq->GetChars() + offset, length);
3535  }
3536  ASSERT(string_tag == kExternalStringTag);
3537  ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
3538  const uc16* start =
3539      reinterpret_cast<const uc16*>(ext->resource()->data());
3540  return Vector<const uc16>(start + offset, length);
3541}
3542
3543
3544SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
3545                                     RobustnessFlag robust_flag,
3546                                     int offset,
3547                                     int length,
3548                                     int* length_return) {
3549  ASSERT(NativeAllocationChecker::allocation_allowed());
3550  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
3551    return SmartPointer<char>(NULL);
3552  }
3553
3554  // Negative length means the to the end of the string.
3555  if (length < 0) length = kMaxInt - offset;
3556
3557  // Compute the size of the UTF-8 string. Start at the specified offset.
3558  Access<StringInputBuffer> buffer(&string_input_buffer);
3559  buffer->Reset(offset, this);
3560  int character_position = offset;
3561  int utf8_bytes = 0;
3562  while (buffer->has_more()) {
3563    uint16_t character = buffer->GetNext();
3564    if (character_position < offset + length) {
3565      utf8_bytes += unibrow::Utf8::Length(character);
3566    }
3567    character_position++;
3568  }
3569
3570  if (length_return) {
3571    *length_return = utf8_bytes;
3572  }
3573
3574  char* result = NewArray<char>(utf8_bytes + 1);
3575
3576  // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
3577  buffer->Rewind();
3578  buffer->Seek(offset);
3579  character_position = offset;
3580  int utf8_byte_position = 0;
3581  while (buffer->has_more()) {
3582    uint16_t character = buffer->GetNext();
3583    if (character_position < offset + length) {
3584      if (allow_nulls == DISALLOW_NULLS && character == 0) {
3585        character = ' ';
3586      }
3587      utf8_byte_position +=
3588          unibrow::Utf8::Encode(result + utf8_byte_position, character);
3589    }
3590    character_position++;
3591  }
3592  result[utf8_byte_position] = 0;
3593  return SmartPointer<char>(result);
3594}
3595
3596
3597SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
3598                                     RobustnessFlag robust_flag,
3599                                     int* length_return) {
3600  return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
3601}
3602
3603
3604const uc16* String::GetTwoByteData() {
3605  return GetTwoByteData(0);
3606}
3607
3608
3609const uc16* String::GetTwoByteData(unsigned start) {
3610  ASSERT(!IsAsciiRepresentation());
3611  switch (StringShape(this).representation_tag()) {
3612    case kSeqStringTag:
3613      return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
3614    case kExternalStringTag:
3615      return ExternalTwoByteString::cast(this)->
3616        ExternalTwoByteStringGetData(start);
3617    case kConsStringTag:
3618      UNREACHABLE();
3619      return NULL;
3620  }
3621  UNREACHABLE();
3622  return NULL;
3623}
3624
3625
3626SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
3627  ASSERT(NativeAllocationChecker::allocation_allowed());
3628
3629  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
3630    return SmartPointer<uc16>();
3631  }
3632
3633  Access<StringInputBuffer> buffer(&string_input_buffer);
3634  buffer->Reset(this);
3635
3636  uc16* result = NewArray<uc16>(length() + 1);
3637
3638  int i = 0;
3639  while (buffer->has_more()) {
3640    uint16_t character = buffer->GetNext();
3641    result[i++] = character;
3642  }
3643  result[i] = 0;
3644  return SmartPointer<uc16>(result);
3645}
3646
3647
3648const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
3649  return reinterpret_cast<uc16*>(
3650      reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
3651}
3652
3653
3654void SeqTwoByteString::SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
3655                                                           unsigned* offset_ptr,
3656                                                           unsigned max_chars) {
3657  unsigned chars_read = 0;
3658  unsigned offset = *offset_ptr;
3659  while (chars_read < max_chars) {
3660    uint16_t c = *reinterpret_cast<uint16_t*>(
3661        reinterpret_cast<char*>(this) -
3662            kHeapObjectTag + kHeaderSize + offset * kShortSize);
3663    if (c <= kMaxAsciiCharCode) {
3664      // Fast case for ASCII characters.   Cursor is an input output argument.
3665      if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
3666                                                          rbb->util_buffer,
3667                                                          rbb->capacity,
3668                                                          rbb->cursor)) {
3669        break;
3670      }
3671    } else {
3672      if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
3673                                                             rbb->util_buffer,
3674                                                             rbb->capacity,
3675                                                             rbb->cursor)) {
3676        break;
3677      }
3678    }
3679    offset++;
3680    chars_read++;
3681  }
3682  *offset_ptr = offset;
3683  rbb->remaining += chars_read;
3684}
3685
3686
3687const unibrow::byte* SeqAsciiString::SeqAsciiStringReadBlock(
3688    unsigned* remaining,
3689    unsigned* offset_ptr,
3690    unsigned max_chars) {
3691  const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
3692      kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
3693  *remaining = max_chars;
3694  *offset_ptr += max_chars;
3695  return b;
3696}
3697
3698
3699// This will iterate unless the block of string data spans two 'halves' of
3700// a ConsString, in which case it will recurse.  Since the block of string
3701// data to be read has a maximum size this limits the maximum recursion
3702// depth to something sane.  Since C++ does not have tail call recursion
3703// elimination, the iteration must be explicit. Since this is not an
3704// -IntoBuffer method it can delegate to one of the efficient
3705// *AsciiStringReadBlock routines.
3706const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
3707                                                     unsigned* offset_ptr,
3708                                                     unsigned max_chars) {
3709  ConsString* current = this;
3710  unsigned offset = *offset_ptr;
3711  int offset_correction = 0;
3712
3713  while (true) {
3714    String* left = current->first();
3715    unsigned left_length = (unsigned)left->length();
3716    if (left_length > offset &&
3717        (max_chars <= left_length - offset ||
3718         (rbb->capacity <= left_length - offset &&
3719          (max_chars = left_length - offset, true)))) {  // comma operator!
3720      // Left hand side only - iterate unless we have reached the bottom of
3721      // the cons tree.  The assignment on the left of the comma operator is
3722      // in order to make use of the fact that the -IntoBuffer routines can
3723      // produce at most 'capacity' characters.  This enables us to postpone
3724      // the point where we switch to the -IntoBuffer routines (below) in order
3725      // to maximize the chances of delegating a big chunk of work to the
3726      // efficient *AsciiStringReadBlock routines.
3727      if (StringShape(left).IsCons()) {
3728        current = ConsString::cast(left);
3729        continue;
3730      } else {
3731        const unibrow::byte* answer =
3732            String::ReadBlock(left, rbb, &offset, max_chars);
3733        *offset_ptr = offset + offset_correction;
3734        return answer;
3735      }
3736    } else if (left_length <= offset) {
3737      // Right hand side only - iterate unless we have reached the bottom of
3738      // the cons tree.
3739      String* right = current->second();
3740      offset -= left_length;
3741      offset_correction += left_length;
3742      if (StringShape(right).IsCons()) {
3743        current = ConsString::cast(right);
3744        continue;
3745      } else {
3746        const unibrow::byte* answer =
3747            String::ReadBlock(right, rbb, &offset, max_chars);
3748        *offset_ptr = offset + offset_correction;
3749        return answer;
3750      }
3751    } else {
3752      // The block to be read spans two sides of the ConsString, so we call the
3753      // -IntoBuffer version, which will recurse.  The -IntoBuffer methods
3754      // are able to assemble data from several part strings because they use
3755      // the util_buffer to store their data and never return direct pointers
3756      // to their storage.  We don't try to read more than the buffer capacity
3757      // here or we can get too much recursion.
3758      ASSERT(rbb->remaining == 0);
3759      ASSERT(rbb->cursor == 0);
3760      current->ConsStringReadBlockIntoBuffer(
3761          rbb,
3762          &offset,
3763          max_chars > rbb->capacity ? rbb->capacity : max_chars);
3764      *offset_ptr = offset + offset_correction;
3765      return rbb->util_buffer;
3766    }
3767  }
3768}
3769
3770
3771uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
3772  ASSERT(index >= 0 && index < length());
3773  return resource()->data()[index];
3774}
3775
3776
3777const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock(
3778      unsigned* remaining,
3779      unsigned* offset_ptr,
3780      unsigned max_chars) {
3781  // Cast const char* to unibrow::byte* (signedness difference).
3782  const unibrow::byte* b =
3783      reinterpret_cast<const unibrow::byte*>(resource()->data()) + *offset_ptr;
3784  *remaining = max_chars;
3785  *offset_ptr += max_chars;
3786  return b;
3787}
3788
3789
3790const uc16* ExternalTwoByteString::ExternalTwoByteStringGetData(
3791      unsigned start) {
3792  return resource()->data() + start;
3793}
3794
3795
3796uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
3797  ASSERT(index >= 0 && index < length());
3798  return resource()->data()[index];
3799}
3800
3801
3802void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer(
3803      ReadBlockBuffer* rbb,
3804      unsigned* offset_ptr,
3805      unsigned max_chars) {
3806  unsigned chars_read = 0;
3807  unsigned offset = *offset_ptr;
3808  const uint16_t* data = resource()->data();
3809  while (chars_read < max_chars) {
3810    uint16_t c = data[offset];
3811    if (c <= kMaxAsciiCharCode) {
3812      // Fast case for ASCII characters. Cursor is an input output argument.
3813      if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
3814                                                          rbb->util_buffer,
3815                                                          rbb->capacity,
3816                                                          rbb->cursor))
3817        break;
3818    } else {
3819      if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
3820                                                             rbb->util_buffer,
3821                                                             rbb->capacity,
3822                                                             rbb->cursor))
3823        break;
3824    }
3825    offset++;
3826    chars_read++;
3827  }
3828  *offset_ptr = offset;
3829  rbb->remaining += chars_read;
3830}
3831
3832
3833void SeqAsciiString::SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
3834                                                 unsigned* offset_ptr,
3835                                                 unsigned max_chars) {
3836  unsigned capacity = rbb->capacity - rbb->cursor;
3837  if (max_chars > capacity) max_chars = capacity;
3838  memcpy(rbb->util_buffer + rbb->cursor,
3839         reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
3840             *offset_ptr * kCharSize,
3841         max_chars);
3842  rbb->remaining += max_chars;
3843  *offset_ptr += max_chars;
3844  rbb->cursor += max_chars;
3845}
3846
3847
3848void ExternalAsciiString::ExternalAsciiStringReadBlockIntoBuffer(
3849      ReadBlockBuffer* rbb,
3850      unsigned* offset_ptr,
3851      unsigned max_chars) {
3852  unsigned capacity = rbb->capacity - rbb->cursor;
3853  if (max_chars > capacity) max_chars = capacity;
3854  memcpy(rbb->util_buffer + rbb->cursor,
3855         resource()->data() + *offset_ptr,
3856         max_chars);
3857  rbb->remaining += max_chars;
3858  *offset_ptr += max_chars;
3859  rbb->cursor += max_chars;
3860}
3861
3862
3863// This method determines the type of string involved and then copies
3864// a whole chunk of characters into a buffer, or returns a pointer to a buffer
3865// where they can be found.  The pointer is not necessarily valid across a GC
3866// (see AsciiStringReadBlock).
3867const unibrow::byte* String::ReadBlock(String* input,
3868                                       ReadBlockBuffer* rbb,
3869                                       unsigned* offset_ptr,
3870                                       unsigned max_chars) {
3871  ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
3872  if (max_chars == 0) {
3873    rbb->remaining = 0;
3874    return NULL;
3875  }
3876  switch (StringShape(input).representation_tag()) {
3877    case kSeqStringTag:
3878      if (input->IsAsciiRepresentation()) {
3879        SeqAsciiString* str = SeqAsciiString::cast(input);
3880        return str->SeqAsciiStringReadBlock(&rbb->remaining,
3881                                            offset_ptr,
3882                                            max_chars);
3883      } else {
3884        SeqTwoByteString* str = SeqTwoByteString::cast(input);
3885        str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
3886                                                 offset_ptr,
3887                                                 max_chars);
3888        return rbb->util_buffer;
3889      }
3890    case kConsStringTag:
3891      return ConsString::cast(input)->ConsStringReadBlock(rbb,
3892                                                          offset_ptr,
3893                                                          max_chars);
3894    case kExternalStringTag:
3895      if (input->IsAsciiRepresentation()) {
3896        return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
3897            &rbb->remaining,
3898            offset_ptr,
3899            max_chars);
3900      } else {
3901        ExternalTwoByteString::cast(input)->
3902            ExternalTwoByteStringReadBlockIntoBuffer(rbb,
3903                                                     offset_ptr,
3904                                                     max_chars);
3905        return rbb->util_buffer;
3906      }
3907    default:
3908      break;
3909  }
3910
3911  UNREACHABLE();
3912  return 0;
3913}
3914
3915
3916Relocatable* Relocatable::top_ = NULL;
3917
3918
3919void Relocatable::PostGarbageCollectionProcessing() {
3920  Relocatable* current = top_;
3921  while (current != NULL) {
3922    current->PostGarbageCollection();
3923    current = current->prev_;
3924  }
3925}
3926
3927
3928// Reserve space for statics needing saving and restoring.
3929int Relocatable::ArchiveSpacePerThread() {
3930  return sizeof(top_);
3931}
3932
3933
3934// Archive statics that are thread local.
3935char* Relocatable::ArchiveState(char* to) {
3936  *reinterpret_cast<Relocatable**>(to) = top_;
3937  top_ = NULL;
3938  return to + ArchiveSpacePerThread();
3939}
3940
3941
3942// Restore statics that are thread local.
3943char* Relocatable::RestoreState(char* from) {
3944  top_ = *reinterpret_cast<Relocatable**>(from);
3945  return from + ArchiveSpacePerThread();
3946}
3947
3948
3949char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
3950  Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
3951  Iterate(v, top);
3952  return thread_storage + ArchiveSpacePerThread();
3953}
3954
3955
3956void Relocatable::Iterate(ObjectVisitor* v) {
3957  Iterate(v, top_);
3958}
3959
3960
3961void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
3962  Relocatable* current = top;
3963  while (current != NULL) {
3964    current->IterateInstance(v);
3965    current = current->prev_;
3966  }
3967}
3968
3969
3970FlatStringReader::FlatStringReader(Handle<String> str)
3971    : str_(str.location()),
3972      length_(str->length()) {
3973  PostGarbageCollection();
3974}
3975
3976
3977FlatStringReader::FlatStringReader(Vector<const char> input)
3978    : str_(0),
3979      is_ascii_(true),
3980      length_(input.length()),
3981      start_(input.start()) { }
3982
3983
3984void FlatStringReader::PostGarbageCollection() {
3985  if (str_ == NULL) return;
3986  Handle<String> str(str_);
3987  ASSERT(str->IsFlat());
3988  is_ascii_ = str->IsAsciiRepresentation();
3989  if (is_ascii_) {
3990    start_ = str->ToAsciiVector().start();
3991  } else {
3992    start_ = str->ToUC16Vector().start();
3993  }
3994}
3995
3996
3997void StringInputBuffer::Seek(unsigned pos) {
3998  Reset(pos, input_);
3999}
4000
4001
4002void SafeStringInputBuffer::Seek(unsigned pos) {
4003  Reset(pos, input_);
4004}
4005
4006
4007// This method determines the type of string involved and then copies
4008// a whole chunk of characters into a buffer.  It can be used with strings
4009// that have been glued together to form a ConsString and which must cooperate
4010// to fill up a buffer.
4011void String::ReadBlockIntoBuffer(String* input,
4012                                 ReadBlockBuffer* rbb,
4013                                 unsigned* offset_ptr,
4014                                 unsigned max_chars) {
4015  ASSERT(*offset_ptr <= (unsigned)input->length());
4016  if (max_chars == 0) return;
4017
4018  switch (StringShape(input).representation_tag()) {
4019    case kSeqStringTag:
4020      if (input->IsAsciiRepresentation()) {
4021        SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
4022                                                                 offset_ptr,
4023                                                                 max_chars);
4024        return;
4025      } else {
4026        SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
4027                                                                     offset_ptr,
4028                                                                     max_chars);
4029        return;
4030      }
4031    case kConsStringTag:
4032      ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
4033                                                             offset_ptr,
4034                                                             max_chars);
4035      return;
4036    case kExternalStringTag:
4037      if (input->IsAsciiRepresentation()) {
4038        ExternalAsciiString::cast(input)->
4039            ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
4040      } else {
4041        ExternalTwoByteString::cast(input)->
4042            ExternalTwoByteStringReadBlockIntoBuffer(rbb,
4043                                                     offset_ptr,
4044                                                     max_chars);
4045       }
4046       return;
4047    default:
4048      break;
4049  }
4050
4051  UNREACHABLE();
4052  return;
4053}
4054
4055
4056const unibrow::byte* String::ReadBlock(String* input,
4057                                       unibrow::byte* util_buffer,
4058                                       unsigned capacity,
4059                                       unsigned* remaining,
4060                                       unsigned* offset_ptr) {
4061  ASSERT(*offset_ptr <= (unsigned)input->length());
4062  unsigned chars = input->length() - *offset_ptr;
4063  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
4064  const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
4065  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
4066  *remaining = rbb.remaining;
4067  return answer;
4068}
4069
4070
4071const unibrow::byte* String::ReadBlock(String** raw_input,
4072                                       unibrow::byte* util_buffer,
4073                                       unsigned capacity,
4074                                       unsigned* remaining,
4075                                       unsigned* offset_ptr) {
4076  Handle<String> input(raw_input);
4077  ASSERT(*offset_ptr <= (unsigned)input->length());
4078  unsigned chars = input->length() - *offset_ptr;
4079  if (chars > capacity) chars = capacity;
4080  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
4081  ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
4082  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
4083  *remaining = rbb.remaining;
4084  return rbb.util_buffer;
4085}
4086
4087
4088// This will iterate unless the block of string data spans two 'halves' of
4089// a ConsString, in which case it will recurse.  Since the block of string
4090// data to be read has a maximum size this limits the maximum recursion
4091// depth to something sane.  Since C++ does not have tail call recursion
4092// elimination, the iteration must be explicit.
4093void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
4094                                               unsigned* offset_ptr,
4095                                               unsigned max_chars) {
4096  ConsString* current = this;
4097  unsigned offset = *offset_ptr;
4098  int offset_correction = 0;
4099
4100  while (true) {
4101    String* left = current->first();
4102    unsigned left_length = (unsigned)left->length();
4103    if (left_length > offset &&
4104      max_chars <= left_length - offset) {
4105      // Left hand side only - iterate unless we have reached the bottom of
4106      // the cons tree.
4107      if (StringShape(left).IsCons()) {
4108        current = ConsString::cast(left);
4109        continue;
4110      } else {
4111        String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
4112        *offset_ptr = offset + offset_correction;
4113        return;
4114      }
4115    } else if (left_length <= offset) {
4116      // Right hand side only - iterate unless we have reached the bottom of
4117      // the cons tree.
4118      offset -= left_length;
4119      offset_correction += left_length;
4120      String* right = current->second();
4121      if (StringShape(right).IsCons()) {
4122        current = ConsString::cast(right);
4123        continue;
4124      } else {
4125        String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
4126        *offset_ptr = offset + offset_correction;
4127        return;
4128      }
4129    } else {
4130      // The block to be read spans two sides of the ConsString, so we recurse.
4131      // First recurse on the left.
4132      max_chars -= left_length - offset;
4133      String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
4134      // We may have reached the max or there may not have been enough space
4135      // in the buffer for the characters in the left hand side.
4136      if (offset == left_length) {
4137        // Recurse on the right.
4138        String* right = String::cast(current->second());
4139        offset -= left_length;
4140        offset_correction += left_length;
4141        String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
4142      }
4143      *offset_ptr = offset + offset_correction;
4144      return;
4145    }
4146  }
4147}
4148
4149
4150void ConsString::ConsStringIterateBody(ObjectVisitor* v) {
4151  IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize);
4152}
4153
4154
4155void JSGlobalPropertyCell::JSGlobalPropertyCellIterateBody(ObjectVisitor* v) {
4156  IteratePointers(v, kValueOffset, kValueOffset + kPointerSize);
4157}
4158
4159
4160uint16_t ConsString::ConsStringGet(int index) {
4161  ASSERT(index >= 0 && index < this->length());
4162
4163  // Check for a flattened cons string
4164  if (second()->length() == 0) {
4165    String* left = first();
4166    return left->Get(index);
4167  }
4168
4169  String* string = String::cast(this);
4170
4171  while (true) {
4172    if (StringShape(string).IsCons()) {
4173      ConsString* cons_string = ConsString::cast(string);
4174      String* left = cons_string->first();
4175      if (left->length() > index) {
4176        string = left;
4177      } else {
4178        index -= left->length();
4179        string = cons_string->second();
4180      }
4181    } else {
4182      return string->Get(index);
4183    }
4184  }
4185
4186  UNREACHABLE();
4187  return 0;
4188}
4189
4190
4191template <typename sinkchar>
4192void String::WriteToFlat(String* src,
4193                         sinkchar* sink,
4194                         int f,
4195                         int t) {
4196  String* source = src;
4197  int from = f;
4198  int to = t;
4199  while (true) {
4200    ASSERT(0 <= from && from <= to && to <= source->length());
4201    switch (StringShape(source).full_representation_tag()) {
4202      case kAsciiStringTag | kExternalStringTag: {
4203        CopyChars(sink,
4204                  ExternalAsciiString::cast(source)->resource()->data() + from,
4205                  to - from);
4206        return;
4207      }
4208      case kTwoByteStringTag | kExternalStringTag: {
4209        const uc16* data =
4210            ExternalTwoByteString::cast(source)->resource()->data();
4211        CopyChars(sink,
4212                  data + from,
4213                  to - from);
4214        return;
4215      }
4216      case kAsciiStringTag | kSeqStringTag: {
4217        CopyChars(sink,
4218                  SeqAsciiString::cast(source)->GetChars() + from,
4219                  to - from);
4220        return;
4221      }
4222      case kTwoByteStringTag | kSeqStringTag: {
4223        CopyChars(sink,
4224                  SeqTwoByteString::cast(source)->GetChars() + from,
4225                  to - from);
4226        return;
4227      }
4228      case kAsciiStringTag | kConsStringTag:
4229      case kTwoByteStringTag | kConsStringTag: {
4230        ConsString* cons_string = ConsString::cast(source);
4231        String* first = cons_string->first();
4232        int boundary = first->length();
4233        if (to - boundary >= boundary - from) {
4234          // Right hand side is longer.  Recurse over left.
4235          if (from < boundary) {
4236            WriteToFlat(first, sink, from, boundary);
4237            sink += boundary - from;
4238            from = 0;
4239          } else {
4240            from -= boundary;
4241          }
4242          to -= boundary;
4243          source = cons_string->second();
4244        } else {
4245          // Left hand side is longer.  Recurse over right.
4246          if (to > boundary) {
4247            String* second = cons_string->second();
4248            WriteToFlat(second,
4249                        sink + boundary - from,
4250                        0,
4251                        to - boundary);
4252            to = boundary;
4253          }
4254          source = first;
4255        }
4256        break;
4257      }
4258    }
4259  }
4260}
4261
4262
4263#define FIELD_ADDR(p, offset) \
4264  (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
4265
4266void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4267  typedef v8::String::ExternalAsciiStringResource Resource;
4268  v->VisitExternalAsciiString(
4269      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4270}
4271
4272
4273void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4274  typedef v8::String::ExternalStringResource Resource;
4275  v->VisitExternalTwoByteString(
4276      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4277}
4278
4279#undef FIELD_ADDR
4280
4281template <typename IteratorA, typename IteratorB>
4282static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
4283  // General slow case check.  We know that the ia and ib iterators
4284  // have the same length.
4285  while (ia->has_more()) {
4286    uc32 ca = ia->GetNext();
4287    uc32 cb = ib->GetNext();
4288    if (ca != cb)
4289      return false;
4290  }
4291  return true;
4292}
4293
4294
4295// Compares the contents of two strings by reading and comparing
4296// int-sized blocks of characters.
4297template <typename Char>
4298static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
4299  int length = a.length();
4300  ASSERT_EQ(length, b.length());
4301  const Char* pa = a.start();
4302  const Char* pb = b.start();
4303  int i = 0;
4304#ifndef V8_HOST_CAN_READ_UNALIGNED
4305  // If this architecture isn't comfortable reading unaligned ints
4306  // then we have to check that the strings are aligned before
4307  // comparing them blockwise.
4308  const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
4309  uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
4310  uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
4311  if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
4312#endif
4313    const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
4314    int endpoint = length - kStepSize;
4315    // Compare blocks until we reach near the end of the string.
4316    for (; i <= endpoint; i += kStepSize) {
4317      uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
4318      uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
4319      if (wa != wb) {
4320        return false;
4321      }
4322    }
4323#ifndef V8_HOST_CAN_READ_UNALIGNED
4324  }
4325#endif
4326  // Compare the remaining characters that didn't fit into a block.
4327  for (; i < length; i++) {
4328    if (a[i] != b[i]) {
4329      return false;
4330    }
4331  }
4332  return true;
4333}
4334
4335
4336static StringInputBuffer string_compare_buffer_b;
4337
4338
4339template <typename IteratorA>
4340static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
4341  if (b->IsFlat()) {
4342    if (b->IsAsciiRepresentation()) {
4343      VectorIterator<char> ib(b->ToAsciiVector());
4344      return CompareStringContents(ia, &ib);
4345    } else {
4346      VectorIterator<uc16> ib(b->ToUC16Vector());
4347      return CompareStringContents(ia, &ib);
4348    }
4349  } else {
4350    string_compare_buffer_b.Reset(0, b);
4351    return CompareStringContents(ia, &string_compare_buffer_b);
4352  }
4353}
4354
4355
4356static StringInputBuffer string_compare_buffer_a;
4357
4358
4359bool String::SlowEquals(String* other) {
4360  // Fast check: negative check with lengths.
4361  int len = length();
4362  if (len != other->length()) return false;
4363  if (len == 0) return true;
4364
4365  // Fast check: if hash code is computed for both strings
4366  // a fast negative check can be performed.
4367  if (HasHashCode() && other->HasHashCode()) {
4368    if (Hash() != other->Hash()) return false;
4369  }
4370
4371  if (StringShape(this).IsSequentialAscii() &&
4372      StringShape(other).IsSequentialAscii()) {
4373    const char* str1 = SeqAsciiString::cast(this)->GetChars();
4374    const char* str2 = SeqAsciiString::cast(other)->GetChars();
4375    return CompareRawStringContents(Vector<const char>(str1, len),
4376                                    Vector<const char>(str2, len));
4377  }
4378
4379  if (this->IsFlat()) {
4380    if (IsAsciiRepresentation()) {
4381      Vector<const char> vec1 = this->ToAsciiVector();
4382      if (other->IsFlat()) {
4383        if (other->IsAsciiRepresentation()) {
4384          Vector<const char> vec2 = other->ToAsciiVector();
4385          return CompareRawStringContents(vec1, vec2);
4386        } else {
4387          VectorIterator<char> buf1(vec1);
4388          VectorIterator<uc16> ib(other->ToUC16Vector());
4389          return CompareStringContents(&buf1, &ib);
4390        }
4391      } else {
4392        VectorIterator<char> buf1(vec1);
4393        string_compare_buffer_b.Reset(0, other);
4394        return CompareStringContents(&buf1, &string_compare_buffer_b);
4395      }
4396    } else {
4397      Vector<const uc16> vec1 = this->ToUC16Vector();
4398      if (other->IsFlat()) {
4399        if (other->IsAsciiRepresentation()) {
4400          VectorIterator<uc16> buf1(vec1);
4401          VectorIterator<char> ib(other->ToAsciiVector());
4402          return CompareStringContents(&buf1, &ib);
4403        } else {
4404          Vector<const uc16> vec2(other->ToUC16Vector());
4405          return CompareRawStringContents(vec1, vec2);
4406        }
4407      } else {
4408        VectorIterator<uc16> buf1(vec1);
4409        string_compare_buffer_b.Reset(0, other);
4410        return CompareStringContents(&buf1, &string_compare_buffer_b);
4411      }
4412    }
4413  } else {
4414    string_compare_buffer_a.Reset(0, this);
4415    return CompareStringContentsPartial(&string_compare_buffer_a, other);
4416  }
4417}
4418
4419
4420bool String::MarkAsUndetectable() {
4421  if (StringShape(this).IsSymbol()) return false;
4422
4423  Map* map = this->map();
4424  if (map == Heap::string_map()) {
4425    this->set_map(Heap::undetectable_string_map());
4426    return true;
4427  } else if (map == Heap::ascii_string_map()) {
4428    this->set_map(Heap::undetectable_ascii_string_map());
4429    return true;
4430  }
4431  // Rest cannot be marked as undetectable
4432  return false;
4433}
4434
4435
4436bool String::IsEqualTo(Vector<const char> str) {
4437  int slen = length();
4438  Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
4439  decoder->Reset(str.start(), str.length());
4440  int i;
4441  for (i = 0; i < slen && decoder->has_more(); i++) {
4442    uc32 r = decoder->GetNext();
4443    if (Get(i) != r) return false;
4444  }
4445  return i == slen && !decoder->has_more();
4446}
4447
4448
4449uint32_t String::ComputeAndSetHash() {
4450  // Should only be called if hash code has not yet been computed.
4451  ASSERT(!(hash_field() & kHashComputedMask));
4452
4453  // Compute the hash code.
4454  StringInputBuffer buffer(this);
4455  uint32_t field = ComputeHashField(&buffer, length());
4456
4457  // Store the hash code in the object.
4458  set_hash_field(field);
4459
4460  // Check the hash code is there.
4461  ASSERT(hash_field() & kHashComputedMask);
4462  uint32_t result = field >> kHashShift;
4463  ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
4464  return result;
4465}
4466
4467
4468bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
4469                               uint32_t* index,
4470                               int length) {
4471  if (length == 0 || length > kMaxArrayIndexSize) return false;
4472  uc32 ch = buffer->GetNext();
4473
4474  // If the string begins with a '0' character, it must only consist
4475  // of it to be a legal array index.
4476  if (ch == '0') {
4477    *index = 0;
4478    return length == 1;
4479  }
4480
4481  // Convert string to uint32 array index; character by character.
4482  int d = ch - '0';
4483  if (d < 0 || d > 9) return false;
4484  uint32_t result = d;
4485  while (buffer->has_more()) {
4486    d = buffer->GetNext() - '0';
4487    if (d < 0 || d > 9) return false;
4488    // Check that the new result is below the 32 bit limit.
4489    if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
4490    result = (result * 10) + d;
4491  }
4492
4493  *index = result;
4494  return true;
4495}
4496
4497
4498bool String::SlowAsArrayIndex(uint32_t* index) {
4499  if (length() <= kMaxCachedArrayIndexLength) {
4500    Hash();  // force computation of hash code
4501    uint32_t field = hash_field();
4502    if ((field & kIsArrayIndexMask) == 0) return false;
4503    // Isolate the array index form the full hash field.
4504    *index = (kArrayIndexHashMask & field) >> kHashShift;
4505    return true;
4506  } else {
4507    StringInputBuffer buffer(this);
4508    return ComputeArrayIndex(&buffer, index, length());
4509  }
4510}
4511
4512
4513static inline uint32_t HashField(uint32_t hash,
4514                                 bool is_array_index,
4515                                 int length = -1) {
4516  uint32_t result =
4517      (hash << String::kHashShift) | String::kHashComputedMask;
4518  if (is_array_index) {
4519    // For array indexes mix the length into the hash as an array index could
4520    // be zero.
4521    ASSERT(length > 0);
4522    ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
4523           (1 << String::kArrayIndexValueBits));
4524    result |= String::kIsArrayIndexMask;
4525    result |= length << String::kArrayIndexHashLengthShift;
4526  }
4527  return result;
4528}
4529
4530
4531uint32_t StringHasher::GetHashField() {
4532  ASSERT(is_valid());
4533  if (length_ <= String::kMaxHashCalcLength) {
4534    if (is_array_index()) {
4535      return v8::internal::HashField(array_index(), true, length_);
4536    } else {
4537      return v8::internal::HashField(GetHash(), false);
4538    }
4539    uint32_t payload = v8::internal::HashField(GetHash(), false);
4540    return payload;
4541  } else {
4542    return v8::internal::HashField(length_, false);
4543  }
4544}
4545
4546
4547uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer,
4548                                  int length) {
4549  StringHasher hasher(length);
4550
4551  // Very long strings have a trivial hash that doesn't inspect the
4552  // string contents.
4553  if (hasher.has_trivial_hash()) {
4554    return hasher.GetHashField();
4555  }
4556
4557  // Do the iterative array index computation as long as there is a
4558  // chance this is an array index.
4559  while (buffer->has_more() && hasher.is_array_index()) {
4560    hasher.AddCharacter(buffer->GetNext());
4561  }
4562
4563  // Process the remaining characters without updating the array
4564  // index.
4565  while (buffer->has_more()) {
4566    hasher.AddCharacterNoIndex(buffer->GetNext());
4567  }
4568
4569  return hasher.GetHashField();
4570}
4571
4572
4573Object* String::SubString(int start, int end) {
4574  if (start == 0 && end == length()) return this;
4575  Object* result = Heap::AllocateSubString(this, start, end);
4576  return result;
4577}
4578
4579
4580void String::PrintOn(FILE* file) {
4581  int length = this->length();
4582  for (int i = 0; i < length; i++) {
4583    fprintf(file, "%c", Get(i));
4584  }
4585}
4586
4587
4588void Map::CreateBackPointers() {
4589  DescriptorArray* descriptors = instance_descriptors();
4590  for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
4591    if (descriptors->GetType(i) == MAP_TRANSITION) {
4592      // Get target.
4593      Map* target = Map::cast(descriptors->GetValue(i));
4594#ifdef DEBUG
4595      // Verify target.
4596      Object* source_prototype = prototype();
4597      Object* target_prototype = target->prototype();
4598      ASSERT(source_prototype->IsJSObject() ||
4599             source_prototype->IsMap() ||
4600             source_prototype->IsNull());
4601      ASSERT(target_prototype->IsJSObject() ||
4602             target_prototype->IsNull());
4603      ASSERT(source_prototype->IsMap() ||
4604             source_prototype == target_prototype);
4605#endif
4606      // Point target back to source.  set_prototype() will not let us set
4607      // the prototype to a map, as we do here.
4608      *RawField(target, kPrototypeOffset) = this;
4609    }
4610  }
4611}
4612
4613
4614void Map::ClearNonLiveTransitions(Object* real_prototype) {
4615  // Live DescriptorArray objects will be marked, so we must use
4616  // low-level accessors to get and modify their data.
4617  DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
4618      *RawField(this, Map::kInstanceDescriptorsOffset));
4619  if (d == Heap::raw_unchecked_empty_descriptor_array()) return;
4620  Smi* NullDescriptorDetails =
4621    PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
4622  FixedArray* contents = reinterpret_cast<FixedArray*>(
4623      d->get(DescriptorArray::kContentArrayIndex));
4624  ASSERT(contents->length() >= 2);
4625  for (int i = 0; i < contents->length(); i += 2) {
4626    // If the pair (value, details) is a map transition,
4627    // check if the target is live.  If not, null the descriptor.
4628    // Also drop the back pointer for that map transition, so that this
4629    // map is not reached again by following a back pointer from a
4630    // non-live object.
4631    PropertyDetails details(Smi::cast(contents->get(i + 1)));
4632    if (details.type() == MAP_TRANSITION) {
4633      Map* target = reinterpret_cast<Map*>(contents->get(i));
4634      ASSERT(target->IsHeapObject());
4635      if (!target->IsMarked()) {
4636        ASSERT(target->IsMap());
4637        contents->set(i + 1, NullDescriptorDetails);
4638        contents->set_null(i);
4639        ASSERT(target->prototype() == this ||
4640               target->prototype() == real_prototype);
4641        // Getter prototype() is read-only, set_prototype() has side effects.
4642        *RawField(target, Map::kPrototypeOffset) = real_prototype;
4643      }
4644    }
4645  }
4646}
4647
4648
4649void Map::MapIterateBody(ObjectVisitor* v) {
4650  // Assumes all Object* members are contiguously allocated!
4651  IteratePointers(v, kPrototypeOffset, kCodeCacheOffset + kPointerSize);
4652}
4653
4654
4655Object* JSFunction::SetInstancePrototype(Object* value) {
4656  ASSERT(value->IsJSObject());
4657
4658  if (has_initial_map()) {
4659    initial_map()->set_prototype(value);
4660  } else {
4661    // Put the value in the initial map field until an initial map is
4662    // needed.  At that point, a new initial map is created and the
4663    // prototype is put into the initial map where it belongs.
4664    set_prototype_or_initial_map(value);
4665  }
4666  return value;
4667}
4668
4669
4670
4671Object* JSFunction::SetPrototype(Object* value) {
4672  Object* construct_prototype = value;
4673
4674  // If the value is not a JSObject, store the value in the map's
4675  // constructor field so it can be accessed.  Also, set the prototype
4676  // used for constructing objects to the original object prototype.
4677  // See ECMA-262 13.2.2.
4678  if (!value->IsJSObject()) {
4679    // Copy the map so this does not affect unrelated functions.
4680    // Remove map transitions because they point to maps with a
4681    // different prototype.
4682    Object* new_map = map()->CopyDropTransitions();
4683    if (new_map->IsFailure()) return new_map;
4684    set_map(Map::cast(new_map));
4685    map()->set_constructor(value);
4686    map()->set_non_instance_prototype(true);
4687    construct_prototype =
4688        Top::context()->global_context()->initial_object_prototype();
4689  } else {
4690    map()->set_non_instance_prototype(false);
4691  }
4692
4693  return SetInstancePrototype(construct_prototype);
4694}
4695
4696
4697Object* JSFunction::SetInstanceClassName(String* name) {
4698  shared()->set_instance_class_name(name);
4699  return this;
4700}
4701
4702
4703Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) {
4704  return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex));
4705}
4706
4707
4708void Oddball::OddballIterateBody(ObjectVisitor* v) {
4709  // Assumes all Object* members are contiguously allocated!
4710  IteratePointers(v, kToStringOffset, kToNumberOffset + kPointerSize);
4711}
4712
4713
4714Object* Oddball::Initialize(const char* to_string, Object* to_number) {
4715  Object* symbol = Heap::LookupAsciiSymbol(to_string);
4716  if (symbol->IsFailure()) return symbol;
4717  set_to_string(String::cast(symbol));
4718  set_to_number(to_number);
4719  return this;
4720}
4721
4722
4723bool SharedFunctionInfo::HasSourceCode() {
4724  return !script()->IsUndefined() &&
4725         !Script::cast(script())->source()->IsUndefined();
4726}
4727
4728
4729Object* SharedFunctionInfo::GetSourceCode() {
4730  HandleScope scope;
4731  if (script()->IsUndefined()) return Heap::undefined_value();
4732  Object* source = Script::cast(script())->source();
4733  if (source->IsUndefined()) return Heap::undefined_value();
4734  return *SubString(Handle<String>(String::cast(source)),
4735                    start_position(), end_position());
4736}
4737
4738
4739int SharedFunctionInfo::CalculateInstanceSize() {
4740  int instance_size =
4741      JSObject::kHeaderSize +
4742      expected_nof_properties() * kPointerSize;
4743  if (instance_size > JSObject::kMaxInstanceSize) {
4744    instance_size = JSObject::kMaxInstanceSize;
4745  }
4746  return instance_size;
4747}
4748
4749
4750int SharedFunctionInfo::CalculateInObjectProperties() {
4751  return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
4752}
4753
4754
4755bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
4756  // Check the basic conditions for generating inline constructor code.
4757  if (!FLAG_inline_new
4758      || !has_only_simple_this_property_assignments()
4759      || this_property_assignments_count() == 0) {
4760    return false;
4761  }
4762
4763  // If the prototype is null inline constructors cause no problems.
4764  if (!prototype->IsJSObject()) {
4765    ASSERT(prototype->IsNull());
4766    return true;
4767  }
4768
4769  // Traverse the proposed prototype chain looking for setters for properties of
4770  // the same names as are set by the inline constructor.
4771  for (Object* obj = prototype;
4772       obj != Heap::null_value();
4773       obj = obj->GetPrototype()) {
4774    JSObject* js_object = JSObject::cast(obj);
4775    for (int i = 0; i < this_property_assignments_count(); i++) {
4776      LookupResult result;
4777      String* name = GetThisPropertyAssignmentName(i);
4778      js_object->LocalLookupRealNamedProperty(name, &result);
4779      if (result.IsProperty() && result.type() == CALLBACKS) {
4780        return false;
4781      }
4782    }
4783  }
4784
4785  return true;
4786}
4787
4788
4789void SharedFunctionInfo::SetThisPropertyAssignmentsInfo(
4790    bool only_simple_this_property_assignments,
4791    FixedArray* assignments) {
4792  set_compiler_hints(BooleanBit::set(compiler_hints(),
4793                                     kHasOnlySimpleThisPropertyAssignments,
4794                                     only_simple_this_property_assignments));
4795  set_this_property_assignments(assignments);
4796  set_this_property_assignments_count(assignments->length() / 3);
4797}
4798
4799
4800void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() {
4801  set_compiler_hints(BooleanBit::set(compiler_hints(),
4802                                     kHasOnlySimpleThisPropertyAssignments,
4803                                     false));
4804  set_this_property_assignments(Heap::undefined_value());
4805  set_this_property_assignments_count(0);
4806}
4807
4808
4809String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) {
4810  Object* obj = this_property_assignments();
4811  ASSERT(obj->IsFixedArray());
4812  ASSERT(index < this_property_assignments_count());
4813  obj = FixedArray::cast(obj)->get(index * 3);
4814  ASSERT(obj->IsString());
4815  return String::cast(obj);
4816}
4817
4818
4819bool SharedFunctionInfo::IsThisPropertyAssignmentArgument(int index) {
4820  Object* obj = this_property_assignments();
4821  ASSERT(obj->IsFixedArray());
4822  ASSERT(index < this_property_assignments_count());
4823  obj = FixedArray::cast(obj)->get(index * 3 + 1);
4824  return Smi::cast(obj)->value() != -1;
4825}
4826
4827
4828int SharedFunctionInfo::GetThisPropertyAssignmentArgument(int index) {
4829  ASSERT(IsThisPropertyAssignmentArgument(index));
4830  Object* obj =
4831      FixedArray::cast(this_property_assignments())->get(index * 3 + 1);
4832  return Smi::cast(obj)->value();
4833}
4834
4835
4836Object* SharedFunctionInfo::GetThisPropertyAssignmentConstant(int index) {
4837  ASSERT(!IsThisPropertyAssignmentArgument(index));
4838  Object* obj =
4839      FixedArray::cast(this_property_assignments())->get(index * 3 + 2);
4840  return obj;
4841}
4842
4843
4844// Support function for printing the source code to a StringStream
4845// without any allocation in the heap.
4846void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
4847                                         int max_length) {
4848  // For some native functions there is no source.
4849  if (script()->IsUndefined() ||
4850      Script::cast(script())->source()->IsUndefined()) {
4851    accumulator->Add("<No Source>");
4852    return;
4853  }
4854
4855  // Get the source for the script which this function came from.
4856  // Don't use String::cast because we don't want more assertion errors while
4857  // we are already creating a stack dump.
4858  String* script_source =
4859      reinterpret_cast<String*>(Script::cast(script())->source());
4860
4861  if (!script_source->LooksValid()) {
4862    accumulator->Add("<Invalid Source>");
4863    return;
4864  }
4865
4866  if (!is_toplevel()) {
4867    accumulator->Add("function ");
4868    Object* name = this->name();
4869    if (name->IsString() && String::cast(name)->length() > 0) {
4870      accumulator->PrintName(name);
4871    }
4872  }
4873
4874  int len = end_position() - start_position();
4875  if (len > max_length) {
4876    accumulator->Put(script_source,
4877                     start_position(),
4878                     start_position() + max_length);
4879    accumulator->Add("...\n");
4880  } else {
4881    accumulator->Put(script_source, start_position(), end_position());
4882  }
4883}
4884
4885
4886void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) {
4887  IteratePointers(v, kNameOffset, kConstructStubOffset + kPointerSize);
4888  IteratePointers(v, kInstanceClassNameOffset, kScriptOffset + kPointerSize);
4889  IteratePointers(v, kDebugInfoOffset, kInferredNameOffset + kPointerSize);
4890  IteratePointers(v, kThisPropertyAssignmentsOffset,
4891      kThisPropertyAssignmentsOffset + kPointerSize);
4892}
4893
4894
4895void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
4896  ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
4897  Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
4898  Object* old_target = target;
4899  VisitPointer(&target);
4900  CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
4901}
4902
4903
4904void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
4905  ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) &&
4906         rinfo->IsPatchedReturnSequence());
4907  Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
4908  Object* old_target = target;
4909  VisitPointer(&target);
4910  CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
4911}
4912
4913
4914void Code::CodeIterateBody(ObjectVisitor* v) {
4915  int mode_mask = RelocInfo::kCodeTargetMask |
4916                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
4917                  RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
4918                  RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
4919                  RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
4920
4921  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
4922    RelocInfo::Mode rmode = it.rinfo()->rmode();
4923    if (rmode == RelocInfo::EMBEDDED_OBJECT) {
4924      v->VisitPointer(it.rinfo()->target_object_address());
4925    } else if (RelocInfo::IsCodeTarget(rmode)) {
4926      v->VisitCodeTarget(it.rinfo());
4927    } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
4928      v->VisitExternalReference(it.rinfo()->target_reference_address());
4929#ifdef ENABLE_DEBUGGER_SUPPORT
4930    } else if (Debug::has_break_points() &&
4931               RelocInfo::IsJSReturn(rmode) &&
4932               it.rinfo()->IsPatchedReturnSequence()) {
4933      v->VisitDebugTarget(it.rinfo());
4934#endif
4935    } else if (rmode == RelocInfo::RUNTIME_ENTRY) {
4936      v->VisitRuntimeEntry(it.rinfo());
4937    }
4938  }
4939
4940  ScopeInfo<>::IterateScopeInfo(this, v);
4941}
4942
4943
4944void Code::Relocate(intptr_t delta) {
4945  for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
4946    it.rinfo()->apply(delta);
4947  }
4948  CPU::FlushICache(instruction_start(), instruction_size());
4949}
4950
4951
4952void Code::CopyFrom(const CodeDesc& desc) {
4953  // copy code
4954  memmove(instruction_start(), desc.buffer, desc.instr_size);
4955
4956  // fill gap with zero bytes
4957  { byte* p = instruction_start() + desc.instr_size;
4958    byte* q = relocation_start();
4959    while (p < q) {
4960      *p++ = 0;
4961    }
4962  }
4963
4964  // copy reloc info
4965  memmove(relocation_start(),
4966          desc.buffer + desc.buffer_size - desc.reloc_size,
4967          desc.reloc_size);
4968
4969  // unbox handles and relocate
4970  intptr_t delta = instruction_start() - desc.buffer;
4971  int mode_mask = RelocInfo::kCodeTargetMask |
4972                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
4973                  RelocInfo::kApplyMask;
4974  Assembler* origin = desc.origin;  // Needed to find target_object on X64.
4975  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
4976    RelocInfo::Mode mode = it.rinfo()->rmode();
4977    if (mode == RelocInfo::EMBEDDED_OBJECT) {
4978      Handle<Object> p = it.rinfo()->target_object_handle(origin);
4979      it.rinfo()->set_target_object(*p);
4980    } else if (RelocInfo::IsCodeTarget(mode)) {
4981      // rewrite code handles in inline cache targets to direct
4982      // pointers to the first instruction in the code object
4983      Handle<Object> p = it.rinfo()->target_object_handle(origin);
4984      Code* code = Code::cast(*p);
4985      it.rinfo()->set_target_address(code->instruction_start());
4986    } else {
4987      it.rinfo()->apply(delta);
4988    }
4989  }
4990  CPU::FlushICache(instruction_start(), instruction_size());
4991}
4992
4993
4994// Locate the source position which is closest to the address in the code. This
4995// is using the source position information embedded in the relocation info.
4996// The position returned is relative to the beginning of the script where the
4997// source for this function is found.
4998int Code::SourcePosition(Address pc) {
4999  int distance = kMaxInt;
5000  int position = RelocInfo::kNoPosition;  // Initially no position found.
5001  // Run through all the relocation info to find the best matching source
5002  // position. All the code needs to be considered as the sequence of the
5003  // instructions in the code does not necessarily follow the same order as the
5004  // source.
5005  RelocIterator it(this, RelocInfo::kPositionMask);
5006  while (!it.done()) {
5007    // Only look at positions after the current pc.
5008    if (it.rinfo()->pc() < pc) {
5009      // Get position and distance.
5010
5011      int dist = static_cast<int>(pc - it.rinfo()->pc());
5012      int pos = static_cast<int>(it.rinfo()->data());
5013      // If this position is closer than the current candidate or if it has the
5014      // same distance as the current candidate and the position is higher then
5015      // this position is the new candidate.
5016      if ((dist < distance) ||
5017          (dist == distance && pos > position)) {
5018        position = pos;
5019        distance = dist;
5020      }
5021    }
5022    it.next();
5023  }
5024  return position;
5025}
5026
5027
5028// Same as Code::SourcePosition above except it only looks for statement
5029// positions.
5030int Code::SourceStatementPosition(Address pc) {
5031  // First find the position as close as possible using all position
5032  // information.
5033  int position = SourcePosition(pc);
5034  // Now find the closest statement position before the position.
5035  int statement_position = 0;
5036  RelocIterator it(this, RelocInfo::kPositionMask);
5037  while (!it.done()) {
5038    if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
5039      int p = static_cast<int>(it.rinfo()->data());
5040      if (statement_position < p && p <= position) {
5041        statement_position = p;
5042      }
5043    }
5044    it.next();
5045  }
5046  return statement_position;
5047}
5048
5049
5050#ifdef ENABLE_DISASSEMBLER
5051// Identify kind of code.
5052const char* Code::Kind2String(Kind kind) {
5053  switch (kind) {
5054    case FUNCTION: return "FUNCTION";
5055    case STUB: return "STUB";
5056    case BUILTIN: return "BUILTIN";
5057    case LOAD_IC: return "LOAD_IC";
5058    case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
5059    case STORE_IC: return "STORE_IC";
5060    case KEYED_STORE_IC: return "KEYED_STORE_IC";
5061    case CALL_IC: return "CALL_IC";
5062  }
5063  UNREACHABLE();
5064  return NULL;
5065}
5066
5067
5068const char* Code::ICState2String(InlineCacheState state) {
5069  switch (state) {
5070    case UNINITIALIZED: return "UNINITIALIZED";
5071    case PREMONOMORPHIC: return "PREMONOMORPHIC";
5072    case MONOMORPHIC: return "MONOMORPHIC";
5073    case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
5074    case MEGAMORPHIC: return "MEGAMORPHIC";
5075    case DEBUG_BREAK: return "DEBUG_BREAK";
5076    case DEBUG_PREPARE_STEP_IN: return "DEBUG_PREPARE_STEP_IN";
5077  }
5078  UNREACHABLE();
5079  return NULL;
5080}
5081
5082
5083const char* Code::PropertyType2String(PropertyType type) {
5084  switch (type) {
5085    case NORMAL: return "NORMAL";
5086    case FIELD: return "FIELD";
5087    case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
5088    case CALLBACKS: return "CALLBACKS";
5089    case INTERCEPTOR: return "INTERCEPTOR";
5090    case MAP_TRANSITION: return "MAP_TRANSITION";
5091    case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
5092    case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
5093  }
5094  UNREACHABLE();
5095  return NULL;
5096}
5097
5098void Code::Disassemble(const char* name) {
5099  PrintF("kind = %s\n", Kind2String(kind()));
5100  if (is_inline_cache_stub()) {
5101    PrintF("ic_state = %s\n", ICState2String(ic_state()));
5102    PrintF("ic_in_loop = %d\n", ic_in_loop() == IN_LOOP);
5103    if (ic_state() == MONOMORPHIC) {
5104      PrintF("type = %s\n", PropertyType2String(type()));
5105    }
5106  }
5107  if ((name != NULL) && (name[0] != '\0')) {
5108    PrintF("name = %s\n", name);
5109  }
5110
5111  PrintF("Instructions (size = %d)\n", instruction_size());
5112  Disassembler::Decode(NULL, this);
5113  PrintF("\n");
5114
5115  PrintF("RelocInfo (size = %d)\n", relocation_size());
5116  for (RelocIterator it(this); !it.done(); it.next())
5117    it.rinfo()->Print();
5118  PrintF("\n");
5119}
5120#endif  // ENABLE_DISASSEMBLER
5121
5122
5123void JSObject::SetFastElements(FixedArray* elems) {
5124  // We should never end in here with a pixel or external array.
5125  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
5126#ifdef DEBUG
5127  // Check the provided array is filled with the_hole.
5128  uint32_t len = static_cast<uint32_t>(elems->length());
5129  for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole());
5130#endif
5131  AssertNoAllocation no_gc;
5132  WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
5133  switch (GetElementsKind()) {
5134    case FAST_ELEMENTS: {
5135      FixedArray* old_elements = FixedArray::cast(elements());
5136      uint32_t old_length = static_cast<uint32_t>(old_elements->length());
5137      // Fill out the new array with this content and array holes.
5138      for (uint32_t i = 0; i < old_length; i++) {
5139        elems->set(i, old_elements->get(i), mode);
5140      }
5141      break;
5142    }
5143    case DICTIONARY_ELEMENTS: {
5144      NumberDictionary* dictionary = NumberDictionary::cast(elements());
5145      for (int i = 0; i < dictionary->Capacity(); i++) {
5146        Object* key = dictionary->KeyAt(i);
5147        if (key->IsNumber()) {
5148          uint32_t entry = static_cast<uint32_t>(key->Number());
5149          elems->set(entry, dictionary->ValueAt(i), mode);
5150        }
5151      }
5152      break;
5153    }
5154    default:
5155      UNREACHABLE();
5156      break;
5157  }
5158  set_elements(elems);
5159}
5160
5161
5162Object* JSObject::SetSlowElements(Object* len) {
5163  // We should never end in here with a pixel or external array.
5164  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
5165
5166  uint32_t new_length = static_cast<uint32_t>(len->Number());
5167
5168  switch (GetElementsKind()) {
5169    case FAST_ELEMENTS: {
5170      // Make sure we never try to shrink dense arrays into sparse arrays.
5171      ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <=
5172                                   new_length);
5173      Object* obj = NormalizeElements();
5174      if (obj->IsFailure()) return obj;
5175
5176      // Update length for JSArrays.
5177      if (IsJSArray()) JSArray::cast(this)->set_length(len);
5178      break;
5179    }
5180    case DICTIONARY_ELEMENTS: {
5181      if (IsJSArray()) {
5182        uint32_t old_length =
5183        static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
5184        element_dictionary()->RemoveNumberEntries(new_length, old_length),
5185        JSArray::cast(this)->set_length(len);
5186      }
5187      break;
5188    }
5189    default:
5190      UNREACHABLE();
5191      break;
5192  }
5193  return this;
5194}
5195
5196
5197Object* JSArray::Initialize(int capacity) {
5198  ASSERT(capacity >= 0);
5199  set_length(Smi::FromInt(0));
5200  FixedArray* new_elements;
5201  if (capacity == 0) {
5202    new_elements = Heap::empty_fixed_array();
5203  } else {
5204    Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
5205    if (obj->IsFailure()) return obj;
5206    new_elements = FixedArray::cast(obj);
5207  }
5208  set_elements(new_elements);
5209  return this;
5210}
5211
5212
5213void JSArray::Expand(int required_size) {
5214  Handle<JSArray> self(this);
5215  Handle<FixedArray> old_backing(FixedArray::cast(elements()));
5216  int old_size = old_backing->length();
5217  int new_size = required_size > old_size ? required_size : old_size;
5218  Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size);
5219  // Can't use this any more now because we may have had a GC!
5220  for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i));
5221  self->SetContent(*new_backing);
5222}
5223
5224
5225// Computes the new capacity when expanding the elements of a JSObject.
5226static int NewElementsCapacity(int old_capacity) {
5227  // (old_capacity + 50%) + 16
5228  return old_capacity + (old_capacity >> 1) + 16;
5229}
5230
5231
5232static Object* ArrayLengthRangeError() {
5233  HandleScope scope;
5234  return Top::Throw(*Factory::NewRangeError("invalid_array_length",
5235                                            HandleVector<Object>(NULL, 0)));
5236}
5237
5238
5239Object* JSObject::SetElementsLength(Object* len) {
5240  // We should never end in here with a pixel or external array.
5241  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
5242
5243  Object* smi_length = len->ToSmi();
5244  if (smi_length->IsSmi()) {
5245    int value = Smi::cast(smi_length)->value();
5246    if (value < 0) return ArrayLengthRangeError();
5247    switch (GetElementsKind()) {
5248      case FAST_ELEMENTS: {
5249        int old_capacity = FixedArray::cast(elements())->length();
5250        if (value <= old_capacity) {
5251          if (IsJSArray()) {
5252            int old_length = FastD2I(JSArray::cast(this)->length()->Number());
5253            // NOTE: We may be able to optimize this by removing the
5254            // last part of the elements backing storage array and
5255            // setting the capacity to the new size.
5256            for (int i = value; i < old_length; i++) {
5257              FixedArray::cast(elements())->set_the_hole(i);
5258            }
5259            JSArray::cast(this)->set_length(Smi::cast(smi_length));
5260          }
5261          return this;
5262        }
5263        int min = NewElementsCapacity(old_capacity);
5264        int new_capacity = value > min ? value : min;
5265        if (new_capacity <= kMaxFastElementsLength ||
5266            !ShouldConvertToSlowElements(new_capacity)) {
5267          Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
5268          if (obj->IsFailure()) return obj;
5269          if (IsJSArray()) {
5270            JSArray::cast(this)->set_length(Smi::cast(smi_length));
5271          }
5272          SetFastElements(FixedArray::cast(obj));
5273          return this;
5274        }
5275        break;
5276      }
5277      case DICTIONARY_ELEMENTS: {
5278        if (IsJSArray()) {
5279          if (value == 0) {
5280            // If the length of a slow array is reset to zero, we clear
5281            // the array and flush backing storage. This has the added
5282            // benefit that the array returns to fast mode.
5283            initialize_elements();
5284          } else {
5285            // Remove deleted elements.
5286            uint32_t old_length =
5287            static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
5288            element_dictionary()->RemoveNumberEntries(value, old_length);
5289          }
5290          JSArray::cast(this)->set_length(Smi::cast(smi_length));
5291        }
5292        return this;
5293      }
5294      default:
5295        UNREACHABLE();
5296        break;
5297    }
5298  }
5299
5300  // General slow case.
5301  if (len->IsNumber()) {
5302    uint32_t length;
5303    if (Array::IndexFromObject(len, &length)) {
5304      return SetSlowElements(len);
5305    } else {
5306      return ArrayLengthRangeError();
5307    }
5308  }
5309
5310  // len is not a number so make the array size one and
5311  // set only element to len.
5312  Object* obj = Heap::AllocateFixedArray(1);
5313  if (obj->IsFailure()) return obj;
5314  FixedArray::cast(obj)->set(0, len);
5315  if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1));
5316  set_elements(FixedArray::cast(obj));
5317  return this;
5318}
5319
5320
5321Object* JSObject::SetPrototype(Object* value,
5322                               bool skip_hidden_prototypes) {
5323  // Silently ignore the change if value is not a JSObject or null.
5324  // SpiderMonkey behaves this way.
5325  if (!value->IsJSObject() && !value->IsNull()) return value;
5326
5327  // Before we can set the prototype we need to be sure
5328  // prototype cycles are prevented.
5329  // It is sufficient to validate that the receiver is not in the new prototype
5330  // chain.
5331  for (Object* pt = value; pt != Heap::null_value(); pt = pt->GetPrototype()) {
5332    if (JSObject::cast(pt) == this) {
5333      // Cycle detected.
5334      HandleScope scope;
5335      return Top::Throw(*Factory::NewError("cyclic_proto",
5336                                           HandleVector<Object>(NULL, 0)));
5337    }
5338  }
5339
5340  JSObject* real_receiver = this;
5341
5342  if (skip_hidden_prototypes) {
5343    // Find the first object in the chain whose prototype object is not
5344    // hidden and set the new prototype on that object.
5345    Object* current_proto = real_receiver->GetPrototype();
5346    while (current_proto->IsJSObject() &&
5347          JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
5348      real_receiver = JSObject::cast(current_proto);
5349      current_proto = current_proto->GetPrototype();
5350    }
5351  }
5352
5353  // Set the new prototype of the object.
5354  Object* new_map = real_receiver->map()->CopyDropTransitions();
5355  if (new_map->IsFailure()) return new_map;
5356  Map::cast(new_map)->set_prototype(value);
5357  real_receiver->set_map(Map::cast(new_map));
5358
5359  return value;
5360}
5361
5362
5363bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) {
5364  switch (GetElementsKind()) {
5365    case FAST_ELEMENTS: {
5366      uint32_t length = IsJSArray() ?
5367          static_cast<uint32_t>
5368              (Smi::cast(JSArray::cast(this)->length())->value()) :
5369          static_cast<uint32_t>(FixedArray::cast(elements())->length());
5370      if ((index < length) &&
5371          !FixedArray::cast(elements())->get(index)->IsTheHole()) {
5372        return true;
5373      }
5374      break;
5375    }
5376    case PIXEL_ELEMENTS: {
5377      // TODO(iposva): Add testcase.
5378      PixelArray* pixels = PixelArray::cast(elements());
5379      if (index < static_cast<uint32_t>(pixels->length())) {
5380        return true;
5381      }
5382      break;
5383    }
5384    case EXTERNAL_BYTE_ELEMENTS:
5385    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
5386    case EXTERNAL_SHORT_ELEMENTS:
5387    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
5388    case EXTERNAL_INT_ELEMENTS:
5389    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
5390    case EXTERNAL_FLOAT_ELEMENTS: {
5391      // TODO(kbr): Add testcase.
5392      ExternalArray* array = ExternalArray::cast(elements());
5393      if (index < static_cast<uint32_t>(array->length())) {
5394        return true;
5395      }
5396      break;
5397    }
5398    case DICTIONARY_ELEMENTS: {
5399      if (element_dictionary()->FindEntry(index)
5400          != NumberDictionary::kNotFound) {
5401        return true;
5402      }
5403      break;
5404    }
5405    default:
5406      UNREACHABLE();
5407      break;
5408  }
5409
5410  // Handle [] on String objects.
5411  if (this->IsStringObjectWithCharacterAt(index)) return true;
5412
5413  Object* pt = GetPrototype();
5414  if (pt == Heap::null_value()) return false;
5415  return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
5416}
5417
5418
5419bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) {
5420  // Make sure that the top context does not change when doing
5421  // callbacks or interceptor calls.
5422  AssertNoContextChange ncc;
5423  HandleScope scope;
5424  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
5425  Handle<JSObject> receiver_handle(receiver);
5426  Handle<JSObject> holder_handle(this);
5427  CustomArguments args(interceptor->data(), receiver, this);
5428  v8::AccessorInfo info(args.end());
5429  if (!interceptor->query()->IsUndefined()) {
5430    v8::IndexedPropertyQuery query =
5431        v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
5432    LOG(ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
5433    v8::Handle<v8::Boolean> result;
5434    {
5435      // Leaving JavaScript.
5436      VMState state(EXTERNAL);
5437      result = query(index, info);
5438    }
5439    if (!result.IsEmpty()) return result->IsTrue();
5440  } else if (!interceptor->getter()->IsUndefined()) {
5441    v8::IndexedPropertyGetter getter =
5442        v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
5443    LOG(ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
5444    v8::Handle<v8::Value> result;
5445    {
5446      // Leaving JavaScript.
5447      VMState state(EXTERNAL);
5448      result = getter(index, info);
5449    }
5450    if (!result.IsEmpty()) return true;
5451  }
5452  return holder_handle->HasElementPostInterceptor(*receiver_handle, index);
5453}
5454
5455
5456bool JSObject::HasLocalElement(uint32_t index) {
5457  // Check access rights if needed.
5458  if (IsAccessCheckNeeded() &&
5459      !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
5460    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
5461    return false;
5462  }
5463
5464  // Check for lookup interceptor
5465  if (HasIndexedInterceptor()) {
5466    return HasElementWithInterceptor(this, index);
5467  }
5468
5469  // Handle [] on String objects.
5470  if (this->IsStringObjectWithCharacterAt(index)) return true;
5471
5472  switch (GetElementsKind()) {
5473    case FAST_ELEMENTS: {
5474      uint32_t length = IsJSArray() ?
5475          static_cast<uint32_t>
5476              (Smi::cast(JSArray::cast(this)->length())->value()) :
5477          static_cast<uint32_t>(FixedArray::cast(elements())->length());
5478      return (index < length) &&
5479          !FixedArray::cast(elements())->get(index)->IsTheHole();
5480    }
5481    case PIXEL_ELEMENTS: {
5482      PixelArray* pixels = PixelArray::cast(elements());
5483      return (index < static_cast<uint32_t>(pixels->length()));
5484    }
5485    case EXTERNAL_BYTE_ELEMENTS:
5486    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
5487    case EXTERNAL_SHORT_ELEMENTS:
5488    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
5489    case EXTERNAL_INT_ELEMENTS:
5490    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
5491    case EXTERNAL_FLOAT_ELEMENTS: {
5492      ExternalArray* array = ExternalArray::cast(elements());
5493      return (index < static_cast<uint32_t>(array->length()));
5494    }
5495    case DICTIONARY_ELEMENTS: {
5496      return element_dictionary()->FindEntry(index)
5497          != NumberDictionary::kNotFound;
5498    }
5499    default:
5500      UNREACHABLE();
5501      break;
5502  }
5503  UNREACHABLE();
5504  return Heap::null_value();
5505}
5506
5507
5508bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
5509  // Check access rights if needed.
5510  if (IsAccessCheckNeeded() &&
5511      !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
5512    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
5513    return false;
5514  }
5515
5516  // Check for lookup interceptor
5517  if (HasIndexedInterceptor()) {
5518    return HasElementWithInterceptor(receiver, index);
5519  }
5520
5521  switch (GetElementsKind()) {
5522    case FAST_ELEMENTS: {
5523      uint32_t length = IsJSArray() ?
5524          static_cast<uint32_t>
5525              (Smi::cast(JSArray::cast(this)->length())->value()) :
5526          static_cast<uint32_t>(FixedArray::cast(elements())->length());
5527      if ((index < length) &&
5528          !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
5529      break;
5530    }
5531    case PIXEL_ELEMENTS: {
5532      PixelArray* pixels = PixelArray::cast(elements());
5533      if (index < static_cast<uint32_t>(pixels->length())) {
5534        return true;
5535      }
5536      break;
5537    }
5538    case EXTERNAL_BYTE_ELEMENTS:
5539    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
5540    case EXTERNAL_SHORT_ELEMENTS:
5541    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
5542    case EXTERNAL_INT_ELEMENTS:
5543    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
5544    case EXTERNAL_FLOAT_ELEMENTS: {
5545      ExternalArray* array = ExternalArray::cast(elements());
5546      if (index < static_cast<uint32_t>(array->length())) {
5547        return true;
5548      }
5549      break;
5550    }
5551    case DICTIONARY_ELEMENTS: {
5552      if (element_dictionary()->FindEntry(index)
5553          != NumberDictionary::kNotFound) {
5554        return true;
5555      }
5556      break;
5557    }
5558    default:
5559      UNREACHABLE();
5560      break;
5561  }
5562
5563  // Handle [] on String objects.
5564  if (this->IsStringObjectWithCharacterAt(index)) return true;
5565
5566  Object* pt = GetPrototype();
5567  if (pt == Heap::null_value()) return false;
5568  return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
5569}
5570
5571
5572Object* JSObject::SetElementWithInterceptor(uint32_t index, Object* value) {
5573  // Make sure that the top context does not change when doing
5574  // callbacks or interceptor calls.
5575  AssertNoContextChange ncc;
5576  HandleScope scope;
5577  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
5578  Handle<JSObject> this_handle(this);
5579  Handle<Object> value_handle(value);
5580  if (!interceptor->setter()->IsUndefined()) {
5581    v8::IndexedPropertySetter setter =
5582        v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
5583    LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
5584    CustomArguments args(interceptor->data(), this, this);
5585    v8::AccessorInfo info(args.end());
5586    v8::Handle<v8::Value> result;
5587    {
5588      // Leaving JavaScript.
5589      VMState state(EXTERNAL);
5590      result = setter(index, v8::Utils::ToLocal(value_handle), info);
5591    }
5592    RETURN_IF_SCHEDULED_EXCEPTION();
5593    if (!result.IsEmpty()) return *value_handle;
5594  }
5595  Object* raw_result =
5596      this_handle->SetElementWithoutInterceptor(index, *value_handle);
5597  RETURN_IF_SCHEDULED_EXCEPTION();
5598  return raw_result;
5599}
5600
5601
5602// Adding n elements in fast case is O(n*n).
5603// Note: revisit design to have dual undefined values to capture absent
5604// elements.
5605Object* JSObject::SetFastElement(uint32_t index, Object* value) {
5606  ASSERT(HasFastElements());
5607
5608  FixedArray* elms = FixedArray::cast(elements());
5609  uint32_t elms_length = static_cast<uint32_t>(elms->length());
5610
5611  if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) {
5612    Object* setter = LookupCallbackSetterInPrototypes(index);
5613    if (setter->IsJSFunction()) {
5614      return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
5615    }
5616  }
5617
5618  // Check whether there is extra space in fixed array..
5619  if (index < elms_length) {
5620    elms->set(index, value);
5621    if (IsJSArray()) {
5622      // Update the length of the array if needed.
5623      uint32_t array_length = 0;
5624      CHECK(Array::IndexFromObject(JSArray::cast(this)->length(),
5625                                   &array_length));
5626      if (index >= array_length) {
5627        JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
5628      }
5629    }
5630    return value;
5631  }
5632
5633  // Allow gap in fast case.
5634  if ((index - elms_length) < kMaxGap) {
5635    // Try allocating extra space.
5636    int new_capacity = NewElementsCapacity(index+1);
5637    if (new_capacity <= kMaxFastElementsLength ||
5638        !ShouldConvertToSlowElements(new_capacity)) {
5639      ASSERT(static_cast<uint32_t>(new_capacity) > index);
5640      Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
5641      if (obj->IsFailure()) return obj;
5642      SetFastElements(FixedArray::cast(obj));
5643      if (IsJSArray()) {
5644        JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
5645      }
5646      FixedArray::cast(elements())->set(index, value);
5647      return value;
5648    }
5649  }
5650
5651  // Otherwise default to slow case.
5652  Object* obj = NormalizeElements();
5653  if (obj->IsFailure()) return obj;
5654  ASSERT(HasDictionaryElements());
5655  return SetElement(index, value);
5656}
5657
5658Object* JSObject::SetElement(uint32_t index, Object* value) {
5659  // Check access rights if needed.
5660  if (IsAccessCheckNeeded() &&
5661      !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) {
5662    Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
5663    return value;
5664  }
5665
5666  if (IsJSGlobalProxy()) {
5667    Object* proto = GetPrototype();
5668    if (proto->IsNull()) return value;
5669    ASSERT(proto->IsJSGlobalObject());
5670    return JSObject::cast(proto)->SetElement(index, value);
5671  }
5672
5673  // Check for lookup interceptor
5674  if (HasIndexedInterceptor()) {
5675    return SetElementWithInterceptor(index, value);
5676  }
5677
5678  return SetElementWithoutInterceptor(index, value);
5679}
5680
5681
5682Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) {
5683  switch (GetElementsKind()) {
5684    case FAST_ELEMENTS:
5685      // Fast case.
5686      return SetFastElement(index, value);
5687    case PIXEL_ELEMENTS: {
5688      PixelArray* pixels = PixelArray::cast(elements());
5689      return pixels->SetValue(index, value);
5690    }
5691    case EXTERNAL_BYTE_ELEMENTS: {
5692      ExternalByteArray* array = ExternalByteArray::cast(elements());
5693      return array->SetValue(index, value);
5694    }
5695    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
5696      ExternalUnsignedByteArray* array =
5697          ExternalUnsignedByteArray::cast(elements());
5698      return array->SetValue(index, value);
5699    }
5700    case EXTERNAL_SHORT_ELEMENTS: {
5701      ExternalShortArray* array = ExternalShortArray::cast(elements());
5702      return array->SetValue(index, value);
5703    }
5704    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
5705      ExternalUnsignedShortArray* array =
5706          ExternalUnsignedShortArray::cast(elements());
5707      return array->SetValue(index, value);
5708    }
5709    case EXTERNAL_INT_ELEMENTS: {
5710      ExternalIntArray* array = ExternalIntArray::cast(elements());
5711      return array->SetValue(index, value);
5712    }
5713    case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
5714      ExternalUnsignedIntArray* array =
5715          ExternalUnsignedIntArray::cast(elements());
5716      return array->SetValue(index, value);
5717    }
5718    case EXTERNAL_FLOAT_ELEMENTS: {
5719      ExternalFloatArray* array = ExternalFloatArray::cast(elements());
5720      return array->SetValue(index, value);
5721    }
5722    case DICTIONARY_ELEMENTS: {
5723      // Insert element in the dictionary.
5724      FixedArray* elms = FixedArray::cast(elements());
5725      NumberDictionary* dictionary = NumberDictionary::cast(elms);
5726
5727      int entry = dictionary->FindEntry(index);
5728      if (entry != NumberDictionary::kNotFound) {
5729        Object* element = dictionary->ValueAt(entry);
5730        PropertyDetails details = dictionary->DetailsAt(entry);
5731        if (details.type() == CALLBACKS) {
5732          // Only accessors allowed as elements.
5733          FixedArray* structure = FixedArray::cast(element);
5734          if (structure->get(kSetterIndex)->IsJSFunction()) {
5735            JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex));
5736            return SetPropertyWithDefinedSetter(setter, value);
5737          } else {
5738            Handle<Object> self(this);
5739            Handle<Object> key(Factory::NewNumberFromUint(index));
5740            Handle<Object> args[2] = { key, self };
5741            return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
5742                                                     HandleVector(args, 2)));
5743          }
5744        } else {
5745          dictionary->UpdateMaxNumberKey(index);
5746          dictionary->ValueAtPut(entry, value);
5747        }
5748      } else {
5749        // Index not already used. Look for an accessor in the prototype chain.
5750        if (!IsJSArray()) {
5751          Object* setter = LookupCallbackSetterInPrototypes(index);
5752          if (setter->IsJSFunction()) {
5753            return SetPropertyWithDefinedSetter(JSFunction::cast(setter),
5754                                                value);
5755          }
5756        }
5757        Object* result = dictionary->AtNumberPut(index, value);
5758        if (result->IsFailure()) return result;
5759        if (elms != FixedArray::cast(result)) {
5760          set_elements(FixedArray::cast(result));
5761        }
5762      }
5763
5764      // Update the array length if this JSObject is an array.
5765      if (IsJSArray()) {
5766        JSArray* array = JSArray::cast(this);
5767        Object* return_value = array->JSArrayUpdateLengthFromIndex(index,
5768                                                                   value);
5769        if (return_value->IsFailure()) return return_value;
5770      }
5771
5772      // Attempt to put this object back in fast case.
5773      if (ShouldConvertToFastElements()) {
5774        uint32_t new_length = 0;
5775        if (IsJSArray()) {
5776          CHECK(Array::IndexFromObject(JSArray::cast(this)->length(),
5777                                       &new_length));
5778          JSArray::cast(this)->set_length(Smi::FromInt(new_length));
5779        } else {
5780          new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
5781        }
5782        Object* obj = Heap::AllocateFixedArrayWithHoles(new_length);
5783        if (obj->IsFailure()) return obj;
5784        SetFastElements(FixedArray::cast(obj));
5785#ifdef DEBUG
5786        if (FLAG_trace_normalization) {
5787          PrintF("Object elements are fast case again:\n");
5788          Print();
5789        }
5790#endif
5791      }
5792
5793      return value;
5794    }
5795    default:
5796      UNREACHABLE();
5797      break;
5798  }
5799  // All possible cases have been handled above. Add a return to avoid the
5800  // complaints from the compiler.
5801  UNREACHABLE();
5802  return Heap::null_value();
5803}
5804
5805
5806Object* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, Object* value) {
5807  uint32_t old_len = 0;
5808  CHECK(Array::IndexFromObject(length(), &old_len));
5809  // Check to see if we need to update the length. For now, we make
5810  // sure that the length stays within 32-bits (unsigned).
5811  if (index >= old_len && index != 0xffffffff) {
5812    Object* len =
5813        Heap::NumberFromDouble(static_cast<double>(index) + 1);
5814    if (len->IsFailure()) return len;
5815    set_length(len);
5816  }
5817  return value;
5818}
5819
5820
5821Object* JSObject::GetElementPostInterceptor(JSObject* receiver,
5822                                            uint32_t index) {
5823  // Get element works for both JSObject and JSArray since
5824  // JSArray::length cannot change.
5825  switch (GetElementsKind()) {
5826    case FAST_ELEMENTS: {
5827      FixedArray* elms = FixedArray::cast(elements());
5828      if (index < static_cast<uint32_t>(elms->length())) {
5829        Object* value = elms->get(index);
5830        if (!value->IsTheHole()) return value;
5831      }
5832      break;
5833    }
5834    case PIXEL_ELEMENTS: {
5835      // TODO(iposva): Add testcase and implement.
5836      UNIMPLEMENTED();
5837      break;
5838    }
5839    case EXTERNAL_BYTE_ELEMENTS:
5840    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
5841    case EXTERNAL_SHORT_ELEMENTS:
5842    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
5843    case EXTERNAL_INT_ELEMENTS:
5844    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
5845    case EXTERNAL_FLOAT_ELEMENTS: {
5846      // TODO(kbr): Add testcase and implement.
5847      UNIMPLEMENTED();
5848      break;
5849    }
5850    case DICTIONARY_ELEMENTS: {
5851      NumberDictionary* dictionary = element_dictionary();
5852      int entry = dictionary->FindEntry(index);
5853      if (entry != NumberDictionary::kNotFound) {
5854        Object* element = dictionary->ValueAt(entry);
5855        PropertyDetails details = dictionary->DetailsAt(entry);
5856        if (details.type() == CALLBACKS) {
5857          // Only accessors allowed as elements.
5858          FixedArray* structure = FixedArray::cast(element);
5859          Object* getter = structure->get(kGetterIndex);
5860          if (getter->IsJSFunction()) {
5861            return GetPropertyWithDefinedGetter(receiver,
5862                                                JSFunction::cast(getter));
5863          } else {
5864            // Getter is not a function.
5865            return Heap::undefined_value();
5866          }
5867        }
5868        return element;
5869      }
5870      break;
5871    }
5872    default:
5873      UNREACHABLE();
5874      break;
5875  }
5876
5877  // Continue searching via the prototype chain.
5878  Object* pt = GetPrototype();
5879  if (pt == Heap::null_value()) return Heap::undefined_value();
5880  return pt->GetElementWithReceiver(receiver, index);
5881}
5882
5883
5884Object* JSObject::GetElementWithInterceptor(JSObject* receiver,
5885                                            uint32_t index) {
5886  // Make sure that the top context does not change when doing
5887  // callbacks or interceptor calls.
5888  AssertNoContextChange ncc;
5889  HandleScope scope;
5890  Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
5891  Handle<JSObject> this_handle(receiver);
5892  Handle<JSObject> holder_handle(this);
5893
5894  if (!interceptor->getter()->IsUndefined()) {
5895    v8::IndexedPropertyGetter getter =
5896        v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
5897    LOG(ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
5898    CustomArguments args(interceptor->data(), receiver, this);
5899    v8::AccessorInfo info(args.end());
5900    v8::Handle<v8::Value> result;
5901    {
5902      // Leaving JavaScript.
5903      VMState state(EXTERNAL);
5904      result = getter(index, info);
5905    }
5906    RETURN_IF_SCHEDULED_EXCEPTION();
5907    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5908  }
5909
5910  Object* raw_result =
5911      holder_handle->GetElementPostInterceptor(*this_handle, index);
5912  RETURN_IF_SCHEDULED_EXCEPTION();
5913  return raw_result;
5914}
5915
5916
5917Object* JSObject::GetElementWithReceiver(JSObject* receiver, uint32_t index) {
5918  // Check access rights if needed.
5919  if (IsAccessCheckNeeded() &&
5920      !Top::MayIndexedAccess(this, index, v8::ACCESS_GET)) {
5921    Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
5922    return Heap::undefined_value();
5923  }
5924
5925  if (HasIndexedInterceptor()) {
5926    return GetElementWithInterceptor(receiver, index);
5927  }
5928
5929  // Get element works for both JSObject and JSArray since
5930  // JSArray::length cannot change.
5931  switch (GetElementsKind()) {
5932    case FAST_ELEMENTS: {
5933      FixedArray* elms = FixedArray::cast(elements());
5934      if (index < static_cast<uint32_t>(elms->length())) {
5935        Object* value = elms->get(index);
5936        if (!value->IsTheHole()) return value;
5937      }
5938      break;
5939    }
5940    case PIXEL_ELEMENTS: {
5941      PixelArray* pixels = PixelArray::cast(elements());
5942      if (index < static_cast<uint32_t>(pixels->length())) {
5943        uint8_t value = pixels->get(index);
5944        return Smi::FromInt(value);
5945      }
5946      break;
5947    }
5948    case EXTERNAL_BYTE_ELEMENTS: {
5949      ExternalByteArray* array = ExternalByteArray::cast(elements());
5950      if (index < static_cast<uint32_t>(array->length())) {
5951        int8_t value = array->get(index);
5952        return Smi::FromInt(value);
5953      }
5954      break;
5955    }
5956    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
5957      ExternalUnsignedByteArray* array =
5958          ExternalUnsignedByteArray::cast(elements());
5959      if (index < static_cast<uint32_t>(array->length())) {
5960        uint8_t value = array->get(index);
5961        return Smi::FromInt(value);
5962      }
5963      break;
5964    }
5965    case EXTERNAL_SHORT_ELEMENTS: {
5966      ExternalShortArray* array = ExternalShortArray::cast(elements());
5967      if (index < static_cast<uint32_t>(array->length())) {
5968        int16_t value = array->get(index);
5969        return Smi::FromInt(value);
5970      }
5971      break;
5972    }
5973    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
5974      ExternalUnsignedShortArray* array =
5975          ExternalUnsignedShortArray::cast(elements());
5976      if (index < static_cast<uint32_t>(array->length())) {
5977        uint16_t value = array->get(index);
5978        return Smi::FromInt(value);
5979      }
5980      break;
5981    }
5982    case EXTERNAL_INT_ELEMENTS: {
5983      ExternalIntArray* array = ExternalIntArray::cast(elements());
5984      if (index < static_cast<uint32_t>(array->length())) {
5985        int32_t value = array->get(index);
5986        return Heap::NumberFromInt32(value);
5987      }
5988      break;
5989    }
5990    case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
5991      ExternalUnsignedIntArray* array =
5992          ExternalUnsignedIntArray::cast(elements());
5993      if (index < static_cast<uint32_t>(array->length())) {
5994        uint32_t value = array->get(index);
5995        return Heap::NumberFromUint32(value);
5996      }
5997      break;
5998    }
5999    case EXTERNAL_FLOAT_ELEMENTS: {
6000      ExternalFloatArray* array = ExternalFloatArray::cast(elements());
6001      if (index < static_cast<uint32_t>(array->length())) {
6002        float value = array->get(index);
6003        return Heap::AllocateHeapNumber(value);
6004      }
6005      break;
6006    }
6007    case DICTIONARY_ELEMENTS: {
6008      NumberDictionary* dictionary = element_dictionary();
6009      int entry = dictionary->FindEntry(index);
6010      if (entry != NumberDictionary::kNotFound) {
6011        Object* element = dictionary->ValueAt(entry);
6012        PropertyDetails details = dictionary->DetailsAt(entry);
6013        if (details.type() == CALLBACKS) {
6014          // Only accessors allowed as elements.
6015          FixedArray* structure = FixedArray::cast(element);
6016          Object* getter = structure->get(kGetterIndex);
6017          if (getter->IsJSFunction()) {
6018            return GetPropertyWithDefinedGetter(receiver,
6019                                                JSFunction::cast(getter));
6020          } else {
6021            // Getter is not a function.
6022            return Heap::undefined_value();
6023          }
6024        }
6025        return element;
6026      }
6027      break;
6028    }
6029  }
6030
6031  Object* pt = GetPrototype();
6032  if (pt == Heap::null_value()) return Heap::undefined_value();
6033  return pt->GetElementWithReceiver(receiver, index);
6034}
6035
6036
6037bool JSObject::HasDenseElements() {
6038  int capacity = 0;
6039  int number_of_elements = 0;
6040
6041  switch (GetElementsKind()) {
6042    case FAST_ELEMENTS: {
6043      FixedArray* elms = FixedArray::cast(elements());
6044      capacity = elms->length();
6045      for (int i = 0; i < capacity; i++) {
6046        if (!elms->get(i)->IsTheHole()) number_of_elements++;
6047      }
6048      break;
6049    }
6050    case PIXEL_ELEMENTS:
6051    case EXTERNAL_BYTE_ELEMENTS:
6052    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
6053    case EXTERNAL_SHORT_ELEMENTS:
6054    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
6055    case EXTERNAL_INT_ELEMENTS:
6056    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
6057    case EXTERNAL_FLOAT_ELEMENTS: {
6058      return true;
6059    }
6060    case DICTIONARY_ELEMENTS: {
6061      NumberDictionary* dictionary = NumberDictionary::cast(elements());
6062      capacity = dictionary->Capacity();
6063      number_of_elements = dictionary->NumberOfElements();
6064      break;
6065    }
6066    default:
6067      UNREACHABLE();
6068      break;
6069  }
6070
6071  if (capacity == 0) return true;
6072  return (number_of_elements > (capacity / 2));
6073}
6074
6075
6076bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
6077  ASSERT(HasFastElements());
6078  // Keep the array in fast case if the current backing storage is
6079  // almost filled and if the new capacity is no more than twice the
6080  // old capacity.
6081  int elements_length = FixedArray::cast(elements())->length();
6082  return !HasDenseElements() || ((new_capacity / 2) > elements_length);
6083}
6084
6085
6086bool JSObject::ShouldConvertToFastElements() {
6087  ASSERT(HasDictionaryElements());
6088  NumberDictionary* dictionary = NumberDictionary::cast(elements());
6089  // If the elements are sparse, we should not go back to fast case.
6090  if (!HasDenseElements()) return false;
6091  // If an element has been added at a very high index in the elements
6092  // dictionary, we cannot go back to fast case.
6093  if (dictionary->requires_slow_elements()) return false;
6094  // An object requiring access checks is never allowed to have fast
6095  // elements.  If it had fast elements we would skip security checks.
6096  if (IsAccessCheckNeeded()) return false;
6097  // If the dictionary backing storage takes up roughly half as much
6098  // space as a fast-case backing storage would the array should have
6099  // fast elements.
6100  uint32_t length = 0;
6101  if (IsJSArray()) {
6102    CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &length));
6103  } else {
6104    length = dictionary->max_number_key();
6105  }
6106  return static_cast<uint32_t>(dictionary->Capacity()) >=
6107      (length / (2 * NumberDictionary::kEntrySize));
6108}
6109
6110
6111// Certain compilers request function template instantiation when they
6112// see the definition of the other template functions in the
6113// class. This requires us to have the template functions put
6114// together, so even though this function belongs in objects-debug.cc,
6115// we keep it here instead to satisfy certain compilers.
6116#ifdef DEBUG
6117template<typename Shape, typename Key>
6118void Dictionary<Shape, Key>::Print() {
6119  int capacity = HashTable<Shape, Key>::Capacity();
6120  for (int i = 0; i < capacity; i++) {
6121    Object* k = HashTable<Shape, Key>::KeyAt(i);
6122    if (HashTable<Shape, Key>::IsKey(k)) {
6123      PrintF(" ");
6124      if (k->IsString()) {
6125        String::cast(k)->StringPrint();
6126      } else {
6127        k->ShortPrint();
6128      }
6129      PrintF(": ");
6130      ValueAt(i)->ShortPrint();
6131      PrintF("\n");
6132    }
6133  }
6134}
6135#endif
6136
6137
6138template<typename Shape, typename Key>
6139void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
6140  int pos = 0;
6141  int capacity = HashTable<Shape, Key>::Capacity();
6142  AssertNoAllocation no_gc;
6143  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6144  for (int i = 0; i < capacity; i++) {
6145    Object* k =  Dictionary<Shape, Key>::KeyAt(i);
6146    if (Dictionary<Shape, Key>::IsKey(k)) {
6147      elements->set(pos++, ValueAt(i), mode);
6148    }
6149  }
6150  ASSERT(pos == elements->length());
6151}
6152
6153
6154InterceptorInfo* JSObject::GetNamedInterceptor() {
6155  ASSERT(map()->has_named_interceptor());
6156  JSFunction* constructor = JSFunction::cast(map()->constructor());
6157  Object* template_info = constructor->shared()->function_data();
6158  Object* result =
6159      FunctionTemplateInfo::cast(template_info)->named_property_handler();
6160  return InterceptorInfo::cast(result);
6161}
6162
6163
6164InterceptorInfo* JSObject::GetIndexedInterceptor() {
6165  ASSERT(map()->has_indexed_interceptor());
6166  JSFunction* constructor = JSFunction::cast(map()->constructor());
6167  Object* template_info = constructor->shared()->function_data();
6168  Object* result =
6169      FunctionTemplateInfo::cast(template_info)->indexed_property_handler();
6170  return InterceptorInfo::cast(result);
6171}
6172
6173
6174Object* JSObject::GetPropertyPostInterceptor(JSObject* receiver,
6175                                             String* name,
6176                                             PropertyAttributes* attributes) {
6177  // Check local property in holder, ignore interceptor.
6178  LookupResult result;
6179  LocalLookupRealNamedProperty(name, &result);
6180  if (result.IsProperty()) {
6181    return GetProperty(receiver, &result, name, attributes);
6182  }
6183  // Continue searching via the prototype chain.
6184  Object* pt = GetPrototype();
6185  *attributes = ABSENT;
6186  if (pt == Heap::null_value()) return Heap::undefined_value();
6187  return pt->GetPropertyWithReceiver(receiver, name, attributes);
6188}
6189
6190
6191Object* JSObject::GetLocalPropertyPostInterceptor(
6192    JSObject* receiver,
6193    String* name,
6194    PropertyAttributes* attributes) {
6195  // Check local property in holder, ignore interceptor.
6196  LookupResult result;
6197  LocalLookupRealNamedProperty(name, &result);
6198  if (result.IsProperty()) {
6199    return GetProperty(receiver, &result, name, attributes);
6200  }
6201  return Heap::undefined_value();
6202}
6203
6204
6205Object* JSObject::GetPropertyWithInterceptor(
6206    JSObject* receiver,
6207    String* name,
6208    PropertyAttributes* attributes) {
6209  InterceptorInfo* interceptor = GetNamedInterceptor();
6210  HandleScope scope;
6211  Handle<JSObject> receiver_handle(receiver);
6212  Handle<JSObject> holder_handle(this);
6213  Handle<String> name_handle(name);
6214
6215  if (!interceptor->getter()->IsUndefined()) {
6216    v8::NamedPropertyGetter getter =
6217        v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
6218    LOG(ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
6219    CustomArguments args(interceptor->data(), receiver, this);
6220    v8::AccessorInfo info(args.end());
6221    v8::Handle<v8::Value> result;
6222    {
6223      // Leaving JavaScript.
6224      VMState state(EXTERNAL);
6225      result = getter(v8::Utils::ToLocal(name_handle), info);
6226    }
6227    RETURN_IF_SCHEDULED_EXCEPTION();
6228    if (!result.IsEmpty()) {
6229      *attributes = NONE;
6230      return *v8::Utils::OpenHandle(*result);
6231    }
6232  }
6233
6234  Object* result = holder_handle->GetPropertyPostInterceptor(
6235      *receiver_handle,
6236      *name_handle,
6237      attributes);
6238  RETURN_IF_SCHEDULED_EXCEPTION();
6239  return result;
6240}
6241
6242
6243bool JSObject::HasRealNamedProperty(String* key) {
6244  // Check access rights if needed.
6245  if (IsAccessCheckNeeded() &&
6246      !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) {
6247    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
6248    return false;
6249  }
6250
6251  LookupResult result;
6252  LocalLookupRealNamedProperty(key, &result);
6253  return result.IsProperty() && (result.type() != INTERCEPTOR);
6254}
6255
6256
6257bool JSObject::HasRealElementProperty(uint32_t index) {
6258  // Check access rights if needed.
6259  if (IsAccessCheckNeeded() &&
6260      !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
6261    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
6262    return false;
6263  }
6264
6265  // Handle [] on String objects.
6266  if (this->IsStringObjectWithCharacterAt(index)) return true;
6267
6268  switch (GetElementsKind()) {
6269    case FAST_ELEMENTS: {
6270      uint32_t length = IsJSArray() ?
6271          static_cast<uint32_t>(
6272              Smi::cast(JSArray::cast(this)->length())->value()) :
6273          static_cast<uint32_t>(FixedArray::cast(elements())->length());
6274      return (index < length) &&
6275          !FixedArray::cast(elements())->get(index)->IsTheHole();
6276    }
6277    case PIXEL_ELEMENTS: {
6278      PixelArray* pixels = PixelArray::cast(elements());
6279      return index < static_cast<uint32_t>(pixels->length());
6280    }
6281    case EXTERNAL_BYTE_ELEMENTS:
6282    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
6283    case EXTERNAL_SHORT_ELEMENTS:
6284    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
6285    case EXTERNAL_INT_ELEMENTS:
6286    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
6287    case EXTERNAL_FLOAT_ELEMENTS: {
6288      ExternalArray* array = ExternalArray::cast(elements());
6289      return index < static_cast<uint32_t>(array->length());
6290    }
6291    case DICTIONARY_ELEMENTS: {
6292      return element_dictionary()->FindEntry(index)
6293          != NumberDictionary::kNotFound;
6294    }
6295    default:
6296      UNREACHABLE();
6297      break;
6298  }
6299  // All possibilities have been handled above already.
6300  UNREACHABLE();
6301  return Heap::null_value();
6302}
6303
6304
6305bool JSObject::HasRealNamedCallbackProperty(String* key) {
6306  // Check access rights if needed.
6307  if (IsAccessCheckNeeded() &&
6308      !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) {
6309    Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
6310    return false;
6311  }
6312
6313  LookupResult result;
6314  LocalLookupRealNamedProperty(key, &result);
6315  return result.IsProperty() && (result.type() == CALLBACKS);
6316}
6317
6318
6319int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
6320  if (HasFastProperties()) {
6321    DescriptorArray* descs = map()->instance_descriptors();
6322    int result = 0;
6323    for (int i = 0; i < descs->number_of_descriptors(); i++) {
6324      PropertyDetails details = descs->GetDetails(i);
6325      if (details.IsProperty() && (details.attributes() & filter) == 0) {
6326        result++;
6327      }
6328    }
6329    return result;
6330  } else {
6331    return property_dictionary()->NumberOfElementsFilterAttributes(filter);
6332  }
6333}
6334
6335
6336int JSObject::NumberOfEnumProperties() {
6337  return NumberOfLocalProperties(static_cast<PropertyAttributes>(DONT_ENUM));
6338}
6339
6340
6341void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
6342  Object* temp = get(i);
6343  set(i, get(j));
6344  set(j, temp);
6345  if (this != numbers) {
6346    temp = numbers->get(i);
6347    numbers->set(i, numbers->get(j));
6348    numbers->set(j, temp);
6349  }
6350}
6351
6352
6353static void InsertionSortPairs(FixedArray* content,
6354                               FixedArray* numbers,
6355                               int len) {
6356  for (int i = 1; i < len; i++) {
6357    int j = i;
6358    while (j > 0 &&
6359           (NumberToUint32(numbers->get(j - 1)) >
6360            NumberToUint32(numbers->get(j)))) {
6361      content->SwapPairs(numbers, j - 1, j);
6362      j--;
6363    }
6364  }
6365}
6366
6367
6368void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
6369  // In-place heap sort.
6370  ASSERT(content->length() == numbers->length());
6371
6372  // Bottom-up max-heap construction.
6373  for (int i = 1; i < len; ++i) {
6374    int child_index = i;
6375    while (child_index > 0) {
6376      int parent_index = ((child_index + 1) >> 1) - 1;
6377      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
6378      uint32_t child_value = NumberToUint32(numbers->get(child_index));
6379      if (parent_value < child_value) {
6380        content->SwapPairs(numbers, parent_index, child_index);
6381      } else {
6382        break;
6383      }
6384      child_index = parent_index;
6385    }
6386  }
6387
6388  // Extract elements and create sorted array.
6389  for (int i = len - 1; i > 0; --i) {
6390    // Put max element at the back of the array.
6391    content->SwapPairs(numbers, 0, i);
6392    // Sift down the new top element.
6393    int parent_index = 0;
6394    while (true) {
6395      int child_index = ((parent_index + 1) << 1) - 1;
6396      if (child_index >= i) break;
6397      uint32_t child1_value = NumberToUint32(numbers->get(child_index));
6398      uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
6399      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
6400      if (child_index + 1 >= i || child1_value > child2_value) {
6401        if (parent_value > child1_value) break;
6402        content->SwapPairs(numbers, parent_index, child_index);
6403        parent_index = child_index;
6404      } else {
6405        if (parent_value > child2_value) break;
6406        content->SwapPairs(numbers, parent_index, child_index + 1);
6407        parent_index = child_index + 1;
6408      }
6409    }
6410  }
6411}
6412
6413
6414// Sort this array and the numbers as pairs wrt. the (distinct) numbers.
6415void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
6416  ASSERT(this->length() == numbers->length());
6417  // For small arrays, simply use insertion sort.
6418  if (len <= 10) {
6419    InsertionSortPairs(this, numbers, len);
6420    return;
6421  }
6422  // Check the range of indices.
6423  uint32_t min_index = NumberToUint32(numbers->get(0));
6424  uint32_t max_index = min_index;
6425  uint32_t i;
6426  for (i = 1; i < len; i++) {
6427    if (NumberToUint32(numbers->get(i)) < min_index) {
6428      min_index = NumberToUint32(numbers->get(i));
6429    } else if (NumberToUint32(numbers->get(i)) > max_index) {
6430      max_index = NumberToUint32(numbers->get(i));
6431    }
6432  }
6433  if (max_index - min_index + 1 == len) {
6434    // Indices form a contiguous range, unless there are duplicates.
6435    // Do an in-place linear time sort assuming distinct numbers, but
6436    // avoid hanging in case they are not.
6437    for (i = 0; i < len; i++) {
6438      uint32_t p;
6439      uint32_t j = 0;
6440      // While the current element at i is not at its correct position p,
6441      // swap the elements at these two positions.
6442      while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
6443             j++ < len) {
6444        SwapPairs(numbers, i, p);
6445      }
6446    }
6447  } else {
6448    HeapSortPairs(this, numbers, len);
6449    return;
6450  }
6451}
6452
6453
6454// Fill in the names of local properties into the supplied storage. The main
6455// purpose of this function is to provide reflection information for the object
6456// mirrors.
6457void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
6458  ASSERT(storage->length() >= (NumberOfLocalProperties(NONE) - index));
6459  if (HasFastProperties()) {
6460    DescriptorArray* descs = map()->instance_descriptors();
6461    for (int i = 0; i < descs->number_of_descriptors(); i++) {
6462      if (descs->IsProperty(i)) storage->set(index++, descs->GetKey(i));
6463    }
6464    ASSERT(storage->length() >= index);
6465  } else {
6466    property_dictionary()->CopyKeysTo(storage);
6467  }
6468}
6469
6470
6471int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
6472  return GetLocalElementKeys(NULL, filter);
6473}
6474
6475
6476int JSObject::NumberOfEnumElements() {
6477  // Fast case for objects with no elements.
6478  if (!IsJSValue() && HasFastElements()) {
6479    uint32_t length = IsJSArray() ?
6480        static_cast<uint32_t>(
6481            Smi::cast(JSArray::cast(this)->length())->value()) :
6482        static_cast<uint32_t>(FixedArray::cast(elements())->length());
6483    if (length == 0) return 0;
6484  }
6485  // Compute the number of enumerable elements.
6486  return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
6487}
6488
6489
6490int JSObject::GetLocalElementKeys(FixedArray* storage,
6491                                  PropertyAttributes filter) {
6492  int counter = 0;
6493  switch (GetElementsKind()) {
6494    case FAST_ELEMENTS: {
6495      int length = IsJSArray() ?
6496          Smi::cast(JSArray::cast(this)->length())->value() :
6497          FixedArray::cast(elements())->length();
6498      for (int i = 0; i < length; i++) {
6499        if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
6500          if (storage != NULL) {
6501            storage->set(counter, Smi::FromInt(i));
6502          }
6503          counter++;
6504        }
6505      }
6506      ASSERT(!storage || storage->length() >= counter);
6507      break;
6508    }
6509    case PIXEL_ELEMENTS: {
6510      int length = PixelArray::cast(elements())->length();
6511      while (counter < length) {
6512        if (storage != NULL) {
6513          storage->set(counter, Smi::FromInt(counter));
6514        }
6515        counter++;
6516      }
6517      ASSERT(!storage || storage->length() >= counter);
6518      break;
6519    }
6520    case EXTERNAL_BYTE_ELEMENTS:
6521    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
6522    case EXTERNAL_SHORT_ELEMENTS:
6523    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
6524    case EXTERNAL_INT_ELEMENTS:
6525    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
6526    case EXTERNAL_FLOAT_ELEMENTS: {
6527      int length = ExternalArray::cast(elements())->length();
6528      while (counter < length) {
6529        if (storage != NULL) {
6530          storage->set(counter, Smi::FromInt(counter));
6531        }
6532        counter++;
6533      }
6534      ASSERT(!storage || storage->length() >= counter);
6535      break;
6536    }
6537    case DICTIONARY_ELEMENTS: {
6538      if (storage != NULL) {
6539        element_dictionary()->CopyKeysTo(storage, filter);
6540      }
6541      counter = element_dictionary()->NumberOfElementsFilterAttributes(filter);
6542      break;
6543    }
6544    default:
6545      UNREACHABLE();
6546      break;
6547  }
6548
6549  if (this->IsJSValue()) {
6550    Object* val = JSValue::cast(this)->value();
6551    if (val->IsString()) {
6552      String* str = String::cast(val);
6553      if (storage) {
6554        for (int i = 0; i < str->length(); i++) {
6555          storage->set(counter + i, Smi::FromInt(i));
6556        }
6557      }
6558      counter += str->length();
6559    }
6560  }
6561  ASSERT(!storage || storage->length() == counter);
6562  return counter;
6563}
6564
6565
6566int JSObject::GetEnumElementKeys(FixedArray* storage) {
6567  return GetLocalElementKeys(storage,
6568                             static_cast<PropertyAttributes>(DONT_ENUM));
6569}
6570
6571
6572bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
6573  ASSERT(other->IsNumber());
6574  return key == static_cast<uint32_t>(other->Number());
6575}
6576
6577
6578uint32_t NumberDictionaryShape::Hash(uint32_t key) {
6579  return ComputeIntegerHash(key);
6580}
6581
6582
6583uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
6584  ASSERT(other->IsNumber());
6585  return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
6586}
6587
6588
6589Object* NumberDictionaryShape::AsObject(uint32_t key) {
6590  return Heap::NumberFromUint32(key);
6591}
6592
6593
6594bool StringDictionaryShape::IsMatch(String* key, Object* other) {
6595  // We know that all entries in a hash table had their hash keys created.
6596  // Use that knowledge to have fast failure.
6597  if (key->Hash() != String::cast(other)->Hash()) return false;
6598  return key->Equals(String::cast(other));
6599}
6600
6601
6602uint32_t StringDictionaryShape::Hash(String* key) {
6603  return key->Hash();
6604}
6605
6606
6607uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
6608  return String::cast(other)->Hash();
6609}
6610
6611
6612Object* StringDictionaryShape::AsObject(String* key) {
6613  return key;
6614}
6615
6616
6617// StringKey simply carries a string object as key.
6618class StringKey : public HashTableKey {
6619 public:
6620  explicit StringKey(String* string) :
6621      string_(string),
6622      hash_(HashForObject(string)) { }
6623
6624  bool IsMatch(Object* string) {
6625    // We know that all entries in a hash table had their hash keys created.
6626    // Use that knowledge to have fast failure.
6627    if (hash_ != HashForObject(string)) {
6628      return false;
6629    }
6630    return string_->Equals(String::cast(string));
6631  }
6632
6633  uint32_t Hash() { return hash_; }
6634
6635  uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
6636
6637  Object* AsObject() { return string_; }
6638
6639  String* string_;
6640  uint32_t hash_;
6641};
6642
6643
6644// StringSharedKeys are used as keys in the eval cache.
6645class StringSharedKey : public HashTableKey {
6646 public:
6647  StringSharedKey(String* source, SharedFunctionInfo* shared)
6648      : source_(source), shared_(shared) { }
6649
6650  bool IsMatch(Object* other) {
6651    if (!other->IsFixedArray()) return false;
6652    FixedArray* pair = FixedArray::cast(other);
6653    SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
6654    if (shared != shared_) return false;
6655    String* source = String::cast(pair->get(1));
6656    return source->Equals(source_);
6657  }
6658
6659  static uint32_t StringSharedHashHelper(String* source,
6660                                         SharedFunctionInfo* shared) {
6661    uint32_t hash = source->Hash();
6662    if (shared->HasSourceCode()) {
6663      // Instead of using the SharedFunctionInfo pointer in the hash
6664      // code computation, we use a combination of the hash of the
6665      // script source code and the start and end positions.  We do
6666      // this to ensure that the cache entries can survive garbage
6667      // collection.
6668      Script* script = Script::cast(shared->script());
6669      hash ^= String::cast(script->source())->Hash();
6670      hash += shared->start_position();
6671    }
6672    return hash;
6673  }
6674
6675  uint32_t Hash() {
6676    return StringSharedHashHelper(source_, shared_);
6677  }
6678
6679  uint32_t HashForObject(Object* obj) {
6680    FixedArray* pair = FixedArray::cast(obj);
6681    SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
6682    String* source = String::cast(pair->get(1));
6683    return StringSharedHashHelper(source, shared);
6684  }
6685
6686  Object* AsObject() {
6687    Object* obj = Heap::AllocateFixedArray(2);
6688    if (obj->IsFailure()) return obj;
6689    FixedArray* pair = FixedArray::cast(obj);
6690    pair->set(0, shared_);
6691    pair->set(1, source_);
6692    return pair;
6693  }
6694
6695 private:
6696  String* source_;
6697  SharedFunctionInfo* shared_;
6698};
6699
6700
6701// RegExpKey carries the source and flags of a regular expression as key.
6702class RegExpKey : public HashTableKey {
6703 public:
6704  RegExpKey(String* string, JSRegExp::Flags flags)
6705      : string_(string),
6706        flags_(Smi::FromInt(flags.value())) { }
6707
6708  // Rather than storing the key in the hash table, a pointer to the
6709  // stored value is stored where the key should be.  IsMatch then
6710  // compares the search key to the found object, rather than comparing
6711  // a key to a key.
6712  bool IsMatch(Object* obj) {
6713    FixedArray* val = FixedArray::cast(obj);
6714    return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
6715        && (flags_ == val->get(JSRegExp::kFlagsIndex));
6716  }
6717
6718  uint32_t Hash() { return RegExpHash(string_, flags_); }
6719
6720  Object* AsObject() {
6721    // Plain hash maps, which is where regexp keys are used, don't
6722    // use this function.
6723    UNREACHABLE();
6724    return NULL;
6725  }
6726
6727  uint32_t HashForObject(Object* obj) {
6728    FixedArray* val = FixedArray::cast(obj);
6729    return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
6730                      Smi::cast(val->get(JSRegExp::kFlagsIndex)));
6731  }
6732
6733  static uint32_t RegExpHash(String* string, Smi* flags) {
6734    return string->Hash() + flags->value();
6735  }
6736
6737  String* string_;
6738  Smi* flags_;
6739};
6740
6741// Utf8SymbolKey carries a vector of chars as key.
6742class Utf8SymbolKey : public HashTableKey {
6743 public:
6744  explicit Utf8SymbolKey(Vector<const char> string)
6745      : string_(string), hash_field_(0) { }
6746
6747  bool IsMatch(Object* string) {
6748    return String::cast(string)->IsEqualTo(string_);
6749  }
6750
6751  uint32_t Hash() {
6752    if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
6753    unibrow::Utf8InputBuffer<> buffer(string_.start(),
6754                                      static_cast<unsigned>(string_.length()));
6755    chars_ = buffer.Length();
6756    hash_field_ = String::ComputeHashField(&buffer, chars_);
6757    uint32_t result = hash_field_ >> String::kHashShift;
6758    ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
6759    return result;
6760  }
6761
6762  uint32_t HashForObject(Object* other) {
6763    return String::cast(other)->Hash();
6764  }
6765
6766  Object* AsObject() {
6767    if (hash_field_ == 0) Hash();
6768    return Heap::AllocateSymbol(string_, chars_, hash_field_);
6769  }
6770
6771  Vector<const char> string_;
6772  uint32_t hash_field_;
6773  int chars_;  // Caches the number of characters when computing the hash code.
6774};
6775
6776
6777// SymbolKey carries a string/symbol object as key.
6778class SymbolKey : public HashTableKey {
6779 public:
6780  explicit SymbolKey(String* string) : string_(string) { }
6781
6782  bool IsMatch(Object* string) {
6783    return String::cast(string)->Equals(string_);
6784  }
6785
6786  uint32_t Hash() { return string_->Hash(); }
6787
6788  uint32_t HashForObject(Object* other) {
6789    return String::cast(other)->Hash();
6790  }
6791
6792  Object* AsObject() {
6793    // If the string is a cons string, attempt to flatten it so that
6794    // symbols will most often be flat strings.
6795    if (StringShape(string_).IsCons()) {
6796      ConsString* cons_string = ConsString::cast(string_);
6797      cons_string->TryFlatten();
6798      if (cons_string->second()->length() == 0) {
6799        string_ = cons_string->first();
6800      }
6801    }
6802    // Transform string to symbol if possible.
6803    Map* map = Heap::SymbolMapForString(string_);
6804    if (map != NULL) {
6805      string_->set_map(map);
6806      ASSERT(string_->IsSymbol());
6807      return string_;
6808    }
6809    // Otherwise allocate a new symbol.
6810    StringInputBuffer buffer(string_);
6811    return Heap::AllocateInternalSymbol(&buffer,
6812                                        string_->length(),
6813                                        string_->hash_field());
6814  }
6815
6816  static uint32_t StringHash(Object* obj) {
6817    return String::cast(obj)->Hash();
6818  }
6819
6820  String* string_;
6821};
6822
6823
6824template<typename Shape, typename Key>
6825void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
6826  IteratePointers(v, 0, kElementsStartOffset);
6827}
6828
6829
6830template<typename Shape, typename Key>
6831void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
6832  IteratePointers(v,
6833                  kElementsStartOffset,
6834                  kHeaderSize + length() * kPointerSize);
6835}
6836
6837
6838template<typename Shape, typename Key>
6839Object* HashTable<Shape, Key>::Allocate(int at_least_space_for) {
6840  int capacity = RoundUpToPowerOf2(at_least_space_for);
6841  if (capacity < 4) {
6842    capacity = 4;  // Guarantee min capacity.
6843  } else if (capacity > HashTable::kMaxCapacity) {
6844    return Failure::OutOfMemoryException();
6845  }
6846
6847  Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity));
6848  if (!obj->IsFailure()) {
6849    HashTable::cast(obj)->SetNumberOfElements(0);
6850    HashTable::cast(obj)->SetNumberOfDeletedElements(0);
6851    HashTable::cast(obj)->SetCapacity(capacity);
6852  }
6853  return obj;
6854}
6855
6856
6857// Find entry for key otherwise return kNotFound.
6858template<typename Shape, typename Key>
6859int HashTable<Shape, Key>::FindEntry(Key key) {
6860  uint32_t capacity = Capacity();
6861  uint32_t entry = FirstProbe(Shape::Hash(key), capacity);
6862  uint32_t count = 1;
6863  // EnsureCapacity will guarantee the hash table is never full.
6864  while (true) {
6865    Object* element = KeyAt(entry);
6866    if (element->IsUndefined()) break;  // Empty entry.
6867    if (!element->IsNull() && Shape::IsMatch(key, element)) return entry;
6868    entry = NextProbe(entry, count++, capacity);
6869  }
6870  return kNotFound;
6871}
6872
6873
6874template<typename Shape, typename Key>
6875Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
6876  int capacity = Capacity();
6877  int nof = NumberOfElements() + n;
6878  int nod = NumberOfDeletedElements();
6879  // Return if:
6880  //   50% is still free after adding n elements and
6881  //   at most 50% of the free elements are deleted elements.
6882  if ((nof + (nof >> 1) <= capacity) &&
6883      (nod <= (capacity - nof) >> 1)) return this;
6884
6885  Object* obj = Allocate(nof * 2);
6886  if (obj->IsFailure()) return obj;
6887
6888  AssertNoAllocation no_gc;
6889  HashTable* table = HashTable::cast(obj);
6890  WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc);
6891
6892  // Copy prefix to new array.
6893  for (int i = kPrefixStartIndex;
6894       i < kPrefixStartIndex + Shape::kPrefixSize;
6895       i++) {
6896    table->set(i, get(i), mode);
6897  }
6898  // Rehash the elements.
6899  for (int i = 0; i < capacity; i++) {
6900    uint32_t from_index = EntryToIndex(i);
6901    Object* k = get(from_index);
6902    if (IsKey(k)) {
6903      uint32_t hash = Shape::HashForObject(key, k);
6904      uint32_t insertion_index =
6905          EntryToIndex(table->FindInsertionEntry(hash));
6906      for (int j = 0; j < Shape::kEntrySize; j++) {
6907        table->set(insertion_index + j, get(from_index + j), mode);
6908      }
6909    }
6910  }
6911  table->SetNumberOfElements(NumberOfElements());
6912  table->SetNumberOfDeletedElements(0);
6913  return table;
6914}
6915
6916
6917
6918template<typename Shape, typename Key>
6919uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
6920  uint32_t capacity = Capacity();
6921  uint32_t entry = FirstProbe(hash, capacity);
6922  uint32_t count = 1;
6923  // EnsureCapacity will guarantee the hash table is never full.
6924  while (true) {
6925    Object* element = KeyAt(entry);
6926    if (element->IsUndefined() || element->IsNull()) break;
6927    entry = NextProbe(entry, count++, capacity);
6928  }
6929  return entry;
6930}
6931
6932// Force instantiation of template instances class.
6933// Please note this list is compiler dependent.
6934
6935template class HashTable<SymbolTableShape, HashTableKey*>;
6936
6937template class HashTable<CompilationCacheShape, HashTableKey*>;
6938
6939template class HashTable<MapCacheShape, HashTableKey*>;
6940
6941template class Dictionary<StringDictionaryShape, String*>;
6942
6943template class Dictionary<NumberDictionaryShape, uint32_t>;
6944
6945template Object* Dictionary<NumberDictionaryShape, uint32_t>::Allocate(
6946    int);
6947
6948template Object* Dictionary<StringDictionaryShape, String*>::Allocate(
6949    int);
6950
6951template Object* Dictionary<NumberDictionaryShape, uint32_t>::AtPut(
6952    uint32_t, Object*);
6953
6954template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup(
6955    Object*);
6956
6957template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
6958    Object*);
6959
6960template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo(
6961    FixedArray*, PropertyAttributes);
6962
6963template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
6964    int, JSObject::DeleteMode);
6965
6966template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty(
6967    int, JSObject::DeleteMode);
6968
6969template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
6970    FixedArray*);
6971
6972template int
6973Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
6974    PropertyAttributes);
6975
6976template Object* Dictionary<StringDictionaryShape, String*>::Add(
6977    String*, Object*, PropertyDetails);
6978
6979template Object*
6980Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
6981
6982template int
6983Dictionary<NumberDictionaryShape, uint32_t>::NumberOfElementsFilterAttributes(
6984    PropertyAttributes);
6985
6986template Object* Dictionary<NumberDictionaryShape, uint32_t>::Add(
6987    uint32_t, Object*, PropertyDetails);
6988
6989template Object* Dictionary<NumberDictionaryShape, uint32_t>::EnsureCapacity(
6990    int, uint32_t);
6991
6992template Object* Dictionary<StringDictionaryShape, String*>::EnsureCapacity(
6993    int, String*);
6994
6995template Object* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry(
6996    uint32_t, Object*, PropertyDetails, uint32_t);
6997
6998template Object* Dictionary<StringDictionaryShape, String*>::AddEntry(
6999    String*, Object*, PropertyDetails, uint32_t);
7000
7001template
7002int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements();
7003
7004template
7005int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
7006
7007template
7008int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
7009
7010
7011// Collates undefined and unexisting elements below limit from position
7012// zero of the elements. The object stays in Dictionary mode.
7013Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
7014  ASSERT(HasDictionaryElements());
7015  // Must stay in dictionary mode, either because of requires_slow_elements,
7016  // or because we are not going to sort (and therefore compact) all of the
7017  // elements.
7018  NumberDictionary* dict = element_dictionary();
7019  HeapNumber* result_double = NULL;
7020  if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
7021    // Allocate space for result before we start mutating the object.
7022    Object* new_double = Heap::AllocateHeapNumber(0.0);
7023    if (new_double->IsFailure()) return new_double;
7024    result_double = HeapNumber::cast(new_double);
7025  }
7026
7027  int capacity = dict->Capacity();
7028  Object* obj = NumberDictionary::Allocate(dict->Capacity());
7029  if (obj->IsFailure()) return obj;
7030  NumberDictionary* new_dict = NumberDictionary::cast(obj);
7031
7032  AssertNoAllocation no_alloc;
7033
7034  uint32_t pos = 0;
7035  uint32_t undefs = 0;
7036  for (int i = 0; i < capacity; i++) {
7037    Object* k = dict->KeyAt(i);
7038    if (dict->IsKey(k)) {
7039      ASSERT(k->IsNumber());
7040      ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
7041      ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
7042      ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
7043      Object* value = dict->ValueAt(i);
7044      PropertyDetails details = dict->DetailsAt(i);
7045      if (details.type() == CALLBACKS) {
7046        // Bail out and do the sorting of undefineds and array holes in JS.
7047        return Smi::FromInt(-1);
7048      }
7049      uint32_t key = NumberToUint32(k);
7050      if (key < limit) {
7051        if (value->IsUndefined()) {
7052          undefs++;
7053        } else {
7054          new_dict->AddNumberEntry(pos, value, details);
7055          pos++;
7056        }
7057      } else {
7058        new_dict->AddNumberEntry(key, value, details);
7059      }
7060    }
7061  }
7062
7063  uint32_t result = pos;
7064  PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
7065  while (undefs > 0) {
7066    new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details);
7067    pos++;
7068    undefs--;
7069  }
7070
7071  set_elements(new_dict);
7072
7073  if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
7074    return Smi::FromInt(static_cast<int>(result));
7075  }
7076
7077  ASSERT_NE(NULL, result_double);
7078  result_double->set_value(static_cast<double>(result));
7079  return result_double;
7080}
7081
7082
7083// Collects all defined (non-hole) and non-undefined (array) elements at
7084// the start of the elements array.
7085// If the object is in dictionary mode, it is converted to fast elements
7086// mode.
7087Object* JSObject::PrepareElementsForSort(uint32_t limit) {
7088  ASSERT(!HasPixelElements() && !HasExternalArrayElements());
7089
7090  if (HasDictionaryElements()) {
7091    // Convert to fast elements containing only the existing properties.
7092    // Ordering is irrelevant, since we are going to sort anyway.
7093    NumberDictionary* dict = element_dictionary();
7094    if (IsJSArray() || dict->requires_slow_elements() ||
7095        dict->max_number_key() >= limit) {
7096      return PrepareSlowElementsForSort(limit);
7097    }
7098    // Convert to fast elements.
7099
7100    PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED;
7101    Object* new_array =
7102        Heap::AllocateFixedArray(dict->NumberOfElements(), tenure);
7103    if (new_array->IsFailure()) {
7104      return new_array;
7105    }
7106    FixedArray* fast_elements = FixedArray::cast(new_array);
7107    dict->CopyValuesTo(fast_elements);
7108    set_elements(fast_elements);
7109  }
7110  ASSERT(HasFastElements());
7111
7112  // Collect holes at the end, undefined before that and the rest at the
7113  // start, and return the number of non-hole, non-undefined values.
7114
7115  FixedArray* elements = FixedArray::cast(this->elements());
7116  uint32_t elements_length = static_cast<uint32_t>(elements->length());
7117  if (limit > elements_length) {
7118    limit = elements_length ;
7119  }
7120  if (limit == 0) {
7121    return Smi::FromInt(0);
7122  }
7123
7124  HeapNumber* result_double = NULL;
7125  if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
7126    // Pessimistically allocate space for return value before
7127    // we start mutating the array.
7128    Object* new_double = Heap::AllocateHeapNumber(0.0);
7129    if (new_double->IsFailure()) return new_double;
7130    result_double = HeapNumber::cast(new_double);
7131  }
7132
7133  AssertNoAllocation no_alloc;
7134
7135  // Split elements into defined, undefined and the_hole, in that order.
7136  // Only count locations for undefined and the hole, and fill them afterwards.
7137  WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
7138  unsigned int undefs = limit;
7139  unsigned int holes = limit;
7140  // Assume most arrays contain no holes and undefined values, so minimize the
7141  // number of stores of non-undefined, non-the-hole values.
7142  for (unsigned int i = 0; i < undefs; i++) {
7143    Object* current = elements->get(i);
7144    if (current->IsTheHole()) {
7145      holes--;
7146      undefs--;
7147    } else if (current->IsUndefined()) {
7148      undefs--;
7149    } else {
7150      continue;
7151    }
7152    // Position i needs to be filled.
7153    while (undefs > i) {
7154      current = elements->get(undefs);
7155      if (current->IsTheHole()) {
7156        holes--;
7157        undefs--;
7158      } else if (current->IsUndefined()) {
7159        undefs--;
7160      } else {
7161        elements->set(i, current, write_barrier);
7162        break;
7163      }
7164    }
7165  }
7166  uint32_t result = undefs;
7167  while (undefs < holes) {
7168    elements->set_undefined(undefs);
7169    undefs++;
7170  }
7171  while (holes < limit) {
7172    elements->set_the_hole(holes);
7173    holes++;
7174  }
7175
7176  if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
7177    return Smi::FromInt(static_cast<int>(result));
7178  }
7179  ASSERT_NE(NULL, result_double);
7180  result_double->set_value(static_cast<double>(result));
7181  return result_double;
7182}
7183
7184
7185Object* PixelArray::SetValue(uint32_t index, Object* value) {
7186  uint8_t clamped_value = 0;
7187  if (index < static_cast<uint32_t>(length())) {
7188    if (value->IsSmi()) {
7189      int int_value = Smi::cast(value)->value();
7190      if (int_value < 0) {
7191        clamped_value = 0;
7192      } else if (int_value > 255) {
7193        clamped_value = 255;
7194      } else {
7195        clamped_value = static_cast<uint8_t>(int_value);
7196      }
7197    } else if (value->IsHeapNumber()) {
7198      double double_value = HeapNumber::cast(value)->value();
7199      if (!(double_value > 0)) {
7200        // NaN and less than zero clamp to zero.
7201        clamped_value = 0;
7202      } else if (double_value > 255) {
7203        // Greater than 255 clamp to 255.
7204        clamped_value = 255;
7205      } else {
7206        // Other doubles are rounded to the nearest integer.
7207        clamped_value = static_cast<uint8_t>(double_value + 0.5);
7208      }
7209    } else {
7210      // Clamp undefined to zero (default). All other types have been
7211      // converted to a number type further up in the call chain.
7212      ASSERT(value->IsUndefined());
7213    }
7214    set(index, clamped_value);
7215  }
7216  return Smi::FromInt(clamped_value);
7217}
7218
7219
7220template<typename ExternalArrayClass, typename ValueType>
7221static Object* ExternalArrayIntSetter(ExternalArrayClass* receiver,
7222                                      uint32_t index,
7223                                      Object* value) {
7224  ValueType cast_value = 0;
7225  if (index < static_cast<uint32_t>(receiver->length())) {
7226    if (value->IsSmi()) {
7227      int int_value = Smi::cast(value)->value();
7228      cast_value = static_cast<ValueType>(int_value);
7229    } else if (value->IsHeapNumber()) {
7230      double double_value = HeapNumber::cast(value)->value();
7231      cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
7232    } else {
7233      // Clamp undefined to zero (default). All other types have been
7234      // converted to a number type further up in the call chain.
7235      ASSERT(value->IsUndefined());
7236    }
7237    receiver->set(index, cast_value);
7238  }
7239  return Heap::NumberFromInt32(cast_value);
7240}
7241
7242
7243Object* ExternalByteArray::SetValue(uint32_t index, Object* value) {
7244  return ExternalArrayIntSetter<ExternalByteArray, int8_t>
7245      (this, index, value);
7246}
7247
7248
7249Object* ExternalUnsignedByteArray::SetValue(uint32_t index, Object* value) {
7250  return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
7251      (this, index, value);
7252}
7253
7254
7255Object* ExternalShortArray::SetValue(uint32_t index, Object* value) {
7256  return ExternalArrayIntSetter<ExternalShortArray, int16_t>
7257      (this, index, value);
7258}
7259
7260
7261Object* ExternalUnsignedShortArray::SetValue(uint32_t index, Object* value) {
7262  return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
7263      (this, index, value);
7264}
7265
7266
7267Object* ExternalIntArray::SetValue(uint32_t index, Object* value) {
7268  return ExternalArrayIntSetter<ExternalIntArray, int32_t>
7269      (this, index, value);
7270}
7271
7272
7273Object* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
7274  uint32_t cast_value = 0;
7275  if (index < static_cast<uint32_t>(length())) {
7276    if (value->IsSmi()) {
7277      int int_value = Smi::cast(value)->value();
7278      cast_value = static_cast<uint32_t>(int_value);
7279    } else if (value->IsHeapNumber()) {
7280      double double_value = HeapNumber::cast(value)->value();
7281      cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
7282    } else {
7283      // Clamp undefined to zero (default). All other types have been
7284      // converted to a number type further up in the call chain.
7285      ASSERT(value->IsUndefined());
7286    }
7287    set(index, cast_value);
7288  }
7289  return Heap::NumberFromUint32(cast_value);
7290}
7291
7292
7293Object* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
7294  float cast_value = 0;
7295  if (index < static_cast<uint32_t>(length())) {
7296    if (value->IsSmi()) {
7297      int int_value = Smi::cast(value)->value();
7298      cast_value = static_cast<float>(int_value);
7299    } else if (value->IsHeapNumber()) {
7300      double double_value = HeapNumber::cast(value)->value();
7301      cast_value = static_cast<float>(double_value);
7302    } else {
7303      // Clamp undefined to zero (default). All other types have been
7304      // converted to a number type further up in the call chain.
7305      ASSERT(value->IsUndefined());
7306    }
7307    set(index, cast_value);
7308  }
7309  return Heap::AllocateHeapNumber(cast_value);
7310}
7311
7312
7313Object* GlobalObject::GetPropertyCell(LookupResult* result) {
7314  ASSERT(!HasFastProperties());
7315  Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
7316  ASSERT(value->IsJSGlobalPropertyCell());
7317  return value;
7318}
7319
7320
7321Object* GlobalObject::EnsurePropertyCell(String* name) {
7322  ASSERT(!HasFastProperties());
7323  int entry = property_dictionary()->FindEntry(name);
7324  if (entry == StringDictionary::kNotFound) {
7325    Object* cell = Heap::AllocateJSGlobalPropertyCell(Heap::the_hole_value());
7326    if (cell->IsFailure()) return cell;
7327    PropertyDetails details(NONE, NORMAL);
7328    details = details.AsDeleted();
7329    Object* dictionary = property_dictionary()->Add(name, cell, details);
7330    if (dictionary->IsFailure()) return dictionary;
7331    set_properties(StringDictionary::cast(dictionary));
7332    return cell;
7333  } else {
7334    Object* value = property_dictionary()->ValueAt(entry);
7335    ASSERT(value->IsJSGlobalPropertyCell());
7336    return value;
7337  }
7338}
7339
7340
7341Object* SymbolTable::LookupString(String* string, Object** s) {
7342  SymbolKey key(string);
7343  return LookupKey(&key, s);
7344}
7345
7346
7347// This class is used for looking up two character strings in the symbol table.
7348// If we don't have a hit we don't want to waste much time so we unroll the
7349// string hash calculation loop here for speed.  Doesn't work if the two
7350// characters form a decimal integer, since such strings have a different hash
7351// algorithm.
7352class TwoCharHashTableKey : public HashTableKey {
7353 public:
7354  TwoCharHashTableKey(uint32_t c1, uint32_t c2)
7355    : c1_(c1), c2_(c2) {
7356    // Char 1.
7357    uint32_t hash = c1 + (c1 << 10);
7358    hash ^= hash >> 6;
7359    // Char 2.
7360    hash += c2;
7361    hash += hash << 10;
7362    hash ^= hash >> 6;
7363    // GetHash.
7364    hash += hash << 3;
7365    hash ^= hash >> 11;
7366    hash += hash << 15;
7367    if (hash == 0) hash = 27;
7368#ifdef DEBUG
7369    StringHasher hasher(2);
7370    hasher.AddCharacter(c1);
7371    hasher.AddCharacter(c2);
7372    // If this assert fails then we failed to reproduce the two-character
7373    // version of the string hashing algorithm above.  One reason could be
7374    // that we were passed two digits as characters, since the hash
7375    // algorithm is different in that case.
7376    ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
7377#endif
7378    hash_ = hash;
7379  }
7380
7381  bool IsMatch(Object* o) {
7382    if (!o->IsString()) return false;
7383    String* other = String::cast(o);
7384    if (other->length() != 2) return false;
7385    if (other->Get(0) != c1_) return false;
7386    return other->Get(1) == c2_;
7387  }
7388
7389  uint32_t Hash() { return hash_; }
7390  uint32_t HashForObject(Object* key) {
7391    if (!key->IsString()) return 0;
7392    return String::cast(key)->Hash();
7393  }
7394
7395  Object* AsObject() {
7396    // The TwoCharHashTableKey is only used for looking in the symbol
7397    // table, not for adding to it.
7398    UNREACHABLE();
7399    return NULL;
7400  }
7401 private:
7402  uint32_t c1_;
7403  uint32_t c2_;
7404  uint32_t hash_;
7405};
7406
7407
7408bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
7409  SymbolKey key(string);
7410  int entry = FindEntry(&key);
7411  if (entry == kNotFound) {
7412    return false;
7413  } else {
7414    String* result = String::cast(KeyAt(entry));
7415    ASSERT(StringShape(result).IsSymbol());
7416    *symbol = result;
7417    return true;
7418  }
7419}
7420
7421
7422bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
7423                                               uint32_t c2,
7424                                               String** symbol) {
7425  TwoCharHashTableKey key(c1, c2);
7426  int entry = FindEntry(&key);
7427  if (entry == kNotFound) {
7428    return false;
7429  } else {
7430    String* result = String::cast(KeyAt(entry));
7431    ASSERT(StringShape(result).IsSymbol());
7432    *symbol = result;
7433    return true;
7434  }
7435}
7436
7437
7438Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
7439  Utf8SymbolKey key(str);
7440  return LookupKey(&key, s);
7441}
7442
7443
7444Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
7445  int entry = FindEntry(key);
7446
7447  // Symbol already in table.
7448  if (entry != kNotFound) {
7449    *s = KeyAt(entry);
7450    return this;
7451  }
7452
7453  // Adding new symbol. Grow table if needed.
7454  Object* obj = EnsureCapacity(1, key);
7455  if (obj->IsFailure()) return obj;
7456
7457  // Create symbol object.
7458  Object* symbol = key->AsObject();
7459  if (symbol->IsFailure()) return symbol;
7460
7461  // If the symbol table grew as part of EnsureCapacity, obj is not
7462  // the current symbol table and therefore we cannot use
7463  // SymbolTable::cast here.
7464  SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
7465
7466  // Add the new symbol and return it along with the symbol table.
7467  entry = table->FindInsertionEntry(key->Hash());
7468  table->set(EntryToIndex(entry), symbol);
7469  table->ElementAdded();
7470  *s = symbol;
7471  return table;
7472}
7473
7474
7475Object* CompilationCacheTable::Lookup(String* src) {
7476  StringKey key(src);
7477  int entry = FindEntry(&key);
7478  if (entry == kNotFound) return Heap::undefined_value();
7479  return get(EntryToIndex(entry) + 1);
7480}
7481
7482
7483Object* CompilationCacheTable::LookupEval(String* src, Context* context) {
7484  StringSharedKey key(src, context->closure()->shared());
7485  int entry = FindEntry(&key);
7486  if (entry == kNotFound) return Heap::undefined_value();
7487  return get(EntryToIndex(entry) + 1);
7488}
7489
7490
7491Object* CompilationCacheTable::LookupRegExp(String* src,
7492                                            JSRegExp::Flags flags) {
7493  RegExpKey key(src, flags);
7494  int entry = FindEntry(&key);
7495  if (entry == kNotFound) return Heap::undefined_value();
7496  return get(EntryToIndex(entry) + 1);
7497}
7498
7499
7500Object* CompilationCacheTable::Put(String* src, Object* value) {
7501  StringKey key(src);
7502  Object* obj = EnsureCapacity(1, &key);
7503  if (obj->IsFailure()) return obj;
7504
7505  CompilationCacheTable* cache =
7506      reinterpret_cast<CompilationCacheTable*>(obj);
7507  int entry = cache->FindInsertionEntry(key.Hash());
7508  cache->set(EntryToIndex(entry), src);
7509  cache->set(EntryToIndex(entry) + 1, value);
7510  cache->ElementAdded();
7511  return cache;
7512}
7513
7514
7515Object* CompilationCacheTable::PutEval(String* src,
7516                                       Context* context,
7517                                       Object* value) {
7518  StringSharedKey key(src, context->closure()->shared());
7519  Object* obj = EnsureCapacity(1, &key);
7520  if (obj->IsFailure()) return obj;
7521
7522  CompilationCacheTable* cache =
7523      reinterpret_cast<CompilationCacheTable*>(obj);
7524  int entry = cache->FindInsertionEntry(key.Hash());
7525
7526  Object* k = key.AsObject();
7527  if (k->IsFailure()) return k;
7528
7529  cache->set(EntryToIndex(entry), k);
7530  cache->set(EntryToIndex(entry) + 1, value);
7531  cache->ElementAdded();
7532  return cache;
7533}
7534
7535
7536Object* CompilationCacheTable::PutRegExp(String* src,
7537                                         JSRegExp::Flags flags,
7538                                         FixedArray* value) {
7539  RegExpKey key(src, flags);
7540  Object* obj = EnsureCapacity(1, &key);
7541  if (obj->IsFailure()) return obj;
7542
7543  CompilationCacheTable* cache =
7544      reinterpret_cast<CompilationCacheTable*>(obj);
7545  int entry = cache->FindInsertionEntry(key.Hash());
7546  // We store the value in the key slot, and compare the search key
7547  // to the stored value with a custon IsMatch function during lookups.
7548  cache->set(EntryToIndex(entry), value);
7549  cache->set(EntryToIndex(entry) + 1, value);
7550  cache->ElementAdded();
7551  return cache;
7552}
7553
7554
7555// SymbolsKey used for HashTable where key is array of symbols.
7556class SymbolsKey : public HashTableKey {
7557 public:
7558  explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
7559
7560  bool IsMatch(Object* symbols) {
7561    FixedArray* o = FixedArray::cast(symbols);
7562    int len = symbols_->length();
7563    if (o->length() != len) return false;
7564    for (int i = 0; i < len; i++) {
7565      if (o->get(i) != symbols_->get(i)) return false;
7566    }
7567    return true;
7568  }
7569
7570  uint32_t Hash() { return HashForObject(symbols_); }
7571
7572  uint32_t HashForObject(Object* obj) {
7573    FixedArray* symbols = FixedArray::cast(obj);
7574    int len = symbols->length();
7575    uint32_t hash = 0;
7576    for (int i = 0; i < len; i++) {
7577      hash ^= String::cast(symbols->get(i))->Hash();
7578    }
7579    return hash;
7580  }
7581
7582  Object* AsObject() { return symbols_; }
7583
7584 private:
7585  FixedArray* symbols_;
7586};
7587
7588
7589Object* MapCache::Lookup(FixedArray* array) {
7590  SymbolsKey key(array);
7591  int entry = FindEntry(&key);
7592  if (entry == kNotFound) return Heap::undefined_value();
7593  return get(EntryToIndex(entry) + 1);
7594}
7595
7596
7597Object* MapCache::Put(FixedArray* array, Map* value) {
7598  SymbolsKey key(array);
7599  Object* obj = EnsureCapacity(1, &key);
7600  if (obj->IsFailure()) return obj;
7601
7602  MapCache* cache = reinterpret_cast<MapCache*>(obj);
7603  int entry = cache->FindInsertionEntry(key.Hash());
7604  cache->set(EntryToIndex(entry), array);
7605  cache->set(EntryToIndex(entry) + 1, value);
7606  cache->ElementAdded();
7607  return cache;
7608}
7609
7610
7611template<typename Shape, typename Key>
7612Object* Dictionary<Shape, Key>::Allocate(int at_least_space_for) {
7613  Object* obj = HashTable<Shape, Key>::Allocate(at_least_space_for);
7614  // Initialize the next enumeration index.
7615  if (!obj->IsFailure()) {
7616    Dictionary<Shape, Key>::cast(obj)->
7617        SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
7618  }
7619  return obj;
7620}
7621
7622
7623template<typename Shape, typename Key>
7624Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
7625  int length = HashTable<Shape, Key>::NumberOfElements();
7626
7627  // Allocate and initialize iteration order array.
7628  Object* obj = Heap::AllocateFixedArray(length);
7629  if (obj->IsFailure()) return obj;
7630  FixedArray* iteration_order = FixedArray::cast(obj);
7631  for (int i = 0; i < length; i++) {
7632    iteration_order->set(i, Smi::FromInt(i));
7633  }
7634
7635  // Allocate array with enumeration order.
7636  obj = Heap::AllocateFixedArray(length);
7637  if (obj->IsFailure()) return obj;
7638  FixedArray* enumeration_order = FixedArray::cast(obj);
7639
7640  // Fill the enumeration order array with property details.
7641  int capacity = HashTable<Shape, Key>::Capacity();
7642  int pos = 0;
7643  for (int i = 0; i < capacity; i++) {
7644    if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
7645      enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
7646    }
7647  }
7648
7649  // Sort the arrays wrt. enumeration order.
7650  iteration_order->SortPairs(enumeration_order, enumeration_order->length());
7651
7652  // Overwrite the enumeration_order with the enumeration indices.
7653  for (int i = 0; i < length; i++) {
7654    int index = Smi::cast(iteration_order->get(i))->value();
7655    int enum_index = PropertyDetails::kInitialIndex + i;
7656    enumeration_order->set(index, Smi::FromInt(enum_index));
7657  }
7658
7659  // Update the dictionary with new indices.
7660  capacity = HashTable<Shape, Key>::Capacity();
7661  pos = 0;
7662  for (int i = 0; i < capacity; i++) {
7663    if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
7664      int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
7665      PropertyDetails details = DetailsAt(i);
7666      PropertyDetails new_details =
7667          PropertyDetails(details.attributes(), details.type(), enum_index);
7668      DetailsAtPut(i, new_details);
7669    }
7670  }
7671
7672  // Set the next enumeration index.
7673  SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
7674  return this;
7675}
7676
7677template<typename Shape, typename Key>
7678Object* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
7679  // Check whether there are enough enumeration indices to add n elements.
7680  if (Shape::kIsEnumerable &&
7681      !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
7682    // If not, we generate new indices for the properties.
7683    Object* result = GenerateNewEnumerationIndices();
7684    if (result->IsFailure()) return result;
7685  }
7686  return HashTable<Shape, Key>::EnsureCapacity(n, key);
7687}
7688
7689
7690void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
7691  // Do nothing if the interval [from, to) is empty.
7692  if (from >= to) return;
7693
7694  int removed_entries = 0;
7695  Object* sentinel = Heap::null_value();
7696  int capacity = Capacity();
7697  for (int i = 0; i < capacity; i++) {
7698    Object* key = KeyAt(i);
7699    if (key->IsNumber()) {
7700      uint32_t number = static_cast<uint32_t>(key->Number());
7701      if (from <= number && number < to) {
7702        SetEntry(i, sentinel, sentinel, Smi::FromInt(0));
7703        removed_entries++;
7704      }
7705    }
7706  }
7707
7708  // Update the number of elements.
7709  ElementsRemoved(removed_entries);
7710}
7711
7712
7713template<typename Shape, typename Key>
7714Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
7715                                               JSObject::DeleteMode mode) {
7716  PropertyDetails details = DetailsAt(entry);
7717  // Ignore attributes if forcing a deletion.
7718  if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) {
7719    return Heap::false_value();
7720  }
7721  SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0));
7722  HashTable<Shape, Key>::ElementRemoved();
7723  return Heap::true_value();
7724}
7725
7726
7727template<typename Shape, typename Key>
7728Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
7729  int entry = FindEntry(key);
7730
7731  // If the entry is present set the value;
7732  if (entry != Dictionary<Shape, Key>::kNotFound) {
7733    ValueAtPut(entry, value);
7734    return this;
7735  }
7736
7737  // Check whether the dictionary should be extended.
7738  Object* obj = EnsureCapacity(1, key);
7739  if (obj->IsFailure()) return obj;
7740
7741  Object* k = Shape::AsObject(key);
7742  if (k->IsFailure()) return k;
7743  PropertyDetails details = PropertyDetails(NONE, NORMAL);
7744  return Dictionary<Shape, Key>::cast(obj)->
7745      AddEntry(key, value, details, Shape::Hash(key));
7746}
7747
7748
7749template<typename Shape, typename Key>
7750Object* Dictionary<Shape, Key>::Add(Key key,
7751                                    Object* value,
7752                                    PropertyDetails details) {
7753  // Valdate key is absent.
7754  SLOW_ASSERT((FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
7755  // Check whether the dictionary should be extended.
7756  Object* obj = EnsureCapacity(1, key);
7757  if (obj->IsFailure()) return obj;
7758  return Dictionary<Shape, Key>::cast(obj)->
7759      AddEntry(key, value, details, Shape::Hash(key));
7760}
7761
7762
7763// Add a key, value pair to the dictionary.
7764template<typename Shape, typename Key>
7765Object* Dictionary<Shape, Key>::AddEntry(Key key,
7766                                         Object* value,
7767                                         PropertyDetails details,
7768                                         uint32_t hash) {
7769  // Compute the key object.
7770  Object* k = Shape::AsObject(key);
7771  if (k->IsFailure()) return k;
7772
7773  uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
7774  // Insert element at empty or deleted entry
7775  if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
7776    // Assign an enumeration index to the property and update
7777    // SetNextEnumerationIndex.
7778    int index = NextEnumerationIndex();
7779    details = PropertyDetails(details.attributes(), details.type(), index);
7780    SetNextEnumerationIndex(index + 1);
7781  }
7782  SetEntry(entry, k, value, details);
7783  ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
7784          || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
7785  HashTable<Shape, Key>::ElementAdded();
7786  return this;
7787}
7788
7789
7790void NumberDictionary::UpdateMaxNumberKey(uint32_t key) {
7791  // If the dictionary requires slow elements an element has already
7792  // been added at a high index.
7793  if (requires_slow_elements()) return;
7794  // Check if this index is high enough that we should require slow
7795  // elements.
7796  if (key > kRequiresSlowElementsLimit) {
7797    set_requires_slow_elements();
7798    return;
7799  }
7800  // Update max key value.
7801  Object* max_index_object = get(kMaxNumberKeyIndex);
7802  if (!max_index_object->IsSmi() || max_number_key() < key) {
7803    FixedArray::set(kMaxNumberKeyIndex,
7804                    Smi::FromInt(key << kRequiresSlowElementsTagSize));
7805  }
7806}
7807
7808
7809Object* NumberDictionary::AddNumberEntry(uint32_t key,
7810                                         Object* value,
7811                                         PropertyDetails details) {
7812  UpdateMaxNumberKey(key);
7813  SLOW_ASSERT(FindEntry(key) == kNotFound);
7814  return Add(key, value, details);
7815}
7816
7817
7818Object* NumberDictionary::AtNumberPut(uint32_t key, Object* value) {
7819  UpdateMaxNumberKey(key);
7820  return AtPut(key, value);
7821}
7822
7823
7824Object* NumberDictionary::Set(uint32_t key,
7825                              Object* value,
7826                              PropertyDetails details) {
7827  int entry = FindEntry(key);
7828  if (entry == kNotFound) return AddNumberEntry(key, value, details);
7829  // Preserve enumeration index.
7830  details = PropertyDetails(details.attributes(),
7831                            details.type(),
7832                            DetailsAt(entry).index());
7833  SetEntry(entry, NumberDictionaryShape::AsObject(key), value, details);
7834  return this;
7835}
7836
7837
7838
7839template<typename Shape, typename Key>
7840int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
7841    PropertyAttributes filter) {
7842  int capacity = HashTable<Shape, Key>::Capacity();
7843  int result = 0;
7844  for (int i = 0; i < capacity; i++) {
7845    Object* k = HashTable<Shape, Key>::KeyAt(i);
7846    if (HashTable<Shape, Key>::IsKey(k)) {
7847      PropertyDetails details = DetailsAt(i);
7848      if (details.IsDeleted()) continue;
7849      PropertyAttributes attr = details.attributes();
7850      if ((attr & filter) == 0) result++;
7851    }
7852  }
7853  return result;
7854}
7855
7856
7857template<typename Shape, typename Key>
7858int Dictionary<Shape, Key>::NumberOfEnumElements() {
7859  return NumberOfElementsFilterAttributes(
7860      static_cast<PropertyAttributes>(DONT_ENUM));
7861}
7862
7863
7864template<typename Shape, typename Key>
7865void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage,
7866                                        PropertyAttributes filter) {
7867  ASSERT(storage->length() >= NumberOfEnumElements());
7868  int capacity = HashTable<Shape, Key>::Capacity();
7869  int index = 0;
7870  for (int i = 0; i < capacity; i++) {
7871     Object* k = HashTable<Shape, Key>::KeyAt(i);
7872     if (HashTable<Shape, Key>::IsKey(k)) {
7873       PropertyDetails details = DetailsAt(i);
7874       if (details.IsDeleted()) continue;
7875       PropertyAttributes attr = details.attributes();
7876       if ((attr & filter) == 0) storage->set(index++, k);
7877     }
7878  }
7879  storage->SortPairs(storage, index);
7880  ASSERT(storage->length() >= index);
7881}
7882
7883
7884void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
7885                                      FixedArray* sort_array) {
7886  ASSERT(storage->length() >= NumberOfEnumElements());
7887  int capacity = Capacity();
7888  int index = 0;
7889  for (int i = 0; i < capacity; i++) {
7890     Object* k = KeyAt(i);
7891     if (IsKey(k)) {
7892       PropertyDetails details = DetailsAt(i);
7893       if (details.IsDeleted() || details.IsDontEnum()) continue;
7894       storage->set(index, k);
7895       sort_array->set(index, Smi::FromInt(details.index()));
7896       index++;
7897     }
7898  }
7899  storage->SortPairs(sort_array, sort_array->length());
7900  ASSERT(storage->length() >= index);
7901}
7902
7903
7904template<typename Shape, typename Key>
7905void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) {
7906  ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
7907      static_cast<PropertyAttributes>(NONE)));
7908  int capacity = HashTable<Shape, Key>::Capacity();
7909  int index = 0;
7910  for (int i = 0; i < capacity; i++) {
7911    Object* k = HashTable<Shape, Key>::KeyAt(i);
7912    if (HashTable<Shape, Key>::IsKey(k)) {
7913      PropertyDetails details = DetailsAt(i);
7914      if (details.IsDeleted()) continue;
7915      storage->set(index++, k);
7916    }
7917  }
7918  ASSERT(storage->length() >= index);
7919}
7920
7921
7922// Backwards lookup (slow).
7923template<typename Shape, typename Key>
7924Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
7925  int capacity = HashTable<Shape, Key>::Capacity();
7926  for (int i = 0; i < capacity; i++) {
7927    Object* k =  HashTable<Shape, Key>::KeyAt(i);
7928    if (Dictionary<Shape, Key>::IsKey(k)) {
7929      Object* e = ValueAt(i);
7930      if (e->IsJSGlobalPropertyCell()) {
7931        e = JSGlobalPropertyCell::cast(e)->value();
7932      }
7933      if (e == value) return k;
7934    }
7935  }
7936  return Heap::undefined_value();
7937}
7938
7939
7940Object* StringDictionary::TransformPropertiesToFastFor(
7941    JSObject* obj, int unused_property_fields) {
7942  // Make sure we preserve dictionary representation if there are too many
7943  // descriptors.
7944  if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
7945
7946  // Figure out if it is necessary to generate new enumeration indices.
7947  int max_enumeration_index =
7948      NextEnumerationIndex() +
7949          (DescriptorArray::kMaxNumberOfDescriptors -
7950           NumberOfElements());
7951  if (!PropertyDetails::IsValidIndex(max_enumeration_index)) {
7952    Object* result = GenerateNewEnumerationIndices();
7953    if (result->IsFailure()) return result;
7954  }
7955
7956  int instance_descriptor_length = 0;
7957  int number_of_fields = 0;
7958
7959  // Compute the length of the instance descriptor.
7960  int capacity = Capacity();
7961  for (int i = 0; i < capacity; i++) {
7962    Object* k = KeyAt(i);
7963    if (IsKey(k)) {
7964      Object* value = ValueAt(i);
7965      PropertyType type = DetailsAt(i).type();
7966      ASSERT(type != FIELD);
7967      instance_descriptor_length++;
7968      if (type == NORMAL &&
7969          (!value->IsJSFunction() || Heap::InNewSpace(value))) {
7970        number_of_fields += 1;
7971      }
7972    }
7973  }
7974
7975  // Allocate the instance descriptor.
7976  Object* descriptors_unchecked =
7977      DescriptorArray::Allocate(instance_descriptor_length);
7978  if (descriptors_unchecked->IsFailure()) return descriptors_unchecked;
7979  DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked);
7980
7981  int inobject_props = obj->map()->inobject_properties();
7982  int number_of_allocated_fields =
7983      number_of_fields + unused_property_fields - inobject_props;
7984
7985  // Allocate the fixed array for the fields.
7986  Object* fields = Heap::AllocateFixedArray(number_of_allocated_fields);
7987  if (fields->IsFailure()) return fields;
7988
7989  // Fill in the instance descriptor and the fields.
7990  int next_descriptor = 0;
7991  int current_offset = 0;
7992  for (int i = 0; i < capacity; i++) {
7993    Object* k = KeyAt(i);
7994    if (IsKey(k)) {
7995      Object* value = ValueAt(i);
7996      // Ensure the key is a symbol before writing into the instance descriptor.
7997      Object* key = Heap::LookupSymbol(String::cast(k));
7998      if (key->IsFailure()) return key;
7999      PropertyDetails details = DetailsAt(i);
8000      PropertyType type = details.type();
8001
8002      if (value->IsJSFunction() && !Heap::InNewSpace(value)) {
8003        ConstantFunctionDescriptor d(String::cast(key),
8004                                     JSFunction::cast(value),
8005                                     details.attributes(),
8006                                     details.index());
8007        descriptors->Set(next_descriptor++, &d);
8008      } else if (type == NORMAL) {
8009        if (current_offset < inobject_props) {
8010          obj->InObjectPropertyAtPut(current_offset,
8011                                     value,
8012                                     UPDATE_WRITE_BARRIER);
8013        } else {
8014          int offset = current_offset - inobject_props;
8015          FixedArray::cast(fields)->set(offset, value);
8016        }
8017        FieldDescriptor d(String::cast(key),
8018                          current_offset++,
8019                          details.attributes(),
8020                          details.index());
8021        descriptors->Set(next_descriptor++, &d);
8022      } else if (type == CALLBACKS) {
8023        CallbacksDescriptor d(String::cast(key),
8024                              value,
8025                              details.attributes(),
8026                              details.index());
8027        descriptors->Set(next_descriptor++, &d);
8028      } else {
8029        UNREACHABLE();
8030      }
8031    }
8032  }
8033  ASSERT(current_offset == number_of_fields);
8034
8035  descriptors->Sort();
8036  // Allocate new map.
8037  Object* new_map = obj->map()->CopyDropDescriptors();
8038  if (new_map->IsFailure()) return new_map;
8039
8040  // Transform the object.
8041  obj->set_map(Map::cast(new_map));
8042  obj->map()->set_instance_descriptors(descriptors);
8043  obj->map()->set_unused_property_fields(unused_property_fields);
8044
8045  obj->set_properties(FixedArray::cast(fields));
8046  ASSERT(obj->IsJSObject());
8047
8048  descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
8049  // Check that it really works.
8050  ASSERT(obj->HasFastProperties());
8051
8052  return obj;
8053}
8054
8055
8056#ifdef ENABLE_DEBUGGER_SUPPORT
8057// Check if there is a break point at this code position.
8058bool DebugInfo::HasBreakPoint(int code_position) {
8059  // Get the break point info object for this code position.
8060  Object* break_point_info = GetBreakPointInfo(code_position);
8061
8062  // If there is no break point info object or no break points in the break
8063  // point info object there is no break point at this code position.
8064  if (break_point_info->IsUndefined()) return false;
8065  return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
8066}
8067
8068
8069// Get the break point info object for this code position.
8070Object* DebugInfo::GetBreakPointInfo(int code_position) {
8071  // Find the index of the break point info object for this code position.
8072  int index = GetBreakPointInfoIndex(code_position);
8073
8074  // Return the break point info object if any.
8075  if (index == kNoBreakPointInfo) return Heap::undefined_value();
8076  return BreakPointInfo::cast(break_points()->get(index));
8077}
8078
8079
8080// Clear a break point at the specified code position.
8081void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
8082                                int code_position,
8083                                Handle<Object> break_point_object) {
8084  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
8085  if (break_point_info->IsUndefined()) return;
8086  BreakPointInfo::ClearBreakPoint(
8087      Handle<BreakPointInfo>::cast(break_point_info),
8088      break_point_object);
8089}
8090
8091
8092void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
8093                              int code_position,
8094                              int source_position,
8095                              int statement_position,
8096                              Handle<Object> break_point_object) {
8097  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
8098  if (!break_point_info->IsUndefined()) {
8099    BreakPointInfo::SetBreakPoint(
8100        Handle<BreakPointInfo>::cast(break_point_info),
8101        break_point_object);
8102    return;
8103  }
8104
8105  // Adding a new break point for a code position which did not have any
8106  // break points before. Try to find a free slot.
8107  int index = kNoBreakPointInfo;
8108  for (int i = 0; i < debug_info->break_points()->length(); i++) {
8109    if (debug_info->break_points()->get(i)->IsUndefined()) {
8110      index = i;
8111      break;
8112    }
8113  }
8114  if (index == kNoBreakPointInfo) {
8115    // No free slot - extend break point info array.
8116    Handle<FixedArray> old_break_points =
8117        Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
8118    debug_info->set_break_points(*Factory::NewFixedArray(
8119        old_break_points->length() +
8120            Debug::kEstimatedNofBreakPointsInFunction));
8121    Handle<FixedArray> new_break_points =
8122        Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
8123    for (int i = 0; i < old_break_points->length(); i++) {
8124      new_break_points->set(i, old_break_points->get(i));
8125    }
8126    index = old_break_points->length();
8127  }
8128  ASSERT(index != kNoBreakPointInfo);
8129
8130  // Allocate new BreakPointInfo object and set the break point.
8131  Handle<BreakPointInfo> new_break_point_info =
8132      Handle<BreakPointInfo>::cast(Factory::NewStruct(BREAK_POINT_INFO_TYPE));
8133  new_break_point_info->set_code_position(Smi::FromInt(code_position));
8134  new_break_point_info->set_source_position(Smi::FromInt(source_position));
8135  new_break_point_info->
8136      set_statement_position(Smi::FromInt(statement_position));
8137  new_break_point_info->set_break_point_objects(Heap::undefined_value());
8138  BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
8139  debug_info->break_points()->set(index, *new_break_point_info);
8140}
8141
8142
8143// Get the break point objects for a code position.
8144Object* DebugInfo::GetBreakPointObjects(int code_position) {
8145  Object* break_point_info = GetBreakPointInfo(code_position);
8146  if (break_point_info->IsUndefined()) {
8147    return Heap::undefined_value();
8148  }
8149  return BreakPointInfo::cast(break_point_info)->break_point_objects();
8150}
8151
8152
8153// Get the total number of break points.
8154int DebugInfo::GetBreakPointCount() {
8155  if (break_points()->IsUndefined()) return 0;
8156  int count = 0;
8157  for (int i = 0; i < break_points()->length(); i++) {
8158    if (!break_points()->get(i)->IsUndefined()) {
8159      BreakPointInfo* break_point_info =
8160          BreakPointInfo::cast(break_points()->get(i));
8161      count += break_point_info->GetBreakPointCount();
8162    }
8163  }
8164  return count;
8165}
8166
8167
8168Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
8169                                      Handle<Object> break_point_object) {
8170  if (debug_info->break_points()->IsUndefined()) return Heap::undefined_value();
8171  for (int i = 0; i < debug_info->break_points()->length(); i++) {
8172    if (!debug_info->break_points()->get(i)->IsUndefined()) {
8173      Handle<BreakPointInfo> break_point_info =
8174          Handle<BreakPointInfo>(BreakPointInfo::cast(
8175              debug_info->break_points()->get(i)));
8176      if (BreakPointInfo::HasBreakPointObject(break_point_info,
8177                                              break_point_object)) {
8178        return *break_point_info;
8179      }
8180    }
8181  }
8182  return Heap::undefined_value();
8183}
8184
8185
8186// Find the index of the break point info object for the specified code
8187// position.
8188int DebugInfo::GetBreakPointInfoIndex(int code_position) {
8189  if (break_points()->IsUndefined()) return kNoBreakPointInfo;
8190  for (int i = 0; i < break_points()->length(); i++) {
8191    if (!break_points()->get(i)->IsUndefined()) {
8192      BreakPointInfo* break_point_info =
8193          BreakPointInfo::cast(break_points()->get(i));
8194      if (break_point_info->code_position()->value() == code_position) {
8195        return i;
8196      }
8197    }
8198  }
8199  return kNoBreakPointInfo;
8200}
8201
8202
8203// Remove the specified break point object.
8204void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
8205                                     Handle<Object> break_point_object) {
8206  // If there are no break points just ignore.
8207  if (break_point_info->break_point_objects()->IsUndefined()) return;
8208  // If there is a single break point clear it if it is the same.
8209  if (!break_point_info->break_point_objects()->IsFixedArray()) {
8210    if (break_point_info->break_point_objects() == *break_point_object) {
8211      break_point_info->set_break_point_objects(Heap::undefined_value());
8212    }
8213    return;
8214  }
8215  // If there are multiple break points shrink the array
8216  ASSERT(break_point_info->break_point_objects()->IsFixedArray());
8217  Handle<FixedArray> old_array =
8218      Handle<FixedArray>(
8219          FixedArray::cast(break_point_info->break_point_objects()));
8220  Handle<FixedArray> new_array =
8221      Factory::NewFixedArray(old_array->length() - 1);
8222  int found_count = 0;
8223  for (int i = 0; i < old_array->length(); i++) {
8224    if (old_array->get(i) == *break_point_object) {
8225      ASSERT(found_count == 0);
8226      found_count++;
8227    } else {
8228      new_array->set(i - found_count, old_array->get(i));
8229    }
8230  }
8231  // If the break point was found in the list change it.
8232  if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
8233}
8234
8235
8236// Add the specified break point object.
8237void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
8238                                   Handle<Object> break_point_object) {
8239  // If there was no break point objects before just set it.
8240  if (break_point_info->break_point_objects()->IsUndefined()) {
8241    break_point_info->set_break_point_objects(*break_point_object);
8242    return;
8243  }
8244  // If the break point object is the same as before just ignore.
8245  if (break_point_info->break_point_objects() == *break_point_object) return;
8246  // If there was one break point object before replace with array.
8247  if (!break_point_info->break_point_objects()->IsFixedArray()) {
8248    Handle<FixedArray> array = Factory::NewFixedArray(2);
8249    array->set(0, break_point_info->break_point_objects());
8250    array->set(1, *break_point_object);
8251    break_point_info->set_break_point_objects(*array);
8252    return;
8253  }
8254  // If there was more than one break point before extend array.
8255  Handle<FixedArray> old_array =
8256      Handle<FixedArray>(
8257          FixedArray::cast(break_point_info->break_point_objects()));
8258  Handle<FixedArray> new_array =
8259      Factory::NewFixedArray(old_array->length() + 1);
8260  for (int i = 0; i < old_array->length(); i++) {
8261    // If the break point was there before just ignore.
8262    if (old_array->get(i) == *break_point_object) return;
8263    new_array->set(i, old_array->get(i));
8264  }
8265  // Add the new break point.
8266  new_array->set(old_array->length(), *break_point_object);
8267  break_point_info->set_break_point_objects(*new_array);
8268}
8269
8270
8271bool BreakPointInfo::HasBreakPointObject(
8272    Handle<BreakPointInfo> break_point_info,
8273    Handle<Object> break_point_object) {
8274  // No break point.
8275  if (break_point_info->break_point_objects()->IsUndefined()) return false;
8276  // Single beak point.
8277  if (!break_point_info->break_point_objects()->IsFixedArray()) {
8278    return break_point_info->break_point_objects() == *break_point_object;
8279  }
8280  // Multiple break points.
8281  FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
8282  for (int i = 0; i < array->length(); i++) {
8283    if (array->get(i) == *break_point_object) {
8284      return true;
8285    }
8286  }
8287  return false;
8288}
8289
8290
8291// Get the number of break points.
8292int BreakPointInfo::GetBreakPointCount() {
8293  // No break point.
8294  if (break_point_objects()->IsUndefined()) return 0;
8295  // Single beak point.
8296  if (!break_point_objects()->IsFixedArray()) return 1;
8297  // Multiple break points.
8298  return FixedArray::cast(break_point_objects())->length();
8299}
8300#endif
8301
8302
8303} }  // namespace v8::internal
8304