Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / v8 / src / objects.cc
1 // Copyright 2013 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 "accessors.h"
31 #include "allocation-site-scopes.h"
32 #include "api.h"
33 #include "arguments.h"
34 #include "bootstrapper.h"
35 #include "codegen.h"
36 #include "code-stubs.h"
37 #include "cpu-profiler.h"
38 #include "debug.h"
39 #include "deoptimizer.h"
40 #include "date.h"
41 #include "elements.h"
42 #include "execution.h"
43 #include "full-codegen.h"
44 #include "hydrogen.h"
45 #include "isolate-inl.h"
46 #include "log.h"
47 #include "objects-inl.h"
48 #include "objects-visiting-inl.h"
49 #include "macro-assembler.h"
50 #include "mark-compact.h"
51 #include "safepoint-table.h"
52 #include "string-stream.h"
53 #include "utils.h"
54
55 #ifdef ENABLE_DISASSEMBLER
56 #include "disasm.h"
57 #include "disassembler.h"
58 #endif
59
60 namespace v8 {
61 namespace internal {
62
63
64 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
65                                                   Object* value) {
66   Object* result;
67   { MaybeObject* maybe_result =
68         constructor->GetHeap()->AllocateJSObject(constructor);
69     if (!maybe_result->ToObject(&result)) return maybe_result;
70   }
71   JSValue::cast(result)->set_value(value);
72   return result;
73 }
74
75
76 MaybeObject* Object::ToObject(Context* native_context) {
77   if (IsNumber()) {
78     return CreateJSValue(native_context->number_function(), this);
79   } else if (IsFloat32x4()) {
80     return CreateJSValue(native_context->float32x4_function(), this);
81   } else if (IsInt32x4()) {
82     return CreateJSValue(native_context->int32x4_function(), this);
83   } else if (IsBoolean()) {
84     return CreateJSValue(native_context->boolean_function(), this);
85   } else if (IsString()) {
86     return CreateJSValue(native_context->string_function(), this);
87   } else if (IsSymbol()) {
88     return CreateJSValue(native_context->symbol_function(), this);
89   }
90   ASSERT(IsJSObject());
91   return this;
92 }
93
94
95 MaybeObject* Object::ToObject(Isolate* isolate) {
96   if (IsJSReceiver()) {
97     return this;
98   } else if (IsNumber()) {
99     Context* native_context = isolate->context()->native_context();
100     return CreateJSValue(native_context->number_function(), this);
101   } else if (IsFloat32x4()) {
102     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
103     Context* native_context = isolate->context()->native_context();
104     return CreateJSValue(native_context->float32x4_function(), this);
105   } else if (IsInt32x4()) {
106     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
107     Context* native_context = isolate->context()->native_context();
108     return CreateJSValue(native_context->int32x4_function(), this);
109   } else if (IsBoolean()) {
110     Context* native_context = isolate->context()->native_context();
111     return CreateJSValue(native_context->boolean_function(), this);
112   } else if (IsString()) {
113     Context* native_context = isolate->context()->native_context();
114     return CreateJSValue(native_context->string_function(), this);
115   } else if (IsSymbol()) {
116     Context* native_context = isolate->context()->native_context();
117     return CreateJSValue(native_context->symbol_function(), this);
118   }
119
120   // Throw a type error.
121   return Failure::InternalError();
122 }
123
124
125 bool Object::BooleanValue() {
126   if (IsBoolean()) return IsTrue();
127   if (IsSmi()) return Smi::cast(this)->value() != 0;
128   if (IsUndefined() || IsNull()) return false;
129   if (IsUndetectableObject()) return false;   // Undetectable object is false.
130   if (IsString()) return String::cast(this)->length() != 0;
131   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
132   return true;
133 }
134
135
136 bool Object::IsCallable() {
137   Object* fun = this;
138   while (fun->IsJSFunctionProxy()) {
139     fun = JSFunctionProxy::cast(fun)->call_trap();
140   }
141   return fun->IsJSFunction() ||
142          (fun->IsHeapObject() &&
143           HeapObject::cast(fun)->map()->has_instance_call_handler());
144 }
145
146
147 void Object::Lookup(Name* name, LookupResult* result) {
148   Object* holder = NULL;
149   if (IsJSReceiver()) {
150     holder = this;
151   } else {
152     Context* native_context = result->isolate()->context()->native_context();
153     if (IsNumber()) {
154       holder = native_context->number_function()->instance_prototype();
155     } else if (IsFloat32x4()) {
156       holder = native_context->float32x4_function()->instance_prototype();
157     } else if (IsInt32x4()) {
158       holder = native_context->int32x4_function()->instance_prototype();
159     } else if (IsString()) {
160       holder = native_context->string_function()->instance_prototype();
161     } else if (IsSymbol()) {
162       holder = native_context->symbol_function()->instance_prototype();
163     } else if (IsBoolean()) {
164       holder = native_context->boolean_function()->instance_prototype();
165     } else {
166       result->isolate()->PushStackTraceAndDie(
167           0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001);
168     }
169   }
170   ASSERT(holder != NULL);  // Cannot handle null or undefined.
171   JSReceiver::cast(holder)->Lookup(name, result);
172 }
173
174
175 Handle<Object> Object::GetPropertyWithReceiver(
176     Handle<Object> object,
177     Handle<Object> receiver,
178     Handle<Name> name,
179     PropertyAttributes* attributes) {
180   LookupResult lookup(name->GetIsolate());
181   object->Lookup(*name, &lookup);
182   Handle<Object> result =
183       GetProperty(object, receiver, &lookup, name, attributes);
184   ASSERT(*attributes <= ABSENT);
185   return result;
186 }
187
188
189 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
190                                              Name* name,
191                                              PropertyAttributes* attributes) {
192   LookupResult result(name->GetIsolate());
193   Lookup(name, &result);
194   MaybeObject* value = GetProperty(receiver, &result, name, attributes);
195   ASSERT(*attributes <= ABSENT);
196   return value;
197 }
198
199
200 bool Object::ToInt32(int32_t* value) {
201   if (IsSmi()) {
202     *value = Smi::cast(this)->value();
203     return true;
204   }
205   if (IsHeapNumber()) {
206     double num = HeapNumber::cast(this)->value();
207     if (FastI2D(FastD2I(num)) == num) {
208       *value = FastD2I(num);
209       return true;
210     }
211   }
212   return false;
213 }
214
215
216 bool Object::ToUint32(uint32_t* value) {
217   if (IsSmi()) {
218     int num = Smi::cast(this)->value();
219     if (num >= 0) {
220       *value = static_cast<uint32_t>(num);
221       return true;
222     }
223   }
224   if (IsHeapNumber()) {
225     double num = HeapNumber::cast(this)->value();
226     if (num >= 0 && FastUI2D(FastD2UI(num)) == num) {
227       *value = FastD2UI(num);
228       return true;
229     }
230   }
231   return false;
232 }
233
234
235 bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
236   if (!object->IsHeapObject()) return false;
237   return IsTemplateFor(HeapObject::cast(object)->map());
238 }
239
240
241 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
242   // There is a constraint on the object; check.
243   if (!map->IsJSObjectMap()) return false;
244   // Fetch the constructor function of the object.
245   Object* cons_obj = map->constructor();
246   if (!cons_obj->IsJSFunction()) return false;
247   JSFunction* fun = JSFunction::cast(cons_obj);
248   // Iterate through the chain of inheriting function templates to
249   // see if the required one occurs.
250   for (Object* type = fun->shared()->function_data();
251        type->IsFunctionTemplateInfo();
252        type = FunctionTemplateInfo::cast(type)->parent_template()) {
253     if (type == this) return true;
254   }
255   // Didn't find the required type in the inheritance chain.
256   return false;
257 }
258
259
260 template<typename To>
261 static inline To* CheckedCast(void *from) {
262   uintptr_t temp = reinterpret_cast<uintptr_t>(from);
263   ASSERT(temp % sizeof(To) == 0);
264   return reinterpret_cast<To*>(temp);
265 }
266
267
268 static MaybeObject* PerformCompare(const BitmaskCompareDescriptor& descriptor,
269                                    char* ptr,
270                                    Heap* heap) {
271   uint32_t bitmask = descriptor.bitmask;
272   uint32_t compare_value = descriptor.compare_value;
273   uint32_t value;
274   switch (descriptor.size) {
275     case 1:
276       value = static_cast<uint32_t>(*CheckedCast<uint8_t>(ptr));
277       compare_value &= 0xff;
278       bitmask &= 0xff;
279       break;
280     case 2:
281       value = static_cast<uint32_t>(*CheckedCast<uint16_t>(ptr));
282       compare_value &= 0xffff;
283       bitmask &= 0xffff;
284       break;
285     case 4:
286       value = *CheckedCast<uint32_t>(ptr);
287       break;
288     default:
289       UNREACHABLE();
290       return NULL;
291   }
292   return heap->ToBoolean((bitmask & value) == (bitmask & compare_value));
293 }
294
295
296 static MaybeObject* PerformCompare(const PointerCompareDescriptor& descriptor,
297                                    char* ptr,
298                                    Heap* heap) {
299   uintptr_t compare_value =
300       reinterpret_cast<uintptr_t>(descriptor.compare_value);
301   uintptr_t value = *CheckedCast<uintptr_t>(ptr);
302   return heap->ToBoolean(compare_value == value);
303 }
304
305
306 static MaybeObject* GetPrimitiveValue(
307     const PrimitiveValueDescriptor& descriptor,
308     char* ptr,
309     Heap* heap) {
310   int32_t int32_value = 0;
311   switch (descriptor.data_type) {
312     case kDescriptorInt8Type:
313       int32_value = *CheckedCast<int8_t>(ptr);
314       break;
315     case kDescriptorUint8Type:
316       int32_value = *CheckedCast<uint8_t>(ptr);
317       break;
318     case kDescriptorInt16Type:
319       int32_value = *CheckedCast<int16_t>(ptr);
320       break;
321     case kDescriptorUint16Type:
322       int32_value = *CheckedCast<uint16_t>(ptr);
323       break;
324     case kDescriptorInt32Type:
325       int32_value = *CheckedCast<int32_t>(ptr);
326       break;
327     case kDescriptorUint32Type: {
328       uint32_t value = *CheckedCast<uint32_t>(ptr);
329       return heap->NumberFromUint32(value);
330     }
331     case kDescriptorBoolType: {
332       uint8_t byte = *CheckedCast<uint8_t>(ptr);
333       return heap->ToBoolean(byte & (0x1 << descriptor.bool_offset));
334     }
335     case kDescriptorFloatType: {
336       float value = *CheckedCast<float>(ptr);
337       return heap->NumberFromDouble(value);
338     }
339     case kDescriptorDoubleType: {
340       double value = *CheckedCast<double>(ptr);
341       return heap->NumberFromDouble(value);
342     }
343   }
344   return heap->NumberFromInt32(int32_value);
345 }
346
347
348 static MaybeObject* GetDeclaredAccessorProperty(Object* receiver,
349                                                 DeclaredAccessorInfo* info,
350                                                 Isolate* isolate) {
351   char* current = reinterpret_cast<char*>(receiver);
352   DeclaredAccessorDescriptorIterator iterator(info->descriptor());
353   while (true) {
354     const DeclaredAccessorDescriptorData* data = iterator.Next();
355     switch (data->type) {
356       case kDescriptorReturnObject: {
357         ASSERT(iterator.Complete());
358         current = *CheckedCast<char*>(current);
359         return *CheckedCast<Object*>(current);
360       }
361       case kDescriptorPointerDereference:
362         ASSERT(!iterator.Complete());
363         current = *reinterpret_cast<char**>(current);
364         break;
365       case kDescriptorPointerShift:
366         ASSERT(!iterator.Complete());
367         current += data->pointer_shift_descriptor.byte_offset;
368         break;
369       case kDescriptorObjectDereference: {
370         ASSERT(!iterator.Complete());
371         Object* object = CheckedCast<Object>(current);
372         int field = data->object_dereference_descriptor.internal_field;
373         Object* smi = JSObject::cast(object)->GetInternalField(field);
374         ASSERT(smi->IsSmi());
375         current = reinterpret_cast<char*>(smi);
376         break;
377       }
378       case kDescriptorBitmaskCompare:
379         ASSERT(iterator.Complete());
380         return PerformCompare(data->bitmask_compare_descriptor,
381                               current,
382                               isolate->heap());
383       case kDescriptorPointerCompare:
384         ASSERT(iterator.Complete());
385         return PerformCompare(data->pointer_compare_descriptor,
386                               current,
387                               isolate->heap());
388       case kDescriptorPrimitiveValue:
389         ASSERT(iterator.Complete());
390         return GetPrimitiveValue(data->primitive_value_descriptor,
391                                  current,
392                                  isolate->heap());
393     }
394   }
395   UNREACHABLE();
396   return NULL;
397 }
398
399
400 Handle<FixedArray> JSObject::EnsureWritableFastElements(
401     Handle<JSObject> object) {
402   CALL_HEAP_FUNCTION(object->GetIsolate(),
403                      object->EnsureWritableFastElements(),
404                      FixedArray);
405 }
406
407
408 Handle<Object> JSObject::GetPropertyWithCallback(Handle<JSObject> object,
409                                                  Handle<Object> receiver,
410                                                  Handle<Object> structure,
411                                                  Handle<Name> name) {
412   Isolate* isolate = name->GetIsolate();
413   // To accommodate both the old and the new api we switch on the
414   // data structure used to store the callbacks.  Eventually foreign
415   // callbacks should be phased out.
416   if (structure->IsForeign()) {
417     AccessorDescriptor* callback =
418         reinterpret_cast<AccessorDescriptor*>(
419             Handle<Foreign>::cast(structure)->foreign_address());
420     CALL_HEAP_FUNCTION(isolate,
421                        (callback->getter)(isolate, *receiver, callback->data),
422                        Object);
423   }
424
425   // api style callbacks.
426   if (structure->IsAccessorInfo()) {
427     Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure);
428     if (!accessor_info->IsCompatibleReceiver(*receiver)) {
429       Handle<Object> args[2] = { name, receiver };
430       Handle<Object> error =
431           isolate->factory()->NewTypeError("incompatible_method_receiver",
432                                            HandleVector(args,
433                                                         ARRAY_SIZE(args)));
434       isolate->Throw(*error);
435       return Handle<Object>::null();
436     }
437     // TODO(rossberg): Handling symbols in the API requires changing the API,
438     // so we do not support it for now.
439     if (name->IsSymbol()) return isolate->factory()->undefined_value();
440     if (structure->IsDeclaredAccessorInfo()) {
441       CALL_HEAP_FUNCTION(
442           isolate,
443           GetDeclaredAccessorProperty(*receiver,
444                                       DeclaredAccessorInfo::cast(*structure),
445                                       isolate),
446           Object);
447     }
448
449     Handle<ExecutableAccessorInfo> data =
450         Handle<ExecutableAccessorInfo>::cast(structure);
451     v8::AccessorGetterCallback call_fun =
452         v8::ToCData<v8::AccessorGetterCallback>(data->getter());
453     if (call_fun == NULL) return isolate->factory()->undefined_value();
454
455     HandleScope scope(isolate);
456     Handle<JSObject> self = Handle<JSObject>::cast(receiver);
457     Handle<String> key = Handle<String>::cast(name);
458     LOG(isolate, ApiNamedPropertyAccess("load", *self, *name));
459     PropertyCallbackArguments args(isolate, data->data(), *self, *object);
460     v8::Handle<v8::Value> result =
461         args.Call(call_fun, v8::Utils::ToLocal(key));
462     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
463     if (result.IsEmpty()) {
464       return isolate->factory()->undefined_value();
465     }
466     Handle<Object> return_value = v8::Utils::OpenHandle(*result);
467     return_value->VerifyApiCallResultType();
468     return scope.CloseAndEscape(return_value);
469   }
470
471   // __defineGetter__ callback
472   Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
473                         isolate);
474   if (getter->IsSpecFunction()) {
475     // TODO(rossberg): nicer would be to cast to some JSCallable here...
476     CALL_HEAP_FUNCTION(
477         isolate,
478         object->GetPropertyWithDefinedGetter(*receiver,
479                                              JSReceiver::cast(*getter)),
480         Object);
481   }
482   // Getter is not a function.
483   return isolate->factory()->undefined_value();
484 }
485
486
487 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
488                                              Name* name_raw) {
489   Isolate* isolate = GetIsolate();
490   HandleScope scope(isolate);
491   Handle<Object> receiver(receiver_raw, isolate);
492   Handle<Object> name(name_raw, isolate);
493
494   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
495   if (name->IsSymbol()) return isolate->heap()->undefined_value();
496
497   Handle<Object> args[] = { receiver, name };
498   Handle<Object> result = CallTrap(
499     "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
500   if (isolate->has_pending_exception()) return Failure::Exception();
501
502   return *result;
503 }
504
505
506 Handle<Object> Object::GetProperty(Handle<Object> object,
507                                    Handle<Name> name) {
508   // TODO(rossberg): The index test should not be here but in the GetProperty
509   // method (or somewhere else entirely). Needs more global clean-up.
510   uint32_t index;
511   Isolate* isolate = name->GetIsolate();
512   if (name->AsArrayIndex(&index)) return GetElement(isolate, object, index);
513   CALL_HEAP_FUNCTION(isolate, object->GetProperty(*name), Object);
514 }
515
516
517 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
518                                             uint32_t index) {
519   String* name;
520   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
521   if (!maybe->To<String>(&name)) return maybe;
522   return GetPropertyWithHandler(receiver, name);
523 }
524
525
526 Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
527                                               Handle<JSReceiver> receiver,
528                                               uint32_t index,
529                                               Handle<Object> value,
530                                               StrictMode strict_mode) {
531   Isolate* isolate = proxy->GetIsolate();
532   Handle<String> name = isolate->factory()->Uint32ToString(index);
533   return SetPropertyWithHandler(
534       proxy, receiver, name, value, NONE, strict_mode);
535 }
536
537
538 bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) {
539   Isolate* isolate = proxy->GetIsolate();
540   Handle<String> name = isolate->factory()->Uint32ToString(index);
541   return HasPropertyWithHandler(proxy, name);
542 }
543
544
545 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver,
546                                                   JSReceiver* getter) {
547   Isolate* isolate = getter->GetIsolate();
548   HandleScope scope(isolate);
549   Handle<JSReceiver> fun(getter);
550   Handle<Object> self(receiver, isolate);
551 #ifdef ENABLE_DEBUGGER_SUPPORT
552   Debug* debug = isolate->debug();
553   // Handle stepping into a getter if step into is active.
554   // TODO(rossberg): should this apply to getters that are function proxies?
555   if (debug->StepInActive() && fun->IsJSFunction()) {
556     debug->HandleStepIn(
557         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
558   }
559 #endif
560
561   bool has_pending_exception;
562   Handle<Object> result = Execution::Call(
563       isolate, fun, self, 0, NULL, &has_pending_exception, true);
564   // Check for pending exception and return the result.
565   if (has_pending_exception) return Failure::Exception();
566   return *result;
567 }
568
569
570 // Only deal with CALLBACKS and INTERCEPTOR
571 Handle<Object> JSObject::GetPropertyWithFailedAccessCheck(
572     Handle<JSObject> object,
573     Handle<Object> receiver,
574     LookupResult* result,
575     Handle<Name> name,
576     PropertyAttributes* attributes) {
577   Isolate* isolate = name->GetIsolate();
578   if (result->IsProperty()) {
579     switch (result->type()) {
580       case CALLBACKS: {
581         // Only allow API accessors.
582         Handle<Object> callback_obj(result->GetCallbackObject(), isolate);
583         if (callback_obj->IsAccessorInfo()) {
584           if (!AccessorInfo::cast(*callback_obj)->all_can_read()) break;
585           *attributes = result->GetAttributes();
586           // Fall through to GetPropertyWithCallback.
587         } else if (callback_obj->IsAccessorPair()) {
588           if (!AccessorPair::cast(*callback_obj)->all_can_read()) break;
589           // Fall through to GetPropertyWithCallback.
590         } else {
591           break;
592         }
593         Handle<JSObject> holder(result->holder(), isolate);
594         return GetPropertyWithCallback(holder, receiver, callback_obj, name);
595       }
596       case NORMAL:
597       case FIELD:
598       case CONSTANT: {
599         // Search ALL_CAN_READ accessors in prototype chain.
600         LookupResult r(isolate);
601         result->holder()->LookupRealNamedPropertyInPrototypes(*name, &r);
602         if (r.IsProperty()) {
603           return GetPropertyWithFailedAccessCheck(
604               object, receiver, &r, name, attributes);
605         }
606         break;
607       }
608       case INTERCEPTOR: {
609         // If the object has an interceptor, try real named properties.
610         // No access check in GetPropertyAttributeWithInterceptor.
611         LookupResult r(isolate);
612         result->holder()->LookupRealNamedProperty(*name, &r);
613         if (r.IsProperty()) {
614           return GetPropertyWithFailedAccessCheck(
615               object, receiver, &r, name, attributes);
616         }
617         break;
618       }
619       default:
620         UNREACHABLE();
621     }
622   }
623
624   // No accessible property found.
625   *attributes = ABSENT;
626   isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_GET);
627   RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
628   return isolate->factory()->undefined_value();
629 }
630
631
632 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
633     Handle<JSObject> object,
634     LookupResult* result,
635     Handle<Name> name,
636     bool continue_search) {
637   if (result->IsProperty()) {
638     switch (result->type()) {
639       case CALLBACKS: {
640         // Only allow API accessors.
641         Handle<Object> obj(result->GetCallbackObject(), object->GetIsolate());
642         if (obj->IsAccessorInfo()) {
643           Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(obj);
644           if (info->all_can_read()) {
645             return result->GetAttributes();
646           }
647         } else if (obj->IsAccessorPair()) {
648           Handle<AccessorPair> pair = Handle<AccessorPair>::cast(obj);
649           if (pair->all_can_read()) {
650             return result->GetAttributes();
651           }
652         }
653         break;
654       }
655
656       case NORMAL:
657       case FIELD:
658       case CONSTANT: {
659         if (!continue_search) break;
660         // Search ALL_CAN_READ accessors in prototype chain.
661         LookupResult r(object->GetIsolate());
662         result->holder()->LookupRealNamedPropertyInPrototypes(*name, &r);
663         if (r.IsProperty()) {
664           return GetPropertyAttributeWithFailedAccessCheck(
665               object, &r, name, continue_search);
666         }
667         break;
668       }
669
670       case INTERCEPTOR: {
671         // If the object has an interceptor, try real named properties.
672         // No access check in GetPropertyAttributeWithInterceptor.
673         LookupResult r(object->GetIsolate());
674         if (continue_search) {
675           result->holder()->LookupRealNamedProperty(*name, &r);
676         } else {
677           result->holder()->LocalLookupRealNamedProperty(*name, &r);
678         }
679         if (!r.IsFound()) break;
680         return GetPropertyAttributeWithFailedAccessCheck(
681             object, &r, name, continue_search);
682       }
683
684       case HANDLER:
685       case TRANSITION:
686       case NONEXISTENT:
687         UNREACHABLE();
688     }
689   }
690
691   object->GetIsolate()->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
692   return ABSENT;
693 }
694
695
696 Object* JSObject::GetNormalizedProperty(const LookupResult* result) {
697   ASSERT(!HasFastProperties());
698   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
699   if (IsGlobalObject()) {
700     value = PropertyCell::cast(value)->value();
701   }
702   ASSERT(!value->IsPropertyCell() && !value->IsCell());
703   return value;
704 }
705
706
707 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
708                                      const LookupResult* result,
709                                      Handle<Object> value) {
710   ASSERT(!object->HasFastProperties());
711   NameDictionary* property_dictionary = object->property_dictionary();
712   if (object->IsGlobalObject()) {
713     Handle<PropertyCell> cell(PropertyCell::cast(
714         property_dictionary->ValueAt(result->GetDictionaryEntry())));
715     PropertyCell::SetValueInferType(cell, value);
716   } else {
717     property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value);
718   }
719 }
720
721
722 // TODO(mstarzinger): Temporary wrapper until handlified.
723 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict,
724                                                 Handle<Name> name,
725                                                 Handle<Object> value,
726                                                 PropertyDetails details) {
727   CALL_HEAP_FUNCTION(dict->GetIsolate(),
728                      dict->Add(*name, *value, details),
729                      NameDictionary);
730 }
731
732
733 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
734                                      Handle<Name> name,
735                                      Handle<Object> value,
736                                      PropertyDetails details) {
737   ASSERT(!object->HasFastProperties());
738   Handle<NameDictionary> property_dictionary(object->property_dictionary());
739
740   if (!name->IsUniqueName()) {
741     name = object->GetIsolate()->factory()->InternalizeString(
742         Handle<String>::cast(name));
743   }
744
745   int entry = property_dictionary->FindEntry(*name);
746   if (entry == NameDictionary::kNotFound) {
747     Handle<Object> store_value = value;
748     if (object->IsGlobalObject()) {
749       store_value = object->GetIsolate()->factory()->NewPropertyCell(value);
750     }
751
752     property_dictionary =
753         NameDictionaryAdd(property_dictionary, name, store_value, details);
754     object->set_properties(*property_dictionary);
755     return;
756   }
757
758   PropertyDetails original_details = property_dictionary->DetailsAt(entry);
759   int enumeration_index;
760   // Preserve the enumeration index unless the property was deleted.
761   if (original_details.IsDeleted()) {
762     enumeration_index = property_dictionary->NextEnumerationIndex();
763     property_dictionary->SetNextEnumerationIndex(enumeration_index + 1);
764   } else {
765     enumeration_index = original_details.dictionary_index();
766     ASSERT(enumeration_index > 0);
767   }
768
769   details = PropertyDetails(
770       details.attributes(), details.type(), enumeration_index);
771
772   if (object->IsGlobalObject()) {
773     Handle<PropertyCell> cell(
774         PropertyCell::cast(property_dictionary->ValueAt(entry)));
775     PropertyCell::SetValueInferType(cell, value);
776     // Please note we have to update the property details.
777     property_dictionary->DetailsAtPut(entry, details);
778   } else {
779     property_dictionary->SetEntry(entry, *name, *value, details);
780   }
781 }
782
783
784 // TODO(mstarzinger): Temporary wrapper until target is handlified.
785 Handle<NameDictionary> NameDictionaryShrink(Handle<NameDictionary> dict,
786                                             Handle<Name> name) {
787   CALL_HEAP_FUNCTION(dict->GetIsolate(), dict->Shrink(*name), NameDictionary);
788 }
789
790
791 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
792                                                   Handle<Name> name,
793                                                   DeleteMode mode) {
794   ASSERT(!object->HasFastProperties());
795   Isolate* isolate = object->GetIsolate();
796   Handle<NameDictionary> dictionary(object->property_dictionary());
797   int entry = dictionary->FindEntry(*name);
798   if (entry != NameDictionary::kNotFound) {
799     // If we have a global object set the cell to the hole.
800     if (object->IsGlobalObject()) {
801       PropertyDetails details = dictionary->DetailsAt(entry);
802       if (details.IsDontDelete()) {
803         if (mode != FORCE_DELETION) return isolate->factory()->false_value();
804         // When forced to delete global properties, we have to make a
805         // map change to invalidate any ICs that think they can load
806         // from the DontDelete cell without checking if it contains
807         // the hole value.
808         Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
809         ASSERT(new_map->is_dictionary_map());
810         object->set_map(*new_map);
811       }
812       Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
813       Handle<Object> value = isolate->factory()->the_hole_value();
814       PropertyCell::SetValueInferType(cell, value);
815       dictionary->DetailsAtPut(entry, details.AsDeleted());
816     } else {
817       Handle<Object> deleted(dictionary->DeleteProperty(entry, mode), isolate);
818       if (*deleted == isolate->heap()->true_value()) {
819         Handle<NameDictionary> new_properties =
820             NameDictionaryShrink(dictionary, name);
821         object->set_properties(*new_properties);
822       }
823       return deleted;
824     }
825   }
826   return isolate->factory()->true_value();
827 }
828
829
830 bool JSObject::IsDirty() {
831   Object* cons_obj = map()->constructor();
832   if (!cons_obj->IsJSFunction())
833     return true;
834   JSFunction* fun = JSFunction::cast(cons_obj);
835   if (!fun->shared()->IsApiFunction())
836     return true;
837   // If the object is fully fast case and has the same map it was
838   // created with then no changes can have been made to it.
839   return map() != fun->initial_map()
840       || !HasFastObjectElements()
841       || !HasFastProperties();
842 }
843
844
845 Handle<Object> Object::GetProperty(Handle<Object> object,
846                                    Handle<Object> receiver,
847                                    LookupResult* result,
848                                    Handle<Name> key,
849                                    PropertyAttributes* attributes) {
850   Isolate* isolate = result->isolate();
851   CALL_HEAP_FUNCTION(
852       isolate,
853       object->GetProperty(*receiver, result, *key, attributes),
854       Object);
855 }
856
857
858 MaybeObject* Object::GetPropertyOrFail(Handle<Object> object,
859                                        Handle<Object> receiver,
860                                        LookupResult* result,
861                                        Handle<Name> key,
862                                        PropertyAttributes* attributes) {
863   Isolate* isolate = result->isolate();
864   CALL_HEAP_FUNCTION_PASS_EXCEPTION(
865       isolate,
866       object->GetProperty(*receiver, result, *key, attributes));
867 }
868
869
870 // TODO(yangguo): handlify this and get rid of.
871 MaybeObject* Object::GetProperty(Object* receiver,
872                                  LookupResult* result,
873                                  Name* name,
874                                  PropertyAttributes* attributes) {
875   Isolate* isolate = name->GetIsolate();
876   Heap* heap = isolate->heap();
877
878 #ifdef DEBUG
879   // TODO(mstarzinger): Only because of the AssertNoContextChange, drop as soon
880   // as this method has been fully handlified.
881   HandleScope scope(isolate);
882 #endif
883
884   // Make sure that the top context does not change when doing
885   // callbacks or interceptor calls.
886   AssertNoContextChange ncc(isolate);
887
888   // Traverse the prototype chain from the current object (this) to
889   // the holder and check for access rights. This avoids traversing the
890   // objects more than once in case of interceptors, because the
891   // holder will always be the interceptor holder and the search may
892   // only continue with a current object just after the interceptor
893   // holder in the prototype chain.
894   // Proxy handlers do not use the proxy's prototype, so we can skip this.
895   if (!result->IsHandler()) {
896     Object* last = result->IsProperty()
897         ? result->holder()
898         : Object::cast(heap->null_value());
899     ASSERT(this != this->GetPrototype(isolate));
900     for (Object* current = this;
901          true;
902          current = current->GetPrototype(isolate)) {
903       if (current->IsAccessCheckNeeded()) {
904         // Check if we're allowed to read from the current object. Note
905         // that even though we may not actually end up loading the named
906         // property from the current object, we still check that we have
907         // access to it.
908         JSObject* checked = JSObject::cast(current);
909         if (!isolate->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
910           HandleScope scope(isolate);
911           Handle<Object> value = JSObject::GetPropertyWithFailedAccessCheck(
912               handle(checked, isolate),
913               handle(receiver, isolate),
914               result,
915               handle(name, isolate),
916               attributes);
917           RETURN_IF_EMPTY_HANDLE(isolate, value);
918           return *value;
919         }
920       }
921       // Stop traversing the chain once we reach the last object in the
922       // chain; either the holder of the result or null in case of an
923       // absent property.
924       if (current == last) break;
925     }
926   }
927
928   if (!result->IsProperty()) {
929     *attributes = ABSENT;
930     return heap->undefined_value();
931   }
932   *attributes = result->GetAttributes();
933   Object* value;
934   switch (result->type()) {
935     case NORMAL:
936       value = result->holder()->GetNormalizedProperty(result);
937       ASSERT(!value->IsTheHole() || result->IsReadOnly());
938       return value->IsTheHole() ? heap->undefined_value() : value;
939     case FIELD: {
940       MaybeObject* maybe_result = result->holder()->FastPropertyAt(
941           result->representation(),
942           result->GetFieldIndex().field_index());
943       if (!maybe_result->To(&value)) return maybe_result;
944       ASSERT(!value->IsTheHole() || result->IsReadOnly());
945       return value->IsTheHole() ? heap->undefined_value() : value;
946     }
947     case CONSTANT:
948       return result->GetConstant();
949     case CALLBACKS: {
950       HandleScope scope(isolate);
951       Handle<Object> value = JSObject::GetPropertyWithCallback(
952           handle(result->holder(), isolate),
953           handle(receiver, isolate),
954           handle(result->GetCallbackObject(), isolate),
955           handle(name, isolate));
956       RETURN_IF_EMPTY_HANDLE(isolate, value);
957       return *value;
958     }
959     case HANDLER:
960       return result->proxy()->GetPropertyWithHandler(receiver, name);
961     case INTERCEPTOR: {
962       HandleScope scope(isolate);
963       Handle<Object> value = JSObject::GetPropertyWithInterceptor(
964           handle(result->holder(), isolate),
965           handle(receiver, isolate),
966           handle(name, isolate),
967           attributes);
968       RETURN_IF_EMPTY_HANDLE(isolate, value);
969       return *value;
970     }
971     case TRANSITION:
972     case NONEXISTENT:
973       UNREACHABLE();
974       break;
975   }
976   UNREACHABLE();
977   return NULL;
978 }
979
980
981 Handle<Object> Object::GetElementWithReceiver(Isolate* isolate,
982                                               Handle<Object> object,
983                                               Handle<Object> receiver,
984                                               uint32_t index) {
985   Handle<Object> holder;
986
987   // Iterate up the prototype chain until an element is found or the null
988   // prototype is encountered.
989   for (holder = object;
990        !holder->IsNull();
991        holder = Handle<Object>(holder->GetPrototype(isolate), isolate)) {
992     if (!holder->IsJSObject()) {
993       Context* native_context = isolate->context()->native_context();
994       if (holder->IsNumber()) {
995         holder = Handle<Object>(
996             native_context->number_function()->instance_prototype(), isolate);
997       } else if (holder->IsFloat32x4()) {
998         holder = Handle<Object>(
999             native_context->float32x4_function()->instance_prototype(),
1000             isolate);
1001       } else if (holder->IsInt32x4()) {
1002         holder = Handle<Object>(
1003             native_context->int32x4_function()->instance_prototype(), isolate);
1004       } else if (holder->IsString()) {
1005         holder = Handle<Object>(
1006             native_context->string_function()->instance_prototype(), isolate);
1007       } else if (holder->IsSymbol()) {
1008         holder = Handle<Object>(
1009             native_context->symbol_function()->instance_prototype(), isolate);
1010       } else if (holder->IsBoolean()) {
1011         holder = Handle<Object>(
1012             native_context->boolean_function()->instance_prototype(), isolate);
1013       } else if (holder->IsJSProxy()) {
1014         CALL_HEAP_FUNCTION(isolate,
1015             Handle<JSProxy>::cast(holder)->GetElementWithHandler(
1016                 *receiver, index),
1017             Object);
1018       } else {
1019         // Undefined and null have no indexed properties.
1020         ASSERT(holder->IsUndefined() || holder->IsNull());
1021         return isolate->factory()->undefined_value();
1022       }
1023     }
1024
1025     // Inline the case for JSObjects. Doing so significantly improves the
1026     // performance of fetching elements where checking the prototype chain is
1027     // necessary.
1028     Handle<JSObject> js_object = Handle<JSObject>::cast(holder);
1029
1030     // Check access rights if needed.
1031     if (js_object->IsAccessCheckNeeded()) {
1032       if (!isolate->MayIndexedAccessWrapper(js_object, index, v8::ACCESS_GET)) {
1033         isolate->ReportFailedAccessCheckWrapper(js_object, v8::ACCESS_GET);
1034         RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1035         return isolate->factory()->undefined_value();
1036       }
1037     }
1038
1039     if (js_object->HasIndexedInterceptor()) {
1040       return JSObject::GetElementWithInterceptor(js_object, receiver, index);
1041     }
1042
1043     if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
1044       Handle<Object> result = js_object->GetElementsAccessor()->Get(
1045           receiver, js_object, index);
1046       RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
1047       if (!result->IsTheHole()) return result;
1048     }
1049   }
1050
1051   return isolate->factory()->undefined_value();
1052 }
1053
1054
1055 Object* Object::GetPrototype(Isolate* isolate) {
1056   if (IsSmi()) {
1057     Context* context = isolate->context()->native_context();
1058     return context->number_function()->instance_prototype();
1059   }
1060
1061   HeapObject* heap_object = HeapObject::cast(this);
1062
1063   // The object is either a number, a string, a boolean,
1064   // a real JS object, or a Harmony proxy.
1065   if (heap_object->IsJSReceiver()) {
1066     return heap_object->map()->prototype();
1067   }
1068   Context* context = isolate->context()->native_context();
1069
1070   if (heap_object->IsHeapNumber()) {
1071     return context->number_function()->instance_prototype();
1072   }
1073   if (heap_object->IsFloat32x4()) {
1074     return context->float32x4_function()->instance_prototype();
1075   }
1076   if (heap_object->IsInt32x4()) {
1077     return context->int32x4_function()->instance_prototype();
1078   }
1079   if (heap_object->IsString()) {
1080     return context->string_function()->instance_prototype();
1081   }
1082   if (heap_object->IsSymbol()) {
1083     return context->symbol_function()->instance_prototype();
1084   }
1085   if (heap_object->IsBoolean()) {
1086     return context->boolean_function()->instance_prototype();
1087   } else {
1088     return isolate->heap()->null_value();
1089   }
1090 }
1091
1092
1093 Map* Object::GetMarkerMap(Isolate* isolate) {
1094   if (IsSmi()) return isolate->heap()->heap_number_map();
1095   return HeapObject::cast(this)->map();
1096 }
1097
1098
1099 Object* Object::GetHash() {
1100   // The object is either a number, a name, an odd-ball,
1101   // a real JS object, or a Harmony proxy.
1102   if (IsNumber()) {
1103     uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
1104     return Smi::FromInt(hash & Smi::kMaxValue);
1105   }
1106   if (IsName()) {
1107     uint32_t hash = Name::cast(this)->Hash();
1108     return Smi::FromInt(hash);
1109   }
1110   if (IsOddball()) {
1111     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
1112     return Smi::FromInt(hash);
1113   }
1114
1115   ASSERT(IsJSReceiver());
1116   return JSReceiver::cast(this)->GetIdentityHash();
1117 }
1118
1119
1120 Handle<Object> Object::GetOrCreateHash(Handle<Object> object,
1121                                        Isolate* isolate) {
1122   Handle<Object> hash(object->GetHash(), isolate);
1123   if (hash->IsSmi())
1124     return hash;
1125
1126   ASSERT(object->IsJSReceiver());
1127   return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
1128 }
1129
1130
1131 bool Object::SameValue(Object* other) {
1132   if (other == this) return true;
1133
1134   // The object is either a number, a name, an odd-ball,
1135   // a real JS object, or a Harmony proxy.
1136   if (IsNumber() && other->IsNumber()) {
1137     double this_value = Number();
1138     double other_value = other->Number();
1139     bool equal = this_value == other_value;
1140     // SameValue(NaN, NaN) is true.
1141     if (!equal) return std::isnan(this_value) && std::isnan(other_value);
1142     // SameValue(0.0, -0.0) is false.
1143     return (this_value != 0) || ((1 / this_value) == (1 / other_value));
1144   }
1145   if (IsString() && other->IsString()) {
1146     return String::cast(this)->Equals(String::cast(other));
1147   }
1148   return false;
1149 }
1150
1151
1152 void Object::ShortPrint(FILE* out) {
1153   HeapStringAllocator allocator;
1154   StringStream accumulator(&allocator);
1155   ShortPrint(&accumulator);
1156   accumulator.OutputToFile(out);
1157 }
1158
1159
1160 void Object::ShortPrint(StringStream* accumulator) {
1161   if (IsSmi()) {
1162     Smi::cast(this)->SmiPrint(accumulator);
1163   } else if (IsFailure()) {
1164     Failure::cast(this)->FailurePrint(accumulator);
1165   } else {
1166     HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
1167   }
1168 }
1169
1170
1171 void Smi::SmiPrint(FILE* out) {
1172   PrintF(out, "%d", value());
1173 }
1174
1175
1176 void Smi::SmiPrint(StringStream* accumulator) {
1177   accumulator->Add("%d", value());
1178 }
1179
1180
1181 void Failure::FailurePrint(StringStream* accumulator) {
1182   accumulator->Add("Failure(%p)", reinterpret_cast<void*>(value()));
1183 }
1184
1185
1186 void Failure::FailurePrint(FILE* out) {
1187   PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
1188 }
1189
1190
1191 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
1192 // English?  Returns false for non-ASCII or words that don't start with
1193 // a capital letter.  The a/an rule follows pronunciation in English.
1194 // We don't use the BBC's overcorrect "an historic occasion" though if
1195 // you speak a dialect you may well say "an 'istoric occasion".
1196 static bool AnWord(String* str) {
1197   if (str->length() == 0) return false;  // A nothing.
1198   int c0 = str->Get(0);
1199   int c1 = str->length() > 1 ? str->Get(1) : 0;
1200   if (c0 == 'U') {
1201     if (c1 > 'Z') {
1202       return true;  // An Umpire, but a UTF8String, a U.
1203     }
1204   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
1205     return true;    // An Ape, an ABCBook.
1206   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
1207            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
1208             c0 == 'S' || c0 == 'X')) {
1209     return true;    // An MP3File, an M.
1210   }
1211   return false;
1212 }
1213
1214
1215 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
1216 #ifdef DEBUG
1217   // Do not attempt to flatten in debug mode when allocation is not
1218   // allowed.  This is to avoid an assertion failure when allocating.
1219   // Flattening strings is the only case where we always allow
1220   // allocation because no GC is performed if the allocation fails.
1221   if (!AllowHeapAllocation::IsAllowed()) return this;
1222 #endif
1223
1224   Heap* heap = GetHeap();
1225   switch (StringShape(this).representation_tag()) {
1226     case kConsStringTag: {
1227       ConsString* cs = ConsString::cast(this);
1228       if (cs->second()->length() == 0) {
1229         return cs->first();
1230       }
1231       // There's little point in putting the flat string in new space if the
1232       // cons string is in old space.  It can never get GCed until there is
1233       // an old space GC.
1234       PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
1235       int len = length();
1236       Object* object;
1237       String* result;
1238       if (IsOneByteRepresentation()) {
1239         { MaybeObject* maybe_object =
1240               heap->AllocateRawOneByteString(len, tenure);
1241           if (!maybe_object->ToObject(&object)) return maybe_object;
1242         }
1243         result = String::cast(object);
1244         String* first = cs->first();
1245         int first_length = first->length();
1246         uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
1247         WriteToFlat(first, dest, 0, first_length);
1248         String* second = cs->second();
1249         WriteToFlat(second,
1250                     dest + first_length,
1251                     0,
1252                     len - first_length);
1253       } else {
1254         { MaybeObject* maybe_object =
1255               heap->AllocateRawTwoByteString(len, tenure);
1256           if (!maybe_object->ToObject(&object)) return maybe_object;
1257         }
1258         result = String::cast(object);
1259         uc16* dest = SeqTwoByteString::cast(result)->GetChars();
1260         String* first = cs->first();
1261         int first_length = first->length();
1262         WriteToFlat(first, dest, 0, first_length);
1263         String* second = cs->second();
1264         WriteToFlat(second,
1265                     dest + first_length,
1266                     0,
1267                     len - first_length);
1268       }
1269       cs->set_first(result);
1270       cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
1271       return result;
1272     }
1273     default:
1274       return this;
1275   }
1276 }
1277
1278
1279 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
1280   // Externalizing twice leaks the external resource, so it's
1281   // prohibited by the API.
1282   ASSERT(!this->IsExternalString());
1283 #ifdef ENABLE_SLOW_ASSERTS
1284   if (FLAG_enable_slow_asserts) {
1285     // Assert that the resource and the string are equivalent.
1286     ASSERT(static_cast<size_t>(this->length()) == resource->length());
1287     ScopedVector<uc16> smart_chars(this->length());
1288     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1289     ASSERT(memcmp(smart_chars.start(),
1290                   resource->data(),
1291                   resource->length() * sizeof(smart_chars[0])) == 0);
1292   }
1293 #endif  // DEBUG
1294   Heap* heap = GetHeap();
1295   int size = this->Size();  // Byte size of the original string.
1296   if (size < ExternalString::kShortSize) {
1297     return false;
1298   }
1299   bool is_ascii = this->IsOneByteRepresentation();
1300   bool is_internalized = this->IsInternalizedString();
1301
1302   // Morph the string to an external string by replacing the map and
1303   // reinitializing the fields.  This won't work if
1304   // - the space the existing string occupies is too small for a regular
1305   //   external string.
1306   // - the existing string is in old pointer space and the backing store of
1307   //   the external string is not aligned.  The GC cannot deal with a field
1308   //   containing a possibly unaligned address to outside of V8's heap.
1309   // In either case we resort to a short external string instead, omitting
1310   // the field caching the address of the backing store.  When we encounter
1311   // short external strings in generated code, we need to bailout to runtime.
1312   if (size < ExternalString::kSize ||
1313       heap->old_pointer_space()->Contains(this)) {
1314     this->set_map_no_write_barrier(
1315         is_internalized
1316             ? (is_ascii
1317                 ? heap->
1318                     short_external_internalized_string_with_one_byte_data_map()
1319                 : heap->short_external_internalized_string_map())
1320             : (is_ascii
1321                 ? heap->short_external_string_with_one_byte_data_map()
1322                 : heap->short_external_string_map()));
1323   } else {
1324     this->set_map_no_write_barrier(
1325         is_internalized
1326             ? (is_ascii
1327                 ? heap->external_internalized_string_with_one_byte_data_map()
1328                 : heap->external_internalized_string_map())
1329             : (is_ascii
1330                 ? heap->external_string_with_one_byte_data_map()
1331                 : heap->external_string_map()));
1332   }
1333   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
1334   self->set_resource(resource);
1335   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1336
1337   // Fill the remainder of the string with dead wood.
1338   int new_size = this->Size();  // Byte size of the external String object.
1339   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1340   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1341   return true;
1342 }
1343
1344
1345 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
1346 #ifdef ENABLE_SLOW_ASSERTS
1347   if (FLAG_enable_slow_asserts) {
1348     // Assert that the resource and the string are equivalent.
1349     ASSERT(static_cast<size_t>(this->length()) == resource->length());
1350     if (this->IsTwoByteRepresentation()) {
1351       ScopedVector<uint16_t> smart_chars(this->length());
1352       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1353       ASSERT(String::IsOneByte(smart_chars.start(), this->length()));
1354     }
1355     ScopedVector<char> smart_chars(this->length());
1356     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1357     ASSERT(memcmp(smart_chars.start(),
1358                   resource->data(),
1359                   resource->length() * sizeof(smart_chars[0])) == 0);
1360   }
1361 #endif  // DEBUG
1362   Heap* heap = GetHeap();
1363   int size = this->Size();  // Byte size of the original string.
1364   if (size < ExternalString::kShortSize) {
1365     return false;
1366   }
1367   bool is_internalized = this->IsInternalizedString();
1368
1369   // Morph the string to an external string by replacing the map and
1370   // reinitializing the fields.  This won't work if
1371   // - the space the existing string occupies is too small for a regular
1372   //   external string.
1373   // - the existing string is in old pointer space and the backing store of
1374   //   the external string is not aligned.  The GC cannot deal with a field
1375   //   containing a possibly unaligned address to outside of V8's heap.
1376   // In either case we resort to a short external string instead, omitting
1377   // the field caching the address of the backing store.  When we encounter
1378   // short external strings in generated code, we need to bailout to runtime.
1379   if (size < ExternalString::kSize ||
1380       heap->old_pointer_space()->Contains(this)) {
1381     this->set_map_no_write_barrier(
1382         is_internalized ? heap->short_external_ascii_internalized_string_map()
1383                         : heap->short_external_ascii_string_map());
1384   } else {
1385     this->set_map_no_write_barrier(
1386         is_internalized ? heap->external_ascii_internalized_string_map()
1387                         : heap->external_ascii_string_map());
1388   }
1389   ExternalAsciiString* self = ExternalAsciiString::cast(this);
1390   self->set_resource(resource);
1391   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1392
1393   // Fill the remainder of the string with dead wood.
1394   int new_size = this->Size();  // Byte size of the external String object.
1395   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1396   heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1397   return true;
1398 }
1399
1400
1401 void String::StringShortPrint(StringStream* accumulator) {
1402   int len = length();
1403   if (len > kMaxShortPrintLength) {
1404     accumulator->Add("<Very long string[%u]>", len);
1405     return;
1406   }
1407
1408   if (!LooksValid()) {
1409     accumulator->Add("<Invalid String>");
1410     return;
1411   }
1412
1413   ConsStringIteratorOp op;
1414   StringCharacterStream stream(this, &op);
1415
1416   bool truncated = false;
1417   if (len > kMaxShortPrintLength) {
1418     len = kMaxShortPrintLength;
1419     truncated = true;
1420   }
1421   bool ascii = true;
1422   for (int i = 0; i < len; i++) {
1423     uint16_t c = stream.GetNext();
1424
1425     if (c < 32 || c >= 127) {
1426       ascii = false;
1427     }
1428   }
1429   stream.Reset(this);
1430   if (ascii) {
1431     accumulator->Add("<String[%u]: ", length());
1432     for (int i = 0; i < len; i++) {
1433       accumulator->Put(static_cast<char>(stream.GetNext()));
1434     }
1435     accumulator->Put('>');
1436   } else {
1437     // Backslash indicates that the string contains control
1438     // characters and that backslashes are therefore escaped.
1439     accumulator->Add("<String[%u]\\: ", length());
1440     for (int i = 0; i < len; i++) {
1441       uint16_t c = stream.GetNext();
1442       if (c == '\n') {
1443         accumulator->Add("\\n");
1444       } else if (c == '\r') {
1445         accumulator->Add("\\r");
1446       } else if (c == '\\') {
1447         accumulator->Add("\\\\");
1448       } else if (c < 32 || c > 126) {
1449         accumulator->Add("\\x%02x", c);
1450       } else {
1451         accumulator->Put(static_cast<char>(c));
1452       }
1453     }
1454     if (truncated) {
1455       accumulator->Put('.');
1456       accumulator->Put('.');
1457       accumulator->Put('.');
1458     }
1459     accumulator->Put('>');
1460   }
1461   return;
1462 }
1463
1464
1465 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1466   switch (map()->instance_type()) {
1467     case JS_ARRAY_TYPE: {
1468       double length = JSArray::cast(this)->length()->IsUndefined()
1469           ? 0
1470           : JSArray::cast(this)->length()->Number();
1471       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1472       break;
1473     }
1474     case JS_WEAK_MAP_TYPE: {
1475       accumulator->Add("<JS WeakMap>");
1476       break;
1477     }
1478     case JS_WEAK_SET_TYPE: {
1479       accumulator->Add("<JS WeakSet>");
1480       break;
1481     }
1482     case JS_REGEXP_TYPE: {
1483       accumulator->Add("<JS RegExp>");
1484       break;
1485     }
1486     case JS_FUNCTION_TYPE: {
1487       JSFunction* function = JSFunction::cast(this);
1488       Object* fun_name = function->shared()->DebugName();
1489       bool printed = false;
1490       if (fun_name->IsString()) {
1491         String* str = String::cast(fun_name);
1492         if (str->length() > 0) {
1493           accumulator->Add("<JS Function ");
1494           accumulator->Put(str);
1495           printed = true;
1496         }
1497       }
1498       if (!printed) {
1499         accumulator->Add("<JS Function");
1500       }
1501       accumulator->Add(" (SharedFunctionInfo %p)",
1502                        reinterpret_cast<void*>(function->shared()));
1503       accumulator->Put('>');
1504       break;
1505     }
1506     case JS_GENERATOR_OBJECT_TYPE: {
1507       accumulator->Add("<JS Generator>");
1508       break;
1509     }
1510     case JS_MODULE_TYPE: {
1511       accumulator->Add("<JS Module>");
1512       break;
1513     }
1514     // All other JSObjects are rather similar to each other (JSObject,
1515     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1516     default: {
1517       Map* map_of_this = map();
1518       Heap* heap = GetHeap();
1519       Object* constructor = map_of_this->constructor();
1520       bool printed = false;
1521       if (constructor->IsHeapObject() &&
1522           !heap->Contains(HeapObject::cast(constructor))) {
1523         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1524       } else {
1525         bool global_object = IsJSGlobalProxy();
1526         if (constructor->IsJSFunction()) {
1527           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1528             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1529           } else {
1530             Object* constructor_name =
1531                 JSFunction::cast(constructor)->shared()->name();
1532             if (constructor_name->IsString()) {
1533               String* str = String::cast(constructor_name);
1534               if (str->length() > 0) {
1535                 bool vowel = AnWord(str);
1536                 accumulator->Add("<%sa%s ",
1537                        global_object ? "Global Object: " : "",
1538                        vowel ? "n" : "");
1539                 accumulator->Put(str);
1540                 accumulator->Add(" with %smap %p",
1541                     map_of_this->is_deprecated() ? "deprecated " : "",
1542                     map_of_this);
1543                 printed = true;
1544               }
1545             }
1546           }
1547         }
1548         if (!printed) {
1549           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1550         }
1551       }
1552       if (IsJSValue()) {
1553         accumulator->Add(" value = ");
1554         JSValue::cast(this)->value()->ShortPrint(accumulator);
1555       }
1556       accumulator->Put('>');
1557       break;
1558     }
1559   }
1560 }
1561
1562
1563 void JSObject::PrintElementsTransition(
1564     FILE* file, Handle<JSObject> object,
1565     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
1566     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
1567   if (from_kind != to_kind) {
1568     PrintF(file, "elements transition [");
1569     PrintElementsKind(file, from_kind);
1570     PrintF(file, " -> ");
1571     PrintElementsKind(file, to_kind);
1572     PrintF(file, "] in ");
1573     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
1574     PrintF(file, " for ");
1575     object->ShortPrint(file);
1576     PrintF(file, " from ");
1577     from_elements->ShortPrint(file);
1578     PrintF(file, " to ");
1579     to_elements->ShortPrint(file);
1580     PrintF(file, "\n");
1581   }
1582 }
1583
1584
1585 void Map::PrintGeneralization(FILE* file,
1586                               const char* reason,
1587                               int modify_index,
1588                               int split,
1589                               int descriptors,
1590                               bool constant_to_field,
1591                               Representation old_representation,
1592                               Representation new_representation) {
1593   PrintF(file, "[generalizing ");
1594   constructor_name()->PrintOn(file);
1595   PrintF(file, "] ");
1596   Name* name = instance_descriptors()->GetKey(modify_index);
1597   if (name->IsString()) {
1598     String::cast(name)->PrintOn(file);
1599   } else {
1600     PrintF(file, "{symbol %p}", static_cast<void*>(name));
1601   }
1602   if (constant_to_field) {
1603     PrintF(file, ":c->f");
1604   } else {
1605     PrintF(file, ":%s->%s",
1606            old_representation.Mnemonic(),
1607            new_representation.Mnemonic());
1608   }
1609   PrintF(file, " (");
1610   if (strlen(reason) > 0) {
1611     PrintF(file, "%s", reason);
1612   } else {
1613     PrintF(file, "+%i maps", descriptors - split);
1614   }
1615   PrintF(file, ") [");
1616   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1617   PrintF(file, "]\n");
1618 }
1619
1620
1621 void JSObject::PrintInstanceMigration(FILE* file,
1622                                       Map* original_map,
1623                                       Map* new_map) {
1624   PrintF(file, "[migrating ");
1625   map()->constructor_name()->PrintOn(file);
1626   PrintF(file, "] ");
1627   DescriptorArray* o = original_map->instance_descriptors();
1628   DescriptorArray* n = new_map->instance_descriptors();
1629   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
1630     Representation o_r = o->GetDetails(i).representation();
1631     Representation n_r = n->GetDetails(i).representation();
1632     if (!o_r.Equals(n_r)) {
1633       String::cast(o->GetKey(i))->PrintOn(file);
1634       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
1635     } else if (o->GetDetails(i).type() == CONSTANT &&
1636                n->GetDetails(i).type() == FIELD) {
1637       Name* name = o->GetKey(i);
1638       if (name->IsString()) {
1639         String::cast(name)->PrintOn(file);
1640       } else {
1641         PrintF(file, "{symbol %p}", static_cast<void*>(name));
1642       }
1643       PrintF(file, " ");
1644     }
1645   }
1646   PrintF(file, "\n");
1647 }
1648
1649
1650 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
1651   Heap* heap = GetHeap();
1652   if (!heap->Contains(this)) {
1653     accumulator->Add("!!!INVALID POINTER!!!");
1654     return;
1655   }
1656   if (!heap->Contains(map())) {
1657     accumulator->Add("!!!INVALID MAP!!!");
1658     return;
1659   }
1660
1661   accumulator->Add("%p ", this);
1662
1663   if (IsString()) {
1664     String::cast(this)->StringShortPrint(accumulator);
1665     return;
1666   }
1667   if (IsJSObject()) {
1668     JSObject::cast(this)->JSObjectShortPrint(accumulator);
1669     return;
1670   }
1671   switch (map()->instance_type()) {
1672     case MAP_TYPE:
1673       accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind());
1674       break;
1675     case FIXED_ARRAY_TYPE:
1676       accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
1677       break;
1678     case FIXED_DOUBLE_ARRAY_TYPE:
1679       accumulator->Add("<FixedDoubleArray[%u]>",
1680                        FixedDoubleArray::cast(this)->length());
1681       break;
1682     case BYTE_ARRAY_TYPE:
1683       accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
1684       break;
1685     case FREE_SPACE_TYPE:
1686       accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size());
1687       break;
1688 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                 \
1689     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
1690       accumulator->Add("<External" #Type "Array[%u]>",                         \
1691                        External##Type##Array::cast(this)->length());           \
1692       break;                                                                   \
1693     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
1694       accumulator->Add("<Fixed" #Type "Array[%u]>",                            \
1695                        Fixed##Type##Array::cast(this)->length());              \
1696       break;
1697
1698     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1699 #undef TYPED_ARRAY_SHORT_PRINT
1700
1701     case SHARED_FUNCTION_INFO_TYPE: {
1702       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
1703       SmartArrayPointer<char> debug_name =
1704           shared->DebugName()->ToCString();
1705       if (debug_name[0] != 0) {
1706         accumulator->Add("<SharedFunctionInfo %s>", debug_name.get());
1707       } else {
1708         accumulator->Add("<SharedFunctionInfo>");
1709       }
1710       break;
1711     }
1712     case JS_MESSAGE_OBJECT_TYPE:
1713       accumulator->Add("<JSMessageObject>");
1714       break;
1715 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1716   case NAME##_TYPE:                        \
1717     accumulator->Put('<');                 \
1718     accumulator->Add(#Name);               \
1719     accumulator->Put('>');                 \
1720     break;
1721   STRUCT_LIST(MAKE_STRUCT_CASE)
1722 #undef MAKE_STRUCT_CASE
1723     case CODE_TYPE:
1724       accumulator->Add("<Code>");
1725       break;
1726     case ODDBALL_TYPE: {
1727       if (IsUndefined())
1728         accumulator->Add("<undefined>");
1729       else if (IsTheHole())
1730         accumulator->Add("<the hole>");
1731       else if (IsNull())
1732         accumulator->Add("<null>");
1733       else if (IsTrue())
1734         accumulator->Add("<true>");
1735       else if (IsFalse())
1736         accumulator->Add("<false>");
1737       else
1738         accumulator->Add("<Odd Oddball>");
1739       break;
1740     }
1741     case SYMBOL_TYPE: {
1742       Symbol* symbol = Symbol::cast(this);
1743       accumulator->Add("<Symbol: %d", symbol->Hash());
1744       if (!symbol->name()->IsUndefined()) {
1745         accumulator->Add(" ");
1746         String::cast(symbol->name())->StringShortPrint(accumulator);
1747       }
1748       accumulator->Add(">");
1749       break;
1750     }
1751     case HEAP_NUMBER_TYPE:
1752       accumulator->Add("<Number: ");
1753       HeapNumber::cast(this)->HeapNumberPrint(accumulator);
1754       accumulator->Put('>');
1755       break;
1756     case FLOAT32x4_TYPE:
1757       accumulator->Add("<Float32x4: ");
1758       Float32x4::cast(this)->Float32x4Print(accumulator);
1759       accumulator->Put('>');
1760       break;
1761     case INT32x4_TYPE:
1762       accumulator->Add("<Int32x4: ");
1763       Int32x4::cast(this)->Int32x4Print(accumulator);
1764       accumulator->Put('>');
1765       break;
1766     case JS_PROXY_TYPE:
1767       accumulator->Add("<JSProxy>");
1768       break;
1769     case JS_FUNCTION_PROXY_TYPE:
1770       accumulator->Add("<JSFunctionProxy>");
1771       break;
1772     case FOREIGN_TYPE:
1773       accumulator->Add("<Foreign>");
1774       break;
1775     case CELL_TYPE:
1776       accumulator->Add("Cell for ");
1777       Cell::cast(this)->value()->ShortPrint(accumulator);
1778       break;
1779     case PROPERTY_CELL_TYPE:
1780       accumulator->Add("PropertyCell for ");
1781       PropertyCell::cast(this)->value()->ShortPrint(accumulator);
1782       break;
1783     default:
1784       accumulator->Add("<Other heap object (%d)>", map()->instance_type());
1785       break;
1786   }
1787 }
1788
1789
1790 void HeapObject::Iterate(ObjectVisitor* v) {
1791   // Handle header
1792   IteratePointer(v, kMapOffset);
1793   // Handle object body
1794   Map* m = map();
1795   IterateBody(m->instance_type(), SizeFromMap(m), v);
1796 }
1797
1798
1799 void HeapObject::IterateBody(InstanceType type, int object_size,
1800                              ObjectVisitor* v) {
1801   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1802   // During GC, the map pointer field is encoded.
1803   if (type < FIRST_NONSTRING_TYPE) {
1804     switch (type & kStringRepresentationMask) {
1805       case kSeqStringTag:
1806         break;
1807       case kConsStringTag:
1808         ConsString::BodyDescriptor::IterateBody(this, v);
1809         break;
1810       case kSlicedStringTag:
1811         SlicedString::BodyDescriptor::IterateBody(this, v);
1812         break;
1813       case kExternalStringTag:
1814         if ((type & kStringEncodingMask) == kOneByteStringTag) {
1815           reinterpret_cast<ExternalAsciiString*>(this)->
1816               ExternalAsciiStringIterateBody(v);
1817         } else {
1818           reinterpret_cast<ExternalTwoByteString*>(this)->
1819               ExternalTwoByteStringIterateBody(v);
1820         }
1821         break;
1822     }
1823     return;
1824   }
1825
1826   switch (type) {
1827     case FIXED_ARRAY_TYPE:
1828       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1829       break;
1830     case CONSTANT_POOL_ARRAY_TYPE:
1831       reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v);
1832       break;
1833     case FIXED_DOUBLE_ARRAY_TYPE:
1834       break;
1835     case JS_OBJECT_TYPE:
1836     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1837     case JS_GENERATOR_OBJECT_TYPE:
1838     case JS_MODULE_TYPE:
1839     case JS_VALUE_TYPE:
1840     case JS_DATE_TYPE:
1841     case JS_ARRAY_TYPE:
1842     case JS_ARRAY_BUFFER_TYPE:
1843     case JS_TYPED_ARRAY_TYPE:
1844     case JS_DATA_VIEW_TYPE:
1845     case JS_SET_TYPE:
1846     case JS_MAP_TYPE:
1847     case JS_WEAK_MAP_TYPE:
1848     case JS_WEAK_SET_TYPE:
1849     case JS_REGEXP_TYPE:
1850     case JS_GLOBAL_PROXY_TYPE:
1851     case JS_GLOBAL_OBJECT_TYPE:
1852     case JS_BUILTINS_OBJECT_TYPE:
1853     case JS_MESSAGE_OBJECT_TYPE:
1854       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1855       break;
1856     case JS_FUNCTION_TYPE:
1857       reinterpret_cast<JSFunction*>(this)
1858           ->JSFunctionIterateBody(object_size, v);
1859       break;
1860     case ODDBALL_TYPE:
1861       Oddball::BodyDescriptor::IterateBody(this, v);
1862       break;
1863     case JS_PROXY_TYPE:
1864       JSProxy::BodyDescriptor::IterateBody(this, v);
1865       break;
1866     case JS_FUNCTION_PROXY_TYPE:
1867       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1868       break;
1869     case FOREIGN_TYPE:
1870       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1871       break;
1872     case MAP_TYPE:
1873       Map::BodyDescriptor::IterateBody(this, v);
1874       break;
1875     case CODE_TYPE:
1876       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1877       break;
1878     case CELL_TYPE:
1879       Cell::BodyDescriptor::IterateBody(this, v);
1880       break;
1881     case PROPERTY_CELL_TYPE:
1882       PropertyCell::BodyDescriptor::IterateBody(this, v);
1883       break;
1884     case SYMBOL_TYPE:
1885       Symbol::BodyDescriptor::IterateBody(this, v);
1886       break;
1887
1888     case HEAP_NUMBER_TYPE:
1889     case FLOAT32x4_TYPE:
1890     case INT32x4_TYPE:
1891     case FILLER_TYPE:
1892     case BYTE_ARRAY_TYPE:
1893     case FREE_SPACE_TYPE:
1894       break;
1895
1896 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
1897     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
1898     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
1899       break;
1900
1901     TYPED_ARRAYS(TYPED_ARRAY_CASE)
1902 #undef TYPED_ARRAY_CASE
1903
1904     case SHARED_FUNCTION_INFO_TYPE: {
1905       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1906       break;
1907     }
1908
1909 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1910         case NAME##_TYPE:
1911       STRUCT_LIST(MAKE_STRUCT_CASE)
1912 #undef MAKE_STRUCT_CASE
1913       if (type == ALLOCATION_SITE_TYPE) {
1914         AllocationSite::BodyDescriptor::IterateBody(this, v);
1915       } else {
1916         StructBodyDescriptor::IterateBody(this, object_size, v);
1917       }
1918       break;
1919     default:
1920       PrintF("Unknown type: %d\n", type);
1921       UNREACHABLE();
1922   }
1923 }
1924
1925
1926 bool HeapNumber::HeapNumberBooleanValue() {
1927   // NaN, +0, and -0 should return the false object
1928 #if __BYTE_ORDER == __LITTLE_ENDIAN
1929   union IeeeDoubleLittleEndianArchType u;
1930 #elif __BYTE_ORDER == __BIG_ENDIAN
1931   union IeeeDoubleBigEndianArchType u;
1932 #endif
1933   u.d = value();
1934   if (u.bits.exp == 2047) {
1935     // Detect NaN for IEEE double precision floating point.
1936     if ((u.bits.man_low | u.bits.man_high) != 0) return false;
1937   }
1938   if (u.bits.exp == 0) {
1939     // Detect +0, and -0 for IEEE double precision floating point.
1940     if ((u.bits.man_low | u.bits.man_high) == 0) return false;
1941   }
1942   return true;
1943 }
1944
1945
1946 void HeapNumber::HeapNumberPrint(FILE* out) {
1947   PrintF(out, "%.16g", Number());
1948 }
1949
1950
1951 void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
1952   // The Windows version of vsnprintf can allocate when printing a %g string
1953   // into a buffer that may not be big enough.  We don't want random memory
1954   // allocation when producing post-crash stack traces, so we print into a
1955   // buffer that is plenty big enough for any floating point number, then
1956   // print that using vsnprintf (which may truncate but never allocate if
1957   // there is no more space in the buffer).
1958   EmbeddedVector<char, 100> buffer;
1959   OS::SNPrintF(buffer, "%.16g", Number());
1960   accumulator->Add("%s", buffer.start());
1961 }
1962
1963
1964 void Float32x4::Float32x4Print(FILE* out) {
1965   PrintF(out, "%.16g %.16g %.16g %.16g", x(), y(), z(), w());
1966 }
1967
1968
1969 void Float32x4::Float32x4Print(StringStream* accumulator) {
1970   // The Windows version of vsnprintf can allocate when printing a %g string
1971   // into a buffer that may not be big enough.  We don't want random memory
1972   // allocation when producing post-crash stack traces, so we print into a
1973   // buffer that is plenty big enough for any floating point number, then
1974   // print that using vsnprintf (which may truncate but never allocate if
1975   // there is no more space in the buffer).
1976   EmbeddedVector<char, 100> buffer;
1977   OS::SNPrintF(buffer, "%.16g %.16g %.16g %.16g", x(), y(), z(), w());
1978   accumulator->Add("%s", buffer.start());
1979 }
1980
1981
1982 void Int32x4::Int32x4Print(FILE* out) {
1983   PrintF(out, "%u %u %u %u", x(), y(), z(), w());
1984 }
1985
1986
1987 void Int32x4::Int32x4Print(StringStream* accumulator) {
1988   // The Windows version of vsnprintf can allocate when printing a %g string
1989   // into a buffer that may not be big enough.  We don't want random memory
1990   // allocation when producing post-crash stack traces, so we print into a
1991   // buffer that is plenty big enough for any floating point number, then
1992   // print that using vsnprintf (which may truncate but never allocate if
1993   // there is no more space in the buffer).
1994   EmbeddedVector<char, 100> buffer;
1995   OS::SNPrintF(buffer, "%u %u %u %u", x(), y(), z(), w());
1996   accumulator->Add("%s", buffer.start());
1997 }
1998
1999
2000 String* JSReceiver::class_name() {
2001   if (IsJSFunction() && IsJSFunctionProxy()) {
2002     return GetHeap()->function_class_string();
2003   }
2004   if (map()->constructor()->IsJSFunction()) {
2005     JSFunction* constructor = JSFunction::cast(map()->constructor());
2006     return String::cast(constructor->shared()->instance_class_name());
2007   }
2008   // If the constructor is not present, return "Object".
2009   return GetHeap()->Object_string();
2010 }
2011
2012
2013 String* Map::constructor_name() {
2014   if (constructor()->IsJSFunction()) {
2015     JSFunction* constructor = JSFunction::cast(this->constructor());
2016     String* name = String::cast(constructor->shared()->name());
2017     if (name->length() > 0) return name;
2018     String* inferred_name = constructor->shared()->inferred_name();
2019     if (inferred_name->length() > 0) return inferred_name;
2020     Object* proto = prototype();
2021     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
2022   }
2023   // TODO(rossberg): what about proxies?
2024   // If the constructor is not present, return "Object".
2025   return GetHeap()->Object_string();
2026 }
2027
2028
2029 String* JSReceiver::constructor_name() {
2030   return map()->constructor_name();
2031 }
2032
2033
2034 // TODO(mstarzinger): Temporary wrapper until handlified.
2035 static Handle<Object> NewStorageFor(Isolate* isolate,
2036                                     Handle<Object> object,
2037                                     Representation representation) {
2038   Heap* heap = isolate->heap();
2039   CALL_HEAP_FUNCTION(isolate,
2040                      object->AllocateNewStorageFor(heap, representation),
2041                      Object);
2042 }
2043
2044
2045 static MaybeObject* CopyAddFieldDescriptor(Map* map,
2046                                            Name* name,
2047                                            int index,
2048                                            PropertyAttributes attributes,
2049                                            Representation representation,
2050                                            TransitionFlag flag) {
2051   Map* new_map;
2052   FieldDescriptor new_field_desc(name, index, attributes, representation);
2053   MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag);
2054   if (!maybe_map->To(&new_map)) return maybe_map;
2055   int unused_property_fields = map->unused_property_fields() - 1;
2056   if (unused_property_fields < 0) {
2057     unused_property_fields += JSObject::kFieldsAdded;
2058   }
2059   new_map->set_unused_property_fields(unused_property_fields);
2060   return new_map;
2061 }
2062
2063
2064 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map,
2065                                           Handle<Name> name,
2066                                           int index,
2067                                           PropertyAttributes attributes,
2068                                           Representation representation,
2069                                           TransitionFlag flag) {
2070   CALL_HEAP_FUNCTION(map->GetIsolate(),
2071                      CopyAddFieldDescriptor(
2072                          *map, *name, index, attributes, representation, flag),
2073                      Map);
2074 }
2075
2076
2077 void JSObject::AddFastProperty(Handle<JSObject> object,
2078                                Handle<Name> name,
2079                                Handle<Object> value,
2080                                PropertyAttributes attributes,
2081                                StoreFromKeyed store_mode,
2082                                ValueType value_type,
2083                                TransitionFlag flag) {
2084   ASSERT(!object->IsJSGlobalProxy());
2085   ASSERT(DescriptorArray::kNotFound ==
2086          object->map()->instance_descriptors()->Search(
2087              *name, object->map()->NumberOfOwnDescriptors()));
2088
2089   // Normalize the object if the name is an actual name (not the
2090   // hidden strings) and is not a real identifier.
2091   // Normalize the object if it will have too many fast properties.
2092   Isolate* isolate = object->GetIsolate();
2093   if (!name->IsCacheable(isolate) ||
2094       object->TooManyFastProperties(store_mode)) {
2095     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
2096     AddSlowProperty(object, name, value, attributes);
2097     return;
2098   }
2099
2100   // Compute the new index for new field.
2101   int index = object->map()->NextFreePropertyIndex();
2102
2103   // Allocate new instance descriptors with (name, index) added
2104   if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
2105   Representation representation = value->OptimalRepresentation(value_type);
2106   Handle<Map> new_map = CopyAddFieldDescriptor(
2107       handle(object->map()), name, index, attributes, representation, flag);
2108
2109   JSObject::MigrateToMap(object, new_map);
2110
2111   if (representation.IsDouble()) {
2112     // Nothing more to be done.
2113     if (value->IsUninitialized()) return;
2114     HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index));
2115     box->set_value(value->Number());
2116   } else {
2117     object->FastPropertyAtPut(index, *value);
2118   }
2119 }
2120
2121
2122 static MaybeObject* CopyAddConstantDescriptor(Map* map,
2123                                               Name* name,
2124                                               Object* value,
2125                                               PropertyAttributes attributes,
2126                                               TransitionFlag flag) {
2127   ConstantDescriptor new_constant_desc(name, value, attributes);
2128   return map->CopyAddDescriptor(&new_constant_desc, flag);
2129 }
2130
2131
2132 static Handle<Map> CopyAddConstantDescriptor(Handle<Map> map,
2133                                              Handle<Name> name,
2134                                              Handle<Object> value,
2135                                              PropertyAttributes attributes,
2136                                              TransitionFlag flag) {
2137   CALL_HEAP_FUNCTION(map->GetIsolate(),
2138                      CopyAddConstantDescriptor(
2139                          *map, *name, *value, attributes, flag),
2140                      Map);
2141 }
2142
2143
2144 void JSObject::AddConstantProperty(Handle<JSObject> object,
2145                                    Handle<Name> name,
2146                                    Handle<Object> constant,
2147                                    PropertyAttributes attributes,
2148                                    TransitionFlag initial_flag) {
2149   TransitionFlag flag =
2150       // Do not add transitions to global objects.
2151       (object->IsGlobalObject() ||
2152       // Don't add transitions to special properties with non-trivial
2153       // attributes.
2154        attributes != NONE)
2155       ? OMIT_TRANSITION
2156       : initial_flag;
2157
2158   // Allocate new instance descriptors with (name, constant) added.
2159   Handle<Map> new_map = CopyAddConstantDescriptor(
2160       handle(object->map()), name, constant, attributes, flag);
2161
2162   JSObject::MigrateToMap(object, new_map);
2163 }
2164
2165
2166 void JSObject::AddSlowProperty(Handle<JSObject> object,
2167                                Handle<Name> name,
2168                                Handle<Object> value,
2169                                PropertyAttributes attributes) {
2170   ASSERT(!object->HasFastProperties());
2171   Isolate* isolate = object->GetIsolate();
2172   Handle<NameDictionary> dict(object->property_dictionary());
2173   if (object->IsGlobalObject()) {
2174     // In case name is an orphaned property reuse the cell.
2175     int entry = dict->FindEntry(*name);
2176     if (entry != NameDictionary::kNotFound) {
2177       Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry)));
2178       PropertyCell::SetValueInferType(cell, value);
2179       // Assign an enumeration index to the property and update
2180       // SetNextEnumerationIndex.
2181       int index = dict->NextEnumerationIndex();
2182       PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
2183       dict->SetNextEnumerationIndex(index + 1);
2184       dict->SetEntry(entry, *name, *cell, details);
2185       return;
2186     }
2187     Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value);
2188     PropertyCell::SetValueInferType(cell, value);
2189     value = cell;
2190   }
2191   PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
2192   Handle<NameDictionary> result = NameDictionaryAdd(dict, name, value, details);
2193   if (*dict != *result) object->set_properties(*result);
2194 }
2195
2196
2197 Handle<Object> JSObject::AddProperty(Handle<JSObject> object,
2198                                      Handle<Name> name,
2199                                      Handle<Object> value,
2200                                      PropertyAttributes attributes,
2201                                      StrictMode strict_mode,
2202                                      JSReceiver::StoreFromKeyed store_mode,
2203                                      ExtensibilityCheck extensibility_check,
2204                                      ValueType value_type,
2205                                      StoreMode mode,
2206                                      TransitionFlag transition_flag) {
2207   ASSERT(!object->IsJSGlobalProxy());
2208   Isolate* isolate = object->GetIsolate();
2209
2210   if (!name->IsUniqueName()) {
2211     name = isolate->factory()->InternalizeString(
2212         Handle<String>::cast(name));
2213   }
2214
2215   if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
2216       !object->map()->is_extensible()) {
2217     if (strict_mode == SLOPPY) {
2218       return value;
2219     } else {
2220       Handle<Object> args[1] = { name };
2221       Handle<Object> error = isolate->factory()->NewTypeError(
2222           "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
2223       isolate->Throw(*error);
2224       return Handle<Object>();
2225     }
2226   }
2227
2228   if (object->HasFastProperties()) {
2229     // Ensure the descriptor array does not get too big.
2230     if (object->map()->NumberOfOwnDescriptors() <= kMaxNumberOfDescriptors) {
2231       // TODO(verwaest): Support other constants.
2232       // if (mode == ALLOW_AS_CONSTANT &&
2233       //     !value->IsTheHole() &&
2234       //     !value->IsConsString()) {
2235       if (value->IsJSFunction()) {
2236         AddConstantProperty(object, name, value, attributes, transition_flag);
2237       } else {
2238         AddFastProperty(object, name, value, attributes, store_mode,
2239                         value_type, transition_flag);
2240       }
2241     } else {
2242       // Normalize the object to prevent very large instance descriptors.
2243       // This eliminates unwanted N^2 allocation and lookup behavior.
2244       NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
2245       AddSlowProperty(object, name, value, attributes);
2246     }
2247   } else {
2248     AddSlowProperty(object, name, value, attributes);
2249   }
2250
2251   if (object->map()->is_observed() &&
2252       *name != isolate->heap()->hidden_string()) {
2253     Handle<Object> old_value = isolate->factory()->the_hole_value();
2254     EnqueueChangeRecord(object, "add", name, old_value);
2255   }
2256
2257   return value;
2258 }
2259
2260
2261 void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
2262                                    const char* type_str,
2263                                    Handle<Name> name,
2264                                    Handle<Object> old_value) {
2265   Isolate* isolate = object->GetIsolate();
2266   HandleScope scope(isolate);
2267   Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
2268   if (object->IsJSGlobalObject()) {
2269     object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate);
2270   }
2271   Handle<Object> args[] = { type, object, name, old_value };
2272   int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
2273   bool threw;
2274
2275   Execution::Call(isolate,
2276                   Handle<JSFunction>(isolate->observers_notify_change()),
2277                   isolate->factory()->undefined_value(),
2278                   argc, args,
2279                   &threw);
2280   ASSERT(!threw);
2281 }
2282
2283
2284 Handle<Object> JSObject::SetPropertyPostInterceptor(
2285     Handle<JSObject> object,
2286     Handle<Name> name,
2287     Handle<Object> value,
2288     PropertyAttributes attributes,
2289     StrictMode strict_mode) {
2290   // Check local property, ignore interceptor.
2291   LookupResult result(object->GetIsolate());
2292   object->LocalLookupRealNamedProperty(*name, &result);
2293   if (!result.IsFound()) {
2294     object->map()->LookupTransition(*object, *name, &result);
2295   }
2296   if (result.IsFound()) {
2297     // An existing property or a map transition was found. Use set property to
2298     // handle all these cases.
2299     return SetPropertyForResult(object, &result, name, value, attributes,
2300                                 strict_mode, MAY_BE_STORE_FROM_KEYED);
2301   }
2302   bool done = false;
2303   Handle<Object> result_object = SetPropertyViaPrototypes(
2304       object, name, value, attributes, strict_mode, &done);
2305   if (done) return result_object;
2306   // Add a new real property.
2307   return AddProperty(object, name, value, attributes, strict_mode);
2308 }
2309
2310
2311 static void ReplaceSlowProperty(Handle<JSObject> object,
2312                                 Handle<Name> name,
2313                                 Handle<Object> value,
2314                                 PropertyAttributes attributes) {
2315   NameDictionary* dictionary = object->property_dictionary();
2316   int old_index = dictionary->FindEntry(*name);
2317   int new_enumeration_index = 0;  // 0 means "Use the next available index."
2318   if (old_index != -1) {
2319     // All calls to ReplaceSlowProperty have had all transitions removed.
2320     new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index();
2321   }
2322
2323   PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
2324   JSObject::SetNormalizedProperty(object, name, value, new_details);
2325 }
2326
2327
2328 const char* Representation::Mnemonic() const {
2329   switch (kind_) {
2330     case kNone: return "v";
2331     case kTagged: return "t";
2332     case kSmi: return "s";
2333     case kDouble: return "d";
2334     case kFloat32x4: return "float32x4";
2335     case kInt32x4: return "int32x44";
2336     case kInteger32: return "i";
2337     case kHeapObject: return "h";
2338     case kExternal: return "x";
2339     default:
2340       UNREACHABLE();
2341       return NULL;
2342   }
2343 }
2344
2345
2346 static void ZapEndOfFixedArray(Address new_end, int to_trim) {
2347   // If we are doing a big trim in old space then we zap the space.
2348   Object** zap = reinterpret_cast<Object**>(new_end);
2349   zap++;  // Header of filler must be at least one word so skip that.
2350   for (int i = 1; i < to_trim; i++) {
2351     *zap++ = Smi::FromInt(0);
2352   }
2353 }
2354
2355
2356 template<Heap::InvocationMode mode>
2357 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
2358   ASSERT(elms->map() != heap->fixed_cow_array_map());
2359   // For now this trick is only applied to fixed arrays in new and paged space.
2360   ASSERT(!heap->lo_space()->Contains(elms));
2361
2362   const int len = elms->length();
2363
2364   ASSERT(to_trim < len);
2365
2366   Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
2367
2368   if (mode != Heap::FROM_GC || Heap::ShouldZapGarbage()) {
2369     ZapEndOfFixedArray(new_end, to_trim);
2370   }
2371
2372   int size_delta = to_trim * kPointerSize;
2373
2374   // Technically in new space this write might be omitted (except for
2375   // debug mode which iterates through the heap), but to play safer
2376   // we still do it.
2377   heap->CreateFillerObjectAt(new_end, size_delta);
2378
2379   elms->set_length(len - to_trim);
2380
2381   heap->AdjustLiveBytes(elms->address(), -size_delta, mode);
2382
2383   // The array may not be moved during GC,
2384   // and size has to be adjusted nevertheless.
2385   HeapProfiler* profiler = heap->isolate()->heap_profiler();
2386   if (profiler->is_tracking_allocations()) {
2387     profiler->UpdateObjectSizeEvent(elms->address(), elms->Size());
2388   }
2389 }
2390
2391
2392 bool Map::InstancesNeedRewriting(Map* target,
2393                                  int target_number_of_fields,
2394                                  int target_inobject,
2395                                  int target_unused) {
2396   // If fields were added (or removed), rewrite the instance.
2397   int number_of_fields = NumberOfFields();
2398   ASSERT(target_number_of_fields >= number_of_fields);
2399   if (target_number_of_fields != number_of_fields) return true;
2400
2401   // If smi descriptors were replaced by double descriptors, rewrite.
2402   DescriptorArray* old_desc = instance_descriptors();
2403   DescriptorArray* new_desc = target->instance_descriptors();
2404   int limit = NumberOfOwnDescriptors();
2405   for (int i = 0; i < limit; i++) {
2406     if (new_desc->GetDetails(i).representation().IsDouble() &&
2407         !old_desc->GetDetails(i).representation().IsDouble()) {
2408       return true;
2409     }
2410   }
2411
2412   // If no fields were added, and no inobject properties were removed, setting
2413   // the map is sufficient.
2414   if (target_inobject == inobject_properties()) return false;
2415   // In-object slack tracking may have reduced the object size of the new map.
2416   // In that case, succeed if all existing fields were inobject, and they still
2417   // fit within the new inobject size.
2418   ASSERT(target_inobject < inobject_properties());
2419   if (target_number_of_fields <= target_inobject) {
2420     ASSERT(target_number_of_fields + target_unused == target_inobject);
2421     return false;
2422   }
2423   // Otherwise, properties will need to be moved to the backing store.
2424   return true;
2425 }
2426
2427
2428 // To migrate an instance to a map:
2429 // - First check whether the instance needs to be rewritten. If not, simply
2430 //   change the map.
2431 // - Otherwise, allocate a fixed array large enough to hold all fields, in
2432 //   addition to unused space.
2433 // - Copy all existing properties in, in the following order: backing store
2434 //   properties, unused fields, inobject properties.
2435 // - If all allocation succeeded, commit the state atomically:
2436 //   * Copy inobject properties from the backing store back into the object.
2437 //   * Trim the difference in instance size of the object. This also cleanly
2438 //     frees inobject properties that moved to the backing store.
2439 //   * If there are properties left in the backing store, trim of the space used
2440 //     to temporarily store the inobject properties.
2441 //   * If there are properties left in the backing store, install the backing
2442 //     store.
2443 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
2444   Isolate* isolate = object->GetIsolate();
2445   Handle<Map> old_map(object->map());
2446   int number_of_fields = new_map->NumberOfFields();
2447   int inobject = new_map->inobject_properties();
2448   int unused = new_map->unused_property_fields();
2449
2450   // Nothing to do if no functions were converted to fields and no smis were
2451   // converted to doubles.
2452   if (!old_map->InstancesNeedRewriting(
2453           *new_map, number_of_fields, inobject, unused)) {
2454     object->set_map(*new_map);
2455     return;
2456   }
2457
2458   int total_size = number_of_fields + unused;
2459   int external = total_size - inobject;
2460   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
2461
2462   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
2463   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
2464   int old_nof = old_map->NumberOfOwnDescriptors();
2465   int new_nof = new_map->NumberOfOwnDescriptors();
2466
2467   // This method only supports generalizing instances to at least the same
2468   // number of properties.
2469   ASSERT(old_nof <= new_nof);
2470
2471   for (int i = 0; i < old_nof; i++) {
2472     PropertyDetails details = new_descriptors->GetDetails(i);
2473     if (details.type() != FIELD) continue;
2474     PropertyDetails old_details = old_descriptors->GetDetails(i);
2475     if (old_details.type() == CALLBACKS) {
2476       ASSERT(details.representation().IsTagged());
2477       continue;
2478     }
2479     ASSERT(old_details.type() == CONSTANT ||
2480            old_details.type() == FIELD);
2481     Object* raw_value = old_details.type() == CONSTANT
2482         ? old_descriptors->GetValue(i)
2483         : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
2484     Handle<Object> value(raw_value, isolate);
2485     if (!old_details.representation().IsDouble() &&
2486         details.representation().IsDouble()) {
2487       if (old_details.representation().IsNone()) {
2488         value = handle(Smi::FromInt(0), isolate);
2489       }
2490       value = NewStorageFor(isolate, value, details.representation());
2491     }
2492     ASSERT(!(details.representation().IsDouble() && value->IsSmi()));
2493     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2494     if (target_index < 0) target_index += total_size;
2495     array->set(target_index, *value);
2496   }
2497
2498   for (int i = old_nof; i < new_nof; i++) {
2499     PropertyDetails details = new_descriptors->GetDetails(i);
2500     if (details.type() != FIELD) continue;
2501     if (details.representation().IsDouble()) {
2502       int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2503       if (target_index < 0) target_index += total_size;
2504       Handle<Object> box = isolate->factory()->NewHeapNumber(0);
2505       array->set(target_index, *box);
2506     }
2507   }
2508
2509   // From here on we cannot fail and we shouldn't GC anymore.
2510   DisallowHeapAllocation no_allocation;
2511
2512   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2513   // avoid overwriting |one_pointer_filler_map|.
2514   int limit = Min(inobject, number_of_fields);
2515   for (int i = 0; i < limit; i++) {
2516     object->FastPropertyAtPut(i, array->get(external + i));
2517   }
2518
2519   // Create filler object past the new instance size.
2520   int new_instance_size = new_map->instance_size();
2521   int instance_size_delta = old_map->instance_size() - new_instance_size;
2522   ASSERT(instance_size_delta >= 0);
2523   Address address = object->address() + new_instance_size;
2524   isolate->heap()->CreateFillerObjectAt(address, instance_size_delta);
2525
2526   // If there are properties in the new backing store, trim it to the correct
2527   // size and install the backing store into the object.
2528   if (external > 0) {
2529     RightTrimFixedArray<Heap::FROM_MUTATOR>(isolate->heap(), *array, inobject);
2530     object->set_properties(*array);
2531   }
2532
2533   object->set_map(*new_map);
2534 }
2535
2536
2537 Handle<TransitionArray> Map::AddTransition(Handle<Map> map,
2538                                            Handle<Name> key,
2539                                            Handle<Map> target,
2540                                            SimpleTransitionFlag flag) {
2541   CALL_HEAP_FUNCTION(map->GetIsolate(),
2542                      map->AddTransition(*key, *target, flag),
2543                      TransitionArray);
2544 }
2545
2546
2547 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object,
2548                                              int modify_index,
2549                                              Representation new_representation,
2550                                              StoreMode store_mode) {
2551   Handle<Map> new_map = Map::GeneralizeRepresentation(
2552       handle(object->map()), modify_index, new_representation, store_mode);
2553   if (object->map() == *new_map) return;
2554   return MigrateToMap(object, new_map);
2555 }
2556
2557
2558 int Map::NumberOfFields() {
2559   DescriptorArray* descriptors = instance_descriptors();
2560   int result = 0;
2561   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2562     if (descriptors->GetDetails(i).type() == FIELD) result++;
2563   }
2564   return result;
2565 }
2566
2567
2568 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
2569                                                   int modify_index,
2570                                                   StoreMode store_mode,
2571                                                   PropertyAttributes attributes,
2572                                                   const char* reason) {
2573   Handle<Map> new_map = Copy(map);
2574
2575   DescriptorArray* descriptors = new_map->instance_descriptors();
2576   descriptors->InitializeRepresentations(Representation::Tagged());
2577
2578   // Unless the instance is being migrated, ensure that modify_index is a field.
2579   PropertyDetails details = descriptors->GetDetails(modify_index);
2580   if (store_mode == FORCE_FIELD && details.type() != FIELD) {
2581     FieldDescriptor d(descriptors->GetKey(modify_index),
2582                       new_map->NumberOfFields(),
2583                       attributes,
2584                       Representation::Tagged());
2585     d.SetSortedKeyIndex(details.pointer());
2586     descriptors->Set(modify_index, &d);
2587     int unused_property_fields = new_map->unused_property_fields() - 1;
2588     if (unused_property_fields < 0) {
2589       unused_property_fields += JSObject::kFieldsAdded;
2590     }
2591     new_map->set_unused_property_fields(unused_property_fields);
2592   }
2593
2594   if (FLAG_trace_generalization) {
2595     map->PrintGeneralization(stdout, reason, modify_index,
2596                         new_map->NumberOfOwnDescriptors(),
2597                         new_map->NumberOfOwnDescriptors(),
2598                         details.type() == CONSTANT && store_mode == FORCE_FIELD,
2599                         Representation::Tagged(), Representation::Tagged());
2600   }
2601   return new_map;
2602 }
2603
2604
2605 void Map::DeprecateTransitionTree() {
2606   if (is_deprecated()) return;
2607   if (HasTransitionArray()) {
2608     TransitionArray* transitions = this->transitions();
2609     for (int i = 0; i < transitions->number_of_transitions(); i++) {
2610       transitions->GetTarget(i)->DeprecateTransitionTree();
2611     }
2612   }
2613   deprecate();
2614   dependent_code()->DeoptimizeDependentCodeGroup(
2615       GetIsolate(), DependentCode::kTransitionGroup);
2616   NotifyLeafMapLayoutChange();
2617 }
2618
2619
2620 // Invalidates a transition target at |key|, and installs |new_descriptors| over
2621 // the current instance_descriptors to ensure proper sharing of descriptor
2622 // arrays.
2623 void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors) {
2624   if (HasTransitionArray()) {
2625     TransitionArray* transitions = this->transitions();
2626     int transition = transitions->Search(key);
2627     if (transition != TransitionArray::kNotFound) {
2628       transitions->GetTarget(transition)->DeprecateTransitionTree();
2629     }
2630   }
2631
2632   // Don't overwrite the empty descriptor array.
2633   if (NumberOfOwnDescriptors() == 0) return;
2634
2635   DescriptorArray* to_replace = instance_descriptors();
2636   Map* current = this;
2637   GetHeap()->incremental_marking()->RecordWrites(to_replace);
2638   while (current->instance_descriptors() == to_replace) {
2639     current->SetEnumLength(kInvalidEnumCacheSentinel);
2640     current->set_instance_descriptors(new_descriptors);
2641     Object* next = current->GetBackPointer();
2642     if (next->IsUndefined()) break;
2643     current = Map::cast(next);
2644   }
2645
2646   set_owns_descriptors(false);
2647 }
2648
2649
2650 Map* Map::FindRootMap() {
2651   Map* result = this;
2652   while (true) {
2653     Object* back = result->GetBackPointer();
2654     if (back->IsUndefined()) return result;
2655     result = Map::cast(back);
2656   }
2657 }
2658
2659
2660 // Returns NULL if the updated map is incompatible.
2661 Map* Map::FindUpdatedMap(int verbatim,
2662                          int length,
2663                          DescriptorArray* descriptors) {
2664   // This can only be called on roots of transition trees.
2665   ASSERT(GetBackPointer()->IsUndefined());
2666
2667   Map* current = this;
2668
2669   for (int i = verbatim; i < length; i++) {
2670     if (!current->HasTransitionArray()) break;
2671     Name* name = descriptors->GetKey(i);
2672     TransitionArray* transitions = current->transitions();
2673     int transition = transitions->Search(name);
2674     if (transition == TransitionArray::kNotFound) break;
2675     current = transitions->GetTarget(transition);
2676     PropertyDetails details = descriptors->GetDetails(i);
2677     PropertyDetails target_details =
2678         current->instance_descriptors()->GetDetails(i);
2679     if (details.attributes() != target_details.attributes()) return NULL;
2680     if (details.type() == CALLBACKS) {
2681       if (target_details.type() != CALLBACKS) return NULL;
2682       if (descriptors->GetValue(i) !=
2683               current->instance_descriptors()->GetValue(i)) {
2684         return NULL;
2685       }
2686     } else if (target_details.type() == CALLBACKS) {
2687       return NULL;
2688     }
2689   }
2690
2691   return current;
2692 }
2693
2694
2695 Map* Map::FindLastMatchMap(int verbatim,
2696                            int length,
2697                            DescriptorArray* descriptors) {
2698   // This can only be called on roots of transition trees.
2699   ASSERT(GetBackPointer()->IsUndefined());
2700
2701   Map* current = this;
2702
2703   for (int i = verbatim; i < length; i++) {
2704     if (!current->HasTransitionArray()) break;
2705     Name* name = descriptors->GetKey(i);
2706     TransitionArray* transitions = current->transitions();
2707     int transition = transitions->Search(name);
2708     if (transition == TransitionArray::kNotFound) break;
2709
2710     Map* next = transitions->GetTarget(transition);
2711     DescriptorArray* next_descriptors = next->instance_descriptors();
2712
2713     if (next_descriptors->GetValue(i) != descriptors->GetValue(i)) break;
2714
2715     PropertyDetails details = descriptors->GetDetails(i);
2716     PropertyDetails next_details = next_descriptors->GetDetails(i);
2717     if (details.type() != next_details.type()) break;
2718     if (details.attributes() != next_details.attributes()) break;
2719     if (!details.representation().Equals(next_details.representation())) break;
2720
2721     current = next;
2722   }
2723   return current;
2724 }
2725
2726
2727 // Generalize the representation of the descriptor at |modify_index|.
2728 // This method rewrites the transition tree to reflect the new change. To avoid
2729 // high degrees over polymorphism, and to stabilize quickly, on every rewrite
2730 // the new type is deduced by merging the current type with any potential new
2731 // (partial) version of the type in the transition tree.
2732 // To do this, on each rewrite:
2733 // - Search the root of the transition tree using FindRootMap.
2734 // - Find |updated|, the newest matching version of this map using
2735 //   FindUpdatedMap. This uses the keys in the own map's descriptor array to
2736 //   walk the transition tree.
2737 // - Merge/generalize the descriptor array of the current map and |updated|.
2738 // - Generalize the |modify_index| descriptor using |new_representation|.
2739 // - Walk the tree again starting from the root towards |updated|. Stop at
2740 //   |split_map|, the first map who's descriptor array does not match the merged
2741 //   descriptor array.
2742 // - If |updated| == |split_map|, |updated| is in the expected state. Return it.
2743 // - Otherwise, invalidate the outdated transition target from |updated|, and
2744 //   replace its transition tree with a new branch for the updated descriptors.
2745 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
2746                                           int modify_index,
2747                                           Representation new_representation,
2748                                           StoreMode store_mode) {
2749   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
2750   PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2751   Representation old_representation = old_details.representation();
2752
2753   // It's fine to transition from None to anything but double without any
2754   // modification to the object, because the default uninitialized value for
2755   // representation None can be overwritten by both smi and tagged values.
2756   // Doubles, however, would require a box allocation.
2757   if (old_representation.IsNone() &&
2758       !new_representation.IsNone() &&
2759       !new_representation.IsDouble()) {
2760     old_descriptors->SetRepresentation(modify_index, new_representation);
2761     return old_map;
2762   }
2763
2764   int descriptors = old_map->NumberOfOwnDescriptors();
2765   Handle<Map> root_map(old_map->FindRootMap());
2766
2767   // Check the state of the root map.
2768   if (!old_map->EquivalentToForTransition(*root_map)) {
2769     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2770         old_details.attributes(), "not equivalent");
2771   }
2772
2773   int verbatim = root_map->NumberOfOwnDescriptors();
2774
2775   if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) {
2776     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2777         old_details.attributes(), "root modification");
2778   }
2779
2780   Map* raw_updated = root_map->FindUpdatedMap(
2781       verbatim, descriptors, *old_descriptors);
2782   if (raw_updated == NULL) {
2783     return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
2784         old_details.attributes(), "incompatible");
2785   }
2786
2787   Handle<Map> updated(raw_updated);
2788   Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors());
2789
2790   int valid = updated->NumberOfOwnDescriptors();
2791
2792   // Directly change the map if the target map is more general. Ensure that the
2793   // target type of the modify_index is a FIELD, unless we are migrating.
2794   if (updated_descriptors->IsMoreGeneralThan(
2795           verbatim, valid, descriptors, *old_descriptors) &&
2796       (store_mode == ALLOW_AS_CONSTANT ||
2797        updated_descriptors->GetDetails(modify_index).type() == FIELD)) {
2798     Representation updated_representation =
2799         updated_descriptors->GetDetails(modify_index).representation();
2800     if (new_representation.fits_into(updated_representation)) return updated;
2801   }
2802
2803   Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge(
2804       updated_descriptors, verbatim, valid, descriptors, modify_index,
2805       store_mode, old_descriptors);
2806   ASSERT(store_mode == ALLOW_AS_CONSTANT ||
2807          new_descriptors->GetDetails(modify_index).type() == FIELD);
2808
2809   old_representation =
2810       new_descriptors->GetDetails(modify_index).representation();
2811   Representation updated_representation =
2812       new_representation.generalize(old_representation);
2813   if (!updated_representation.Equals(old_representation)) {
2814     new_descriptors->SetRepresentation(modify_index, updated_representation);
2815   }
2816
2817   Handle<Map> split_map(root_map->FindLastMatchMap(
2818       verbatim, descriptors, *new_descriptors));
2819
2820   int split_descriptors = split_map->NumberOfOwnDescriptors();
2821   // This is shadowed by |updated_descriptors| being more general than
2822   // |old_descriptors|.
2823   ASSERT(descriptors != split_descriptors);
2824
2825   int descriptor = split_descriptors;
2826   split_map->DeprecateTarget(
2827       old_descriptors->GetKey(descriptor), *new_descriptors);
2828
2829   if (FLAG_trace_generalization) {
2830     old_map->PrintGeneralization(
2831         stdout, "", modify_index, descriptor, descriptors,
2832         old_descriptors->GetDetails(modify_index).type() == CONSTANT &&
2833             store_mode == FORCE_FIELD,
2834         old_representation, updated_representation);
2835   }
2836
2837   // Add missing transitions.
2838   Handle<Map> new_map = split_map;
2839   for (; descriptor < descriptors; descriptor++) {
2840     new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors);
2841   }
2842
2843   new_map->set_owns_descriptors(true);
2844   return new_map;
2845 }
2846
2847
2848 // Generalize the representation of all FIELD descriptors.
2849 Handle<Map> Map::GeneralizeAllFieldRepresentations(
2850     Handle<Map> map,
2851     Representation new_representation) {
2852   Handle<DescriptorArray> descriptors(map->instance_descriptors());
2853   for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
2854     PropertyDetails details = descriptors->GetDetails(i);
2855     if (details.type() == FIELD) {
2856       map = GeneralizeRepresentation(map, i, new_representation, FORCE_FIELD);
2857     }
2858   }
2859   return map;
2860 }
2861
2862
2863 Handle<Map> Map::CurrentMapForDeprecated(Handle<Map> map) {
2864   Handle<Map> proto_map(map);
2865   while (proto_map->prototype()->IsJSObject()) {
2866     Handle<JSObject> holder(JSObject::cast(proto_map->prototype()));
2867     if (holder->map()->is_deprecated()) {
2868       JSObject::TryMigrateInstance(holder);
2869     }
2870     proto_map = Handle<Map>(holder->map());
2871   }
2872   return CurrentMapForDeprecatedInternal(map);
2873 }
2874
2875
2876 Handle<Map> Map::CurrentMapForDeprecatedInternal(Handle<Map> map) {
2877   if (!map->is_deprecated()) return map;
2878
2879   DisallowHeapAllocation no_allocation;
2880   DescriptorArray* old_descriptors = map->instance_descriptors();
2881
2882   int descriptors = map->NumberOfOwnDescriptors();
2883   Map* root_map = map->FindRootMap();
2884
2885   // Check the state of the root map.
2886   if (!map->EquivalentToForTransition(root_map)) return Handle<Map>();
2887   int verbatim = root_map->NumberOfOwnDescriptors();
2888
2889   Map* updated = root_map->FindUpdatedMap(
2890       verbatim, descriptors, old_descriptors);
2891   if (updated == NULL) return Handle<Map>();
2892
2893   DescriptorArray* updated_descriptors = updated->instance_descriptors();
2894   int valid = updated->NumberOfOwnDescriptors();
2895   if (!updated_descriptors->IsMoreGeneralThan(
2896           verbatim, valid, descriptors, old_descriptors)) {
2897     return Handle<Map>();
2898   }
2899
2900   return handle(updated);
2901 }
2902
2903
2904 Handle<Object> JSObject::SetPropertyWithInterceptor(
2905     Handle<JSObject> object,
2906     Handle<Name> name,
2907     Handle<Object> value,
2908     PropertyAttributes attributes,
2909     StrictMode strict_mode) {
2910   // TODO(rossberg): Support symbols in the API.
2911   if (name->IsSymbol()) return value;
2912   Isolate* isolate = object->GetIsolate();
2913   Handle<String> name_string = Handle<String>::cast(name);
2914   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
2915   if (!interceptor->setter()->IsUndefined()) {
2916     LOG(isolate,
2917         ApiNamedPropertyAccess("interceptor-named-set", *object, *name));
2918     PropertyCallbackArguments args(
2919         isolate, interceptor->data(), *object, *object);
2920     v8::NamedPropertySetterCallback setter =
2921         v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter());
2922     Handle<Object> value_unhole = value->IsTheHole()
2923         ? Handle<Object>(isolate->factory()->undefined_value()) : value;
2924     v8::Handle<v8::Value> result = args.Call(setter,
2925                                              v8::Utils::ToLocal(name_string),
2926                                              v8::Utils::ToLocal(value_unhole));
2927     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
2928     if (!result.IsEmpty()) return value;
2929   }
2930   Handle<Object> result =
2931       SetPropertyPostInterceptor(object, name, value, attributes, strict_mode);
2932   RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
2933   return result;
2934 }
2935
2936
2937 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
2938                                        Handle<Name> name,
2939                                        Handle<Object> value,
2940                                        PropertyAttributes attributes,
2941                                        StrictMode strict_mode,
2942                                        StoreFromKeyed store_mode) {
2943   LookupResult result(object->GetIsolate());
2944   object->LocalLookup(*name, &result, true);
2945   if (!result.IsFound()) {
2946     object->map()->LookupTransition(JSObject::cast(*object), *name, &result);
2947   }
2948   return SetProperty(object, &result, name, value, attributes, strict_mode,
2949                      store_mode);
2950 }
2951
2952
2953 Handle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object,
2954                                                  Handle<Object> structure,
2955                                                  Handle<Name> name,
2956                                                  Handle<Object> value,
2957                                                  Handle<JSObject> holder,
2958                                                  StrictMode strict_mode) {
2959   Isolate* isolate = object->GetIsolate();
2960
2961   // We should never get here to initialize a const with the hole
2962   // value since a const declaration would conflict with the setter.
2963   ASSERT(!value->IsTheHole());
2964
2965   // To accommodate both the old and the new api we switch on the
2966   // data structure used to store the callbacks.  Eventually foreign
2967   // callbacks should be phased out.
2968   if (structure->IsForeign()) {
2969     AccessorDescriptor* callback =
2970         reinterpret_cast<AccessorDescriptor*>(
2971             Handle<Foreign>::cast(structure)->foreign_address());
2972     CALL_AND_RETRY_OR_DIE(isolate,
2973                           (callback->setter)(
2974                               isolate, *object, *value, callback->data),
2975                           break,
2976                           return Handle<Object>());
2977     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
2978     return value;
2979   }
2980
2981   if (structure->IsExecutableAccessorInfo()) {
2982     // api style callbacks
2983     ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure);
2984     if (!data->IsCompatibleReceiver(*object)) {
2985       Handle<Object> args[2] = { name, object };
2986       Handle<Object> error =
2987           isolate->factory()->NewTypeError("incompatible_method_receiver",
2988                                            HandleVector(args,
2989                                                         ARRAY_SIZE(args)));
2990       isolate->Throw(*error);
2991       return Handle<Object>();
2992     }
2993     // TODO(rossberg): Support symbols in the API.
2994     if (name->IsSymbol()) return value;
2995     Object* call_obj = data->setter();
2996     v8::AccessorSetterCallback call_fun =
2997         v8::ToCData<v8::AccessorSetterCallback>(call_obj);
2998     if (call_fun == NULL) return value;
2999     Handle<String> key = Handle<String>::cast(name);
3000     LOG(isolate, ApiNamedPropertyAccess("store", *object, *name));
3001     PropertyCallbackArguments args(
3002         isolate, data->data(), *object, JSObject::cast(*holder));
3003     args.Call(call_fun,
3004               v8::Utils::ToLocal(key),
3005               v8::Utils::ToLocal(value));
3006     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
3007     return value;
3008   }
3009
3010   if (structure->IsAccessorPair()) {
3011     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
3012     if (setter->IsSpecFunction()) {
3013       // TODO(rossberg): nicer would be to cast to some JSCallable here...
3014       return SetPropertyWithDefinedSetter(
3015           object, Handle<JSReceiver>::cast(setter), value);
3016     } else {
3017       if (strict_mode == SLOPPY) return value;
3018       Handle<Object> args[2] = { name, holder };
3019       Handle<Object> error =
3020           isolate->factory()->NewTypeError("no_setter_in_callback",
3021                                            HandleVector(args, 2));
3022       isolate->Throw(*error);
3023       return Handle<Object>();
3024     }
3025   }
3026
3027   // TODO(dcarney): Handle correctly.
3028   if (structure->IsDeclaredAccessorInfo()) {
3029     return value;
3030   }
3031
3032   UNREACHABLE();
3033   return Handle<Object>();
3034 }
3035
3036
3037 Handle<Object> JSReceiver::SetPropertyWithDefinedSetter(
3038     Handle<JSReceiver> object,
3039     Handle<JSReceiver> setter,
3040     Handle<Object> value) {
3041   Isolate* isolate = object->GetIsolate();
3042
3043 #ifdef ENABLE_DEBUGGER_SUPPORT
3044   Debug* debug = isolate->debug();
3045   // Handle stepping into a setter if step into is active.
3046   // TODO(rossberg): should this apply to getters that are function proxies?
3047   if (debug->StepInActive() && setter->IsJSFunction()) {
3048     debug->HandleStepIn(
3049         Handle<JSFunction>::cast(setter), Handle<Object>::null(), 0, false);
3050   }
3051 #endif
3052
3053   bool has_pending_exception;
3054   Handle<Object> argv[] = { value };
3055   Execution::Call(
3056       isolate, setter, object, ARRAY_SIZE(argv), argv, &has_pending_exception);
3057   // Check for pending exception and return the result.
3058   if (has_pending_exception) return Handle<Object>();
3059   return value;
3060 }
3061
3062
3063 Handle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3064     Handle<JSObject> object,
3065     uint32_t index,
3066     Handle<Object> value,
3067     bool* found,
3068     StrictMode strict_mode) {
3069   Isolate *isolate = object->GetIsolate();
3070   for (Handle<Object> proto = handle(object->GetPrototype(), isolate);
3071        !proto->IsNull();
3072        proto = handle(proto->GetPrototype(isolate), isolate)) {
3073     if (proto->IsJSProxy()) {
3074       return JSProxy::SetPropertyViaPrototypesWithHandler(
3075           Handle<JSProxy>::cast(proto),
3076           object,
3077           isolate->factory()->Uint32ToString(index),  // name
3078           value,
3079           NONE,
3080           strict_mode,
3081           found);
3082     }
3083     Handle<JSObject> js_proto = Handle<JSObject>::cast(proto);
3084     if (!js_proto->HasDictionaryElements()) {
3085       continue;
3086     }
3087     Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
3088     int entry = dictionary->FindEntry(index);
3089     if (entry != SeededNumberDictionary::kNotFound) {
3090       PropertyDetails details = dictionary->DetailsAt(entry);
3091       if (details.type() == CALLBACKS) {
3092         *found = true;
3093         Handle<Object> structure(dictionary->ValueAt(entry), isolate);
3094         return SetElementWithCallback(object, structure, index, value, js_proto,
3095                                       strict_mode);
3096       }
3097     }
3098   }
3099   *found = false;
3100   return isolate->factory()->the_hole_value();
3101 }
3102
3103
3104 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object,
3105                                                   Handle<Name> name,
3106                                                   Handle<Object> value,
3107                                                   PropertyAttributes attributes,
3108                                                   StrictMode strict_mode,
3109                                                   bool* done) {
3110   Isolate* isolate = object->GetIsolate();
3111
3112   *done = false;
3113   // We could not find a local property so let's check whether there is an
3114   // accessor that wants to handle the property, or whether the property is
3115   // read-only on the prototype chain.
3116   LookupResult result(isolate);
3117   object->LookupRealNamedPropertyInPrototypes(*name, &result);
3118   if (result.IsFound()) {
3119     switch (result.type()) {
3120       case NORMAL:
3121       case FIELD:
3122       case CONSTANT:
3123         *done = result.IsReadOnly();
3124         break;
3125       case INTERCEPTOR: {
3126         PropertyAttributes attr = GetPropertyAttributeWithInterceptor(
3127             handle(result.holder()), object, name, true);
3128         *done = !!(attr & READ_ONLY);
3129         break;
3130       }
3131       case CALLBACKS: {
3132         *done = true;
3133         Handle<Object> callback_object(result.GetCallbackObject(), isolate);
3134         return SetPropertyWithCallback(object, callback_object, name, value,
3135                                        handle(result.holder()), strict_mode);
3136       }
3137       case HANDLER: {
3138         Handle<JSProxy> proxy(result.proxy());
3139         return JSProxy::SetPropertyViaPrototypesWithHandler(
3140             proxy, object, name, value, attributes, strict_mode, done);
3141       }
3142       case TRANSITION:
3143       case NONEXISTENT:
3144         UNREACHABLE();
3145         break;
3146     }
3147   }
3148
3149   // If we get here with *done true, we have encountered a read-only property.
3150   if (*done) {
3151     if (strict_mode == SLOPPY) return value;
3152     Handle<Object> args[] = { name, object };
3153     Handle<Object> error = isolate->factory()->NewTypeError(
3154         "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3155     isolate->Throw(*error);
3156     return Handle<Object>();
3157   }
3158   return isolate->factory()->the_hole_value();
3159 }
3160
3161
3162 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3163   Handle<DescriptorArray> descriptors(map->instance_descriptors());
3164   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3165   int number_of_descriptors = descriptors->number_of_descriptors();
3166   Isolate* isolate = map->GetIsolate();
3167   Handle<DescriptorArray> new_descriptors =
3168       isolate->factory()->NewDescriptorArray(number_of_descriptors, slack);
3169   DescriptorArray::WhitenessWitness witness(*new_descriptors);
3170
3171   for (int i = 0; i < number_of_descriptors; ++i) {
3172     new_descriptors->CopyFrom(i, *descriptors, i, witness);
3173   }
3174
3175   map->set_instance_descriptors(*new_descriptors);
3176 }
3177
3178
3179 template<class T>
3180 static int AppendUniqueCallbacks(NeanderArray* callbacks,
3181                                  Handle<typename T::Array> array,
3182                                  int valid_descriptors) {
3183   int nof_callbacks = callbacks->length();
3184
3185   Isolate* isolate = array->GetIsolate();
3186   // Ensure the keys are unique names before writing them into the
3187   // instance descriptor. Since it may cause a GC, it has to be done before we
3188   // temporarily put the heap in an invalid state while appending descriptors.
3189   for (int i = 0; i < nof_callbacks; ++i) {
3190     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3191     if (entry->name()->IsUniqueName()) continue;
3192     Handle<String> key =
3193         isolate->factory()->InternalizeString(
3194             Handle<String>(String::cast(entry->name())));
3195     entry->set_name(*key);
3196   }
3197
3198   // Fill in new callback descriptors.  Process the callbacks from
3199   // back to front so that the last callback with a given name takes
3200   // precedence over previously added callbacks with that name.
3201   for (int i = nof_callbacks - 1; i >= 0; i--) {
3202     AccessorInfo* entry = AccessorInfo::cast(callbacks->get(i));
3203     Name* key = Name::cast(entry->name());
3204     // Check if a descriptor with this name already exists before writing.
3205     if (!T::Contains(key, entry, valid_descriptors, array)) {
3206       T::Insert(key, entry, valid_descriptors, array);
3207       valid_descriptors++;
3208     }
3209   }
3210
3211   return valid_descriptors;
3212 }
3213
3214 struct DescriptorArrayAppender {
3215   typedef DescriptorArray Array;
3216   static bool Contains(Name* key,
3217                        AccessorInfo* entry,
3218                        int valid_descriptors,
3219                        Handle<DescriptorArray> array) {
3220     return array->Search(key, valid_descriptors) != DescriptorArray::kNotFound;
3221   }
3222   static void Insert(Name* key,
3223                      AccessorInfo* entry,
3224                      int valid_descriptors,
3225                      Handle<DescriptorArray> array) {
3226     CallbacksDescriptor desc(key, entry, entry->property_attributes());
3227     array->Append(&desc);
3228   }
3229 };
3230
3231
3232 struct FixedArrayAppender {
3233   typedef FixedArray Array;
3234   static bool Contains(Name* key,
3235                        AccessorInfo* entry,
3236                        int valid_descriptors,
3237                        Handle<FixedArray> array) {
3238     for (int i = 0; i < valid_descriptors; i++) {
3239       if (key == AccessorInfo::cast(array->get(i))->name()) return true;
3240     }
3241     return false;
3242   }
3243   static void Insert(Name* key,
3244                      AccessorInfo* entry,
3245                      int valid_descriptors,
3246                      Handle<FixedArray> array) {
3247     array->set(valid_descriptors, entry);
3248   }
3249 };
3250
3251
3252 void Map::AppendCallbackDescriptors(Handle<Map> map,
3253                                     Handle<Object> descriptors) {
3254   int nof = map->NumberOfOwnDescriptors();
3255   Handle<DescriptorArray> array(map->instance_descriptors());
3256   NeanderArray callbacks(descriptors);
3257   ASSERT(array->NumberOfSlackDescriptors() >= callbacks.length());
3258   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3259   map->SetNumberOfOwnDescriptors(nof);
3260 }
3261
3262
3263 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
3264                                Handle<FixedArray> array,
3265                                int valid_descriptors) {
3266   NeanderArray callbacks(descriptors);
3267   ASSERT(array->length() >= callbacks.length() + valid_descriptors);
3268   return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3269                                                    array,
3270                                                    valid_descriptors);
3271 }
3272
3273
3274 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
3275   ASSERT(!map.is_null());
3276   for (int i = 0; i < maps->length(); ++i) {
3277     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
3278   }
3279   return false;
3280 }
3281
3282
3283 template <class T>
3284 static Handle<T> MaybeNull(T* p) {
3285   if (p == NULL) return Handle<T>::null();
3286   return Handle<T>(p);
3287 }
3288
3289
3290 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
3291   ElementsKind kind = elements_kind();
3292   Handle<Map> transitioned_map = Handle<Map>::null();
3293   Handle<Map> current_map(this);
3294   bool packed = IsFastPackedElementsKind(kind);
3295   if (IsTransitionableFastElementsKind(kind)) {
3296     while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
3297       kind = GetNextMoreGeneralFastElementsKind(kind, false);
3298       Handle<Map> maybe_transitioned_map =
3299           MaybeNull(current_map->LookupElementsTransitionMap(kind));
3300       if (maybe_transitioned_map.is_null()) break;
3301       if (ContainsMap(candidates, maybe_transitioned_map) &&
3302           (packed || !IsFastPackedElementsKind(kind))) {
3303         transitioned_map = maybe_transitioned_map;
3304         if (!IsFastPackedElementsKind(kind)) packed = false;
3305       }
3306       current_map = maybe_transitioned_map;
3307     }
3308   }
3309   return transitioned_map;
3310 }
3311
3312
3313 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
3314   Map* current_map = map;
3315   int target_kind =
3316       IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
3317       ? to_kind
3318       : TERMINAL_FAST_ELEMENTS_KIND;
3319
3320   // Support for legacy API.
3321   if (IsExternalArrayElementsKind(to_kind) &&
3322       !IsFixedTypedArrayElementsKind(map->elements_kind())) {
3323     return map;
3324   }
3325
3326   ElementsKind kind = map->elements_kind();
3327   while (kind != target_kind) {
3328     kind = GetNextTransitionElementsKind(kind);
3329     if (!current_map->HasElementsTransition()) return current_map;
3330     current_map = current_map->elements_transition_map();
3331   }
3332
3333   if (to_kind != kind && current_map->HasElementsTransition()) {
3334     ASSERT(to_kind == DICTIONARY_ELEMENTS);
3335     Map* next_map = current_map->elements_transition_map();
3336     if (next_map->elements_kind() == to_kind) return next_map;
3337   }
3338
3339   ASSERT(current_map->elements_kind() == target_kind);
3340   return current_map;
3341 }
3342
3343
3344 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3345   Map* to_map = FindClosestElementsTransition(this, to_kind);
3346   if (to_map->elements_kind() == to_kind) return to_map;
3347   return NULL;
3348 }
3349
3350
3351 bool Map::IsMapInArrayPrototypeChain() {
3352   Isolate* isolate = GetIsolate();
3353   if (isolate->initial_array_prototype()->map() == this) {
3354     return true;
3355   }
3356
3357   if (isolate->initial_object_prototype()->map() == this) {
3358     return true;
3359   }
3360
3361   return false;
3362 }
3363
3364
3365 static MaybeObject* AddMissingElementsTransitions(Map* map,
3366                                                   ElementsKind to_kind) {
3367   ASSERT(IsTransitionElementsKind(map->elements_kind()));
3368
3369   Map* current_map = map;
3370
3371   ElementsKind kind = map->elements_kind();
3372   while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3373     kind = GetNextTransitionElementsKind(kind);
3374     MaybeObject* maybe_next_map =
3375         current_map->CopyAsElementsKind(kind, INSERT_TRANSITION);
3376     if (!maybe_next_map->To(&current_map)) return maybe_next_map;
3377   }
3378
3379   // In case we are exiting the fast elements kind system, just add the map in
3380   // the end.
3381   if (kind != to_kind) {
3382     MaybeObject* maybe_next_map =
3383         current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION);
3384     if (!maybe_next_map->To(&current_map)) return maybe_next_map;
3385   }
3386
3387   ASSERT(current_map->elements_kind() == to_kind);
3388   return current_map;
3389 }
3390
3391
3392 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
3393                                                ElementsKind to_kind) {
3394   Isolate* isolate = object->GetIsolate();
3395   CALL_HEAP_FUNCTION(isolate,
3396                      object->GetElementsTransitionMap(isolate, to_kind),
3397                      Map);
3398 }
3399
3400
3401 MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
3402   Map* start_map = map();
3403   ElementsKind from_kind = start_map->elements_kind();
3404
3405   if (from_kind == to_kind) {
3406     return start_map;
3407   }
3408
3409   bool allow_store_transition =
3410       // Only remember the map transition if there is not an already existing
3411       // non-matching element transition.
3412       !start_map->IsUndefined() && !start_map->is_shared() &&
3413       IsTransitionElementsKind(from_kind);
3414
3415   // Only store fast element maps in ascending generality.
3416   if (IsFastElementsKind(to_kind)) {
3417     allow_store_transition &=
3418         IsTransitionableFastElementsKind(from_kind) &&
3419         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3420   }
3421
3422   if (!allow_store_transition) {
3423     return start_map->CopyAsElementsKind(to_kind, OMIT_TRANSITION);
3424   }
3425
3426   return start_map->AsElementsKind(to_kind);
3427 }
3428
3429
3430 // TODO(ishell): Temporary wrapper until handlified.
3431 // static
3432 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
3433   CALL_HEAP_FUNCTION(map->GetIsolate(),
3434                      map->AsElementsKind(kind),
3435                      Map);
3436 }
3437
3438
3439 MaybeObject* Map::AsElementsKind(ElementsKind kind) {
3440   Map* closest_map = FindClosestElementsTransition(this, kind);
3441
3442   if (closest_map->elements_kind() == kind) {
3443     return closest_map;
3444   }
3445
3446   return AddMissingElementsTransitions(closest_map, kind);
3447 }
3448
3449
3450 void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) {
3451   DisallowHeapAllocation no_gc;
3452   if (IsJSGlobalProxy()) {
3453     Object* proto = GetPrototype();
3454     if (proto->IsNull()) return result->NotFound();
3455     ASSERT(proto->IsJSGlobalObject());
3456     return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
3457   }
3458
3459   if (HasFastProperties()) {
3460     map()->LookupDescriptor(this, name, result);
3461     // A property or a map transition was found. We return all of these result
3462     // types because LocalLookupRealNamedProperty is used when setting
3463     // properties where map transitions are handled.
3464     ASSERT(!result->IsFound() ||
3465            (result->holder() == this && result->IsFastPropertyType()));
3466     // Disallow caching for uninitialized constants. These can only
3467     // occur as fields.
3468     if (result->IsField() &&
3469         result->IsReadOnly() &&
3470         RawFastPropertyAt(result->GetFieldIndex().field_index())->IsTheHole()) {
3471       result->DisallowCaching();
3472     }
3473     return;
3474   }
3475
3476   int entry = property_dictionary()->FindEntry(name);
3477   if (entry != NameDictionary::kNotFound) {
3478     Object* value = property_dictionary()->ValueAt(entry);
3479     if (IsGlobalObject()) {
3480       PropertyDetails d = property_dictionary()->DetailsAt(entry);
3481       if (d.IsDeleted()) {
3482         result->NotFound();
3483         return;
3484       }
3485       value = PropertyCell::cast(value)->value();
3486     }
3487     // Make sure to disallow caching for uninitialized constants
3488     // found in the dictionary-mode objects.
3489     if (value->IsTheHole()) result->DisallowCaching();
3490     result->DictionaryResult(this, entry);
3491     return;
3492   }
3493
3494   result->NotFound();
3495 }
3496
3497
3498 void JSObject::LookupRealNamedProperty(Name* name, LookupResult* result) {
3499   LocalLookupRealNamedProperty(name, result);
3500   if (result->IsFound()) return;
3501
3502   LookupRealNamedPropertyInPrototypes(name, result);
3503 }
3504
3505
3506 void JSObject::LookupRealNamedPropertyInPrototypes(Name* name,
3507                                                    LookupResult* result) {
3508   Isolate* isolate = GetIsolate();
3509   Heap* heap = isolate->heap();
3510   for (Object* pt = GetPrototype();
3511        pt != heap->null_value();
3512        pt = pt->GetPrototype(isolate)) {
3513     if (pt->IsJSProxy()) {
3514       return result->HandlerResult(JSProxy::cast(pt));
3515     }
3516     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
3517     ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
3518     if (result->IsFound()) return;
3519   }
3520   result->NotFound();
3521 }
3522
3523
3524 // We only need to deal with CALLBACKS and INTERCEPTORS
3525 Handle<Object> JSObject::SetPropertyWithFailedAccessCheck(
3526     Handle<JSObject> object,
3527     LookupResult* result,
3528     Handle<Name> name,
3529     Handle<Object> value,
3530     bool check_prototype,
3531     StrictMode strict_mode) {
3532   if (check_prototype && !result->IsProperty()) {
3533     object->LookupRealNamedPropertyInPrototypes(*name, result);
3534   }
3535
3536   if (result->IsProperty()) {
3537     if (!result->IsReadOnly()) {
3538       switch (result->type()) {
3539         case CALLBACKS: {
3540           Object* obj = result->GetCallbackObject();
3541           if (obj->IsAccessorInfo()) {
3542             Handle<AccessorInfo> info(AccessorInfo::cast(obj));
3543             if (info->all_can_write()) {
3544               return SetPropertyWithCallback(object,
3545                                              info,
3546                                              name,
3547                                              value,
3548                                              handle(result->holder()),
3549                                              strict_mode);
3550             }
3551           } else if (obj->IsAccessorPair()) {
3552             Handle<AccessorPair> pair(AccessorPair::cast(obj));
3553             if (pair->all_can_read()) {
3554               return SetPropertyWithCallback(object,
3555                                              pair,
3556                                              name,
3557                                              value,
3558                                              handle(result->holder()),
3559                                              strict_mode);
3560             }
3561           }
3562           break;
3563         }
3564         case INTERCEPTOR: {
3565           // Try lookup real named properties. Note that only property can be
3566           // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
3567           LookupResult r(object->GetIsolate());
3568           object->LookupRealNamedProperty(*name, &r);
3569           if (r.IsProperty()) {
3570             return SetPropertyWithFailedAccessCheck(object,
3571                                                     &r,
3572                                                     name,
3573                                                     value,
3574                                                     check_prototype,
3575                                                     strict_mode);
3576           }
3577           break;
3578         }
3579         default: {
3580           break;
3581         }
3582       }
3583     }
3584   }
3585
3586   Isolate* isolate = object->GetIsolate();
3587   isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET);
3588   RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
3589   return value;
3590 }
3591
3592
3593 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
3594                                        LookupResult* result,
3595                                        Handle<Name> key,
3596                                        Handle<Object> value,
3597                                        PropertyAttributes attributes,
3598                                        StrictMode strict_mode,
3599                                        StoreFromKeyed store_mode) {
3600   if (result->IsHandler()) {
3601     return JSProxy::SetPropertyWithHandler(handle(result->proxy()),
3602         object, key, value, attributes, strict_mode);
3603   } else {
3604     return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object),
3605         result, key, value, attributes, strict_mode, store_mode);
3606   }
3607 }
3608
3609
3610 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) {
3611   Isolate* isolate = proxy->GetIsolate();
3612
3613   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3614   if (name->IsSymbol()) return false;
3615
3616   Handle<Object> args[] = { name };
3617   Handle<Object> result = proxy->CallTrap(
3618     "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
3619   if (isolate->has_pending_exception()) return false;
3620
3621   return result->BooleanValue();
3622 }
3623
3624
3625 Handle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy,
3626                                                Handle<JSReceiver> receiver,
3627                                                Handle<Name> name,
3628                                                Handle<Object> value,
3629                                                PropertyAttributes attributes,
3630                                                StrictMode strict_mode) {
3631   Isolate* isolate = proxy->GetIsolate();
3632
3633   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3634   if (name->IsSymbol()) return value;
3635
3636   Handle<Object> args[] = { receiver, name, value };
3637   proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
3638   if (isolate->has_pending_exception()) return Handle<Object>();
3639
3640   return value;
3641 }
3642
3643
3644 Handle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3645     Handle<JSProxy> proxy,
3646     Handle<JSReceiver> receiver,
3647     Handle<Name> name,
3648     Handle<Object> value,
3649     PropertyAttributes attributes,
3650     StrictMode strict_mode,
3651     bool* done) {
3652   Isolate* isolate = proxy->GetIsolate();
3653   Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy.
3654
3655   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3656   if (name->IsSymbol()) {
3657     *done = false;
3658     return isolate->factory()->the_hole_value();
3659   }
3660
3661   *done = true;  // except where redefined...
3662   Handle<Object> args[] = { name };
3663   Handle<Object> result = proxy->CallTrap(
3664       "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
3665   if (isolate->has_pending_exception()) return Handle<Object>();
3666
3667   if (result->IsUndefined()) {
3668     *done = false;
3669     return isolate->factory()->the_hole_value();
3670   }
3671
3672   // Emulate [[GetProperty]] semantics for proxies.
3673   bool has_pending_exception;
3674   Handle<Object> argv[] = { result };
3675   Handle<Object> desc = Execution::Call(
3676       isolate, isolate->to_complete_property_descriptor(), result,
3677       ARRAY_SIZE(argv), argv, &has_pending_exception);
3678   if (has_pending_exception) return Handle<Object>();
3679
3680   // [[GetProperty]] requires to check that all properties are configurable.
3681   Handle<String> configurable_name =
3682       isolate->factory()->InternalizeOneByteString(
3683           STATIC_ASCII_VECTOR("configurable_"));
3684   Handle<Object> configurable(
3685       v8::internal::GetProperty(isolate, desc, configurable_name));
3686   ASSERT(!isolate->has_pending_exception());
3687   ASSERT(configurable->IsTrue() || configurable->IsFalse());
3688   if (configurable->IsFalse()) {
3689     Handle<String> trap =
3690         isolate->factory()->InternalizeOneByteString(
3691             STATIC_ASCII_VECTOR("getPropertyDescriptor"));
3692     Handle<Object> args[] = { handler, trap, name };
3693     Handle<Object> error = isolate->factory()->NewTypeError(
3694         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
3695     isolate->Throw(*error);
3696     return Handle<Object>();
3697   }
3698   ASSERT(configurable->IsTrue());
3699
3700   // Check for DataDescriptor.
3701   Handle<String> hasWritable_name =
3702       isolate->factory()->InternalizeOneByteString(
3703           STATIC_ASCII_VECTOR("hasWritable_"));
3704   Handle<Object> hasWritable(
3705       v8::internal::GetProperty(isolate, desc, hasWritable_name));
3706   ASSERT(!isolate->has_pending_exception());
3707   ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse());
3708   if (hasWritable->IsTrue()) {
3709     Handle<String> writable_name =
3710         isolate->factory()->InternalizeOneByteString(
3711             STATIC_ASCII_VECTOR("writable_"));
3712     Handle<Object> writable(
3713         v8::internal::GetProperty(isolate, desc, writable_name));
3714     ASSERT(!isolate->has_pending_exception());
3715     ASSERT(writable->IsTrue() || writable->IsFalse());
3716     *done = writable->IsFalse();
3717     if (!*done) return isolate->factory()->the_hole_value();
3718     if (strict_mode == SLOPPY) return value;
3719     Handle<Object> args[] = { name, receiver };
3720     Handle<Object> error = isolate->factory()->NewTypeError(
3721         "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3722     isolate->Throw(*error);
3723     return Handle<Object>();
3724   }
3725
3726   // We have an AccessorDescriptor.
3727   Handle<String> set_name = isolate->factory()->InternalizeOneByteString(
3728       STATIC_ASCII_VECTOR("set_"));
3729   Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_name));
3730   ASSERT(!isolate->has_pending_exception());
3731   if (!setter->IsUndefined()) {
3732     // TODO(rossberg): nicer would be to cast to some JSCallable here...
3733     return SetPropertyWithDefinedSetter(
3734         receiver, Handle<JSReceiver>::cast(setter), value);
3735   }
3736
3737   if (strict_mode == SLOPPY) return value;
3738   Handle<Object> args2[] = { name, proxy };
3739   Handle<Object> error = isolate->factory()->NewTypeError(
3740       "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
3741   isolate->Throw(*error);
3742   return Handle<Object>();
3743 }
3744
3745
3746 Handle<Object> JSProxy::DeletePropertyWithHandler(
3747     Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) {
3748   Isolate* isolate = proxy->GetIsolate();
3749
3750   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3751   if (name->IsSymbol()) return isolate->factory()->false_value();
3752
3753   Handle<Object> args[] = { name };
3754   Handle<Object> result = proxy->CallTrap(
3755       "delete", Handle<Object>(), ARRAY_SIZE(args), args);
3756   if (isolate->has_pending_exception()) return Handle<Object>();
3757
3758   bool result_bool = result->BooleanValue();
3759   if (mode == STRICT_DELETION && !result_bool) {
3760     Handle<Object> handler(proxy->handler(), isolate);
3761     Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
3762         STATIC_ASCII_VECTOR("delete"));
3763     Handle<Object> args[] = { handler, trap_name };
3764     Handle<Object> error = isolate->factory()->NewTypeError(
3765         "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
3766     isolate->Throw(*error);
3767     return Handle<Object>();
3768   }
3769   return isolate->factory()->ToBoolean(result_bool);
3770 }
3771
3772
3773 Handle<Object> JSProxy::DeleteElementWithHandler(
3774     Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) {
3775   Isolate* isolate = proxy->GetIsolate();
3776   Handle<String> name = isolate->factory()->Uint32ToString(index);
3777   return JSProxy::DeletePropertyWithHandler(proxy, name, mode);
3778 }
3779
3780
3781 PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
3782     Handle<JSProxy> proxy,
3783     Handle<JSReceiver> receiver,
3784     Handle<Name> name) {
3785   Isolate* isolate = proxy->GetIsolate();
3786   HandleScope scope(isolate);
3787
3788   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3789   if (name->IsSymbol()) return ABSENT;
3790
3791   Handle<Object> args[] = { name };
3792   Handle<Object> result = proxy->CallTrap(
3793     "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
3794   if (isolate->has_pending_exception()) return NONE;
3795
3796   if (result->IsUndefined()) return ABSENT;
3797
3798   bool has_pending_exception;
3799   Handle<Object> argv[] = { result };
3800   Handle<Object> desc = Execution::Call(
3801       isolate, isolate->to_complete_property_descriptor(), result,
3802       ARRAY_SIZE(argv), argv, &has_pending_exception);
3803   if (has_pending_exception) return NONE;
3804
3805   // Convert result to PropertyAttributes.
3806   Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3807       STATIC_ASCII_VECTOR("enumerable_"));
3808   Handle<Object> enumerable(v8::internal::GetProperty(isolate, desc, enum_n));
3809   if (isolate->has_pending_exception()) return NONE;
3810   Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
3811       STATIC_ASCII_VECTOR("configurable_"));
3812   Handle<Object> configurable(v8::internal::GetProperty(isolate, desc, conf_n));
3813   if (isolate->has_pending_exception()) return NONE;
3814   Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
3815       STATIC_ASCII_VECTOR("writable_"));
3816   Handle<Object> writable(v8::internal::GetProperty(isolate, desc, writ_n));
3817   if (isolate->has_pending_exception()) return NONE;
3818   if (!writable->BooleanValue()) {
3819     Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
3820         STATIC_ASCII_VECTOR("set_"));
3821     Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_n));
3822     if (isolate->has_pending_exception()) return NONE;
3823     writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
3824   }
3825
3826   if (configurable->IsFalse()) {
3827     Handle<Object> handler(proxy->handler(), isolate);
3828     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3829         STATIC_ASCII_VECTOR("getPropertyDescriptor"));
3830     Handle<Object> args[] = { handler, trap, name };
3831     Handle<Object> error = isolate->factory()->NewTypeError(
3832         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
3833     isolate->Throw(*error);
3834     return NONE;
3835   }
3836
3837   int attributes = NONE;
3838   if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
3839   if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
3840   if (!writable->BooleanValue()) attributes |= READ_ONLY;
3841   return static_cast<PropertyAttributes>(attributes);
3842 }
3843
3844
3845 PropertyAttributes JSProxy::GetElementAttributeWithHandler(
3846     Handle<JSProxy> proxy,
3847     Handle<JSReceiver> receiver,
3848     uint32_t index) {
3849   Isolate* isolate = proxy->GetIsolate();
3850   Handle<String> name = isolate->factory()->Uint32ToString(index);
3851   return GetPropertyAttributeWithHandler(proxy, receiver, name);
3852 }
3853
3854
3855 void JSProxy::Fix(Handle<JSProxy> proxy) {
3856   Isolate* isolate = proxy->GetIsolate();
3857
3858   // Save identity hash.
3859   Handle<Object> hash(proxy->GetIdentityHash(), isolate);
3860
3861   if (proxy->IsJSFunctionProxy()) {
3862     isolate->factory()->BecomeJSFunction(proxy);
3863     // Code will be set on the JavaScript side.
3864   } else {
3865     isolate->factory()->BecomeJSObject(proxy);
3866   }
3867   ASSERT(proxy->IsJSObject());
3868
3869   // Inherit identity, if it was present.
3870   if (hash->IsSmi()) {
3871     JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
3872                               Handle<Smi>::cast(hash));
3873   }
3874 }
3875
3876
3877 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
3878                                                  Handle<Object> derived,
3879                                                  int argc,
3880                                                  Handle<Object> argv[]) {
3881   Isolate* isolate = GetIsolate();
3882   Handle<Object> handler(this->handler(), isolate);
3883
3884   Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
3885   Handle<Object> trap(v8::internal::GetProperty(isolate, handler, trap_name));
3886   if (isolate->has_pending_exception()) return trap;
3887
3888   if (trap->IsUndefined()) {
3889     if (derived.is_null()) {
3890       Handle<Object> args[] = { handler, trap_name };
3891       Handle<Object> error = isolate->factory()->NewTypeError(
3892         "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
3893       isolate->Throw(*error);
3894       return Handle<Object>();
3895     }
3896     trap = Handle<Object>(derived);
3897   }
3898
3899   bool threw;
3900   return Execution::Call(isolate, trap, handler, argc, argv, &threw);
3901 }
3902
3903
3904 // TODO(mstarzinger): Temporary wrapper until handlified.
3905 static Handle<Map> MapAsElementsKind(Handle<Map> map, ElementsKind kind) {
3906   CALL_HEAP_FUNCTION(map->GetIsolate(), map->AsElementsKind(kind), Map);
3907 }
3908
3909
3910 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
3911   ASSERT(object->map()->inobject_properties() == map->inobject_properties());
3912   ElementsKind obj_kind = object->map()->elements_kind();
3913   ElementsKind map_kind = map->elements_kind();
3914   if (map_kind != obj_kind) {
3915     ElementsKind to_kind = map_kind;
3916     if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
3917         IsDictionaryElementsKind(obj_kind)) {
3918       to_kind = obj_kind;
3919     }
3920     if (IsDictionaryElementsKind(to_kind)) {
3921       NormalizeElements(object);
3922     } else {
3923       TransitionElementsKind(object, to_kind);
3924     }
3925     map = MapAsElementsKind(map, to_kind);
3926   }
3927   JSObject::MigrateToMap(object, map);
3928 }
3929
3930
3931 void JSObject::MigrateInstance(Handle<JSObject> object) {
3932   // Converting any field to the most specific type will cause the
3933   // GeneralizeFieldRepresentation algorithm to create the most general existing
3934   // transition that matches the object. This achieves what is needed.
3935   Handle<Map> original_map(object->map());
3936   GeneralizeFieldRepresentation(
3937       object, 0, Representation::None(), ALLOW_AS_CONSTANT);
3938   object->map()->set_migration_target(true);
3939   if (FLAG_trace_migration) {
3940     object->PrintInstanceMigration(stdout, *original_map, object->map());
3941   }
3942 }
3943
3944
3945 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) {
3946   Handle<Map> original_map(object->map());
3947   Handle<Map> new_map = Map::CurrentMapForDeprecatedInternal(original_map);
3948   if (new_map.is_null()) return Handle<Object>();
3949   JSObject::MigrateToMap(object, new_map);
3950   if (FLAG_trace_migration) {
3951     object->PrintInstanceMigration(stdout, *original_map, object->map());
3952   }
3953   return object;
3954 }
3955
3956
3957 Handle<Object> JSObject::SetPropertyUsingTransition(
3958     Handle<JSObject> object,
3959     LookupResult* lookup,
3960     Handle<Name> name,
3961     Handle<Object> value,
3962     PropertyAttributes attributes) {
3963   Handle<Map> transition_map(lookup->GetTransitionTarget());
3964   int descriptor = transition_map->LastAdded();
3965
3966   DescriptorArray* descriptors = transition_map->instance_descriptors();
3967   PropertyDetails details = descriptors->GetDetails(descriptor);
3968
3969   if (details.type() == CALLBACKS || attributes != details.attributes()) {
3970     // AddProperty will either normalize the object, or create a new fast copy
3971     // of the map. If we get a fast copy of the map, all field representations
3972     // will be tagged since the transition is omitted.
3973     return JSObject::AddProperty(
3974         object, name, value, attributes, SLOPPY,
3975         JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED,
3976         JSReceiver::OMIT_EXTENSIBILITY_CHECK,
3977         JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION);
3978   }
3979
3980   // Keep the target CONSTANT if the same value is stored.
3981   // TODO(verwaest): Also support keeping the placeholder
3982   // (value->IsUninitialized) as constant.
3983   if (!value->FitsRepresentation(details.representation()) ||
3984       (details.type() == CONSTANT &&
3985        descriptors->GetValue(descriptor) != *value)) {
3986     transition_map = Map::GeneralizeRepresentation(transition_map,
3987         descriptor, value->OptimalRepresentation(), FORCE_FIELD);
3988   }
3989
3990   JSObject::MigrateToMap(object, transition_map);
3991
3992   // Reload.
3993   descriptors = transition_map->instance_descriptors();
3994   details = descriptors->GetDetails(descriptor);
3995
3996   if (details.type() != FIELD) return value;
3997
3998   int field_index = descriptors->GetFieldIndex(descriptor);
3999   if (details.representation().IsDouble()) {
4000     // Nothing more to be done.
4001     if (value->IsUninitialized()) return value;
4002     HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index));
4003     box->set_value(value->Number());
4004   } else {
4005     object->FastPropertyAtPut(field_index, *value);
4006   }
4007
4008   return value;
4009 }
4010
4011
4012 static void SetPropertyToField(LookupResult* lookup,
4013                                Handle<Name> name,
4014                                Handle<Object> value) {
4015   Representation representation = lookup->representation();
4016   if (!value->FitsRepresentation(representation) ||
4017       lookup->type() == CONSTANT) {
4018     JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()),
4019                                             lookup->GetDescriptorIndex(),
4020                                             value->OptimalRepresentation(),
4021                                             FORCE_FIELD);
4022     DescriptorArray* desc = lookup->holder()->map()->instance_descriptors();
4023     int descriptor = lookup->GetDescriptorIndex();
4024     representation = desc->GetDetails(descriptor).representation();
4025   }
4026
4027   if (representation.IsDouble()) {
4028     HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt(
4029         lookup->GetFieldIndex().field_index()));
4030     storage->set_value(value->Number());
4031     return;
4032   }
4033
4034   lookup->holder()->FastPropertyAtPut(
4035       lookup->GetFieldIndex().field_index(), *value);
4036 }
4037
4038
4039 static void ConvertAndSetLocalProperty(LookupResult* lookup,
4040                                        Handle<Name> name,
4041                                        Handle<Object> value,
4042                                        PropertyAttributes attributes) {
4043   Handle<JSObject> object(lookup->holder());
4044   if (object->TooManyFastProperties()) {
4045     JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
4046   }
4047
4048   if (!object->HasFastProperties()) {
4049     ReplaceSlowProperty(object, name, value, attributes);
4050     return;
4051   }
4052
4053   int descriptor_index = lookup->GetDescriptorIndex();
4054   if (lookup->GetAttributes() == attributes) {
4055     JSObject::GeneralizeFieldRepresentation(
4056         object, descriptor_index, Representation::Tagged(), FORCE_FIELD);
4057   } else {
4058     Handle<Map> old_map(object->map());
4059     Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map,
4060         descriptor_index, FORCE_FIELD, attributes, "attributes mismatch");
4061     JSObject::MigrateToMap(object, new_map);
4062   }
4063
4064   DescriptorArray* descriptors = object->map()->instance_descriptors();
4065   int index = descriptors->GetDetails(descriptor_index).field_index();
4066   object->FastPropertyAtPut(index, *value);
4067 }
4068
4069
4070 static void SetPropertyToFieldWithAttributes(LookupResult* lookup,
4071                                              Handle<Name> name,
4072                                              Handle<Object> value,
4073                                              PropertyAttributes attributes) {
4074   if (lookup->GetAttributes() == attributes) {
4075     if (value->IsUninitialized()) return;
4076     SetPropertyToField(lookup, name, value);
4077   } else {
4078     ConvertAndSetLocalProperty(lookup, name, value, attributes);
4079   }
4080 }
4081
4082
4083 Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object,
4084                                               LookupResult* lookup,
4085                                               Handle<Name> name,
4086                                               Handle<Object> value,
4087                                               PropertyAttributes attributes,
4088                                               StrictMode strict_mode,
4089                                               StoreFromKeyed store_mode) {
4090   Isolate* isolate = object->GetIsolate();
4091
4092   // Make sure that the top context does not change when doing callbacks or
4093   // interceptor calls.
4094   AssertNoContextChange ncc(isolate);
4095
4096   // Optimization for 2-byte strings often used as keys in a decompression
4097   // dictionary.  We internalize these short keys to avoid constantly
4098   // reallocating them.
4099   if (name->IsString() && !name->IsInternalizedString() &&
4100       Handle<String>::cast(name)->length() <= 2) {
4101     name = isolate->factory()->InternalizeString(Handle<String>::cast(name));
4102   }
4103
4104   // Check access rights if needed.
4105   if (object->IsAccessCheckNeeded()) {
4106     if (!isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) {
4107       return SetPropertyWithFailedAccessCheck(object, lookup, name, value,
4108                                               true, strict_mode);
4109     }
4110   }
4111
4112   if (object->IsJSGlobalProxy()) {
4113     Handle<Object> proto(object->GetPrototype(), isolate);
4114     if (proto->IsNull()) return value;
4115     ASSERT(proto->IsJSGlobalObject());
4116     return SetPropertyForResult(Handle<JSObject>::cast(proto),
4117         lookup, name, value, attributes, strict_mode, store_mode);
4118   }
4119
4120   ASSERT(!lookup->IsFound() || lookup->holder() == *object ||
4121          lookup->holder()->map()->is_hidden_prototype());
4122
4123   if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) {
4124     bool done = false;
4125     Handle<Object> result_object = SetPropertyViaPrototypes(
4126         object, name, value, attributes, strict_mode, &done);
4127     if (done) return result_object;
4128   }
4129
4130   if (!lookup->IsFound()) {
4131     // Neither properties nor transitions found.
4132     return AddProperty(
4133         object, name, value, attributes, strict_mode, store_mode);
4134   }
4135
4136   if (lookup->IsProperty() && lookup->IsReadOnly()) {
4137     if (strict_mode == STRICT) {
4138       Handle<Object> args[] = { name, object };
4139       Handle<Object> error = isolate->factory()->NewTypeError(
4140           "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
4141       isolate->Throw(*error);
4142       return Handle<Object>();
4143     } else {
4144       return value;
4145     }
4146   }
4147
4148   Handle<Object> old_value = isolate->factory()->the_hole_value();
4149   bool is_observed = object->map()->is_observed() &&
4150                      *name != isolate->heap()->hidden_string();
4151   if (is_observed && lookup->IsDataProperty()) {
4152     old_value = Object::GetProperty(object, name);
4153     CHECK_NOT_EMPTY_HANDLE(isolate, old_value);
4154   }
4155
4156   // This is a real property that is not read-only, or it is a
4157   // transition or null descriptor and there are no setters in the prototypes.
4158   Handle<Object> result = value;
4159   switch (lookup->type()) {
4160     case NORMAL:
4161       SetNormalizedProperty(handle(lookup->holder()), lookup, value);
4162       break;
4163     case FIELD:
4164       SetPropertyToField(lookup, name, value);
4165       break;
4166     case CONSTANT:
4167       // Only replace the constant if necessary.
4168       if (*value == lookup->GetConstant()) return value;
4169       SetPropertyToField(lookup, name, value);
4170       break;
4171     case CALLBACKS: {
4172       Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
4173       return SetPropertyWithCallback(object, callback_object, name, value,
4174                                      handle(lookup->holder()), strict_mode);
4175     }
4176     case INTERCEPTOR:
4177       result = SetPropertyWithInterceptor(handle(lookup->holder()), name, value,
4178                                           attributes, strict_mode);
4179       break;
4180     case TRANSITION:
4181       result = SetPropertyUsingTransition(handle(lookup->holder()), lookup,
4182                                           name, value, attributes);
4183       break;
4184     case HANDLER:
4185     case NONEXISTENT:
4186       UNREACHABLE();
4187   }
4188
4189   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
4190
4191   if (is_observed) {
4192     if (lookup->IsTransition()) {
4193       EnqueueChangeRecord(object, "add", name, old_value);
4194     } else {
4195       LookupResult new_lookup(isolate);
4196       object->LocalLookup(*name, &new_lookup, true);
4197       if (new_lookup.IsDataProperty()) {
4198         Handle<Object> new_value = Object::GetProperty(object, name);
4199         CHECK_NOT_EMPTY_HANDLE(isolate, new_value);
4200         if (!new_value->SameValue(*old_value)) {
4201           EnqueueChangeRecord(object, "update", name, old_value);
4202         }
4203       }
4204     }
4205   }
4206
4207   return result;
4208 }
4209
4210
4211 // Set a real local property, even if it is READ_ONLY.  If the property is not
4212 // present, add it with attributes NONE.  This code is an exact clone of
4213 // SetProperty, with the check for IsReadOnly and the check for a
4214 // callback setter removed.  The two lines looking up the LookupResult
4215 // result are also added.  If one of the functions is changed, the other
4216 // should be.
4217 // Note that this method cannot be used to set the prototype of a function
4218 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
4219 // doesn't handle function prototypes correctly.
4220 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
4221     Handle<JSObject> object,
4222     Handle<Name> name,
4223     Handle<Object> value,
4224     PropertyAttributes attributes,
4225     ValueType value_type,
4226     StoreMode mode,
4227     ExtensibilityCheck extensibility_check) {
4228   Isolate* isolate = object->GetIsolate();
4229
4230   // Make sure that the top context does not change when doing callbacks or
4231   // interceptor calls.
4232   AssertNoContextChange ncc(isolate);
4233
4234   LookupResult lookup(isolate);
4235   object->LocalLookup(*name, &lookup, true);
4236   if (!lookup.IsFound()) {
4237     object->map()->LookupTransition(*object, *name, &lookup);
4238   }
4239
4240   // Check access rights if needed.
4241   if (object->IsAccessCheckNeeded()) {
4242     if (!isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) {
4243       return SetPropertyWithFailedAccessCheck(object, &lookup, name, value,
4244                                               false, SLOPPY);
4245     }
4246   }
4247
4248   if (object->IsJSGlobalProxy()) {
4249     Handle<Object> proto(object->GetPrototype(), isolate);
4250     if (proto->IsNull()) return value;
4251     ASSERT(proto->IsJSGlobalObject());
4252     return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto),
4253         name, value, attributes, value_type, mode, extensibility_check);
4254   }
4255
4256   if (lookup.IsFound() &&
4257       (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) {
4258     object->LocalLookupRealNamedProperty(*name, &lookup);
4259   }
4260
4261   // Check for accessor in prototype chain removed here in clone.
4262   if (!lookup.IsFound()) {
4263     object->map()->LookupTransition(*object, *name, &lookup);
4264     TransitionFlag flag = lookup.IsFound()
4265         ? OMIT_TRANSITION : INSERT_TRANSITION;
4266     // Neither properties nor transitions found.
4267     return AddProperty(object, name, value, attributes, SLOPPY,
4268         MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag);
4269   }
4270
4271   Handle<Object> old_value = isolate->factory()->the_hole_value();
4272   PropertyAttributes old_attributes = ABSENT;
4273   bool is_observed = object->map()->is_observed() &&
4274                      *name != isolate->heap()->hidden_string();
4275   if (is_observed && lookup.IsProperty()) {
4276     if (lookup.IsDataProperty()) {
4277       old_value = Object::GetProperty(object, name);
4278       CHECK_NOT_EMPTY_HANDLE(isolate, old_value);
4279     }
4280     old_attributes = lookup.GetAttributes();
4281   }
4282
4283   // Check of IsReadOnly removed from here in clone.
4284   switch (lookup.type()) {
4285     case NORMAL:
4286       ReplaceSlowProperty(object, name, value, attributes);
4287       break;
4288     case FIELD:
4289       SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4290       break;
4291     case CONSTANT:
4292       // Only replace the constant if necessary.
4293       if (lookup.GetAttributes() != attributes ||
4294           *value != lookup.GetConstant()) {
4295         SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4296       }
4297       break;
4298     case CALLBACKS:
4299       ConvertAndSetLocalProperty(&lookup, name, value, attributes);
4300       break;
4301     case TRANSITION: {
4302       Handle<Object> result = SetPropertyUsingTransition(
4303           handle(lookup.holder()), &lookup, name, value, attributes);
4304       RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
4305       break;
4306     }
4307     case NONEXISTENT:
4308     case HANDLER:
4309     case INTERCEPTOR:
4310       UNREACHABLE();
4311   }
4312
4313   if (is_observed) {
4314     if (lookup.IsTransition()) {
4315       EnqueueChangeRecord(object, "add", name, old_value);
4316     } else if (old_value->IsTheHole()) {
4317       EnqueueChangeRecord(object, "reconfigure", name, old_value);
4318     } else {
4319       LookupResult new_lookup(isolate);
4320       object->LocalLookup(*name, &new_lookup, true);
4321       bool value_changed = false;
4322       if (new_lookup.IsDataProperty()) {
4323         Handle<Object> new_value = Object::GetProperty(object, name);
4324         CHECK_NOT_EMPTY_HANDLE(isolate, new_value);
4325         value_changed = !old_value->SameValue(*new_value);
4326       }
4327       if (new_lookup.GetAttributes() != old_attributes) {
4328         if (!value_changed) old_value = isolate->factory()->the_hole_value();
4329         EnqueueChangeRecord(object, "reconfigure", name, old_value);
4330       } else if (value_changed) {
4331         EnqueueChangeRecord(object, "update", name, old_value);
4332       }
4333     }
4334   }
4335
4336   return value;
4337 }
4338
4339
4340 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
4341     Handle<JSObject> object,
4342     Handle<JSObject> receiver,
4343     Handle<Name> name,
4344     bool continue_search) {
4345   // Check local property, ignore interceptor.
4346   Isolate* isolate = object->GetIsolate();
4347   LookupResult result(isolate);
4348   object->LocalLookupRealNamedProperty(*name, &result);
4349   if (result.IsFound()) return result.GetAttributes();
4350
4351   if (continue_search) {
4352     // Continue searching via the prototype chain.
4353     Handle<Object> proto(object->GetPrototype(), isolate);
4354     if (!proto->IsNull()) {
4355       return JSReceiver::GetPropertyAttributeWithReceiver(
4356           Handle<JSObject>::cast(proto), receiver, name);
4357     }
4358   }
4359   return ABSENT;
4360 }
4361
4362
4363 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
4364     Handle<JSObject> object,
4365     Handle<JSObject> receiver,
4366     Handle<Name> name,
4367     bool continue_search) {
4368   // TODO(rossberg): Support symbols in the API.
4369   if (name->IsSymbol()) return ABSENT;
4370
4371   Isolate* isolate = object->GetIsolate();
4372   HandleScope scope(isolate);
4373
4374   // Make sure that the top context does not change when doing
4375   // callbacks or interceptor calls.
4376   AssertNoContextChange ncc(isolate);
4377
4378   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
4379   PropertyCallbackArguments args(
4380       isolate, interceptor->data(), *receiver, *object);
4381   if (!interceptor->query()->IsUndefined()) {
4382     v8::NamedPropertyQueryCallback query =
4383         v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query());
4384     LOG(isolate,
4385         ApiNamedPropertyAccess("interceptor-named-has", *object, *name));
4386     v8::Handle<v8::Integer> result =
4387         args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name)));
4388     if (!result.IsEmpty()) {
4389       ASSERT(result->IsInt32());
4390       return static_cast<PropertyAttributes>(result->Int32Value());
4391     }
4392   } else if (!interceptor->getter()->IsUndefined()) {
4393     v8::NamedPropertyGetterCallback getter =
4394         v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
4395     LOG(isolate,
4396         ApiNamedPropertyAccess("interceptor-named-get-has", *object, *name));
4397     v8::Handle<v8::Value> result =
4398         args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name)));
4399     if (!result.IsEmpty()) return DONT_ENUM;
4400   }
4401   return GetPropertyAttributePostInterceptor(
4402       object, receiver, name, continue_search);
4403 }
4404
4405
4406 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
4407     Handle<JSReceiver> object,
4408     Handle<JSReceiver> receiver,
4409     Handle<Name> key) {
4410   uint32_t index = 0;
4411   if (object->IsJSObject() && key->AsArrayIndex(&index)) {
4412     return JSObject::GetElementAttributeWithReceiver(
4413         Handle<JSObject>::cast(object), receiver, index, true);
4414   }
4415   // Named property.
4416   LookupResult lookup(object->GetIsolate());
4417   object->Lookup(*key, &lookup);
4418   return GetPropertyAttributeForResult(object, receiver, &lookup, key, true);
4419 }
4420
4421
4422 PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
4423     Handle<JSReceiver> object,
4424     Handle<JSReceiver> receiver,
4425     LookupResult* lookup,
4426     Handle<Name> name,
4427     bool continue_search) {
4428   // Check access rights if needed.
4429   if (object->IsAccessCheckNeeded()) {
4430     Heap* heap = object->GetHeap();
4431     Handle<JSObject> obj = Handle<JSObject>::cast(object);
4432     if (!heap->isolate()->MayNamedAccessWrapper(obj, name, v8::ACCESS_HAS)) {
4433       return JSObject::GetPropertyAttributeWithFailedAccessCheck(
4434           obj, lookup, name, continue_search);
4435     }
4436   }
4437   if (lookup->IsFound()) {
4438     switch (lookup->type()) {
4439       case NORMAL:  // fall through
4440       case FIELD:
4441       case CONSTANT:
4442       case CALLBACKS:
4443         return lookup->GetAttributes();
4444       case HANDLER: {
4445         return JSProxy::GetPropertyAttributeWithHandler(
4446             handle(lookup->proxy()), receiver, name);
4447       }
4448       case INTERCEPTOR:
4449         return JSObject::GetPropertyAttributeWithInterceptor(
4450             handle(lookup->holder()),
4451             Handle<JSObject>::cast(receiver),
4452             name,
4453             continue_search);
4454       case TRANSITION:
4455       case NONEXISTENT:
4456         UNREACHABLE();
4457     }
4458   }
4459   return ABSENT;
4460 }
4461
4462
4463 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(
4464     Handle<JSReceiver> object, Handle<Name> name) {
4465   // Check whether the name is an array index.
4466   uint32_t index = 0;
4467   if (object->IsJSObject() && name->AsArrayIndex(&index)) {
4468     return GetLocalElementAttribute(object, index);
4469   }
4470   // Named property.
4471   LookupResult lookup(object->GetIsolate());
4472   object->LocalLookup(*name, &lookup, true);
4473   return GetPropertyAttributeForResult(object, object, &lookup, name, false);
4474 }
4475
4476
4477 PropertyAttributes JSObject::GetElementAttributeWithReceiver(
4478     Handle<JSObject> object,
4479     Handle<JSReceiver> receiver,
4480     uint32_t index,
4481     bool continue_search) {
4482   Isolate* isolate = object->GetIsolate();
4483
4484   // Check access rights if needed.
4485   if (object->IsAccessCheckNeeded()) {
4486     if (!isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_HAS)) {
4487       isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
4488       return ABSENT;
4489     }
4490   }
4491
4492   if (object->IsJSGlobalProxy()) {
4493     Handle<Object> proto(object->GetPrototype(), isolate);
4494     if (proto->IsNull()) return ABSENT;
4495     ASSERT(proto->IsJSGlobalObject());
4496     return JSObject::GetElementAttributeWithReceiver(
4497         Handle<JSObject>::cast(proto), receiver, index, continue_search);
4498   }
4499
4500   // Check for lookup interceptor except when bootstrapping.
4501   if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
4502     return JSObject::GetElementAttributeWithInterceptor(
4503         object, receiver, index, continue_search);
4504   }
4505
4506   return GetElementAttributeWithoutInterceptor(
4507       object, receiver, index, continue_search);
4508 }
4509
4510
4511 PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
4512     Handle<JSObject> object,
4513     Handle<JSReceiver> receiver,
4514     uint32_t index,
4515     bool continue_search) {
4516   Isolate* isolate = object->GetIsolate();
4517   HandleScope scope(isolate);
4518
4519   // Make sure that the top context does not change when doing
4520   // callbacks or interceptor calls.
4521   AssertNoContextChange ncc(isolate);
4522
4523   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
4524   PropertyCallbackArguments args(
4525       isolate, interceptor->data(), *receiver, *object);
4526   if (!interceptor->query()->IsUndefined()) {
4527     v8::IndexedPropertyQueryCallback query =
4528         v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4529     LOG(isolate,
4530         ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index));
4531     v8::Handle<v8::Integer> result = args.Call(query, index);
4532     if (!result.IsEmpty())
4533       return static_cast<PropertyAttributes>(result->Int32Value());
4534   } else if (!interceptor->getter()->IsUndefined()) {
4535     v8::IndexedPropertyGetterCallback getter =
4536         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4537     LOG(isolate,
4538         ApiIndexedPropertyAccess(
4539             "interceptor-indexed-get-has", *object, index));
4540     v8::Handle<v8::Value> result = args.Call(getter, index);
4541     if (!result.IsEmpty()) return NONE;
4542   }
4543
4544   return GetElementAttributeWithoutInterceptor(
4545        object, receiver, index, continue_search);
4546 }
4547
4548
4549 PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
4550     Handle<JSObject> object,
4551     Handle<JSReceiver> receiver,
4552     uint32_t index,
4553     bool continue_search) {
4554   PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes(
4555       *receiver, *object, index);
4556   if (attr != ABSENT) return attr;
4557
4558   // Handle [] on String objects.
4559   if (object->IsStringObjectWithCharacterAt(index)) {
4560     return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
4561   }
4562
4563   if (!continue_search) return ABSENT;
4564
4565   Handle<Object> proto(object->GetPrototype(), object->GetIsolate());
4566   if (proto->IsJSProxy()) {
4567     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
4568     return JSProxy::GetElementAttributeWithHandler(
4569         Handle<JSProxy>::cast(proto), receiver, index);
4570   }
4571   if (proto->IsNull()) return ABSENT;
4572   return GetElementAttributeWithReceiver(
4573       Handle<JSObject>::cast(proto), receiver, index, true);
4574 }
4575
4576
4577 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache,
4578                                     Handle<JSObject> obj,
4579                                     PropertyNormalizationMode mode) {
4580   int index = obj->map()->Hash() % kEntries;
4581   Handle<Object> result = handle(cache->get(index), cache->GetIsolate());
4582   if (result->IsMap() &&
4583       Handle<Map>::cast(result)->EquivalentToForNormalization(obj->map(),
4584                                                               mode)) {
4585 #ifdef VERIFY_HEAP
4586     if (FLAG_verify_heap) {
4587       Handle<Map>::cast(result)->SharedMapVerify();
4588     }
4589 #endif
4590 #ifdef ENABLE_SLOW_ASSERTS
4591     if (FLAG_enable_slow_asserts) {
4592       // The cached map should match newly created normalized map bit-by-bit,
4593       // except for the code cache, which can contain some ics which can be
4594       // applied to the shared map.
4595       Handle<Map> fresh = Map::CopyNormalized(handle(obj->map()), mode,
4596                                               SHARED_NORMALIZED_MAP);
4597
4598       ASSERT(memcmp(fresh->address(),
4599                     Handle<Map>::cast(result)->address(),
4600                     Map::kCodeCacheOffset) == 0);
4601       STATIC_ASSERT(Map::kDependentCodeOffset ==
4602                     Map::kCodeCacheOffset + kPointerSize);
4603       int offset = Map::kDependentCodeOffset + kPointerSize;
4604       ASSERT(memcmp(fresh->address() + offset,
4605                     Handle<Map>::cast(result)->address() + offset,
4606                     Map::kSize - offset) == 0);
4607     }
4608 #endif
4609     return Handle<Map>::cast(result);
4610   }
4611
4612   Isolate* isolate = cache->GetIsolate();
4613   Handle<Map> map = Map::CopyNormalized(handle(obj->map()), mode,
4614                                         SHARED_NORMALIZED_MAP);
4615   ASSERT(map->is_dictionary_map());
4616   cache->set(index, *map);
4617   isolate->counters()->normalized_maps()->Increment();
4618
4619   return map;
4620 }
4621
4622
4623 void NormalizedMapCache::Clear() {
4624   int entries = length();
4625   for (int i = 0; i != entries; i++) {
4626     set_undefined(i);
4627   }
4628 }
4629
4630
4631 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
4632                                     Handle<Name> name,
4633                                     Handle<Code> code) {
4634   Handle<Map> map(object->map());
4635   Map::UpdateCodeCache(map, name, code);
4636 }
4637
4638
4639 void JSObject::NormalizeProperties(Handle<JSObject> object,
4640                                    PropertyNormalizationMode mode,
4641                                    int expected_additional_properties) {
4642   if (!object->HasFastProperties()) return;
4643
4644   // The global object is always normalized.
4645   ASSERT(!object->IsGlobalObject());
4646   // JSGlobalProxy must never be normalized
4647   ASSERT(!object->IsJSGlobalProxy());
4648
4649   Isolate* isolate = object->GetIsolate();
4650   HandleScope scope(isolate);
4651   Handle<Map> map(object->map());
4652
4653   // Allocate new content.
4654   int real_size = map->NumberOfOwnDescriptors();
4655   int property_count = real_size;
4656   if (expected_additional_properties > 0) {
4657     property_count += expected_additional_properties;
4658   } else {
4659     property_count += 2;  // Make space for two more properties.
4660   }
4661   Handle<NameDictionary> dictionary =
4662       isolate->factory()->NewNameDictionary(property_count);
4663
4664   Handle<DescriptorArray> descs(map->instance_descriptors());
4665   for (int i = 0; i < real_size; i++) {
4666     PropertyDetails details = descs->GetDetails(i);
4667     switch (details.type()) {
4668       case CONSTANT: {
4669         Handle<Name> key(descs->GetKey(i));
4670         Handle<Object> value(descs->GetConstant(i), isolate);
4671         PropertyDetails d = PropertyDetails(
4672             details.attributes(), NORMAL, i + 1);
4673         dictionary = NameDictionaryAdd(dictionary, key, value, d);
4674         break;
4675       }
4676       case FIELD: {
4677         Handle<Name> key(descs->GetKey(i));
4678         Handle<Object> value(
4679             object->RawFastPropertyAt(descs->GetFieldIndex(i)), isolate);
4680         PropertyDetails d =
4681             PropertyDetails(details.attributes(), NORMAL, i + 1);
4682         dictionary = NameDictionaryAdd(dictionary, key, value, d);
4683         break;
4684       }
4685       case CALLBACKS: {
4686         Handle<Name> key(descs->GetKey(i));
4687         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4688         PropertyDetails d = PropertyDetails(
4689             details.attributes(), CALLBACKS, i + 1);
4690         dictionary = NameDictionaryAdd(dictionary, key, value, d);
4691         break;
4692       }
4693       case INTERCEPTOR:
4694         break;
4695       case HANDLER:
4696       case NORMAL:
4697       case TRANSITION:
4698       case NONEXISTENT:
4699         UNREACHABLE();
4700         break;
4701     }
4702   }
4703
4704   // Copy the next enumeration index from instance descriptor.
4705   dictionary->SetNextEnumerationIndex(real_size + 1);
4706
4707   Handle<NormalizedMapCache> cache(
4708       isolate->context()->native_context()->normalized_map_cache());
4709   Handle<Map> new_map = NormalizedMapCache::Get(cache, object, mode);
4710   ASSERT(new_map->is_dictionary_map());
4711
4712   // From here on we cannot fail and we shouldn't GC anymore.
4713   DisallowHeapAllocation no_allocation;
4714
4715   // Resize the object in the heap if necessary.
4716   int new_instance_size = new_map->instance_size();
4717   int instance_size_delta = map->instance_size() - new_instance_size;
4718   ASSERT(instance_size_delta >= 0);
4719   Heap* heap = isolate->heap();
4720   heap->CreateFillerObjectAt(object->address() + new_instance_size,
4721                              instance_size_delta);
4722   heap->AdjustLiveBytes(object->address(),
4723                         -instance_size_delta,
4724                         Heap::FROM_MUTATOR);
4725
4726   object->set_map(*new_map);
4727   map->NotifyLeafMapLayoutChange();
4728
4729   object->set_properties(*dictionary);
4730
4731   isolate->counters()->props_to_dictionary()->Increment();
4732
4733 #ifdef DEBUG
4734   if (FLAG_trace_normalization) {
4735     PrintF("Object properties have been normalized:\n");
4736     object->Print();
4737   }
4738 #endif
4739 }
4740
4741
4742 void JSObject::TransformToFastProperties(Handle<JSObject> object,
4743                                          int unused_property_fields) {
4744   if (object->HasFastProperties()) return;
4745   ASSERT(!object->IsGlobalObject());
4746   CALL_HEAP_FUNCTION_VOID(
4747       object->GetIsolate(),
4748       object->property_dictionary()->TransformPropertiesToFastFor(
4749           *object, unused_property_fields));
4750 }
4751
4752
4753 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4754     Handle<FixedArrayBase> array,
4755     int length,
4756     Handle<SeededNumberDictionary> dictionary) {
4757   Isolate* isolate = array->GetIsolate();
4758   Factory* factory = isolate->factory();
4759   bool has_double_elements = array->IsFixedDoubleArray();
4760   for (int i = 0; i < length; i++) {
4761     Handle<Object> value;
4762     if (has_double_elements) {
4763       Handle<FixedDoubleArray> double_array =
4764           Handle<FixedDoubleArray>::cast(array);
4765       if (double_array->is_the_hole(i)) {
4766         value = factory->the_hole_value();
4767       } else {
4768         value = factory->NewHeapNumber(double_array->get_scalar(i));
4769       }
4770     } else {
4771       value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4772     }
4773     if (!value->IsTheHole()) {
4774       PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
4775       dictionary =
4776           SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4777     }
4778   }
4779   return dictionary;
4780 }
4781
4782
4783 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4784     Handle<JSObject> object) {
4785   ASSERT(!object->HasExternalArrayElements() &&
4786          !object->HasFixedTypedArrayElements());
4787   Isolate* isolate = object->GetIsolate();
4788   Factory* factory = isolate->factory();
4789
4790   // Find the backing store.
4791   Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements()));
4792   bool is_arguments =
4793       (array->map() == isolate->heap()->sloppy_arguments_elements_map());
4794   if (is_arguments) {
4795     array = handle(FixedArrayBase::cast(
4796         Handle<FixedArray>::cast(array)->get(1)));
4797   }
4798   if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array);
4799
4800   ASSERT(object->HasFastSmiOrObjectElements() ||
4801          object->HasFastDoubleElements() ||
4802          object->HasFastArgumentsElements());
4803   // Compute the effective length and allocate a new backing store.
4804   int length = object->IsJSArray()
4805       ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4806       : array->length();
4807   int old_capacity = 0;
4808   int used_elements = 0;
4809   object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4810   Handle<SeededNumberDictionary> dictionary =
4811       factory->NewSeededNumberDictionary(used_elements);
4812
4813   dictionary = CopyFastElementsToDictionary(array, length, dictionary);
4814
4815   // Switch to using the dictionary as the backing storage for elements.
4816   if (is_arguments) {
4817     FixedArray::cast(object->elements())->set(1, *dictionary);
4818   } else {
4819     // Set the new map first to satify the elements type assert in
4820     // set_elements().
4821     Handle<Map> new_map =
4822         JSObject::GetElementsTransitionMap(object, DICTIONARY_ELEMENTS);
4823
4824     JSObject::MigrateToMap(object, new_map);
4825     object->set_elements(*dictionary);
4826   }
4827
4828   isolate->counters()->elements_to_dictionary()->Increment();
4829
4830 #ifdef DEBUG
4831   if (FLAG_trace_normalization) {
4832     PrintF("Object elements have been normalized:\n");
4833     object->Print();
4834   }
4835 #endif
4836
4837   ASSERT(object->HasDictionaryElements() ||
4838          object->HasDictionaryArgumentsElements());
4839   return dictionary;
4840 }
4841
4842
4843 Smi* JSReceiver::GenerateIdentityHash() {
4844   Isolate* isolate = GetIsolate();
4845
4846   int hash_value;
4847   int attempts = 0;
4848   do {
4849     // Generate a random 32-bit hash value but limit range to fit
4850     // within a smi.
4851     hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4852     attempts++;
4853   } while (hash_value == 0 && attempts < 30);
4854   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
4855
4856   return Smi::FromInt(hash_value);
4857 }
4858
4859
4860 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4861   Isolate* isolate = object->GetIsolate();
4862   SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4863 }
4864
4865
4866 Object* JSObject::GetIdentityHash() {
4867   Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_string());
4868   return stored_value->IsSmi() ? stored_value : GetHeap()->undefined_value();
4869 }
4870
4871
4872 Handle<Object> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
4873   Handle<Object> hash(object->GetIdentityHash(), object->GetIsolate());
4874   if (hash->IsSmi())
4875     return hash;
4876
4877   Isolate* isolate = object->GetIsolate();
4878
4879   hash = handle(object->GenerateIdentityHash(), isolate);
4880   Handle<Object> result = SetHiddenProperty(object,
4881       isolate->factory()->identity_hash_string(), hash);
4882
4883   if (result->IsUndefined()) {
4884     // Trying to get hash of detached proxy.
4885     return handle(Smi::FromInt(0), isolate);
4886   }
4887
4888   return hash;
4889 }
4890
4891
4892 Object* JSProxy::GetIdentityHash() {
4893   return this->hash();
4894 }
4895
4896
4897 Handle<Object> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
4898   Isolate* isolate = proxy->GetIsolate();
4899
4900   Handle<Object> hash(proxy->GetIdentityHash(), isolate);
4901   if (hash->IsSmi())
4902     return hash;
4903
4904   hash = handle(proxy->GenerateIdentityHash(), isolate);
4905   proxy->set_hash(*hash);
4906   return hash;
4907 }
4908
4909
4910 Object* JSObject::GetHiddenProperty(Name* key) {
4911   ASSERT(key->IsUniqueName());
4912   if (IsJSGlobalProxy()) {
4913     // For a proxy, use the prototype as target object.
4914     Object* proxy_parent = GetPrototype();
4915     // If the proxy is detached, return undefined.
4916     if (proxy_parent->IsNull()) return GetHeap()->the_hole_value();
4917     ASSERT(proxy_parent->IsJSGlobalObject());
4918     return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
4919   }
4920   ASSERT(!IsJSGlobalProxy());
4921   Object* inline_value = GetHiddenPropertiesHashTable();
4922
4923   if (inline_value->IsSmi()) {
4924     // Handle inline-stored identity hash.
4925     if (key == GetHeap()->identity_hash_string()) {
4926       return inline_value;
4927     } else {
4928       return GetHeap()->the_hole_value();
4929     }
4930   }
4931
4932   if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
4933
4934   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
4935   Object* entry = hashtable->Lookup(key);
4936   return entry;
4937 }
4938
4939
4940 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
4941                                            Handle<Name> key,
4942                                            Handle<Object> value) {
4943   Isolate* isolate = object->GetIsolate();
4944
4945   ASSERT(key->IsUniqueName());
4946   if (object->IsJSGlobalProxy()) {
4947     // For a proxy, use the prototype as target object.
4948     Handle<Object> proxy_parent(object->GetPrototype(), isolate);
4949     // If the proxy is detached, return undefined.
4950     if (proxy_parent->IsNull()) return isolate->factory()->undefined_value();
4951     ASSERT(proxy_parent->IsJSGlobalObject());
4952     return SetHiddenProperty(Handle<JSObject>::cast(proxy_parent), key, value);
4953   }
4954   ASSERT(!object->IsJSGlobalProxy());
4955
4956   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
4957
4958   // If there is no backing store yet, store the identity hash inline.
4959   if (value->IsSmi() &&
4960       *key == *isolate->factory()->identity_hash_string() &&
4961       (inline_value->IsUndefined() || inline_value->IsSmi())) {
4962     return JSObject::SetHiddenPropertiesHashTable(object, value);
4963   }
4964
4965   Handle<ObjectHashTable> hashtable =
4966       GetOrCreateHiddenPropertiesHashtable(object);
4967
4968   // If it was found, check if the key is already in the dictionary.
4969   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
4970                                                            value);
4971   if (*new_table != *hashtable) {
4972     // If adding the key expanded the dictionary (i.e., Add returned a new
4973     // dictionary), store it back to the object.
4974     SetHiddenPropertiesHashTable(object, new_table);
4975   }
4976
4977   // Return this to mark success.
4978   return object;
4979 }
4980
4981
4982 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
4983   Isolate* isolate = object->GetIsolate();
4984   ASSERT(key->IsUniqueName());
4985
4986   if (object->IsJSGlobalProxy()) {
4987     Handle<Object> proto(object->GetPrototype(), isolate);
4988     if (proto->IsNull()) return;
4989     ASSERT(proto->IsJSGlobalObject());
4990     return DeleteHiddenProperty(Handle<JSObject>::cast(proto), key);
4991   }
4992
4993   Object* inline_value = object->GetHiddenPropertiesHashTable();
4994
4995   // We never delete (inline-stored) identity hashes.
4996   ASSERT(*key != *isolate->factory()->identity_hash_string());
4997   if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
4998
4999   Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
5000   ObjectHashTable::Put(hashtable, key, isolate->factory()->the_hole_value());
5001 }
5002
5003
5004 bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
5005   Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
5006   return GetPropertyAttributePostInterceptor(
5007       object, object, hidden, false) != ABSENT;
5008 }
5009
5010
5011 Object* JSObject::GetHiddenPropertiesHashTable() {
5012   ASSERT(!IsJSGlobalProxy());
5013   if (HasFastProperties()) {
5014     // If the object has fast properties, check whether the first slot
5015     // in the descriptor array matches the hidden string. Since the
5016     // hidden strings hash code is zero (and no other name has hash
5017     // code zero) it will always occupy the first entry if present.
5018     DescriptorArray* descriptors = this->map()->instance_descriptors();
5019     if (descriptors->number_of_descriptors() > 0) {
5020       int sorted_index = descriptors->GetSortedKeyIndex(0);
5021       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
5022           sorted_index < map()->NumberOfOwnDescriptors()) {
5023         ASSERT(descriptors->GetType(sorted_index) == FIELD);
5024         ASSERT(descriptors->GetDetails(sorted_index).representation().
5025                IsCompatibleForLoad(Representation::Tagged()));
5026         return this->RawFastPropertyAt(
5027             descriptors->GetFieldIndex(sorted_index));
5028       } else {
5029         return GetHeap()->undefined_value();
5030       }
5031     } else {
5032       return GetHeap()->undefined_value();
5033     }
5034   } else {
5035     PropertyAttributes attributes;
5036     // You can't install a getter on a property indexed by the hidden string,
5037     // so we can be sure that GetLocalPropertyPostInterceptor returns a real
5038     // object.
5039     return GetLocalPropertyPostInterceptor(this,
5040                                            GetHeap()->hidden_string(),
5041                                            &attributes)->ToObjectUnchecked();
5042   }
5043 }
5044
5045 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
5046     Handle<JSObject> object) {
5047   Isolate* isolate = object->GetIsolate();
5048
5049   static const int kInitialCapacity = 4;
5050   Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
5051   if (inline_value->IsHashTable()) {
5052     return Handle<ObjectHashTable>::cast(inline_value);
5053   }
5054
5055   Handle<ObjectHashTable> hashtable = isolate->factory()->NewObjectHashTable(
5056       kInitialCapacity,
5057       USE_CUSTOM_MINIMUM_CAPACITY);
5058
5059   if (inline_value->IsSmi()) {
5060     // We were storing the identity hash inline and now allocated an actual
5061     // dictionary.  Put the identity hash into the new dictionary.
5062     hashtable = ObjectHashTable::Put(hashtable,
5063                                      isolate->factory()->identity_hash_string(),
5064                                      inline_value);
5065   }
5066
5067   JSObject::SetLocalPropertyIgnoreAttributes(
5068       object,
5069       isolate->factory()->hidden_string(),
5070       hashtable,
5071       DONT_ENUM,
5072       OPTIMAL_REPRESENTATION,
5073       ALLOW_AS_CONSTANT,
5074       OMIT_EXTENSIBILITY_CHECK);
5075
5076   return hashtable;
5077 }
5078
5079
5080 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
5081                                                       Handle<Object> value) {
5082   ASSERT(!object->IsJSGlobalProxy());
5083
5084   Isolate* isolate = object->GetIsolate();
5085
5086   // We can store the identity hash inline iff there is no backing store
5087   // for hidden properties yet.
5088   ASSERT(JSObject::HasHiddenProperties(object) != value->IsSmi());
5089   if (object->HasFastProperties()) {
5090     // If the object has fast properties, check whether the first slot
5091     // in the descriptor array matches the hidden string. Since the
5092     // hidden strings hash code is zero (and no other name has hash
5093     // code zero) it will always occupy the first entry if present.
5094     DescriptorArray* descriptors = object->map()->instance_descriptors();
5095     if (descriptors->number_of_descriptors() > 0) {
5096       int sorted_index = descriptors->GetSortedKeyIndex(0);
5097       if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string()
5098           && sorted_index < object->map()->NumberOfOwnDescriptors()) {
5099         ASSERT(descriptors->GetType(sorted_index) == FIELD);
5100         object->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
5101                                   *value);
5102         return object;
5103       }
5104     }
5105   }
5106
5107   SetLocalPropertyIgnoreAttributes(object,
5108                                    isolate->factory()->hidden_string(),
5109                                    value,
5110                                    DONT_ENUM,
5111                                    OPTIMAL_REPRESENTATION,
5112                                    ALLOW_AS_CONSTANT,
5113                                    OMIT_EXTENSIBILITY_CHECK);
5114   return object;
5115 }
5116
5117
5118 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object,
5119                                                        Handle<Name> name,
5120                                                        DeleteMode mode) {
5121   // Check local property, ignore interceptor.
5122   Isolate* isolate = object->GetIsolate();
5123   LookupResult result(isolate);
5124   object->LocalLookupRealNamedProperty(*name, &result);
5125   if (!result.IsFound()) return isolate->factory()->true_value();
5126
5127   // Normalize object if needed.
5128   NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5129
5130   return DeleteNormalizedProperty(object, name, mode);
5131 }
5132
5133
5134 Handle<Object> JSObject::DeletePropertyWithInterceptor(Handle<JSObject> object,
5135                                                        Handle<Name> name) {
5136   Isolate* isolate = object->GetIsolate();
5137
5138   // TODO(rossberg): Support symbols in the API.
5139   if (name->IsSymbol()) return isolate->factory()->false_value();
5140
5141   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
5142   if (!interceptor->deleter()->IsUndefined()) {
5143     v8::NamedPropertyDeleterCallback deleter =
5144         v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter());
5145     LOG(isolate,
5146         ApiNamedPropertyAccess("interceptor-named-delete", *object, *name));
5147     PropertyCallbackArguments args(
5148         isolate, interceptor->data(), *object, *object);
5149     v8::Handle<v8::Boolean> result =
5150         args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name)));
5151     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5152     if (!result.IsEmpty()) {
5153       ASSERT(result->IsBoolean());
5154       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5155       result_internal->VerifyApiCallResultType();
5156       // Rebox CustomArguments::kReturnValueOffset before returning.
5157       return handle(*result_internal, isolate);
5158     }
5159   }
5160   Handle<Object> result =
5161       DeletePropertyPostInterceptor(object, name, NORMAL_DELETION);
5162   RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5163   return result;
5164 }
5165
5166
5167 Handle<Object> JSObject::DeleteElementWithInterceptor(Handle<JSObject> object,
5168                                                       uint32_t index) {
5169   Isolate* isolate = object->GetIsolate();
5170   Factory* factory = isolate->factory();
5171
5172   // Make sure that the top context does not change when doing
5173   // callbacks or interceptor calls.
5174   AssertNoContextChange ncc(isolate);
5175
5176   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
5177   if (interceptor->deleter()->IsUndefined()) return factory->false_value();
5178   v8::IndexedPropertyDeleterCallback deleter =
5179       v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
5180   LOG(isolate,
5181       ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index));
5182   PropertyCallbackArguments args(
5183       isolate, interceptor->data(), *object, *object);
5184   v8::Handle<v8::Boolean> result = args.Call(deleter, index);
5185   RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5186   if (!result.IsEmpty()) {
5187     ASSERT(result->IsBoolean());
5188     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
5189     result_internal->VerifyApiCallResultType();
5190     // Rebox CustomArguments::kReturnValueOffset before returning.
5191     return handle(*result_internal, isolate);
5192   }
5193   Handle<Object> delete_result = object->GetElementsAccessor()->Delete(
5194       object, index, NORMAL_DELETION);
5195   RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5196   return delete_result;
5197 }
5198
5199
5200 Handle<Object> JSObject::DeleteElement(Handle<JSObject> object,
5201                                        uint32_t index,
5202                                        DeleteMode mode) {
5203   Isolate* isolate = object->GetIsolate();
5204   Factory* factory = isolate->factory();
5205
5206   // Check access rights if needed.
5207   if (object->IsAccessCheckNeeded() &&
5208       !isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_DELETE)) {
5209     isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_DELETE);
5210     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5211     return factory->false_value();
5212   }
5213
5214   if (object->IsStringObjectWithCharacterAt(index)) {
5215     if (mode == STRICT_DELETION) {
5216       // Deleting a non-configurable property in strict mode.
5217       Handle<Object> name = factory->NewNumberFromUint(index);
5218       Handle<Object> args[2] = { name, object };
5219       Handle<Object> error =
5220           factory->NewTypeError("strict_delete_property",
5221                                 HandleVector(args, 2));
5222       isolate->Throw(*error);
5223       return Handle<Object>();
5224     }
5225     return factory->false_value();
5226   }
5227
5228   if (object->IsJSGlobalProxy()) {
5229     Handle<Object> proto(object->GetPrototype(), isolate);
5230     if (proto->IsNull()) return factory->false_value();
5231     ASSERT(proto->IsJSGlobalObject());
5232     return DeleteElement(Handle<JSObject>::cast(proto), index, mode);
5233   }
5234
5235   Handle<Object> old_value;
5236   bool should_enqueue_change_record = false;
5237   if (object->map()->is_observed()) {
5238     should_enqueue_change_record = HasLocalElement(object, index);
5239     if (should_enqueue_change_record) {
5240       if (object->GetLocalElementAccessorPair(index) != NULL) {
5241         old_value = Handle<Object>::cast(factory->the_hole_value());
5242       } else {
5243         old_value = Object::GetElementNoExceptionThrown(isolate, object, index);
5244       }
5245     }
5246   }
5247
5248   // Skip interceptor if forcing deletion.
5249   Handle<Object> result;
5250   if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) {
5251     result = DeleteElementWithInterceptor(object, index);
5252   } else {
5253     result = object->GetElementsAccessor()->Delete(object, index, mode);
5254   }
5255
5256   if (should_enqueue_change_record && !HasLocalElement(object, index)) {
5257     Handle<String> name = factory->Uint32ToString(index);
5258     EnqueueChangeRecord(object, "delete", name, old_value);
5259   }
5260
5261   return result;
5262 }
5263
5264
5265 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
5266                                         Handle<Name> name,
5267                                         DeleteMode mode) {
5268   Isolate* isolate = object->GetIsolate();
5269   // ECMA-262, 3rd, 8.6.2.5
5270   ASSERT(name->IsName());
5271
5272   // Check access rights if needed.
5273   if (object->IsAccessCheckNeeded() &&
5274       !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_DELETE)) {
5275     isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_DELETE);
5276     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5277     return isolate->factory()->false_value();
5278   }
5279
5280   if (object->IsJSGlobalProxy()) {
5281     Object* proto = object->GetPrototype();
5282     if (proto->IsNull()) return isolate->factory()->false_value();
5283     ASSERT(proto->IsJSGlobalObject());
5284     return JSGlobalObject::DeleteProperty(
5285         handle(JSGlobalObject::cast(proto)), name, mode);
5286   }
5287
5288   uint32_t index = 0;
5289   if (name->AsArrayIndex(&index)) {
5290     return DeleteElement(object, index, mode);
5291   }
5292
5293   LookupResult lookup(isolate);
5294   object->LocalLookup(*name, &lookup, true);
5295   if (!lookup.IsFound()) return isolate->factory()->true_value();
5296   // Ignore attributes if forcing a deletion.
5297   if (lookup.IsDontDelete() && mode != FORCE_DELETION) {
5298     if (mode == STRICT_DELETION) {
5299       // Deleting a non-configurable property in strict mode.
5300       Handle<Object> args[2] = { name, object };
5301       Handle<Object> error = isolate->factory()->NewTypeError(
5302           "strict_delete_property", HandleVector(args, ARRAY_SIZE(args)));
5303       isolate->Throw(*error);
5304       return Handle<Object>();
5305     }
5306     return isolate->factory()->false_value();
5307   }
5308
5309   Handle<Object> old_value = isolate->factory()->the_hole_value();
5310   bool is_observed = object->map()->is_observed() &&
5311                      *name != isolate->heap()->hidden_string();
5312   if (is_observed && lookup.IsDataProperty()) {
5313     old_value = Object::GetProperty(object, name);
5314     CHECK_NOT_EMPTY_HANDLE(isolate, old_value);
5315   }
5316   Handle<Object> result;
5317
5318   // Check for interceptor.
5319   if (lookup.IsInterceptor()) {
5320     // Skip interceptor if forcing a deletion.
5321     if (mode == FORCE_DELETION) {
5322       result = DeletePropertyPostInterceptor(object, name, mode);
5323     } else {
5324       result = DeletePropertyWithInterceptor(object, name);
5325     }
5326   } else {
5327     // Normalize object if needed.
5328     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5329     // Make sure the properties are normalized before removing the entry.
5330     result = DeleteNormalizedProperty(object, name, mode);
5331   }
5332
5333   if (is_observed && !HasLocalProperty(object, name)) {
5334     EnqueueChangeRecord(object, "delete", name, old_value);
5335   }
5336
5337   return result;
5338 }
5339
5340
5341 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
5342                                          uint32_t index,
5343                                          DeleteMode mode) {
5344   if (object->IsJSProxy()) {
5345     return JSProxy::DeleteElementWithHandler(
5346         Handle<JSProxy>::cast(object), index, mode);
5347   }
5348   return JSObject::DeleteElement(Handle<JSObject>::cast(object), index, mode);
5349 }
5350
5351
5352 Handle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
5353                                           Handle<Name> name,
5354                                           DeleteMode mode) {
5355   if (object->IsJSProxy()) {
5356     return JSProxy::DeletePropertyWithHandler(
5357         Handle<JSProxy>::cast(object), name, mode);
5358   }
5359   return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, mode);
5360 }
5361
5362
5363 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
5364                                             ElementsKind kind,
5365                                             Object* object) {
5366   ASSERT(IsFastObjectElementsKind(kind) ||
5367          kind == DICTIONARY_ELEMENTS);
5368   if (IsFastObjectElementsKind(kind)) {
5369     int length = IsJSArray()
5370         ? Smi::cast(JSArray::cast(this)->length())->value()
5371         : elements->length();
5372     for (int i = 0; i < length; ++i) {
5373       Object* element = elements->get(i);
5374       if (!element->IsTheHole() && element == object) return true;
5375     }
5376   } else {
5377     Object* key =
5378         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5379     if (!key->IsUndefined()) return true;
5380   }
5381   return false;
5382 }
5383
5384
5385 // Check whether this object references another object.
5386 bool JSObject::ReferencesObject(Object* obj) {
5387   Map* map_of_this = map();
5388   Heap* heap = GetHeap();
5389   DisallowHeapAllocation no_allocation;
5390
5391   // Is the object the constructor for this object?
5392   if (map_of_this->constructor() == obj) {
5393     return true;
5394   }
5395
5396   // Is the object the prototype for this object?
5397   if (map_of_this->prototype() == obj) {
5398     return true;
5399   }
5400
5401   // Check if the object is among the named properties.
5402   Object* key = SlowReverseLookup(obj);
5403   if (!key->IsUndefined()) {
5404     return true;
5405   }
5406
5407   // Check if the object is among the indexed properties.
5408   ElementsKind kind = GetElementsKind();
5409   switch (kind) {
5410     // Raw pixels and external arrays do not reference other
5411     // objects.
5412 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5413     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
5414     case TYPE##_ELEMENTS:                                                      \
5415       break;
5416
5417     TYPED_ARRAYS(TYPED_ARRAY_CASE)
5418 #undef TYPED_ARRAY_CASE
5419
5420     case FAST_DOUBLE_ELEMENTS:
5421     case FAST_HOLEY_DOUBLE_ELEMENTS:
5422       break;
5423     case FAST_SMI_ELEMENTS:
5424     case FAST_HOLEY_SMI_ELEMENTS:
5425       break;
5426     case FAST_ELEMENTS:
5427     case FAST_HOLEY_ELEMENTS:
5428     case DICTIONARY_ELEMENTS: {
5429       FixedArray* elements = FixedArray::cast(this->elements());
5430       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5431       break;
5432     }
5433     case SLOPPY_ARGUMENTS_ELEMENTS: {
5434       FixedArray* parameter_map = FixedArray::cast(elements());
5435       // Check the mapped parameters.
5436       int length = parameter_map->length();
5437       for (int i = 2; i < length; ++i) {
5438         Object* value = parameter_map->get(i);
5439         if (!value->IsTheHole() && value == obj) return true;
5440       }
5441       // Check the arguments.
5442       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5443       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5444           FAST_HOLEY_ELEMENTS;
5445       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5446       break;
5447     }
5448   }
5449
5450   // For functions check the context.
5451   if (IsJSFunction()) {
5452     // Get the constructor function for arguments array.
5453     JSObject* arguments_boilerplate =
5454         heap->isolate()->context()->native_context()->
5455             sloppy_arguments_boilerplate();
5456     JSFunction* arguments_function =
5457         JSFunction::cast(arguments_boilerplate->map()->constructor());
5458
5459     // Get the context and don't check if it is the native context.
5460     JSFunction* f = JSFunction::cast(this);
5461     Context* context = f->context();
5462     if (context->IsNativeContext()) {
5463       return false;
5464     }
5465
5466     // Check the non-special context slots.
5467     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5468       // Only check JS objects.
5469       if (context->get(i)->IsJSObject()) {
5470         JSObject* ctxobj = JSObject::cast(context->get(i));
5471         // If it is an arguments array check the content.
5472         if (ctxobj->map()->constructor() == arguments_function) {
5473           if (ctxobj->ReferencesObject(obj)) {
5474             return true;
5475           }
5476         } else if (ctxobj == obj) {
5477           return true;
5478         }
5479       }
5480     }
5481
5482     // Check the context extension (if any) if it can have references.
5483     if (context->has_extension() && !context->IsCatchContext()) {
5484       // With harmony scoping, a JSFunction may have a global context.
5485       // TODO(mvstanton): walk into the ScopeInfo.
5486       if (FLAG_harmony_scoping && context->IsGlobalContext()) {
5487         return false;
5488       }
5489
5490       return JSObject::cast(context->extension())->ReferencesObject(obj);
5491     }
5492   }
5493
5494   // No references to object.
5495   return false;
5496 }
5497
5498
5499 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5500   Isolate* isolate = object->GetIsolate();
5501
5502   if (!object->map()->is_extensible()) return object;
5503
5504   if (object->IsAccessCheckNeeded() &&
5505       !isolate->MayNamedAccessWrapper(object,
5506                                       isolate->factory()->undefined_value(),
5507                                       v8::ACCESS_KEYS)) {
5508     isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS);
5509     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5510     return isolate->factory()->false_value();
5511   }
5512
5513   if (object->IsJSGlobalProxy()) {
5514     Handle<Object> proto(object->GetPrototype(), isolate);
5515     if (proto->IsNull()) return object;
5516     ASSERT(proto->IsJSGlobalObject());
5517     return PreventExtensions(Handle<JSObject>::cast(proto));
5518   }
5519
5520   // It's not possible to seal objects with external array elements
5521   if (object->HasExternalArrayElements() ||
5522       object->HasFixedTypedArrayElements()) {
5523     Handle<Object> error  =
5524         isolate->factory()->NewTypeError(
5525             "cant_prevent_ext_external_array_elements",
5526             HandleVector(&object, 1));
5527     isolate->Throw(*error);
5528     return Handle<Object>();
5529   }
5530
5531   // If there are fast elements we normalize.
5532   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5533   ASSERT(object->HasDictionaryElements() ||
5534          object->HasDictionaryArgumentsElements());
5535
5536   // Make sure that we never go back to fast case.
5537   dictionary->set_requires_slow_elements();
5538
5539   // Do a map transition, other objects with this map may still
5540   // be extensible.
5541   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5542   Handle<Map> new_map = Map::Copy(handle(object->map()));
5543
5544   new_map->set_is_extensible(false);
5545   JSObject::MigrateToMap(object, new_map);
5546   ASSERT(!object->map()->is_extensible());
5547
5548   if (object->map()->is_observed()) {
5549     EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5550                         isolate->factory()->the_hole_value());
5551   }
5552   return object;
5553 }
5554
5555
5556 template<typename Dictionary>
5557 static void FreezeDictionary(Dictionary* dictionary) {
5558   int capacity = dictionary->Capacity();
5559   for (int i = 0; i < capacity; i++) {
5560     Object* k = dictionary->KeyAt(i);
5561     if (dictionary->IsKey(k)) {
5562       PropertyDetails details = dictionary->DetailsAt(i);
5563       int attrs = DONT_DELETE;
5564       // READ_ONLY is an invalid attribute for JS setters/getters.
5565       if (details.type() != CALLBACKS ||
5566           !dictionary->ValueAt(i)->IsAccessorPair()) {
5567         attrs |= READ_ONLY;
5568       }
5569       details = details.CopyAddAttributes(
5570           static_cast<PropertyAttributes>(attrs));
5571       dictionary->DetailsAtPut(i, details);
5572     }
5573   }
5574 }
5575
5576
5577 Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
5578   // Freezing sloppy arguments should be handled elsewhere.
5579   ASSERT(!object->HasSloppyArgumentsElements());
5580   ASSERT(!object->map()->is_observed());
5581
5582   if (object->map()->is_frozen()) return object;
5583
5584   Isolate* isolate = object->GetIsolate();
5585   if (object->IsAccessCheckNeeded() &&
5586       !isolate->MayNamedAccessWrapper(object,
5587                                       isolate->factory()->undefined_value(),
5588                                       v8::ACCESS_KEYS)) {
5589     isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS);
5590     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5591     return isolate->factory()->false_value();
5592   }
5593
5594   if (object->IsJSGlobalProxy()) {
5595     Handle<Object> proto(object->GetPrototype(), isolate);
5596     if (proto->IsNull()) return object;
5597     ASSERT(proto->IsJSGlobalObject());
5598     return Freeze(Handle<JSObject>::cast(proto));
5599   }
5600
5601   // It's not possible to freeze objects with external array elements
5602   if (object->HasExternalArrayElements() ||
5603       object->HasFixedTypedArrayElements()) {
5604     Handle<Object> error  =
5605         isolate->factory()->NewTypeError(
5606             "cant_prevent_ext_external_array_elements",
5607             HandleVector(&object, 1));
5608     isolate->Throw(*error);
5609     return Handle<Object>();
5610   }
5611
5612   Handle<SeededNumberDictionary> new_element_dictionary;
5613   if (!object->elements()->IsDictionary()) {
5614     int length = object->IsJSArray()
5615         ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5616         : object->elements()->length();
5617     if (length > 0) {
5618       int capacity = 0;
5619       int used = 0;
5620       object->GetElementsCapacityAndUsage(&capacity, &used);
5621       new_element_dictionary =
5622           isolate->factory()->NewSeededNumberDictionary(used);
5623
5624       // Move elements to a dictionary; avoid calling NormalizeElements to avoid
5625       // unnecessary transitions.
5626       new_element_dictionary = CopyFastElementsToDictionary(
5627           handle(object->elements()), length, new_element_dictionary);
5628     } else {
5629       // No existing elements, use a pre-allocated empty backing store
5630       new_element_dictionary =
5631           isolate->factory()->empty_slow_element_dictionary();
5632     }
5633   }
5634
5635   LookupResult result(isolate);
5636   Handle<Map> old_map(object->map());
5637   old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result);
5638   if (result.IsTransition()) {
5639     Handle<Map> transition_map(result.GetTransitionTarget());
5640     ASSERT(transition_map->has_dictionary_elements());
5641     ASSERT(transition_map->is_frozen());
5642     ASSERT(!transition_map->is_extensible());
5643     JSObject::MigrateToMap(object, transition_map);
5644   } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5645     // Create a new descriptor array with fully-frozen properties
5646     int num_descriptors = old_map->NumberOfOwnDescriptors();
5647     Handle<DescriptorArray> new_descriptors =
5648         DescriptorArray::CopyUpToAddAttributes(
5649             handle(old_map->instance_descriptors()), num_descriptors, FROZEN);
5650     Handle<Map> new_map = Map::CopyReplaceDescriptors(
5651         old_map, new_descriptors, INSERT_TRANSITION,
5652         isolate->factory()->frozen_symbol());
5653     new_map->freeze();
5654     new_map->set_is_extensible(false);
5655     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5656     JSObject::MigrateToMap(object, new_map);
5657   } else {
5658     // Slow path: need to normalize properties for safety
5659     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5660
5661     // Create a new map, since other objects with this map may be extensible.
5662     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5663     Handle<Map> new_map = Map::Copy(handle(object->map()));
5664     new_map->freeze();
5665     new_map->set_is_extensible(false);
5666     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5667     JSObject::MigrateToMap(object, new_map);
5668
5669     // Freeze dictionary-mode properties
5670     FreezeDictionary(object->property_dictionary());
5671   }
5672
5673   ASSERT(object->map()->has_dictionary_elements());
5674   if (!new_element_dictionary.is_null()) {
5675     object->set_elements(*new_element_dictionary);
5676   }
5677
5678   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5679     SeededNumberDictionary* dictionary = object->element_dictionary();
5680     // Make sure we never go back to the fast case
5681     dictionary->set_requires_slow_elements();
5682     // Freeze all elements in the dictionary
5683     FreezeDictionary(dictionary);
5684   }
5685
5686   return object;
5687 }
5688
5689
5690 void JSObject::SetObserved(Handle<JSObject> object) {
5691   Isolate* isolate = object->GetIsolate();
5692
5693   if (object->map()->is_observed())
5694     return;
5695
5696   LookupResult result(isolate);
5697   object->map()->LookupTransition(*object,
5698                                   isolate->heap()->observed_symbol(),
5699                                   &result);
5700
5701   Handle<Map> new_map;
5702   if (result.IsTransition()) {
5703     new_map = handle(result.GetTransitionTarget());
5704     ASSERT(new_map->is_observed());
5705   } else if (object->map()->CanHaveMoreTransitions()) {
5706     new_map = Map::CopyForObserved(handle(object->map()));
5707   } else {
5708     new_map = Map::Copy(handle(object->map()));
5709     new_map->set_is_observed();
5710   }
5711   JSObject::MigrateToMap(object, new_map);
5712 }
5713
5714
5715 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) {
5716   Isolate* isolate = object->GetIsolate();
5717   CALL_HEAP_FUNCTION(isolate,
5718                      isolate->heap()->CopyJSObject(*object), JSObject);
5719 }
5720
5721
5722 template<class ContextObject>
5723 class JSObjectWalkVisitor {
5724  public:
5725   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5726                       JSObject::DeepCopyHints hints)
5727     : site_context_(site_context),
5728       copying_(copying),
5729       hints_(hints) {}
5730
5731   Handle<JSObject> StructureWalk(Handle<JSObject> object);
5732
5733  protected:
5734   inline Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object,
5735                                                  Handle<JSObject> value) {
5736     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5737     Handle<JSObject> copy_of_value = StructureWalk(value);
5738     site_context()->ExitScope(current_site, value);
5739     return copy_of_value;
5740   }
5741
5742   inline ContextObject* site_context() { return site_context_; }
5743   inline Isolate* isolate() { return site_context()->isolate(); }
5744
5745   inline bool copying() const { return copying_; }
5746
5747  private:
5748   ContextObject* site_context_;
5749   const bool copying_;
5750   const JSObject::DeepCopyHints hints_;
5751 };
5752
5753
5754 template <class ContextObject>
5755 Handle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
5756     Handle<JSObject> object) {
5757   Isolate* isolate = this->isolate();
5758   bool copying = this->copying();
5759   bool shallow = hints_ == JSObject::kObjectIsShallowArray;
5760
5761   if (!shallow) {
5762     StackLimitCheck check(isolate);
5763
5764     if (check.HasOverflowed()) {
5765       isolate->StackOverflow();
5766       return Handle<JSObject>::null();
5767     }
5768   }
5769
5770   if (object->map()->is_deprecated()) {
5771     JSObject::MigrateInstance(object);
5772   }
5773
5774   Handle<JSObject> copy;
5775   if (copying) {
5776     Handle<AllocationSite> site_to_pass;
5777     if (site_context()->ShouldCreateMemento(object)) {
5778       site_to_pass = site_context()->current();
5779     }
5780     CALL_AND_RETRY_OR_DIE(isolate,
5781                           isolate->heap()->CopyJSObject(*object,
5782                               site_to_pass.is_null() ? NULL : *site_to_pass),
5783                           { copy = Handle<JSObject>(JSObject::cast(__object__),
5784                                                     isolate);
5785                             break;
5786                           },
5787                           return Handle<JSObject>());
5788   } else {
5789     copy = object;
5790   }
5791
5792   ASSERT(copying || copy.is_identical_to(object));
5793
5794   ElementsKind kind = copy->GetElementsKind();
5795   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5796       FixedArray::cast(copy->elements())->map() ==
5797         isolate->heap()->fixed_cow_array_map()) {
5798     isolate->counters()->cow_arrays_created_runtime()->Increment();
5799   }
5800
5801   if (!shallow) {
5802     HandleScope scope(isolate);
5803
5804     // Deep copy local properties.
5805     if (copy->HasFastProperties()) {
5806       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5807       int limit = copy->map()->NumberOfOwnDescriptors();
5808       for (int i = 0; i < limit; i++) {
5809         PropertyDetails details = descriptors->GetDetails(i);
5810         if (details.type() != FIELD) continue;
5811         int index = descriptors->GetFieldIndex(i);
5812         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5813         if (value->IsJSObject()) {
5814           value = VisitElementOrProperty(copy, Handle<JSObject>::cast(value));
5815           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>());
5816         } else {
5817           Representation representation = details.representation();
5818           value = NewStorageFor(isolate, value, representation);
5819         }
5820         if (copying) {
5821           copy->FastPropertyAtPut(index, *value);
5822         }
5823       }
5824     } else {
5825       Handle<FixedArray> names =
5826           isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties());
5827       copy->GetLocalPropertyNames(*names, 0);
5828       for (int i = 0; i < names->length(); i++) {
5829         ASSERT(names->get(i)->IsString());
5830         Handle<String> key_string(String::cast(names->get(i)));
5831         PropertyAttributes attributes =
5832             JSReceiver::GetLocalPropertyAttribute(copy, key_string);
5833         // Only deep copy fields from the object literal expression.
5834         // In particular, don't try to copy the length attribute of
5835         // an array.
5836         if (attributes != NONE) continue;
5837         Handle<Object> value(
5838             copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(),
5839             isolate);
5840         if (value->IsJSObject()) {
5841           Handle<JSObject> result = VisitElementOrProperty(
5842               copy, Handle<JSObject>::cast(value));
5843           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
5844           if (copying) {
5845             // Creating object copy for literals. No strict mode needed.
5846             CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty(
5847                 copy, key_string, result, NONE, SLOPPY));
5848           }
5849         }
5850       }
5851     }
5852
5853     // Deep copy local elements.
5854     // Pixel elements cannot be created using an object literal.
5855     ASSERT(!copy->HasExternalArrayElements());
5856     switch (kind) {
5857       case FAST_SMI_ELEMENTS:
5858       case FAST_ELEMENTS:
5859       case FAST_HOLEY_SMI_ELEMENTS:
5860       case FAST_HOLEY_ELEMENTS: {
5861         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5862         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5863 #ifdef DEBUG
5864           for (int i = 0; i < elements->length(); i++) {
5865             ASSERT(!elements->get(i)->IsJSObject());
5866           }
5867 #endif
5868         } else {
5869           for (int i = 0; i < elements->length(); i++) {
5870             Handle<Object> value(elements->get(i), isolate);
5871             ASSERT(value->IsSmi() ||
5872                    value->IsTheHole() ||
5873                    (IsFastObjectElementsKind(copy->GetElementsKind())));
5874             if (value->IsJSObject()) {
5875               Handle<JSObject> result = VisitElementOrProperty(
5876                   copy, Handle<JSObject>::cast(value));
5877               RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
5878               if (copying) {
5879                 elements->set(i, *result);
5880               }
5881             }
5882           }
5883         }
5884         break;
5885       }
5886       case DICTIONARY_ELEMENTS: {
5887         Handle<SeededNumberDictionary> element_dictionary(
5888             copy->element_dictionary());
5889         int capacity = element_dictionary->Capacity();
5890         for (int i = 0; i < capacity; i++) {
5891           Object* k = element_dictionary->KeyAt(i);
5892           if (element_dictionary->IsKey(k)) {
5893             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
5894             if (value->IsJSObject()) {
5895               Handle<JSObject> result = VisitElementOrProperty(
5896                   copy, Handle<JSObject>::cast(value));
5897               RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
5898               if (copying) {
5899                 element_dictionary->ValueAtPut(i, *result);
5900               }
5901             }
5902           }
5903         }
5904         break;
5905       }
5906       case SLOPPY_ARGUMENTS_ELEMENTS:
5907         UNIMPLEMENTED();
5908         break;
5909
5910
5911 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5912       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
5913       case TYPE##_ELEMENTS:                                                    \
5914
5915       TYPED_ARRAYS(TYPED_ARRAY_CASE)
5916 #undef TYPED_ARRAY_CASE
5917
5918       case FAST_DOUBLE_ELEMENTS:
5919       case FAST_HOLEY_DOUBLE_ELEMENTS:
5920         // No contained objects, nothing to do.
5921         break;
5922     }
5923   }
5924
5925   return copy;
5926 }
5927
5928
5929 Handle<JSObject> JSObject::DeepWalk(
5930     Handle<JSObject> object,
5931     AllocationSiteCreationContext* site_context) {
5932   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
5933                                                        kNoHints);
5934   Handle<JSObject> result = v.StructureWalk(object);
5935   ASSERT(result.is_null() || result.is_identical_to(object));
5936   return result;
5937 }
5938
5939
5940 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object,
5941                                     AllocationSiteUsageContext* site_context,
5942                                     DeepCopyHints hints) {
5943   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
5944   Handle<JSObject> copy = v.StructureWalk(object);
5945   ASSERT(!copy.is_identical_to(object));
5946   return copy;
5947 }
5948
5949
5950 // Tests for the fast common case for property enumeration:
5951 // - This object and all prototypes has an enum cache (which means that
5952 //   it is no proxy, has no interceptors and needs no access checks).
5953 // - This object has no elements.
5954 // - No prototype has enumerable properties/elements.
5955 bool JSReceiver::IsSimpleEnum() {
5956   Heap* heap = GetHeap();
5957   for (Object* o = this;
5958        o != heap->null_value();
5959        o = JSObject::cast(o)->GetPrototype()) {
5960     if (!o->IsJSObject()) return false;
5961     JSObject* curr = JSObject::cast(o);
5962     int enum_length = curr->map()->EnumLength();
5963     if (enum_length == kInvalidEnumCacheSentinel) return false;
5964     if (curr->IsAccessCheckNeeded()) return false;
5965     ASSERT(!curr->HasNamedInterceptor());
5966     ASSERT(!curr->HasIndexedInterceptor());
5967     if (curr->NumberOfEnumElements() > 0) return false;
5968     if (curr != this && enum_length != 0) return false;
5969   }
5970   return true;
5971 }
5972
5973
5974 static bool FilterKey(Object* key, PropertyAttributes filter) {
5975   if ((filter & SYMBOLIC) && key->IsSymbol()) {
5976     return true;
5977   }
5978
5979   if ((filter & PRIVATE_SYMBOL) &&
5980       key->IsSymbol() && Symbol::cast(key)->is_private()) {
5981     return true;
5982   }
5983
5984   if ((filter & STRING) && !key->IsSymbol()) {
5985     return true;
5986   }
5987
5988   return false;
5989 }
5990
5991
5992 int Map::NumberOfDescribedProperties(DescriptorFlag which,
5993                                      PropertyAttributes filter) {
5994   int result = 0;
5995   DescriptorArray* descs = instance_descriptors();
5996   int limit = which == ALL_DESCRIPTORS
5997       ? descs->number_of_descriptors()
5998       : NumberOfOwnDescriptors();
5999   for (int i = 0; i < limit; i++) {
6000     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
6001         !FilterKey(descs->GetKey(i), filter)) {
6002       result++;
6003     }
6004   }
6005   return result;
6006 }
6007
6008
6009 int Map::NextFreePropertyIndex() {
6010   int max_index = -1;
6011   int number_of_own_descriptors = NumberOfOwnDescriptors();
6012   DescriptorArray* descs = instance_descriptors();
6013   for (int i = 0; i < number_of_own_descriptors; i++) {
6014     if (descs->GetType(i) == FIELD) {
6015       int current_index = descs->GetFieldIndex(i);
6016       if (current_index > max_index) max_index = current_index;
6017     }
6018   }
6019   return max_index + 1;
6020 }
6021
6022
6023 AccessorDescriptor* Map::FindAccessor(Name* name) {
6024   DescriptorArray* descs = instance_descriptors();
6025   int number_of_own_descriptors = NumberOfOwnDescriptors();
6026   for (int i = 0; i < number_of_own_descriptors; i++) {
6027     if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
6028       return descs->GetCallbacks(i);
6029     }
6030   }
6031   return NULL;
6032 }
6033
6034
6035 void JSReceiver::LocalLookup(
6036     Name* name, LookupResult* result, bool search_hidden_prototypes) {
6037   ASSERT(name->IsName());
6038
6039   Heap* heap = GetHeap();
6040
6041   if (IsJSGlobalProxy()) {
6042     Object* proto = GetPrototype();
6043     if (proto->IsNull()) return result->NotFound();
6044     ASSERT(proto->IsJSGlobalObject());
6045     return JSReceiver::cast(proto)->LocalLookup(
6046         name, result, search_hidden_prototypes);
6047   }
6048
6049   if (IsJSProxy()) {
6050     result->HandlerResult(JSProxy::cast(this));
6051     return;
6052   }
6053
6054   // Do not use inline caching if the object is a non-global object
6055   // that requires access checks.
6056   if (IsAccessCheckNeeded()) {
6057     result->DisallowCaching();
6058   }
6059
6060   JSObject* js_object = JSObject::cast(this);
6061
6062   // Check for lookup interceptor except when bootstrapping.
6063   if (js_object->HasNamedInterceptor() &&
6064       !heap->isolate()->bootstrapper()->IsActive()) {
6065     result->InterceptorResult(js_object);
6066     return;
6067   }
6068
6069   js_object->LocalLookupRealNamedProperty(name, result);
6070   if (result->IsFound() || !search_hidden_prototypes) return;
6071
6072   Object* proto = js_object->GetPrototype();
6073   if (!proto->IsJSReceiver()) return;
6074   JSReceiver* receiver = JSReceiver::cast(proto);
6075   if (receiver->map()->is_hidden_prototype()) {
6076     receiver->LocalLookup(name, result, search_hidden_prototypes);
6077   }
6078 }
6079
6080
6081 void JSReceiver::Lookup(Name* name, LookupResult* result) {
6082   // Ecma-262 3rd 8.6.2.4
6083   Heap* heap = GetHeap();
6084   for (Object* current = this;
6085        current != heap->null_value();
6086        current = JSObject::cast(current)->GetPrototype()) {
6087     JSReceiver::cast(current)->LocalLookup(name, result, false);
6088     if (result->IsFound()) return;
6089   }
6090   result->NotFound();
6091 }
6092
6093
6094 // Search object and its prototype chain for callback properties.
6095 void JSObject::LookupCallbackProperty(Name* name, LookupResult* result) {
6096   Heap* heap = GetHeap();
6097   for (Object* current = this;
6098        current != heap->null_value() && current->IsJSObject();
6099        current = JSObject::cast(current)->GetPrototype()) {
6100     JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
6101     if (result->IsPropertyCallbacks()) return;
6102   }
6103   result->NotFound();
6104 }
6105
6106
6107 // Try to update an accessor in an elements dictionary. Return true if the
6108 // update succeeded, and false otherwise.
6109 static bool UpdateGetterSetterInDictionary(
6110     SeededNumberDictionary* dictionary,
6111     uint32_t index,
6112     Object* getter,
6113     Object* setter,
6114     PropertyAttributes attributes) {
6115   int entry = dictionary->FindEntry(index);
6116   if (entry != SeededNumberDictionary::kNotFound) {
6117     Object* result = dictionary->ValueAt(entry);
6118     PropertyDetails details = dictionary->DetailsAt(entry);
6119     if (details.type() == CALLBACKS && result->IsAccessorPair()) {
6120       ASSERT(!details.IsDontDelete());
6121       if (details.attributes() != attributes) {
6122         dictionary->DetailsAtPut(
6123             entry,
6124             PropertyDetails(attributes, CALLBACKS, index));
6125       }
6126       AccessorPair::cast(result)->SetComponents(getter, setter);
6127       return true;
6128     }
6129   }
6130   return false;
6131 }
6132
6133
6134 void JSObject::DefineElementAccessor(Handle<JSObject> object,
6135                                      uint32_t index,
6136                                      Handle<Object> getter,
6137                                      Handle<Object> setter,
6138                                      PropertyAttributes attributes,
6139                                      v8::AccessControl access_control) {
6140   switch (object->GetElementsKind()) {
6141     case FAST_SMI_ELEMENTS:
6142     case FAST_ELEMENTS:
6143     case FAST_DOUBLE_ELEMENTS:
6144     case FAST_HOLEY_SMI_ELEMENTS:
6145     case FAST_HOLEY_ELEMENTS:
6146     case FAST_HOLEY_DOUBLE_ELEMENTS:
6147       break;
6148
6149 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6150     case EXTERNAL_##TYPE##_ELEMENTS:                                           \
6151     case TYPE##_ELEMENTS:                                                      \
6152
6153     TYPED_ARRAYS(TYPED_ARRAY_CASE)
6154 #undef TYPED_ARRAY_CASE
6155       // Ignore getters and setters on pixel and external array elements.
6156       return;
6157
6158     case DICTIONARY_ELEMENTS:
6159       if (UpdateGetterSetterInDictionary(object->element_dictionary(),
6160                                          index,
6161                                          *getter,
6162                                          *setter,
6163                                          attributes)) {
6164         return;
6165       }
6166       break;
6167     case SLOPPY_ARGUMENTS_ELEMENTS: {
6168       // Ascertain whether we have read-only properties or an existing
6169       // getter/setter pair in an arguments elements dictionary backing
6170       // store.
6171       FixedArray* parameter_map = FixedArray::cast(object->elements());
6172       uint32_t length = parameter_map->length();
6173       Object* probe =
6174           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
6175       if (probe == NULL || probe->IsTheHole()) {
6176         FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
6177         if (arguments->IsDictionary()) {
6178           SeededNumberDictionary* dictionary =
6179               SeededNumberDictionary::cast(arguments);
6180           if (UpdateGetterSetterInDictionary(dictionary,
6181                                              index,
6182                                              *getter,
6183                                              *setter,
6184                                              attributes)) {
6185             return;
6186           }
6187         }
6188       }
6189       break;
6190     }
6191   }
6192
6193   Isolate* isolate = object->GetIsolate();
6194   Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair();
6195   accessors->SetComponents(*getter, *setter);
6196   accessors->set_access_flags(access_control);
6197
6198   SetElementCallback(object, index, accessors, attributes);
6199 }
6200
6201
6202 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object,
6203                                                      Handle<Name> name) {
6204   Isolate* isolate = object->GetIsolate();
6205   LookupResult result(isolate);
6206   object->LocalLookupRealNamedProperty(*name, &result);
6207   if (result.IsPropertyCallbacks()) {
6208     // Note that the result can actually have IsDontDelete() == true when we
6209     // e.g. have to fall back to the slow case while adding a setter after
6210     // successfully reusing a map transition for a getter. Nevertheless, this is
6211     // OK, because the assertion only holds for the whole addition of both
6212     // accessors, not for the addition of each part. See first comment in
6213     // DefinePropertyAccessor below.
6214     Object* obj = result.GetCallbackObject();
6215     if (obj->IsAccessorPair()) {
6216       return AccessorPair::Copy(handle(AccessorPair::cast(obj), isolate));
6217     }
6218   }
6219   return isolate->factory()->NewAccessorPair();
6220 }
6221
6222
6223 void JSObject::DefinePropertyAccessor(Handle<JSObject> object,
6224                                       Handle<Name> name,
6225                                       Handle<Object> getter,
6226                                       Handle<Object> setter,
6227                                       PropertyAttributes attributes,
6228                                       v8::AccessControl access_control) {
6229   // We could assert that the property is configurable here, but we would need
6230   // to do a lookup, which seems to be a bit of overkill.
6231   bool only_attribute_changes = getter->IsNull() && setter->IsNull();
6232   if (object->HasFastProperties() && !only_attribute_changes &&
6233       access_control == v8::DEFAULT &&
6234       (object->map()->NumberOfOwnDescriptors() <= kMaxNumberOfDescriptors)) {
6235     bool getterOk = getter->IsNull() ||
6236         DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes);
6237     bool setterOk = !getterOk || setter->IsNull() ||
6238         DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes);
6239     if (getterOk && setterOk) return;
6240   }
6241
6242   Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name);
6243   accessors->SetComponents(*getter, *setter);
6244   accessors->set_access_flags(access_control);
6245
6246   SetPropertyCallback(object, name, accessors, attributes);
6247 }
6248
6249
6250 bool JSObject::CanSetCallback(Handle<JSObject> object, Handle<Name> name) {
6251   Isolate* isolate = object->GetIsolate();
6252   ASSERT(!object->IsAccessCheckNeeded() ||
6253          isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET));
6254
6255   // Check if there is an API defined callback object which prohibits
6256   // callback overwriting in this object or its prototype chain.
6257   // This mechanism is needed for instance in a browser setting, where
6258   // certain accessors such as window.location should not be allowed
6259   // to be overwritten because allowing overwriting could potentially
6260   // cause security problems.
6261   LookupResult callback_result(isolate);
6262   object->LookupCallbackProperty(*name, &callback_result);
6263   if (callback_result.IsFound()) {
6264     Object* callback_obj = callback_result.GetCallbackObject();
6265     if (callback_obj->IsAccessorInfo()) {
6266       return !AccessorInfo::cast(callback_obj)->prohibits_overwriting();
6267     }
6268     if (callback_obj->IsAccessorPair()) {
6269       return !AccessorPair::cast(callback_obj)->prohibits_overwriting();
6270     }
6271   }
6272   return true;
6273 }
6274
6275
6276 bool Map::DictionaryElementsInPrototypeChainOnly() {
6277   Heap* heap = GetHeap();
6278
6279   if (IsDictionaryElementsKind(elements_kind())) {
6280     return false;
6281   }
6282
6283   for (Object* prototype = this->prototype();
6284        prototype != heap->null_value();
6285        prototype = prototype->GetPrototype(GetIsolate())) {
6286     if (prototype->IsJSProxy()) {
6287       // Be conservative, don't walk into proxies.
6288       return true;
6289     }
6290
6291     if (IsDictionaryElementsKind(
6292             JSObject::cast(prototype)->map()->elements_kind())) {
6293       return true;
6294     }
6295   }
6296
6297   return false;
6298 }
6299
6300
6301 void JSObject::SetElementCallback(Handle<JSObject> object,
6302                                   uint32_t index,
6303                                   Handle<Object> structure,
6304                                   PropertyAttributes attributes) {
6305   Heap* heap = object->GetHeap();
6306   PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6307
6308   // Normalize elements to make this operation simple.
6309   bool had_dictionary_elements = object->HasDictionaryElements();
6310   Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
6311   ASSERT(object->HasDictionaryElements() ||
6312          object->HasDictionaryArgumentsElements());
6313   // Update the dictionary with the new CALLBACKS property.
6314   dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
6315                                            details);
6316   dictionary->set_requires_slow_elements();
6317
6318   // Update the dictionary backing store on the object.
6319   if (object->elements()->map() == heap->sloppy_arguments_elements_map()) {
6320     // Also delete any parameter alias.
6321     //
6322     // TODO(kmillikin): when deleting the last parameter alias we could
6323     // switch to a direct backing store without the parameter map.  This
6324     // would allow GC of the context.
6325     FixedArray* parameter_map = FixedArray::cast(object->elements());
6326     if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
6327       parameter_map->set(index + 2, heap->the_hole_value());
6328     }
6329     parameter_map->set(1, *dictionary);
6330   } else {
6331     object->set_elements(*dictionary);
6332
6333     if (!had_dictionary_elements) {
6334       // KeyedStoreICs (at least the non-generic ones) need a reset.
6335       heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
6336     }
6337   }
6338 }
6339
6340
6341 void JSObject::SetPropertyCallback(Handle<JSObject> object,
6342                                    Handle<Name> name,
6343                                    Handle<Object> structure,
6344                                    PropertyAttributes attributes) {
6345   // Normalize object to make this operation simple.
6346   NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
6347
6348   // For the global object allocate a new map to invalidate the global inline
6349   // caches which have a global property cell reference directly in the code.
6350   if (object->IsGlobalObject()) {
6351     Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
6352     ASSERT(new_map->is_dictionary_map());
6353     object->set_map(*new_map);
6354
6355     // When running crankshaft, changing the map is not enough. We
6356     // need to deoptimize all functions that rely on this global
6357     // object.
6358     Deoptimizer::DeoptimizeGlobalObject(*object);
6359   }
6360
6361   // Update the dictionary with the new CALLBACKS property.
6362   PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6363   SetNormalizedProperty(object, name, structure, details);
6364 }
6365
6366
6367 void JSObject::DefineAccessor(Handle<JSObject> object,
6368                               Handle<Name> name,
6369                               Handle<Object> getter,
6370                               Handle<Object> setter,
6371                               PropertyAttributes attributes,
6372                               v8::AccessControl access_control) {
6373   Isolate* isolate = object->GetIsolate();
6374   // Check access rights if needed.
6375   if (object->IsAccessCheckNeeded() &&
6376       !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) {
6377     isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET);
6378     return;
6379   }
6380
6381   if (object->IsJSGlobalProxy()) {
6382     Handle<Object> proto(object->GetPrototype(), isolate);
6383     if (proto->IsNull()) return;
6384     ASSERT(proto->IsJSGlobalObject());
6385     DefineAccessor(Handle<JSObject>::cast(proto),
6386                    name,
6387                    getter,
6388                    setter,
6389                    attributes,
6390                    access_control);
6391     return;
6392   }
6393
6394   // Make sure that the top context does not change when doing callbacks or
6395   // interceptor calls.
6396   AssertNoContextChange ncc(isolate);
6397
6398   // Try to flatten before operating on the string.
6399   if (name->IsString()) String::cast(*name)->TryFlatten();
6400
6401   if (!JSObject::CanSetCallback(object, name)) return;
6402
6403   uint32_t index = 0;
6404   bool is_element = name->AsArrayIndex(&index);
6405
6406   Handle<Object> old_value = isolate->factory()->the_hole_value();
6407   bool is_observed = object->map()->is_observed() &&
6408                      *name != isolate->heap()->hidden_string();
6409   bool preexists = false;
6410   if (is_observed) {
6411     if (is_element) {
6412       preexists = HasLocalElement(object, index);
6413       if (preexists && object->GetLocalElementAccessorPair(index) == NULL) {
6414         old_value = Object::GetElementNoExceptionThrown(isolate, object, index);
6415       }
6416     } else {
6417       LookupResult lookup(isolate);
6418       object->LocalLookup(*name, &lookup, true);
6419       preexists = lookup.IsProperty();
6420       if (preexists && lookup.IsDataProperty()) {
6421         old_value = Object::GetProperty(object, name);
6422         CHECK_NOT_EMPTY_HANDLE(isolate, old_value);
6423       }
6424     }
6425   }
6426
6427   if (is_element) {
6428     DefineElementAccessor(
6429         object, index, getter, setter, attributes, access_control);
6430   } else {
6431     DefinePropertyAccessor(
6432         object, name, getter, setter, attributes, access_control);
6433   }
6434
6435   if (is_observed) {
6436     const char* type = preexists ? "reconfigure" : "add";
6437     EnqueueChangeRecord(object, type, name, old_value);
6438   }
6439 }
6440
6441
6442 static bool TryAccessorTransition(Handle<JSObject> self,
6443                                   Handle<Map> transitioned_map,
6444                                   int target_descriptor,
6445                                   AccessorComponent component,
6446                                   Handle<Object> accessor,
6447                                   PropertyAttributes attributes) {
6448   DescriptorArray* descs = transitioned_map->instance_descriptors();
6449   PropertyDetails details = descs->GetDetails(target_descriptor);
6450
6451   // If the transition target was not callbacks, fall back to the slow case.
6452   if (details.type() != CALLBACKS) return false;
6453   Object* descriptor = descs->GetCallbacksObject(target_descriptor);
6454   if (!descriptor->IsAccessorPair()) return false;
6455
6456   Object* target_accessor = AccessorPair::cast(descriptor)->get(component);
6457   PropertyAttributes target_attributes = details.attributes();
6458
6459   // Reuse transition if adding same accessor with same attributes.
6460   if (target_accessor == *accessor && target_attributes == attributes) {
6461     JSObject::MigrateToMap(self, transitioned_map);
6462     return true;
6463   }
6464
6465   // If either not the same accessor, or not the same attributes, fall back to
6466   // the slow case.
6467   return false;
6468 }
6469
6470
6471 static MaybeObject* CopyInsertDescriptor(Map* map,
6472                                          Name* name,
6473                                          AccessorPair* accessors,
6474                                          PropertyAttributes attributes) {
6475   CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
6476   return map->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION);
6477 }
6478
6479
6480 static Handle<Map> CopyInsertDescriptor(Handle<Map> map,
6481                                         Handle<Name> name,
6482                                         Handle<AccessorPair> accessors,
6483                                         PropertyAttributes attributes) {
6484   CALL_HEAP_FUNCTION(map->GetIsolate(),
6485                      CopyInsertDescriptor(*map, *name, *accessors, attributes),
6486                      Map);
6487 }
6488
6489
6490 bool JSObject::DefineFastAccessor(Handle<JSObject> object,
6491                                   Handle<Name> name,
6492                                   AccessorComponent component,
6493                                   Handle<Object> accessor,
6494                                   PropertyAttributes attributes) {
6495   ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
6496   Isolate* isolate = object->GetIsolate();
6497   LookupResult result(isolate);
6498   object->LocalLookup(*name, &result);
6499
6500   if (result.IsFound() && !result.IsPropertyCallbacks()) {
6501     return false;
6502   }
6503
6504   // Return success if the same accessor with the same attributes already exist.
6505   AccessorPair* source_accessors = NULL;
6506   if (result.IsPropertyCallbacks()) {
6507     Object* callback_value = result.GetCallbackObject();
6508     if (callback_value->IsAccessorPair()) {
6509       source_accessors = AccessorPair::cast(callback_value);
6510       Object* entry = source_accessors->get(component);
6511       if (entry == *accessor && result.GetAttributes() == attributes) {
6512         return true;
6513       }
6514     } else {
6515       return false;
6516     }
6517
6518     int descriptor_number = result.GetDescriptorIndex();
6519
6520     object->map()->LookupTransition(*object, *name, &result);
6521
6522     if (result.IsFound()) {
6523       Handle<Map> target(result.GetTransitionTarget());
6524       ASSERT(target->NumberOfOwnDescriptors() ==
6525              object->map()->NumberOfOwnDescriptors());
6526       // This works since descriptors are sorted in order of addition.
6527       ASSERT(object->map()->instance_descriptors()->
6528              GetKey(descriptor_number) == *name);
6529       return TryAccessorTransition(object, target, descriptor_number,
6530                                    component, accessor, attributes);
6531     }
6532   } else {
6533     // If not, lookup a transition.
6534     object->map()->LookupTransition(*object, *name, &result);
6535
6536     // If there is a transition, try to follow it.
6537     if (result.IsFound()) {
6538       Handle<Map> target(result.GetTransitionTarget());
6539       int descriptor_number = target->LastAdded();
6540       ASSERT(target->instance_descriptors()->GetKey(descriptor_number)
6541              ->Equals(*name));
6542       return TryAccessorTransition(object, target, descriptor_number,
6543                                    component, accessor, attributes);
6544     }
6545   }
6546
6547   // If there is no transition yet, add a transition to the a new accessor pair
6548   // containing the accessor.  Allocate a new pair if there were no source
6549   // accessors.  Otherwise, copy the pair and modify the accessor.
6550   Handle<AccessorPair> accessors = source_accessors != NULL
6551       ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
6552       : isolate->factory()->NewAccessorPair();
6553   accessors->set(component, *accessor);
6554   Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()),
6555                                              name, accessors, attributes);
6556   JSObject::MigrateToMap(object, new_map);
6557   return true;
6558 }
6559
6560
6561 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6562                                      Handle<AccessorInfo> info) {
6563   Isolate* isolate = object->GetIsolate();
6564   Factory* factory = isolate->factory();
6565   Handle<Name> name(Name::cast(info->name()));
6566
6567   // Check access rights if needed.
6568   if (object->IsAccessCheckNeeded() &&
6569       !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) {
6570     isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET);
6571     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
6572     return factory->undefined_value();
6573   }
6574
6575   if (object->IsJSGlobalProxy()) {
6576     Handle<Object> proto(object->GetPrototype(), isolate);
6577     if (proto->IsNull()) return object;
6578     ASSERT(proto->IsJSGlobalObject());
6579     return SetAccessor(Handle<JSObject>::cast(proto), info);
6580   }
6581
6582   // Make sure that the top context does not change when doing callbacks or
6583   // interceptor calls.
6584   AssertNoContextChange ncc(isolate);
6585
6586   // Try to flatten before operating on the string.
6587   if (name->IsString()) FlattenString(Handle<String>::cast(name));
6588
6589   if (!JSObject::CanSetCallback(object, name)) {
6590     return factory->undefined_value();
6591   }
6592
6593   uint32_t index = 0;
6594   bool is_element = name->AsArrayIndex(&index);
6595
6596   if (is_element) {
6597     if (object->IsJSArray()) return factory->undefined_value();
6598
6599     // Accessors overwrite previous callbacks (cf. with getters/setters).
6600     switch (object->GetElementsKind()) {
6601       case FAST_SMI_ELEMENTS:
6602       case FAST_ELEMENTS:
6603       case FAST_DOUBLE_ELEMENTS:
6604       case FAST_HOLEY_SMI_ELEMENTS:
6605       case FAST_HOLEY_ELEMENTS:
6606       case FAST_HOLEY_DOUBLE_ELEMENTS:
6607         break;
6608
6609 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6610       case EXTERNAL_##TYPE##_ELEMENTS:                                         \
6611       case TYPE##_ELEMENTS:                                                    \
6612
6613       TYPED_ARRAYS(TYPED_ARRAY_CASE)
6614 #undef TYPED_ARRAY_CASE
6615         // Ignore getters and setters on pixel and external array
6616         // elements.
6617         return factory->undefined_value();
6618
6619       case DICTIONARY_ELEMENTS:
6620         break;
6621       case SLOPPY_ARGUMENTS_ELEMENTS:
6622         UNIMPLEMENTED();
6623         break;
6624     }
6625
6626     SetElementCallback(object, index, info, info->property_attributes());
6627   } else {
6628     // Lookup the name.
6629     LookupResult result(isolate);
6630     object->LocalLookup(*name, &result, true);
6631     // ES5 forbids turning a property into an accessor if it's not
6632     // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
6633     if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) {
6634       return factory->undefined_value();
6635     }
6636
6637     SetPropertyCallback(object, name, info, info->property_attributes());
6638   }
6639
6640   return object;
6641 }
6642
6643
6644 Handle<Object> JSObject::GetAccessor(Handle<JSObject> object,
6645                                      Handle<Name> name,
6646                                      AccessorComponent component) {
6647   Isolate* isolate = object->GetIsolate();
6648
6649   // Make sure that the top context does not change when doing callbacks or
6650   // interceptor calls.
6651   AssertNoContextChange ncc(isolate);
6652
6653   // Check access rights if needed.
6654   if (object->IsAccessCheckNeeded() &&
6655       !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_HAS)) {
6656     isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
6657     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
6658     return isolate->factory()->undefined_value();
6659   }
6660
6661   // Make the lookup and include prototypes.
6662   uint32_t index = 0;
6663   if (name->AsArrayIndex(&index)) {
6664     for (Handle<Object> obj = object;
6665          !obj->IsNull();
6666          obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) {
6667       if (obj->IsJSObject() && JSObject::cast(*obj)->HasDictionaryElements()) {
6668         JSObject* js_object = JSObject::cast(*obj);
6669         SeededNumberDictionary* dictionary = js_object->element_dictionary();
6670         int entry = dictionary->FindEntry(index);
6671         if (entry != SeededNumberDictionary::kNotFound) {
6672           Object* element = dictionary->ValueAt(entry);
6673           if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
6674               element->IsAccessorPair()) {
6675             return handle(AccessorPair::cast(element)->GetComponent(component),
6676                           isolate);
6677           }
6678         }
6679       }
6680     }
6681   } else {
6682     for (Handle<Object> obj = object;
6683          !obj->IsNull();
6684          obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) {
6685       LookupResult result(isolate);
6686       JSReceiver::cast(*obj)->LocalLookup(*name, &result);
6687       if (result.IsFound()) {
6688         if (result.IsReadOnly()) return isolate->factory()->undefined_value();
6689         if (result.IsPropertyCallbacks()) {
6690           Object* obj = result.GetCallbackObject();
6691           if (obj->IsAccessorPair()) {
6692             return handle(AccessorPair::cast(obj)->GetComponent(component),
6693                           isolate);
6694           }
6695         }
6696       }
6697     }
6698   }
6699   return isolate->factory()->undefined_value();
6700 }
6701
6702
6703 Object* JSObject::SlowReverseLookup(Object* value) {
6704   if (HasFastProperties()) {
6705     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
6706     DescriptorArray* descs = map()->instance_descriptors();
6707     for (int i = 0; i < number_of_own_descriptors; i++) {
6708       if (descs->GetType(i) == FIELD) {
6709         Object* property = RawFastPropertyAt(descs->GetFieldIndex(i));
6710         if (descs->GetDetails(i).representation().IsDouble()) {
6711           ASSERT(property->IsHeapNumber());
6712           if (value->IsNumber() && property->Number() == value->Number()) {
6713             return descs->GetKey(i);
6714           }
6715         } else if (property == value) {
6716           return descs->GetKey(i);
6717         }
6718       } else if (descs->GetType(i) == CONSTANT) {
6719         if (descs->GetConstant(i) == value) {
6720           return descs->GetKey(i);
6721         }
6722       }
6723     }
6724     return GetHeap()->undefined_value();
6725   } else {
6726     return property_dictionary()->SlowReverseLookup(value);
6727   }
6728 }
6729
6730
6731 Handle<Map> Map::RawCopy(Handle<Map> map,
6732                          int instance_size) {
6733   CALL_HEAP_FUNCTION(map->GetIsolate(),
6734                      map->RawCopy(instance_size),
6735                      Map);
6736 }
6737
6738
6739 MaybeObject* Map::RawCopy(int instance_size) {
6740   Map* result;
6741   MaybeObject* maybe_result =
6742       GetHeap()->AllocateMap(instance_type(), instance_size);
6743   if (!maybe_result->To(&result)) return maybe_result;
6744
6745   result->set_prototype(prototype());
6746   result->set_constructor(constructor());
6747   result->set_bit_field(bit_field());
6748   result->set_bit_field2(bit_field2());
6749   int new_bit_field3 = bit_field3();
6750   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6751   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6752   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6753                                           kInvalidEnumCacheSentinel);
6754   new_bit_field3 = Deprecated::update(new_bit_field3, false);
6755   if (!is_dictionary_map()) {
6756     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
6757   }
6758   result->set_bit_field3(new_bit_field3);
6759   return result;
6760 }
6761
6762
6763 Handle<Map> Map::CopyNormalized(Handle<Map> map,
6764                                 PropertyNormalizationMode mode,
6765                                 NormalizedMapSharingMode sharing) {
6766   int new_instance_size = map->instance_size();
6767   if (mode == CLEAR_INOBJECT_PROPERTIES) {
6768     new_instance_size -= map->inobject_properties() * kPointerSize;
6769   }
6770
6771   Handle<Map> result = Map::RawCopy(map, new_instance_size);
6772
6773   if (mode != CLEAR_INOBJECT_PROPERTIES) {
6774     result->set_inobject_properties(map->inobject_properties());
6775   }
6776
6777   result->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
6778   result->set_dictionary_map(true);
6779   result->set_migration_target(false);
6780
6781 #ifdef VERIFY_HEAP
6782   if (FLAG_verify_heap && result->is_shared()) {
6783     result->SharedMapVerify();
6784   }
6785 #endif
6786
6787   return result;
6788 }
6789
6790
6791 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
6792   CALL_HEAP_FUNCTION(map->GetIsolate(), map->CopyDropDescriptors(), Map);
6793 }
6794
6795
6796 MaybeObject* Map::CopyDropDescriptors() {
6797   Map* result;
6798   MaybeObject* maybe_result = RawCopy(instance_size());
6799   if (!maybe_result->To(&result)) return maybe_result;
6800
6801   // Please note instance_type and instance_size are set when allocated.
6802   result->set_inobject_properties(inobject_properties());
6803   result->set_unused_property_fields(unused_property_fields());
6804
6805   result->set_pre_allocated_property_fields(pre_allocated_property_fields());
6806   result->set_is_shared(false);
6807   result->ClearCodeCache(GetHeap());
6808   NotifyLeafMapLayoutChange();
6809   return result;
6810 }
6811
6812
6813 MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors,
6814                                   Descriptor* descriptor) {
6815   // Sanity check. This path is only to be taken if the map owns its descriptor
6816   // array, implying that its NumberOfOwnDescriptors equals the number of
6817   // descriptors in the descriptor array.
6818   ASSERT(NumberOfOwnDescriptors() ==
6819          instance_descriptors()->number_of_descriptors());
6820   Map* result;
6821   MaybeObject* maybe_result = CopyDropDescriptors();
6822   if (!maybe_result->To(&result)) return maybe_result;
6823
6824   Name* name = descriptor->GetKey();
6825
6826   TransitionArray* transitions;
6827   MaybeObject* maybe_transitions =
6828       AddTransition(name, result, SIMPLE_TRANSITION);
6829   if (!maybe_transitions->To(&transitions)) return maybe_transitions;
6830
6831   int old_size = descriptors->number_of_descriptors();
6832
6833   DescriptorArray* new_descriptors;
6834
6835   if (descriptors->NumberOfSlackDescriptors() > 0) {
6836     new_descriptors = descriptors;
6837     new_descriptors->Append(descriptor);
6838   } else {
6839     // Descriptor arrays grow by 50%.
6840     MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
6841         GetIsolate(), old_size, old_size < 4 ? 1 : old_size / 2);
6842     if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
6843
6844     DescriptorArray::WhitenessWitness witness(new_descriptors);
6845
6846     // Copy the descriptors, inserting a descriptor.
6847     for (int i = 0; i < old_size; ++i) {
6848       new_descriptors->CopyFrom(i, descriptors, i, witness);
6849     }
6850
6851     new_descriptors->Append(descriptor, witness);
6852
6853     if (old_size > 0) {
6854       // If the source descriptors had an enum cache we copy it. This ensures
6855       // that the maps to which we push the new descriptor array back can rely
6856       // on a cache always being available once it is set. If the map has more
6857       // enumerated descriptors than available in the original cache, the cache
6858       // will be lazily replaced by the extended cache when needed.
6859       if (descriptors->HasEnumCache()) {
6860         new_descriptors->CopyEnumCacheFrom(descriptors);
6861       }
6862
6863       Map* map;
6864       // Replace descriptors by new_descriptors in all maps that share it.
6865
6866       GetHeap()->incremental_marking()->RecordWrites(descriptors);
6867       for (Object* current = GetBackPointer();
6868            !current->IsUndefined();
6869            current = map->GetBackPointer()) {
6870         map = Map::cast(current);
6871         if (map->instance_descriptors() != descriptors) break;
6872         map->set_instance_descriptors(new_descriptors);
6873       }
6874
6875       set_instance_descriptors(new_descriptors);
6876     }
6877   }
6878
6879   result->SetBackPointer(this);
6880   result->InitializeDescriptors(new_descriptors);
6881   ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
6882
6883   set_transitions(transitions);
6884   set_owns_descriptors(false);
6885
6886   return result;
6887 }
6888
6889
6890 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
6891                                         Handle<DescriptorArray> descriptors,
6892                                         TransitionFlag flag,
6893                                         Handle<Name> name) {
6894   CALL_HEAP_FUNCTION(map->GetIsolate(),
6895                      map->CopyReplaceDescriptors(*descriptors, flag, *name),
6896                      Map);
6897 }
6898
6899
6900 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
6901                                          TransitionFlag flag,
6902                                          Name* name,
6903                                          SimpleTransitionFlag simple_flag) {
6904   ASSERT(descriptors->IsSortedNoDuplicates());
6905
6906   Map* result;
6907   MaybeObject* maybe_result = CopyDropDescriptors();
6908   if (!maybe_result->To(&result)) return maybe_result;
6909
6910   result->InitializeDescriptors(descriptors);
6911
6912   if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
6913     TransitionArray* transitions;
6914     MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
6915     if (!maybe_transitions->To(&transitions)) return maybe_transitions;
6916     set_transitions(transitions);
6917     result->SetBackPointer(this);
6918   } else {
6919     descriptors->InitializeRepresentations(Representation::Tagged());
6920   }
6921
6922   return result;
6923 }
6924
6925
6926 // Since this method is used to rewrite an existing transition tree, it can
6927 // always insert transitions without checking.
6928 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map,
6929                                         int new_descriptor,
6930                                         Handle<DescriptorArray> descriptors) {
6931   ASSERT(descriptors->IsSortedNoDuplicates());
6932
6933   Handle<Map> result = Map::CopyDropDescriptors(map);
6934
6935   result->InitializeDescriptors(*descriptors);
6936   result->SetNumberOfOwnDescriptors(new_descriptor + 1);
6937
6938   int unused_property_fields = map->unused_property_fields();
6939   if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
6940     unused_property_fields = map->unused_property_fields() - 1;
6941     if (unused_property_fields < 0) {
6942       unused_property_fields += JSObject::kFieldsAdded;
6943     }
6944   }
6945
6946   result->set_unused_property_fields(unused_property_fields);
6947   result->set_owns_descriptors(false);
6948
6949   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
6950   Handle<TransitionArray> transitions = Map::AddTransition(map, name, result,
6951                                                            SIMPLE_TRANSITION);
6952
6953   map->set_transitions(*transitions);
6954   result->SetBackPointer(*map);
6955
6956   return result;
6957 }
6958
6959
6960 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
6961   if (flag == INSERT_TRANSITION) {
6962     ASSERT(!HasElementsTransition() ||
6963         ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
6964           IsExternalArrayElementsKind(
6965               elements_transition_map()->elements_kind())) &&
6966          (kind == DICTIONARY_ELEMENTS ||
6967           IsExternalArrayElementsKind(kind))));
6968     ASSERT(!IsFastElementsKind(kind) ||
6969            IsMoreGeneralElementsKindTransition(elements_kind(), kind));
6970     ASSERT(kind != elements_kind());
6971   }
6972
6973   bool insert_transition =
6974       flag == INSERT_TRANSITION && !HasElementsTransition();
6975
6976   if (insert_transition && owns_descriptors()) {
6977     // In case the map owned its own descriptors, share the descriptors and
6978     // transfer ownership to the new map.
6979     Map* new_map;
6980     MaybeObject* maybe_new_map = CopyDropDescriptors();
6981     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
6982
6983     MaybeObject* added_elements = set_elements_transition_map(new_map);
6984     if (added_elements->IsFailure()) return added_elements;
6985
6986     new_map->set_elements_kind(kind);
6987     new_map->InitializeDescriptors(instance_descriptors());
6988     new_map->SetBackPointer(this);
6989     set_owns_descriptors(false);
6990     return new_map;
6991   }
6992
6993   // In case the map did not own its own descriptors, a split is forced by
6994   // copying the map; creating a new descriptor array cell.
6995   // Create a new free-floating map only if we are not allowed to store it.
6996   Map* new_map;
6997   MaybeObject* maybe_new_map = Copy();
6998   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
6999
7000   new_map->set_elements_kind(kind);
7001
7002   if (insert_transition) {
7003     MaybeObject* added_elements = set_elements_transition_map(new_map);
7004     if (added_elements->IsFailure()) return added_elements;
7005     new_map->SetBackPointer(this);
7006   }
7007
7008   return new_map;
7009 }
7010
7011
7012 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
7013   ASSERT(!map->is_observed());
7014
7015   Isolate* isolate = map->GetIsolate();
7016
7017   // In case the map owned its own descriptors, share the descriptors and
7018   // transfer ownership to the new map.
7019   Handle<Map> new_map;
7020   if (map->owns_descriptors()) {
7021     new_map = Map::CopyDropDescriptors(map);
7022   } else {
7023     new_map = Map::Copy(map);
7024   }
7025
7026   Handle<TransitionArray> transitions =
7027       Map::AddTransition(map, isolate->factory()->observed_symbol(), new_map,
7028                          FULL_TRANSITION);
7029
7030   map->set_transitions(*transitions);
7031
7032   new_map->set_is_observed();
7033
7034   if (map->owns_descriptors()) {
7035     new_map->InitializeDescriptors(map->instance_descriptors());
7036     map->set_owns_descriptors(false);
7037   }
7038
7039   new_map->SetBackPointer(*map);
7040   return new_map;
7041 }
7042
7043
7044 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
7045   if (pre_allocated_property_fields() == 0) return CopyDropDescriptors();
7046
7047   // If the map has pre-allocated properties always start out with a descriptor
7048   // array describing these properties.
7049   ASSERT(constructor()->IsJSFunction());
7050   JSFunction* ctor = JSFunction::cast(constructor());
7051   Map* map = ctor->initial_map();
7052   DescriptorArray* descriptors = map->instance_descriptors();
7053
7054   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
7055   DescriptorArray* new_descriptors;
7056   MaybeObject* maybe_descriptors =
7057       descriptors->CopyUpTo(number_of_own_descriptors);
7058   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
7059
7060   return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION);
7061 }
7062
7063
7064 Handle<Map> Map::Copy(Handle<Map> map) {
7065   CALL_HEAP_FUNCTION(map->GetIsolate(), map->Copy(), Map);
7066 }
7067
7068
7069 MaybeObject* Map::Copy() {
7070   DescriptorArray* descriptors = instance_descriptors();
7071   DescriptorArray* new_descriptors;
7072   int number_of_own_descriptors = NumberOfOwnDescriptors();
7073   MaybeObject* maybe_descriptors =
7074       descriptors->CopyUpTo(number_of_own_descriptors);
7075   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
7076
7077   return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION);
7078 }
7079
7080
7081 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
7082                                     TransitionFlag flag) {
7083   DescriptorArray* descriptors = instance_descriptors();
7084
7085   // Ensure the key is unique.
7086   MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
7087   if (maybe_failure->IsFailure()) return maybe_failure;
7088
7089   int old_size = NumberOfOwnDescriptors();
7090   int new_size = old_size + 1;
7091
7092   if (flag == INSERT_TRANSITION &&
7093       owns_descriptors() &&
7094       CanHaveMoreTransitions()) {
7095     return ShareDescriptor(descriptors, descriptor);
7096   }
7097
7098   DescriptorArray* new_descriptors;
7099   MaybeObject* maybe_descriptors =
7100       DescriptorArray::Allocate(GetIsolate(), old_size, 1);
7101   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
7102
7103   DescriptorArray::WhitenessWitness witness(new_descriptors);
7104
7105   // Copy the descriptors, inserting a descriptor.
7106   for (int i = 0; i < old_size; ++i) {
7107     new_descriptors->CopyFrom(i, descriptors, i, witness);
7108   }
7109
7110   if (old_size != descriptors->number_of_descriptors()) {
7111     new_descriptors->SetNumberOfDescriptors(new_size);
7112     new_descriptors->Set(old_size, descriptor, witness);
7113     new_descriptors->Sort();
7114   } else {
7115     new_descriptors->Append(descriptor, witness);
7116   }
7117
7118   Name* key = descriptor->GetKey();
7119   return CopyReplaceDescriptors(new_descriptors, flag, key, SIMPLE_TRANSITION);
7120 }
7121
7122
7123 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
7124                                        TransitionFlag flag) {
7125   DescriptorArray* old_descriptors = instance_descriptors();
7126
7127   // Ensure the key is unique.
7128   MaybeObject* maybe_result = descriptor->KeyToUniqueName();
7129   if (maybe_result->IsFailure()) return maybe_result;
7130
7131   // We replace the key if it is already present.
7132   int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this);
7133   if (index != DescriptorArray::kNotFound) {
7134     return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag);
7135   }
7136   return CopyAddDescriptor(descriptor, flag);
7137 }
7138
7139
7140 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
7141     Handle<DescriptorArray> desc,
7142     int enumeration_index,
7143     PropertyAttributes attributes) {
7144   CALL_HEAP_FUNCTION(desc->GetIsolate(),
7145                      desc->CopyUpToAddAttributes(enumeration_index, attributes),
7146                      DescriptorArray);
7147 }
7148
7149
7150 MaybeObject* DescriptorArray::CopyUpToAddAttributes(
7151     int enumeration_index, PropertyAttributes attributes) {
7152   if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
7153
7154   int size = enumeration_index;
7155
7156   DescriptorArray* descriptors;
7157   MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size);
7158   if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
7159   DescriptorArray::WhitenessWitness witness(descriptors);
7160
7161   if (attributes != NONE) {
7162     for (int i = 0; i < size; ++i) {
7163       Object* value = GetValue(i);
7164       PropertyDetails details = GetDetails(i);
7165       int mask = DONT_DELETE | DONT_ENUM;
7166       // READ_ONLY is an invalid attribute for JS setters/getters.
7167       if (details.type() != CALLBACKS || !value->IsAccessorPair()) {
7168         mask |= READ_ONLY;
7169       }
7170       details = details.CopyAddAttributes(
7171           static_cast<PropertyAttributes>(attributes & mask));
7172       Descriptor desc(GetKey(i), value, details);
7173       descriptors->Set(i, &desc, witness);
7174     }
7175   } else {
7176     for (int i = 0; i < size; ++i) {
7177       descriptors->CopyFrom(i, this, i, witness);
7178     }
7179   }
7180
7181   if (number_of_descriptors() != enumeration_index) descriptors->Sort();
7182
7183   return descriptors;
7184 }
7185
7186
7187 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors,
7188                                         Descriptor* descriptor,
7189                                         int insertion_index,
7190                                         TransitionFlag flag) {
7191   // Ensure the key is unique.
7192   MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
7193   if (maybe_failure->IsFailure()) return maybe_failure;
7194
7195   Name* key = descriptor->GetKey();
7196   ASSERT(key == descriptors->GetKey(insertion_index));
7197
7198   int new_size = NumberOfOwnDescriptors();
7199   ASSERT(0 <= insertion_index && insertion_index < new_size);
7200
7201   ASSERT_LT(insertion_index, new_size);
7202
7203   DescriptorArray* new_descriptors;
7204   MaybeObject* maybe_descriptors =
7205       DescriptorArray::Allocate(GetIsolate(), new_size);
7206   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
7207   DescriptorArray::WhitenessWitness witness(new_descriptors);
7208
7209   for (int i = 0; i < new_size; ++i) {
7210     if (i == insertion_index) {
7211       new_descriptors->Set(i, descriptor, witness);
7212     } else {
7213       new_descriptors->CopyFrom(i, descriptors, i, witness);
7214     }
7215   }
7216
7217   // Re-sort if descriptors were removed.
7218   if (new_size != descriptors->length()) new_descriptors->Sort();
7219
7220   SimpleTransitionFlag simple_flag =
7221       (insertion_index == descriptors->number_of_descriptors() - 1)
7222       ? SIMPLE_TRANSITION
7223       : FULL_TRANSITION;
7224   return CopyReplaceDescriptors(new_descriptors, flag, key, simple_flag);
7225 }
7226
7227
7228 void Map::UpdateCodeCache(Handle<Map> map,
7229                           Handle<Name> name,
7230                           Handle<Code> code) {
7231   Isolate* isolate = map->GetIsolate();
7232   CALL_HEAP_FUNCTION_VOID(isolate,
7233                           map->UpdateCodeCache(*name, *code));
7234 }
7235
7236
7237 MaybeObject* Map::UpdateCodeCache(Name* name, Code* code) {
7238   // Allocate the code cache if not present.
7239   if (code_cache()->IsFixedArray()) {
7240     Object* result;
7241     { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
7242       if (!maybe_result->ToObject(&result)) return maybe_result;
7243     }
7244     set_code_cache(result);
7245   }
7246
7247   // Update the code cache.
7248   return CodeCache::cast(code_cache())->Update(name, code);
7249 }
7250
7251
7252 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
7253   // Do a lookup if a code cache exists.
7254   if (!code_cache()->IsFixedArray()) {
7255     return CodeCache::cast(code_cache())->Lookup(name, flags);
7256   } else {
7257     return GetHeap()->undefined_value();
7258   }
7259 }
7260
7261
7262 int Map::IndexInCodeCache(Object* name, Code* code) {
7263   // Get the internal index if a code cache exists.
7264   if (!code_cache()->IsFixedArray()) {
7265     return CodeCache::cast(code_cache())->GetIndex(name, code);
7266   }
7267   return -1;
7268 }
7269
7270
7271 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7272   // No GC is supposed to happen between a call to IndexInCodeCache and
7273   // RemoveFromCodeCache so the code cache must be there.
7274   ASSERT(!code_cache()->IsFixedArray());
7275   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7276 }
7277
7278
7279 // An iterator over all map transitions in an descriptor array, reusing the map
7280 // field of the contens array while it is running.
7281 class IntrusiveMapTransitionIterator {
7282  public:
7283   explicit IntrusiveMapTransitionIterator(TransitionArray* transition_array)
7284       : transition_array_(transition_array) { }
7285
7286   void Start() {
7287     ASSERT(!IsIterating());
7288     *TransitionArrayHeader() = Smi::FromInt(0);
7289   }
7290
7291   bool IsIterating() {
7292     return (*TransitionArrayHeader())->IsSmi();
7293   }
7294
7295   Map* Next() {
7296     ASSERT(IsIterating());
7297     int index = Smi::cast(*TransitionArrayHeader())->value();
7298     int number_of_transitions = transition_array_->number_of_transitions();
7299     while (index < number_of_transitions) {
7300       *TransitionArrayHeader() = Smi::FromInt(index + 1);
7301       return transition_array_->GetTarget(index);
7302     }
7303
7304     *TransitionArrayHeader() = transition_array_->GetHeap()->fixed_array_map();
7305     return NULL;
7306   }
7307
7308  private:
7309   Object** TransitionArrayHeader() {
7310     return HeapObject::RawField(transition_array_, TransitionArray::kMapOffset);
7311   }
7312
7313   TransitionArray* transition_array_;
7314 };
7315
7316
7317 // An iterator over all prototype transitions, reusing the map field of the
7318 // underlying array while it is running.
7319 class IntrusivePrototypeTransitionIterator {
7320  public:
7321   explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans)
7322       : proto_trans_(proto_trans) { }
7323
7324   void Start() {
7325     ASSERT(!IsIterating());
7326     *Header() = Smi::FromInt(0);
7327   }
7328
7329   bool IsIterating() {
7330     return (*Header())->IsSmi();
7331   }
7332
7333   Map* Next() {
7334     ASSERT(IsIterating());
7335     int transitionNumber = Smi::cast(*Header())->value();
7336     if (transitionNumber < NumberOfTransitions()) {
7337       *Header() = Smi::FromInt(transitionNumber + 1);
7338       return GetTransition(transitionNumber);
7339     }
7340     *Header() = proto_trans_->GetHeap()->fixed_array_map();
7341     return NULL;
7342   }
7343
7344  private:
7345   Object** Header() {
7346     return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
7347   }
7348
7349   int NumberOfTransitions() {
7350     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7351     Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
7352     return Smi::cast(num)->value();
7353   }
7354
7355   Map* GetTransition(int transitionNumber) {
7356     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7357     return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
7358   }
7359
7360   int IndexFor(int transitionNumber) {
7361     return Map::kProtoTransitionHeaderSize +
7362         Map::kProtoTransitionMapOffset +
7363         transitionNumber * Map::kProtoTransitionElementsPerEntry;
7364   }
7365
7366   HeapObject* proto_trans_;
7367 };
7368
7369
7370 // To traverse the transition tree iteratively, we have to store two kinds of
7371 // information in a map: The parent map in the traversal and which children of a
7372 // node have already been visited. To do this without additional memory, we
7373 // temporarily reuse two maps with known values:
7374 //
7375 //  (1) The map of the map temporarily holds the parent, and is restored to the
7376 //      meta map afterwards.
7377 //
7378 //  (2) The info which children have already been visited depends on which part
7379 //      of the map we currently iterate:
7380 //
7381 //    (a) If we currently follow normal map transitions, we temporarily store
7382 //        the current index in the map of the FixedArray of the desciptor
7383 //        array's contents, and restore it to the fixed array map afterwards.
7384 //        Note that a single descriptor can have 0, 1, or 2 transitions.
7385 //
7386 //    (b) If we currently follow prototype transitions, we temporarily store
7387 //        the current index in the map of the FixedArray holding the prototype
7388 //        transitions, and restore it to the fixed array map afterwards.
7389 //
7390 // Note that the child iterator is just a concatenation of two iterators: One
7391 // iterating over map transitions and one iterating over prototype transisitons.
7392 class TraversableMap : public Map {
7393  public:
7394   // Record the parent in the traversal within this map. Note that this destroys
7395   // this map's map!
7396   void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
7397
7398   // Reset the current map's map, returning the parent previously stored in it.
7399   TraversableMap* GetAndResetParent() {
7400     TraversableMap* old_parent = static_cast<TraversableMap*>(map());
7401     set_map_no_write_barrier(GetHeap()->meta_map());
7402     return old_parent;
7403   }
7404
7405   // Start iterating over this map's children, possibly destroying a FixedArray
7406   // map (see explanation above).
7407   void ChildIteratorStart() {
7408     if (HasTransitionArray()) {
7409       if (HasPrototypeTransitions()) {
7410         IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start();
7411       }
7412
7413       IntrusiveMapTransitionIterator(transitions()).Start();
7414     }
7415   }
7416
7417   // If we have an unvisited child map, return that one and advance. If we have
7418   // none, return NULL and reset any destroyed FixedArray maps.
7419   TraversableMap* ChildIteratorNext() {
7420     TransitionArray* transition_array = unchecked_transition_array();
7421     if (!transition_array->map()->IsSmi() &&
7422         !transition_array->IsTransitionArray()) {
7423       return NULL;
7424     }
7425
7426     if (transition_array->HasPrototypeTransitions()) {
7427       HeapObject* proto_transitions =
7428           transition_array->UncheckedPrototypeTransitions();
7429       IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions);
7430       if (proto_iterator.IsIterating()) {
7431         Map* next = proto_iterator.Next();
7432         if (next != NULL) return static_cast<TraversableMap*>(next);
7433       }
7434     }
7435
7436     IntrusiveMapTransitionIterator transition_iterator(transition_array);
7437     if (transition_iterator.IsIterating()) {
7438       Map* next = transition_iterator.Next();
7439       if (next != NULL) return static_cast<TraversableMap*>(next);
7440     }
7441
7442     return NULL;
7443   }
7444 };
7445
7446
7447 // Traverse the transition tree in postorder without using the C++ stack by
7448 // doing pointer reversal.
7449 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
7450   TraversableMap* current = static_cast<TraversableMap*>(this);
7451   current->ChildIteratorStart();
7452   while (true) {
7453     TraversableMap* child = current->ChildIteratorNext();
7454     if (child != NULL) {
7455       child->ChildIteratorStart();
7456       child->SetParent(current);
7457       current = child;
7458     } else {
7459       TraversableMap* parent = current->GetAndResetParent();
7460       callback(current, data);
7461       if (current == this) break;
7462       current = parent;
7463     }
7464   }
7465 }
7466
7467
7468 MaybeObject* CodeCache::Update(Name* name, Code* code) {
7469   // The number of monomorphic stubs for normal load/store/call IC's can grow to
7470   // a large number and therefore they need to go into a hash table. They are
7471   // used to load global properties from cells.
7472   if (code->type() == Code::NORMAL) {
7473     // Make sure that a hash table is allocated for the normal load code cache.
7474     if (normal_type_cache()->IsUndefined()) {
7475       Object* result;
7476       { MaybeObject* maybe_result =
7477             CodeCacheHashTable::Allocate(GetHeap(),
7478                                          CodeCacheHashTable::kInitialSize);
7479         if (!maybe_result->ToObject(&result)) return maybe_result;
7480       }
7481       set_normal_type_cache(result);
7482     }
7483     return UpdateNormalTypeCache(name, code);
7484   } else {
7485     ASSERT(default_cache()->IsFixedArray());
7486     return UpdateDefaultCache(name, code);
7487   }
7488 }
7489
7490
7491 MaybeObject* CodeCache::UpdateDefaultCache(Name* name, Code* code) {
7492   // When updating the default code cache we disregard the type encoded in the
7493   // flags. This allows call constant stubs to overwrite call field
7494   // stubs, etc.
7495   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7496
7497   // First check whether we can update existing code cache without
7498   // extending it.
7499   FixedArray* cache = default_cache();
7500   int length = cache->length();
7501   int deleted_index = -1;
7502   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7503     Object* key = cache->get(i);
7504     if (key->IsNull()) {
7505       if (deleted_index < 0) deleted_index = i;
7506       continue;
7507     }
7508     if (key->IsUndefined()) {
7509       if (deleted_index >= 0) i = deleted_index;
7510       cache->set(i + kCodeCacheEntryNameOffset, name);
7511       cache->set(i + kCodeCacheEntryCodeOffset, code);
7512       return this;
7513     }
7514     if (name->Equals(Name::cast(key))) {
7515       Code::Flags found =
7516           Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7517       if (Code::RemoveTypeFromFlags(found) == flags) {
7518         cache->set(i + kCodeCacheEntryCodeOffset, code);
7519         return this;
7520       }
7521     }
7522   }
7523
7524   // Reached the end of the code cache.  If there were deleted
7525   // elements, reuse the space for the first of them.
7526   if (deleted_index >= 0) {
7527     cache->set(deleted_index + kCodeCacheEntryNameOffset, name);
7528     cache->set(deleted_index + kCodeCacheEntryCodeOffset, code);
7529     return this;
7530   }
7531
7532   // Extend the code cache with some new entries (at least one). Must be a
7533   // multiple of the entry size.
7534   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7535   new_length = new_length - new_length % kCodeCacheEntrySize;
7536   ASSERT((new_length % kCodeCacheEntrySize) == 0);
7537   Object* result;
7538   { MaybeObject* maybe_result = cache->CopySize(new_length);
7539     if (!maybe_result->ToObject(&result)) return maybe_result;
7540   }
7541
7542   // Add the (name, code) pair to the new cache.
7543   cache = FixedArray::cast(result);
7544   cache->set(length + kCodeCacheEntryNameOffset, name);
7545   cache->set(length + kCodeCacheEntryCodeOffset, code);
7546   set_default_cache(cache);
7547   return this;
7548 }
7549
7550
7551 MaybeObject* CodeCache::UpdateNormalTypeCache(Name* name, Code* code) {
7552   // Adding a new entry can cause a new cache to be allocated.
7553   CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7554   Object* new_cache;
7555   { MaybeObject* maybe_new_cache = cache->Put(name, code);
7556     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
7557   }
7558   set_normal_type_cache(new_cache);
7559   return this;
7560 }
7561
7562
7563 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
7564   Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7565   if (result->IsCode()) {
7566     if (Code::cast(result)->flags() == flags) return result;
7567     return GetHeap()->undefined_value();
7568   }
7569   return LookupNormalTypeCache(name, flags);
7570 }
7571
7572
7573 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
7574   FixedArray* cache = default_cache();
7575   int length = cache->length();
7576   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7577     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7578     // Skip deleted elements.
7579     if (key->IsNull()) continue;
7580     if (key->IsUndefined()) return key;
7581     if (name->Equals(Name::cast(key))) {
7582       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
7583       if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
7584         return code;
7585       }
7586     }
7587   }
7588   return GetHeap()->undefined_value();
7589 }
7590
7591
7592 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
7593   if (!normal_type_cache()->IsUndefined()) {
7594     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7595     return cache->Lookup(name, flags);
7596   } else {
7597     return GetHeap()->undefined_value();
7598   }
7599 }
7600
7601
7602 int CodeCache::GetIndex(Object* name, Code* code) {
7603   if (code->type() == Code::NORMAL) {
7604     if (normal_type_cache()->IsUndefined()) return -1;
7605     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7606     return cache->GetIndex(Name::cast(name), code->flags());
7607   }
7608
7609   FixedArray* array = default_cache();
7610   int len = array->length();
7611   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
7612     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
7613   }
7614   return -1;
7615 }
7616
7617
7618 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
7619   if (code->type() == Code::NORMAL) {
7620     ASSERT(!normal_type_cache()->IsUndefined());
7621     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7622     ASSERT(cache->GetIndex(Name::cast(name), code->flags()) == index);
7623     cache->RemoveByIndex(index);
7624   } else {
7625     FixedArray* array = default_cache();
7626     ASSERT(array->length() >= index && array->get(index)->IsCode());
7627     // Use null instead of undefined for deleted elements to distinguish
7628     // deleted elements from unused elements.  This distinction is used
7629     // when looking up in the cache and when updating the cache.
7630     ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
7631     array->set_null(index - 1);  // Name.
7632     array->set_null(index);  // Code.
7633   }
7634 }
7635
7636
7637 // The key in the code cache hash table consists of the property name and the
7638 // code object. The actual match is on the name and the code flags. If a key
7639 // is created using the flags and not a code object it can only be used for
7640 // lookup not to create a new entry.
7641 class CodeCacheHashTableKey : public HashTableKey {
7642  public:
7643   CodeCacheHashTableKey(Name* name, Code::Flags flags)
7644       : name_(name), flags_(flags), code_(NULL) { }
7645
7646   CodeCacheHashTableKey(Name* name, Code* code)
7647       : name_(name), flags_(code->flags()), code_(code) { }
7648
7649
7650   bool IsMatch(Object* other) {
7651     if (!other->IsFixedArray()) return false;
7652     FixedArray* pair = FixedArray::cast(other);
7653     Name* name = Name::cast(pair->get(0));
7654     Code::Flags flags = Code::cast(pair->get(1))->flags();
7655     if (flags != flags_) {
7656       return false;
7657     }
7658     return name_->Equals(name);
7659   }
7660
7661   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
7662     return name->Hash() ^ flags;
7663   }
7664
7665   uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); }
7666
7667   uint32_t HashForObject(Object* obj) {
7668     FixedArray* pair = FixedArray::cast(obj);
7669     Name* name = Name::cast(pair->get(0));
7670     Code* code = Code::cast(pair->get(1));
7671     return NameFlagsHashHelper(name, code->flags());
7672   }
7673
7674   MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) {
7675     ASSERT(code_ != NULL);
7676     Object* obj;
7677     { MaybeObject* maybe_obj = heap->AllocateFixedArray(2);
7678       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7679     }
7680     FixedArray* pair = FixedArray::cast(obj);
7681     pair->set(0, name_);
7682     pair->set(1, code_);
7683     return pair;
7684   }
7685
7686  private:
7687   Name* name_;
7688   Code::Flags flags_;
7689   // TODO(jkummerow): We should be able to get by without this.
7690   Code* code_;
7691 };
7692
7693
7694 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
7695   CodeCacheHashTableKey key(name, flags);
7696   int entry = FindEntry(&key);
7697   if (entry == kNotFound) return GetHeap()->undefined_value();
7698   return get(EntryToIndex(entry) + 1);
7699 }
7700
7701
7702 MaybeObject* CodeCacheHashTable::Put(Name* name, Code* code) {
7703   CodeCacheHashTableKey key(name, code);
7704   Object* obj;
7705   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
7706     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7707   }
7708
7709   // Don't use |this|, as the table might have grown.
7710   CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
7711
7712   int entry = cache->FindInsertionEntry(key.Hash());
7713   Object* k;
7714   { MaybeObject* maybe_k = key.AsObject(GetHeap());
7715     if (!maybe_k->ToObject(&k)) return maybe_k;
7716   }
7717
7718   cache->set(EntryToIndex(entry), k);
7719   cache->set(EntryToIndex(entry) + 1, code);
7720   cache->ElementAdded();
7721   return cache;
7722 }
7723
7724
7725 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
7726   CodeCacheHashTableKey key(name, flags);
7727   int entry = FindEntry(&key);
7728   return (entry == kNotFound) ? -1 : entry;
7729 }
7730
7731
7732 void CodeCacheHashTable::RemoveByIndex(int index) {
7733   ASSERT(index >= 0);
7734   Heap* heap = GetHeap();
7735   set(EntryToIndex(index), heap->the_hole_value());
7736   set(EntryToIndex(index) + 1, heap->the_hole_value());
7737   ElementRemoved();
7738 }
7739
7740
7741 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache,
7742                                   MapHandleList* maps,
7743                                   Code::Flags flags,
7744                                   Handle<Code> code) {
7745   Isolate* isolate = cache->GetIsolate();
7746   CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code));
7747 }
7748
7749
7750 MaybeObject* PolymorphicCodeCache::Update(MapHandleList* maps,
7751                                           Code::Flags flags,
7752                                           Code* code) {
7753   // Initialize cache if necessary.
7754   if (cache()->IsUndefined()) {
7755     Object* result;
7756     { MaybeObject* maybe_result =
7757           PolymorphicCodeCacheHashTable::Allocate(
7758               GetHeap(),
7759               PolymorphicCodeCacheHashTable::kInitialSize);
7760       if (!maybe_result->ToObject(&result)) return maybe_result;
7761     }
7762     set_cache(result);
7763   } else {
7764     // This entry shouldn't be contained in the cache yet.
7765     ASSERT(PolymorphicCodeCacheHashTable::cast(cache())
7766                ->Lookup(maps, flags)->IsUndefined());
7767   }
7768   PolymorphicCodeCacheHashTable* hash_table =
7769       PolymorphicCodeCacheHashTable::cast(cache());
7770   Object* new_cache;
7771   { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
7772     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
7773   }
7774   set_cache(new_cache);
7775   return this;
7776 }
7777
7778
7779 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
7780                                             Code::Flags flags) {
7781   if (!cache()->IsUndefined()) {
7782     PolymorphicCodeCacheHashTable* hash_table =
7783         PolymorphicCodeCacheHashTable::cast(cache());
7784     return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
7785   } else {
7786     return GetIsolate()->factory()->undefined_value();
7787   }
7788 }
7789
7790
7791 // Despite their name, object of this class are not stored in the actual
7792 // hash table; instead they're temporarily used for lookups. It is therefore
7793 // safe to have a weak (non-owning) pointer to a MapList as a member field.
7794 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
7795  public:
7796   // Callers must ensure that |maps| outlives the newly constructed object.
7797   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
7798       : maps_(maps),
7799         code_flags_(code_flags) {}
7800
7801   bool IsMatch(Object* other) {
7802     MapHandleList other_maps(kDefaultListAllocationSize);
7803     int other_flags;
7804     FromObject(other, &other_flags, &other_maps);
7805     if (code_flags_ != other_flags) return false;
7806     if (maps_->length() != other_maps.length()) return false;
7807     // Compare just the hashes first because it's faster.
7808     int this_hash = MapsHashHelper(maps_, code_flags_);
7809     int other_hash = MapsHashHelper(&other_maps, other_flags);
7810     if (this_hash != other_hash) return false;
7811
7812     // Full comparison: for each map in maps_, look for an equivalent map in
7813     // other_maps. This implementation is slow, but probably good enough for
7814     // now because the lists are short (<= 4 elements currently).
7815     for (int i = 0; i < maps_->length(); ++i) {
7816       bool match_found = false;
7817       for (int j = 0; j < other_maps.length(); ++j) {
7818         if (*(maps_->at(i)) == *(other_maps.at(j))) {
7819           match_found = true;
7820           break;
7821         }
7822       }
7823       if (!match_found) return false;
7824     }
7825     return true;
7826   }
7827
7828   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
7829     uint32_t hash = code_flags;
7830     for (int i = 0; i < maps->length(); ++i) {
7831       hash ^= maps->at(i)->Hash();
7832     }
7833     return hash;
7834   }
7835
7836   uint32_t Hash() {
7837     return MapsHashHelper(maps_, code_flags_);
7838   }
7839
7840   uint32_t HashForObject(Object* obj) {
7841     MapHandleList other_maps(kDefaultListAllocationSize);
7842     int other_flags;
7843     FromObject(obj, &other_flags, &other_maps);
7844     return MapsHashHelper(&other_maps, other_flags);
7845   }
7846
7847   MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) {
7848     Object* obj;
7849     // The maps in |maps_| must be copied to a newly allocated FixedArray,
7850     // both because the referenced MapList is short-lived, and because C++
7851     // objects can't be stored in the heap anyway.
7852     { MaybeObject* maybe_obj =
7853           heap->AllocateUninitializedFixedArray(maps_->length() + 1);
7854       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7855     }
7856     FixedArray* list = FixedArray::cast(obj);
7857     list->set(0, Smi::FromInt(code_flags_));
7858     for (int i = 0; i < maps_->length(); ++i) {
7859       list->set(i + 1, *maps_->at(i));
7860     }
7861     return list;
7862   }
7863
7864  private:
7865   static MapHandleList* FromObject(Object* obj,
7866                                    int* code_flags,
7867                                    MapHandleList* maps) {
7868     FixedArray* list = FixedArray::cast(obj);
7869     maps->Rewind(0);
7870     *code_flags = Smi::cast(list->get(0))->value();
7871     for (int i = 1; i < list->length(); ++i) {
7872       maps->Add(Handle<Map>(Map::cast(list->get(i))));
7873     }
7874     return maps;
7875   }
7876
7877   MapHandleList* maps_;  // weak.
7878   int code_flags_;
7879   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
7880 };
7881
7882
7883 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
7884                                               int code_flags) {
7885   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
7886   int entry = FindEntry(&key);
7887   if (entry == kNotFound) return GetHeap()->undefined_value();
7888   return get(EntryToIndex(entry) + 1);
7889 }
7890
7891
7892 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps,
7893                                                 int code_flags,
7894                                                 Code* code) {
7895   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
7896   Object* obj;
7897   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
7898     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7899   }
7900   PolymorphicCodeCacheHashTable* cache =
7901       reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
7902   int entry = cache->FindInsertionEntry(key.Hash());
7903   { MaybeObject* maybe_obj = key.AsObject(GetHeap());
7904     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7905   }
7906   cache->set(EntryToIndex(entry), obj);
7907   cache->set(EntryToIndex(entry) + 1, code);
7908   cache->ElementAdded();
7909   return cache;
7910 }
7911
7912
7913 void FixedArray::Shrink(int new_length) {
7914   ASSERT(0 <= new_length && new_length <= length());
7915   if (new_length < length()) {
7916     RightTrimFixedArray<Heap::FROM_MUTATOR>(
7917         GetHeap(), this, length() - new_length);
7918   }
7919 }
7920
7921
7922 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
7923   ElementsAccessor* accessor = array->GetElementsAccessor();
7924   MaybeObject* maybe_result =
7925       accessor->AddElementsToFixedArray(array, array, this);
7926   FixedArray* result;
7927   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
7928 #ifdef ENABLE_SLOW_ASSERTS
7929   if (FLAG_enable_slow_asserts) {
7930     for (int i = 0; i < result->length(); i++) {
7931       Object* current = result->get(i);
7932       ASSERT(current->IsNumber() || current->IsName());
7933     }
7934   }
7935 #endif
7936   return result;
7937 }
7938
7939
7940 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
7941   ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
7942   MaybeObject* maybe_result =
7943       accessor->AddElementsToFixedArray(NULL, NULL, this, other);
7944   FixedArray* result;
7945   if (!maybe_result->To(&result)) return maybe_result;
7946 #ifdef ENABLE_SLOW_ASSERTS
7947   if (FLAG_enable_slow_asserts) {
7948     for (int i = 0; i < result->length(); i++) {
7949       Object* current = result->get(i);
7950       ASSERT(current->IsNumber() || current->IsName());
7951     }
7952   }
7953 #endif
7954   return result;
7955 }
7956
7957
7958 MaybeObject* FixedArray::CopySize(int new_length, PretenureFlag pretenure) {
7959   Heap* heap = GetHeap();
7960   if (new_length == 0) return heap->empty_fixed_array();
7961   Object* obj;
7962   { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length, pretenure);
7963     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7964   }
7965   FixedArray* result = FixedArray::cast(obj);
7966   // Copy the content
7967   DisallowHeapAllocation no_gc;
7968   int len = length();
7969   if (new_length < len) len = new_length;
7970   // We are taking the map from the old fixed array so the map is sure to
7971   // be an immortal immutable object.
7972   result->set_map_no_write_barrier(map());
7973   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
7974   for (int i = 0; i < len; i++) {
7975     result->set(i, get(i), mode);
7976   }
7977   return result;
7978 }
7979
7980
7981 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
7982   DisallowHeapAllocation no_gc;
7983   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
7984   for (int index = 0; index < len; index++) {
7985     dest->set(dest_pos+index, get(pos+index), mode);
7986   }
7987 }
7988
7989
7990 #ifdef DEBUG
7991 bool FixedArray::IsEqualTo(FixedArray* other) {
7992   if (length() != other->length()) return false;
7993   for (int i = 0 ; i < length(); ++i) {
7994     if (get(i) != other->get(i)) return false;
7995   }
7996   return true;
7997 }
7998 #endif
7999
8000
8001 MaybeObject* DescriptorArray::Allocate(Isolate* isolate,
8002                                        int number_of_descriptors,
8003                                        int slack) {
8004   Heap* heap = isolate->heap();
8005   // Do not use DescriptorArray::cast on incomplete object.
8006   int size = number_of_descriptors + slack;
8007   if (size == 0) return heap->empty_descriptor_array();
8008   FixedArray* result;
8009   // Allocate the array of keys.
8010   MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size));
8011   if (!maybe_array->To(&result)) return maybe_array;
8012
8013   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
8014   result->set(kEnumCacheIndex, Smi::FromInt(0));
8015   return result;
8016 }
8017
8018
8019 void DescriptorArray::ClearEnumCache() {
8020   set(kEnumCacheIndex, Smi::FromInt(0));
8021 }
8022
8023
8024 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
8025                                    FixedArray* new_cache,
8026                                    Object* new_index_cache) {
8027   ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
8028   ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
8029   ASSERT(!IsEmpty());
8030   ASSERT(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
8031   FixedArray::cast(bridge_storage)->
8032     set(kEnumCacheBridgeCacheIndex, new_cache);
8033   FixedArray::cast(bridge_storage)->
8034     set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
8035   set(kEnumCacheIndex, bridge_storage);
8036 }
8037
8038
8039 void DescriptorArray::CopyFrom(int dst_index,
8040                                DescriptorArray* src,
8041                                int src_index,
8042                                const WhitenessWitness& witness) {
8043   Object* value = src->GetValue(src_index);
8044   PropertyDetails details = src->GetDetails(src_index);
8045   Descriptor desc(src->GetKey(src_index), value, details);
8046   Set(dst_index, &desc, witness);
8047 }
8048
8049
8050 Handle<DescriptorArray> DescriptorArray::Merge(Handle<DescriptorArray> desc,
8051                                                int verbatim,
8052                                                int valid,
8053                                                int new_size,
8054                                                int modify_index,
8055                                                StoreMode store_mode,
8056                                                Handle<DescriptorArray> other) {
8057   CALL_HEAP_FUNCTION(desc->GetIsolate(),
8058                      desc->Merge(verbatim, valid, new_size, modify_index,
8059                                  store_mode, *other),
8060                      DescriptorArray);
8061 }
8062
8063
8064 // Generalize the |other| descriptor array by merging it into the (at least
8065 // partly) updated |this| descriptor array.
8066 // The method merges two descriptor array in three parts. Both descriptor arrays
8067 // are identical up to |verbatim|. They also overlap in keys up to |valid|.
8068 // Between |verbatim| and |valid|, the resulting descriptor type as well as the
8069 // representation are generalized from both |this| and |other|. Beyond |valid|,
8070 // the descriptors are copied verbatim from |other| up to |new_size|.
8071 // In case of incompatible types, the type and representation of |other| is
8072 // used.
8073 MaybeObject* DescriptorArray::Merge(int verbatim,
8074                                     int valid,
8075                                     int new_size,
8076                                     int modify_index,
8077                                     StoreMode store_mode,
8078                                     DescriptorArray* other) {
8079   ASSERT(verbatim <= valid);
8080   ASSERT(valid <= new_size);
8081
8082   DescriptorArray* result;
8083   // Allocate a new descriptor array large enough to hold the required
8084   // descriptors, with minimally the exact same size as this descriptor array.
8085   MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
8086       GetIsolate(), new_size,
8087       Max(new_size, other->number_of_descriptors()) - new_size);
8088   if (!maybe_descriptors->To(&result)) return maybe_descriptors;
8089   ASSERT(result->length() > length() ||
8090          result->NumberOfSlackDescriptors() > 0 ||
8091          result->number_of_descriptors() == other->number_of_descriptors());
8092   ASSERT(result->number_of_descriptors() == new_size);
8093
8094   DescriptorArray::WhitenessWitness witness(result);
8095
8096   int descriptor;
8097
8098   // 0 -> |verbatim|
8099   int current_offset = 0;
8100   for (descriptor = 0; descriptor < verbatim; descriptor++) {
8101     if (GetDetails(descriptor).type() == FIELD) current_offset++;
8102     result->CopyFrom(descriptor, other, descriptor, witness);
8103   }
8104
8105   // |verbatim| -> |valid|
8106   for (; descriptor < valid; descriptor++) {
8107     Name* key = GetKey(descriptor);
8108     PropertyDetails details = GetDetails(descriptor);
8109     PropertyDetails other_details = other->GetDetails(descriptor);
8110
8111     if (details.type() == FIELD || other_details.type() == FIELD ||
8112         (store_mode == FORCE_FIELD && descriptor == modify_index) ||
8113         (details.type() == CONSTANT &&
8114          other_details.type() == CONSTANT &&
8115          GetValue(descriptor) != other->GetValue(descriptor))) {
8116       Representation representation =
8117           details.representation().generalize(other_details.representation());
8118       FieldDescriptor d(key,
8119                         current_offset++,
8120                         other_details.attributes(),
8121                         representation);
8122       result->Set(descriptor, &d, witness);
8123     } else {
8124       result->CopyFrom(descriptor, other, descriptor, witness);
8125     }
8126   }
8127
8128   // |valid| -> |new_size|
8129   for (; descriptor < new_size; descriptor++) {
8130     PropertyDetails details = other->GetDetails(descriptor);
8131     if (details.type() == FIELD ||
8132         (store_mode == FORCE_FIELD && descriptor == modify_index)) {
8133       Name* key = other->GetKey(descriptor);
8134       FieldDescriptor d(key,
8135                         current_offset++,
8136                         details.attributes(),
8137                         details.representation());
8138       result->Set(descriptor, &d, witness);
8139     } else {
8140       result->CopyFrom(descriptor, other, descriptor, witness);
8141     }
8142   }
8143
8144   result->Sort();
8145   return result;
8146 }
8147
8148
8149 // Checks whether a merge of |other| into |this| would return a copy of |this|.
8150 bool DescriptorArray::IsMoreGeneralThan(int verbatim,
8151                                         int valid,
8152                                         int new_size,
8153                                         DescriptorArray* other) {
8154   ASSERT(verbatim <= valid);
8155   ASSERT(valid <= new_size);
8156   if (valid != new_size) return false;
8157
8158   for (int descriptor = verbatim; descriptor < valid; descriptor++) {
8159     PropertyDetails details = GetDetails(descriptor);
8160     PropertyDetails other_details = other->GetDetails(descriptor);
8161     if (!other_details.representation().fits_into(details.representation())) {
8162       return false;
8163     }
8164     if (details.type() == CONSTANT) {
8165       if (other_details.type() != CONSTANT) return false;
8166       if (GetValue(descriptor) != other->GetValue(descriptor)) return false;
8167     }
8168   }
8169
8170   return true;
8171 }
8172
8173
8174 // We need the whiteness witness since sort will reshuffle the entries in the
8175 // descriptor array. If the descriptor array were to be black, the shuffling
8176 // would move a slot that was already recorded as pointing into an evacuation
8177 // candidate. This would result in missing updates upon evacuation.
8178 void DescriptorArray::Sort() {
8179   // In-place heap sort.
8180   int len = number_of_descriptors();
8181   // Reset sorting since the descriptor array might contain invalid pointers.
8182   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
8183   // Bottom-up max-heap construction.
8184   // Index of the last node with children
8185   const int max_parent_index = (len / 2) - 1;
8186   for (int i = max_parent_index; i >= 0; --i) {
8187     int parent_index = i;
8188     const uint32_t parent_hash = GetSortedKey(i)->Hash();
8189     while (parent_index <= max_parent_index) {
8190       int child_index = 2 * parent_index + 1;
8191       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8192       if (child_index + 1 < len) {
8193         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8194         if (right_child_hash > child_hash) {
8195           child_index++;
8196           child_hash = right_child_hash;
8197         }
8198       }
8199       if (child_hash <= parent_hash) break;
8200       SwapSortedKeys(parent_index, child_index);
8201       // Now element at child_index could be < its children.
8202       parent_index = child_index;  // parent_hash remains correct.
8203     }
8204   }
8205
8206   // Extract elements and create sorted array.
8207   for (int i = len - 1; i > 0; --i) {
8208     // Put max element at the back of the array.
8209     SwapSortedKeys(0, i);
8210     // Shift down the new top element.
8211     int parent_index = 0;
8212     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
8213     const int max_parent_index = (i / 2) - 1;
8214     while (parent_index <= max_parent_index) {
8215       int child_index = parent_index * 2 + 1;
8216       uint32_t child_hash = GetSortedKey(child_index)->Hash();
8217       if (child_index + 1 < i) {
8218         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
8219         if (right_child_hash > child_hash) {
8220           child_index++;
8221           child_hash = right_child_hash;
8222         }
8223       }
8224       if (child_hash <= parent_hash) break;
8225       SwapSortedKeys(parent_index, child_index);
8226       parent_index = child_index;
8227     }
8228   }
8229   ASSERT(IsSortedNoDuplicates());
8230 }
8231
8232
8233 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
8234   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
8235   copy->set_getter(pair->getter());
8236   copy->set_setter(pair->setter());
8237   return copy;
8238 }
8239
8240
8241 Object* AccessorPair::GetComponent(AccessorComponent component) {
8242   Object* accessor = get(component);
8243   return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
8244 }
8245
8246
8247 MaybeObject* DeoptimizationInputData::Allocate(Isolate* isolate,
8248                                                int deopt_entry_count,
8249                                                PretenureFlag pretenure) {
8250   ASSERT(deopt_entry_count > 0);
8251   return isolate->heap()->AllocateFixedArray(LengthFor(deopt_entry_count),
8252                                              pretenure);
8253 }
8254
8255
8256 MaybeObject* DeoptimizationOutputData::Allocate(Isolate* isolate,
8257                                                 int number_of_deopt_points,
8258                                                 PretenureFlag pretenure) {
8259   if (number_of_deopt_points == 0) return isolate->heap()->empty_fixed_array();
8260   return isolate->heap()->AllocateFixedArray(
8261       LengthOfFixedArray(number_of_deopt_points), pretenure);
8262 }
8263
8264
8265 #ifdef DEBUG
8266 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
8267   if (IsEmpty()) return other->IsEmpty();
8268   if (other->IsEmpty()) return false;
8269   if (length() != other->length()) return false;
8270   for (int i = 0; i < length(); ++i) {
8271     if (get(i) != other->get(i)) return false;
8272   }
8273   return true;
8274 }
8275 #endif
8276
8277
8278 static bool IsIdentifier(UnicodeCache* cache, Name* name) {
8279   // Checks whether the buffer contains an identifier (no escape).
8280   if (!name->IsString()) return false;
8281   String* string = String::cast(name);
8282   if (string->length() == 0) return true;
8283   ConsStringIteratorOp op;
8284   StringCharacterStream stream(string, &op);
8285   if (!cache->IsIdentifierStart(stream.GetNext())) {
8286     return false;
8287   }
8288   while (stream.HasMore()) {
8289     if (!cache->IsIdentifierPart(stream.GetNext())) {
8290       return false;
8291     }
8292   }
8293   return true;
8294 }
8295
8296
8297 bool Name::IsCacheable(Isolate* isolate) {
8298   return IsSymbol() || IsIdentifier(isolate->unicode_cache(), this);
8299 }
8300
8301
8302 bool String::LooksValid() {
8303   if (!GetIsolate()->heap()->Contains(this)) return false;
8304   return true;
8305 }
8306
8307
8308 String::FlatContent String::GetFlatContent() {
8309   ASSERT(!AllowHeapAllocation::IsAllowed());
8310   int length = this->length();
8311   StringShape shape(this);
8312   String* string = this;
8313   int offset = 0;
8314   if (shape.representation_tag() == kConsStringTag) {
8315     ConsString* cons = ConsString::cast(string);
8316     if (cons->second()->length() != 0) {
8317       return FlatContent();
8318     }
8319     string = cons->first();
8320     shape = StringShape(string);
8321   }
8322   if (shape.representation_tag() == kSlicedStringTag) {
8323     SlicedString* slice = SlicedString::cast(string);
8324     offset = slice->offset();
8325     string = slice->parent();
8326     shape = StringShape(string);
8327     ASSERT(shape.representation_tag() != kConsStringTag &&
8328            shape.representation_tag() != kSlicedStringTag);
8329   }
8330   if (shape.encoding_tag() == kOneByteStringTag) {
8331     const uint8_t* start;
8332     if (shape.representation_tag() == kSeqStringTag) {
8333       start = SeqOneByteString::cast(string)->GetChars();
8334     } else {
8335       start = ExternalAsciiString::cast(string)->GetChars();
8336     }
8337     return FlatContent(Vector<const uint8_t>(start + offset, length));
8338   } else {
8339     ASSERT(shape.encoding_tag() == kTwoByteStringTag);
8340     const uc16* start;
8341     if (shape.representation_tag() == kSeqStringTag) {
8342       start = SeqTwoByteString::cast(string)->GetChars();
8343     } else {
8344       start = ExternalTwoByteString::cast(string)->GetChars();
8345     }
8346     return FlatContent(Vector<const uc16>(start + offset, length));
8347   }
8348 }
8349
8350
8351 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8352                                           RobustnessFlag robust_flag,
8353                                           int offset,
8354                                           int length,
8355                                           int* length_return) {
8356   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8357     return SmartArrayPointer<char>(NULL);
8358   }
8359   Heap* heap = GetHeap();
8360
8361   // Negative length means the to the end of the string.
8362   if (length < 0) length = kMaxInt - offset;
8363
8364   // Compute the size of the UTF-8 string. Start at the specified offset.
8365   Access<ConsStringIteratorOp> op(
8366       heap->isolate()->objects_string_iterator());
8367   StringCharacterStream stream(this, op.value(), offset);
8368   int character_position = offset;
8369   int utf8_bytes = 0;
8370   int last = unibrow::Utf16::kNoPreviousCharacter;
8371   while (stream.HasMore() && character_position++ < offset + length) {
8372     uint16_t character = stream.GetNext();
8373     utf8_bytes += unibrow::Utf8::Length(character, last);
8374     last = character;
8375   }
8376
8377   if (length_return) {
8378     *length_return = utf8_bytes;
8379   }
8380
8381   char* result = NewArray<char>(utf8_bytes + 1);
8382
8383   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8384   stream.Reset(this, offset);
8385   character_position = offset;
8386   int utf8_byte_position = 0;
8387   last = unibrow::Utf16::kNoPreviousCharacter;
8388   while (stream.HasMore() && character_position++ < offset + length) {
8389     uint16_t character = stream.GetNext();
8390     if (allow_nulls == DISALLOW_NULLS && character == 0) {
8391       character = ' ';
8392     }
8393     utf8_byte_position +=
8394         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8395     last = character;
8396   }
8397   result[utf8_byte_position] = 0;
8398   return SmartArrayPointer<char>(result);
8399 }
8400
8401
8402 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8403                                           RobustnessFlag robust_flag,
8404                                           int* length_return) {
8405   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8406 }
8407
8408
8409 const uc16* String::GetTwoByteData(unsigned start) {
8410   ASSERT(!IsOneByteRepresentationUnderneath());
8411   switch (StringShape(this).representation_tag()) {
8412     case kSeqStringTag:
8413       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8414     case kExternalStringTag:
8415       return ExternalTwoByteString::cast(this)->
8416         ExternalTwoByteStringGetData(start);
8417     case kSlicedStringTag: {
8418       SlicedString* slice = SlicedString::cast(this);
8419       return slice->parent()->GetTwoByteData(start + slice->offset());
8420     }
8421     case kConsStringTag:
8422       UNREACHABLE();
8423       return NULL;
8424   }
8425   UNREACHABLE();
8426   return NULL;
8427 }
8428
8429
8430 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
8431   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8432     return SmartArrayPointer<uc16>();
8433   }
8434   Heap* heap = GetHeap();
8435
8436   Access<ConsStringIteratorOp> op(
8437       heap->isolate()->objects_string_iterator());
8438   StringCharacterStream stream(this, op.value());
8439
8440   uc16* result = NewArray<uc16>(length() + 1);
8441
8442   int i = 0;
8443   while (stream.HasMore()) {
8444     uint16_t character = stream.GetNext();
8445     result[i++] = character;
8446   }
8447   result[i] = 0;
8448   return SmartArrayPointer<uc16>(result);
8449 }
8450
8451
8452 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
8453   return reinterpret_cast<uc16*>(
8454       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8455 }
8456
8457
8458 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8459   Relocatable* current = isolate->relocatable_top();
8460   while (current != NULL) {
8461     current->PostGarbageCollection();
8462     current = current->prev_;
8463   }
8464 }
8465
8466
8467 // Reserve space for statics needing saving and restoring.
8468 int Relocatable::ArchiveSpacePerThread() {
8469   return sizeof(Relocatable*);  // NOLINT
8470 }
8471
8472
8473 // Archive statics that are thread local.
8474 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8475   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8476   isolate->set_relocatable_top(NULL);
8477   return to + ArchiveSpacePerThread();
8478 }
8479
8480
8481 // Restore statics that are thread local.
8482 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8483   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8484   return from + ArchiveSpacePerThread();
8485 }
8486
8487
8488 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8489   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8490   Iterate(v, top);
8491   return thread_storage + ArchiveSpacePerThread();
8492 }
8493
8494
8495 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8496   Iterate(v, isolate->relocatable_top());
8497 }
8498
8499
8500 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8501   Relocatable* current = top;
8502   while (current != NULL) {
8503     current->IterateInstance(v);
8504     current = current->prev_;
8505   }
8506 }
8507
8508
8509 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
8510     : Relocatable(isolate),
8511       str_(str.location()),
8512       length_(str->length()) {
8513   PostGarbageCollection();
8514 }
8515
8516
8517 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
8518     : Relocatable(isolate),
8519       str_(0),
8520       is_ascii_(true),
8521       length_(input.length()),
8522       start_(input.start()) { }
8523
8524
8525 void FlatStringReader::PostGarbageCollection() {
8526   if (str_ == NULL) return;
8527   Handle<String> str(str_);
8528   ASSERT(str->IsFlat());
8529   DisallowHeapAllocation no_gc;
8530   // This does not actually prevent the vector from being relocated later.
8531   String::FlatContent content = str->GetFlatContent();
8532   ASSERT(content.IsFlat());
8533   is_ascii_ = content.IsAscii();
8534   if (is_ascii_) {
8535     start_ = content.ToOneByteVector().start();
8536   } else {
8537     start_ = content.ToUC16Vector().start();
8538   }
8539 }
8540
8541
8542 String* ConsStringIteratorOp::Operate(String* string,
8543                                       unsigned* offset_out,
8544                                       int32_t* type_out,
8545                                       unsigned* length_out) {
8546   ASSERT(string->IsConsString());
8547   ConsString* cons_string = ConsString::cast(string);
8548   // Set up search data.
8549   root_ = cons_string;
8550   consumed_ = *offset_out;
8551   // Now search.
8552   return Search(offset_out, type_out, length_out);
8553 }
8554
8555
8556 String* ConsStringIteratorOp::Search(unsigned* offset_out,
8557                                      int32_t* type_out,
8558                                      unsigned* length_out) {
8559   ConsString* cons_string = root_;
8560   // Reset the stack, pushing the root string.
8561   depth_ = 1;
8562   maximum_depth_ = 1;
8563   frames_[0] = cons_string;
8564   const unsigned consumed = consumed_;
8565   unsigned offset = 0;
8566   while (true) {
8567     // Loop until the string is found which contains the target offset.
8568     String* string = cons_string->first();
8569     unsigned length = string->length();
8570     int32_t type;
8571     if (consumed < offset + length) {
8572       // Target offset is in the left branch.
8573       // Keep going if we're still in a ConString.
8574       type = string->map()->instance_type();
8575       if ((type & kStringRepresentationMask) == kConsStringTag) {
8576         cons_string = ConsString::cast(string);
8577         PushLeft(cons_string);
8578         continue;
8579       }
8580       // Tell the stack we're done decending.
8581       AdjustMaximumDepth();
8582     } else {
8583       // Descend right.
8584       // Update progress through the string.
8585       offset += length;
8586       // Keep going if we're still in a ConString.
8587       string = cons_string->second();
8588       type = string->map()->instance_type();
8589       if ((type & kStringRepresentationMask) == kConsStringTag) {
8590         cons_string = ConsString::cast(string);
8591         PushRight(cons_string);
8592         // TODO(dcarney) Add back root optimization.
8593         continue;
8594       }
8595       // Need this to be updated for the current string.
8596       length = string->length();
8597       // Account for the possibility of an empty right leaf.
8598       // This happens only if we have asked for an offset outside the string.
8599       if (length == 0) {
8600         // Reset depth so future operations will return null immediately.
8601         Reset();
8602         return NULL;
8603       }
8604       // Tell the stack we're done decending.
8605       AdjustMaximumDepth();
8606       // Pop stack so next iteration is in correct place.
8607       Pop();
8608     }
8609     ASSERT(length != 0);
8610     // Adjust return values and exit.
8611     consumed_ = offset + length;
8612     *offset_out = consumed - offset;
8613     *type_out = type;
8614     *length_out = length;
8615     return string;
8616   }
8617   UNREACHABLE();
8618   return NULL;
8619 }
8620
8621
8622 String* ConsStringIteratorOp::NextLeaf(bool* blew_stack,
8623                                        int32_t* type_out,
8624                                        unsigned* length_out) {
8625   while (true) {
8626     // Tree traversal complete.
8627     if (depth_ == 0) {
8628       *blew_stack = false;
8629       return NULL;
8630     }
8631     // We've lost track of higher nodes.
8632     if (maximum_depth_ - depth_ == kStackSize) {
8633       *blew_stack = true;
8634       return NULL;
8635     }
8636     // Go right.
8637     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
8638     String* string = cons_string->second();
8639     int32_t type = string->map()->instance_type();
8640     if ((type & kStringRepresentationMask) != kConsStringTag) {
8641       // Pop stack so next iteration is in correct place.
8642       Pop();
8643       unsigned length = static_cast<unsigned>(string->length());
8644       // Could be a flattened ConsString.
8645       if (length == 0) continue;
8646       *length_out = length;
8647       *type_out = type;
8648       consumed_ += length;
8649       return string;
8650     }
8651     cons_string = ConsString::cast(string);
8652     // TODO(dcarney) Add back root optimization.
8653     PushRight(cons_string);
8654     // Need to traverse all the way left.
8655     while (true) {
8656       // Continue left.
8657       string = cons_string->first();
8658       type = string->map()->instance_type();
8659       if ((type & kStringRepresentationMask) != kConsStringTag) {
8660         AdjustMaximumDepth();
8661         unsigned length = static_cast<unsigned>(string->length());
8662         ASSERT(length != 0);
8663         *length_out = length;
8664         *type_out = type;
8665         consumed_ += length;
8666         return string;
8667       }
8668       cons_string = ConsString::cast(string);
8669       PushLeft(cons_string);
8670     }
8671   }
8672   UNREACHABLE();
8673   return NULL;
8674 }
8675
8676
8677 uint16_t ConsString::ConsStringGet(int index) {
8678   ASSERT(index >= 0 && index < this->length());
8679
8680   // Check for a flattened cons string
8681   if (second()->length() == 0) {
8682     String* left = first();
8683     return left->Get(index);
8684   }
8685
8686   String* string = String::cast(this);
8687
8688   while (true) {
8689     if (StringShape(string).IsCons()) {
8690       ConsString* cons_string = ConsString::cast(string);
8691       String* left = cons_string->first();
8692       if (left->length() > index) {
8693         string = left;
8694       } else {
8695         index -= left->length();
8696         string = cons_string->second();
8697       }
8698     } else {
8699       return string->Get(index);
8700     }
8701   }
8702
8703   UNREACHABLE();
8704   return 0;
8705 }
8706
8707
8708 uint16_t SlicedString::SlicedStringGet(int index) {
8709   return parent()->Get(offset() + index);
8710 }
8711
8712
8713 template <typename sinkchar>
8714 void String::WriteToFlat(String* src,
8715                          sinkchar* sink,
8716                          int f,
8717                          int t) {
8718   String* source = src;
8719   int from = f;
8720   int to = t;
8721   while (true) {
8722     ASSERT(0 <= from && from <= to && to <= source->length());
8723     switch (StringShape(source).full_representation_tag()) {
8724       case kOneByteStringTag | kExternalStringTag: {
8725         CopyChars(sink,
8726                   ExternalAsciiString::cast(source)->GetChars() + from,
8727                   to - from);
8728         return;
8729       }
8730       case kTwoByteStringTag | kExternalStringTag: {
8731         const uc16* data =
8732             ExternalTwoByteString::cast(source)->GetChars();
8733         CopyChars(sink,
8734                   data + from,
8735                   to - from);
8736         return;
8737       }
8738       case kOneByteStringTag | kSeqStringTag: {
8739         CopyChars(sink,
8740                   SeqOneByteString::cast(source)->GetChars() + from,
8741                   to - from);
8742         return;
8743       }
8744       case kTwoByteStringTag | kSeqStringTag: {
8745         CopyChars(sink,
8746                   SeqTwoByteString::cast(source)->GetChars() + from,
8747                   to - from);
8748         return;
8749       }
8750       case kOneByteStringTag | kConsStringTag:
8751       case kTwoByteStringTag | kConsStringTag: {
8752         ConsString* cons_string = ConsString::cast(source);
8753         String* first = cons_string->first();
8754         int boundary = first->length();
8755         if (to - boundary >= boundary - from) {
8756           // Right hand side is longer.  Recurse over left.
8757           if (from < boundary) {
8758             WriteToFlat(first, sink, from, boundary);
8759             sink += boundary - from;
8760             from = 0;
8761           } else {
8762             from -= boundary;
8763           }
8764           to -= boundary;
8765           source = cons_string->second();
8766         } else {
8767           // Left hand side is longer.  Recurse over right.
8768           if (to > boundary) {
8769             String* second = cons_string->second();
8770             // When repeatedly appending to a string, we get a cons string that
8771             // is unbalanced to the left, a list, essentially.  We inline the
8772             // common case of sequential ascii right child.
8773             if (to - boundary == 1) {
8774               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
8775             } else if (second->IsSeqOneByteString()) {
8776               CopyChars(sink + boundary - from,
8777                         SeqOneByteString::cast(second)->GetChars(),
8778                         to - boundary);
8779             } else {
8780               WriteToFlat(second,
8781                           sink + boundary - from,
8782                           0,
8783                           to - boundary);
8784             }
8785             to = boundary;
8786           }
8787           source = first;
8788         }
8789         break;
8790       }
8791       case kOneByteStringTag | kSlicedStringTag:
8792       case kTwoByteStringTag | kSlicedStringTag: {
8793         SlicedString* slice = SlicedString::cast(source);
8794         unsigned offset = slice->offset();
8795         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
8796         return;
8797       }
8798     }
8799   }
8800 }
8801
8802
8803 // Compares the contents of two strings by reading and comparing
8804 // int-sized blocks of characters.
8805 template <typename Char>
8806 static inline bool CompareRawStringContents(const Char* const a,
8807                                             const Char* const b,
8808                                             int length) {
8809   int i = 0;
8810 #ifndef V8_HOST_CAN_READ_UNALIGNED
8811   // If this architecture isn't comfortable reading unaligned ints
8812   // then we have to check that the strings are aligned before
8813   // comparing them blockwise.
8814   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
8815   uint32_t pa_addr = reinterpret_cast<uint32_t>(a);
8816   uint32_t pb_addr = reinterpret_cast<uint32_t>(b);
8817   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
8818 #endif
8819     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
8820     int endpoint = length - kStepSize;
8821     // Compare blocks until we reach near the end of the string.
8822     for (; i <= endpoint; i += kStepSize) {
8823       uint32_t wa = *reinterpret_cast<const uint32_t*>(a + i);
8824       uint32_t wb = *reinterpret_cast<const uint32_t*>(b + i);
8825       if (wa != wb) {
8826         return false;
8827       }
8828     }
8829 #ifndef V8_HOST_CAN_READ_UNALIGNED
8830   }
8831 #endif
8832   // Compare the remaining characters that didn't fit into a block.
8833   for (; i < length; i++) {
8834     if (a[i] != b[i]) {
8835       return false;
8836     }
8837   }
8838   return true;
8839 }
8840
8841
8842 template<typename Chars1, typename Chars2>
8843 class RawStringComparator : public AllStatic {
8844  public:
8845   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
8846     ASSERT(sizeof(Chars1) != sizeof(Chars2));
8847     for (int i = 0; i < len; i++) {
8848       if (a[i] != b[i]) {
8849         return false;
8850       }
8851     }
8852     return true;
8853   }
8854 };
8855
8856
8857 template<>
8858 class RawStringComparator<uint16_t, uint16_t> {
8859  public:
8860   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
8861     return CompareRawStringContents(a, b, len);
8862   }
8863 };
8864
8865
8866 template<>
8867 class RawStringComparator<uint8_t, uint8_t> {
8868  public:
8869   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
8870     return CompareRawStringContents(a, b, len);
8871   }
8872 };
8873
8874
8875 class StringComparator {
8876   class State {
8877    public:
8878     explicit inline State(ConsStringIteratorOp* op)
8879       : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {}
8880
8881     inline void Init(String* string, unsigned len) {
8882       op_->Reset();
8883       int32_t type = string->map()->instance_type();
8884       String::Visit(string, 0, *this, *op_, type, len);
8885     }
8886
8887     inline void VisitOneByteString(const uint8_t* chars, unsigned length) {
8888       is_one_byte_ = true;
8889       buffer8_ = chars;
8890       length_ = length;
8891     }
8892
8893     inline void VisitTwoByteString(const uint16_t* chars, unsigned length) {
8894       is_one_byte_ = false;
8895       buffer16_ = chars;
8896       length_ = length;
8897     }
8898
8899     void Advance(unsigned consumed) {
8900       ASSERT(consumed <= length_);
8901       // Still in buffer.
8902       if (length_ != consumed) {
8903         if (is_one_byte_) {
8904           buffer8_ += consumed;
8905         } else {
8906           buffer16_ += consumed;
8907         }
8908         length_ -= consumed;
8909         return;
8910       }
8911       // Advance state.
8912       ASSERT(op_->HasMore());
8913       int32_t type = 0;
8914       unsigned length = 0;
8915       String* next = op_->ContinueOperation(&type, &length);
8916       ASSERT(next != NULL);
8917       ConsStringNullOp null_op;
8918       String::Visit(next, 0, *this, null_op, type, length);
8919     }
8920
8921     ConsStringIteratorOp* const op_;
8922     bool is_one_byte_;
8923     unsigned length_;
8924     union {
8925       const uint8_t* buffer8_;
8926       const uint16_t* buffer16_;
8927     };
8928
8929    private:
8930     DISALLOW_IMPLICIT_CONSTRUCTORS(State);
8931   };
8932
8933  public:
8934   inline StringComparator(ConsStringIteratorOp* op_1,
8935                           ConsStringIteratorOp* op_2)
8936     : state_1_(op_1),
8937       state_2_(op_2) {
8938   }
8939
8940   template<typename Chars1, typename Chars2>
8941   static inline bool Equals(State* state_1, State* state_2, unsigned to_check) {
8942     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
8943     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
8944     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
8945   }
8946
8947   bool Equals(unsigned length, String* string_1, String* string_2) {
8948     ASSERT(length != 0);
8949     state_1_.Init(string_1, length);
8950     state_2_.Init(string_2, length);
8951     while (true) {
8952       unsigned to_check = Min(state_1_.length_, state_2_.length_);
8953       ASSERT(to_check > 0 && to_check <= length);
8954       bool is_equal;
8955       if (state_1_.is_one_byte_) {
8956         if (state_2_.is_one_byte_) {
8957           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
8958         } else {
8959           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
8960         }
8961       } else {
8962         if (state_2_.is_one_byte_) {
8963           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
8964         } else {
8965           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
8966         }
8967       }
8968       // Looping done.
8969       if (!is_equal) return false;
8970       length -= to_check;
8971       // Exit condition. Strings are equal.
8972       if (length == 0) return true;
8973       state_1_.Advance(to_check);
8974       state_2_.Advance(to_check);
8975     }
8976   }
8977
8978  private:
8979   State state_1_;
8980   State state_2_;
8981   DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator);
8982 };
8983
8984
8985 bool String::SlowEquals(String* other) {
8986   // Fast check: negative check with lengths.
8987   int len = length();
8988   if (len != other->length()) return false;
8989   if (len == 0) return true;
8990
8991   // Fast check: if hash code is computed for both strings
8992   // a fast negative check can be performed.
8993   if (HasHashCode() && other->HasHashCode()) {
8994 #ifdef ENABLE_SLOW_ASSERTS
8995     if (FLAG_enable_slow_asserts) {
8996       if (Hash() != other->Hash()) {
8997         bool found_difference = false;
8998         for (int i = 0; i < len; i++) {
8999           if (Get(i) != other->Get(i)) {
9000             found_difference = true;
9001             break;
9002           }
9003         }
9004         ASSERT(found_difference);
9005       }
9006     }
9007 #endif
9008     if (Hash() != other->Hash()) return false;
9009   }
9010
9011   // We know the strings are both non-empty. Compare the first chars
9012   // before we try to flatten the strings.
9013   if (this->Get(0) != other->Get(0)) return false;
9014
9015   String* lhs = this->TryFlattenGetString();
9016   String* rhs = other->TryFlattenGetString();
9017
9018   // TODO(dcarney): Compare all types of flat strings with a Visitor.
9019   if (StringShape(lhs).IsSequentialAscii() &&
9020       StringShape(rhs).IsSequentialAscii()) {
9021     const uint8_t* str1 = SeqOneByteString::cast(lhs)->GetChars();
9022     const uint8_t* str2 = SeqOneByteString::cast(rhs)->GetChars();
9023     return CompareRawStringContents(str1, str2, len);
9024   }
9025
9026   Isolate* isolate = GetIsolate();
9027   StringComparator comparator(isolate->objects_string_compare_iterator_a(),
9028                               isolate->objects_string_compare_iterator_b());
9029
9030   return comparator.Equals(static_cast<unsigned>(len), lhs, rhs);
9031 }
9032
9033
9034 bool String::MarkAsUndetectable() {
9035   if (StringShape(this).IsInternalized()) return false;
9036
9037   Map* map = this->map();
9038   Heap* heap = GetHeap();
9039   if (map == heap->string_map()) {
9040     this->set_map(heap->undetectable_string_map());
9041     return true;
9042   } else if (map == heap->ascii_string_map()) {
9043     this->set_map(heap->undetectable_ascii_string_map());
9044     return true;
9045   }
9046   // Rest cannot be marked as undetectable
9047   return false;
9048 }
9049
9050
9051 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
9052   int slen = length();
9053   // Can't check exact length equality, but we can check bounds.
9054   int str_len = str.length();
9055   if (!allow_prefix_match &&
9056       (str_len < slen ||
9057           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
9058     return false;
9059   }
9060   int i;
9061   unsigned remaining_in_str = static_cast<unsigned>(str_len);
9062   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
9063   for (i = 0; i < slen && remaining_in_str > 0; i++) {
9064     unsigned cursor = 0;
9065     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
9066     ASSERT(cursor > 0 && cursor <= remaining_in_str);
9067     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
9068       if (i > slen - 1) return false;
9069       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
9070       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
9071     } else {
9072       if (Get(i) != r) return false;
9073     }
9074     utf8_data += cursor;
9075     remaining_in_str -= cursor;
9076   }
9077   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
9078 }
9079
9080
9081 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
9082   int slen = length();
9083   if (str.length() != slen) return false;
9084   DisallowHeapAllocation no_gc;
9085   FlatContent content = GetFlatContent();
9086   if (content.IsAscii()) {
9087     return CompareChars(content.ToOneByteVector().start(),
9088                         str.start(), slen) == 0;
9089   }
9090   for (int i = 0; i < slen; i++) {
9091     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
9092   }
9093   return true;
9094 }
9095
9096
9097 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
9098   int slen = length();
9099   if (str.length() != slen) return false;
9100   DisallowHeapAllocation no_gc;
9101   FlatContent content = GetFlatContent();
9102   if (content.IsTwoByte()) {
9103     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
9104   }
9105   for (int i = 0; i < slen; i++) {
9106     if (Get(i) != str[i]) return false;
9107   }
9108   return true;
9109 }
9110
9111
9112 class IteratingStringHasher: public StringHasher {
9113  public:
9114   static inline uint32_t Hash(String* string, uint32_t seed) {
9115     const unsigned len = static_cast<unsigned>(string->length());
9116     IteratingStringHasher hasher(len, seed);
9117     if (hasher.has_trivial_hash()) {
9118       return hasher.GetHashField();
9119     }
9120     int32_t type = string->map()->instance_type();
9121     ConsStringNullOp null_op;
9122     String::Visit(string, 0, hasher, null_op, type, len);
9123     // Flat strings terminate immediately.
9124     if (hasher.consumed_ == len) {
9125       ASSERT(!string->IsConsString());
9126       return hasher.GetHashField();
9127     }
9128     ASSERT(string->IsConsString());
9129     // This is a ConsString, iterate across it.
9130     ConsStringIteratorOp op;
9131     unsigned offset = 0;
9132     unsigned leaf_length = len;
9133     string = op.Operate(string, &offset, &type, &leaf_length);
9134     while (true) {
9135       ASSERT(hasher.consumed_ < len);
9136       String::Visit(string, 0, hasher, null_op, type, leaf_length);
9137       if (hasher.consumed_ == len) break;
9138       string = op.ContinueOperation(&type, &leaf_length);
9139       // This should be taken care of by the length check.
9140       ASSERT(string != NULL);
9141     }
9142     return hasher.GetHashField();
9143   }
9144   inline void VisitOneByteString(const uint8_t* chars, unsigned length) {
9145     AddCharacters(chars, static_cast<int>(length));
9146     consumed_ += length;
9147   }
9148   inline void VisitTwoByteString(const uint16_t* chars, unsigned length) {
9149     AddCharacters(chars, static_cast<int>(length));
9150     consumed_ += length;
9151   }
9152
9153  private:
9154   inline IteratingStringHasher(int len, uint32_t seed)
9155     : StringHasher(len, seed),
9156       consumed_(0) {}
9157   unsigned consumed_;
9158   DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher);
9159 };
9160
9161
9162 uint32_t String::ComputeAndSetHash() {
9163   // Should only be called if hash code has not yet been computed.
9164   ASSERT(!HasHashCode());
9165
9166   // Store the hash code in the object.
9167   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
9168   set_hash_field(field);
9169
9170   // Check the hash code is there.
9171   ASSERT(HasHashCode());
9172   uint32_t result = field >> kHashShift;
9173   ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
9174   return result;
9175 }
9176
9177
9178 bool String::ComputeArrayIndex(uint32_t* index) {
9179   int length = this->length();
9180   if (length == 0 || length > kMaxArrayIndexSize) return false;
9181   ConsStringIteratorOp op;
9182   StringCharacterStream stream(this, &op);
9183   uint16_t ch = stream.GetNext();
9184
9185   // If the string begins with a '0' character, it must only consist
9186   // of it to be a legal array index.
9187   if (ch == '0') {
9188     *index = 0;
9189     return length == 1;
9190   }
9191
9192   // Convert string to uint32 array index; character by character.
9193   int d = ch - '0';
9194   if (d < 0 || d > 9) return false;
9195   uint32_t result = d;
9196   while (stream.HasMore()) {
9197     d = stream.GetNext() - '0';
9198     if (d < 0 || d > 9) return false;
9199     // Check that the new result is below the 32 bit limit.
9200     if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
9201     result = (result * 10) + d;
9202   }
9203
9204   *index = result;
9205   return true;
9206 }
9207
9208
9209 bool String::SlowAsArrayIndex(uint32_t* index) {
9210   if (length() <= kMaxCachedArrayIndexLength) {
9211     Hash();  // force computation of hash code
9212     uint32_t field = hash_field();
9213     if ((field & kIsNotArrayIndexMask) != 0) return false;
9214     // Isolate the array index form the full hash field.
9215     *index = (kArrayIndexHashMask & field) >> kHashShift;
9216     return true;
9217   } else {
9218     return ComputeArrayIndex(index);
9219   }
9220 }
9221
9222
9223 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
9224   int new_size, old_size;
9225   int old_length = string->length();
9226   if (old_length <= new_length) return string;
9227
9228   if (string->IsSeqOneByteString()) {
9229     old_size = SeqOneByteString::SizeFor(old_length);
9230     new_size = SeqOneByteString::SizeFor(new_length);
9231   } else {
9232     ASSERT(string->IsSeqTwoByteString());
9233     old_size = SeqTwoByteString::SizeFor(old_length);
9234     new_size = SeqTwoByteString::SizeFor(new_length);
9235   }
9236
9237   int delta = old_size - new_size;
9238   string->set_length(new_length);
9239
9240   Address start_of_string = string->address();
9241   ASSERT_OBJECT_ALIGNED(start_of_string);
9242   ASSERT_OBJECT_ALIGNED(start_of_string + new_size);
9243
9244   Heap* heap = string->GetHeap();
9245   NewSpace* newspace = heap->new_space();
9246   if (newspace->Contains(start_of_string) &&
9247       newspace->top() == start_of_string + old_size) {
9248     // Last allocated object in new space.  Simply lower allocation top.
9249     newspace->set_top(start_of_string + new_size);
9250   } else {
9251     // Sizes are pointer size aligned, so that we can use filler objects
9252     // that are a multiple of pointer size.
9253     heap->CreateFillerObjectAt(start_of_string + new_size, delta);
9254   }
9255   heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR);
9256
9257   if (new_length == 0) return heap->isolate()->factory()->empty_string();
9258   return string;
9259 }
9260
9261
9262 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
9263   // For array indexes mix the length into the hash as an array index could
9264   // be zero.
9265   ASSERT(length > 0);
9266   ASSERT(length <= String::kMaxArrayIndexSize);
9267   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
9268          (1 << String::kArrayIndexValueBits));
9269
9270   value <<= String::kHashShift;
9271   value |= length << String::kArrayIndexHashLengthShift;
9272
9273   ASSERT((value & String::kIsNotArrayIndexMask) == 0);
9274   ASSERT((length > String::kMaxCachedArrayIndexLength) ||
9275          (value & String::kContainsCachedArrayIndexMask) == 0);
9276   return value;
9277 }
9278
9279
9280 uint32_t StringHasher::GetHashField() {
9281   if (length_ <= String::kMaxHashCalcLength) {
9282     if (is_array_index_) {
9283       return MakeArrayIndexHash(array_index_, length_);
9284     }
9285     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
9286            String::kIsNotArrayIndexMask;
9287   } else {
9288     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
9289   }
9290 }
9291
9292
9293 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
9294                                        uint32_t seed,
9295                                        int* utf16_length_out) {
9296   int vector_length = chars.length();
9297   // Handle some edge cases
9298   if (vector_length <= 1) {
9299     ASSERT(vector_length == 0 ||
9300            static_cast<uint8_t>(chars.start()[0]) <=
9301                unibrow::Utf8::kMaxOneByteChar);
9302     *utf16_length_out = vector_length;
9303     return HashSequentialString(chars.start(), vector_length, seed);
9304   }
9305   // Start with a fake length which won't affect computation.
9306   // It will be updated later.
9307   StringHasher hasher(String::kMaxArrayIndexSize, seed);
9308   unsigned remaining = static_cast<unsigned>(vector_length);
9309   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
9310   int utf16_length = 0;
9311   bool is_index = true;
9312   ASSERT(hasher.is_array_index_);
9313   while (remaining > 0) {
9314     unsigned consumed = 0;
9315     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
9316     ASSERT(consumed > 0 && consumed <= remaining);
9317     stream += consumed;
9318     remaining -= consumed;
9319     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
9320     utf16_length += is_two_characters ? 2 : 1;
9321     // No need to keep hashing. But we do need to calculate utf16_length.
9322     if (utf16_length > String::kMaxHashCalcLength) continue;
9323     if (is_two_characters) {
9324       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
9325       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
9326       hasher.AddCharacter(c1);
9327       hasher.AddCharacter(c2);
9328       if (is_index) is_index = hasher.UpdateIndex(c1);
9329       if (is_index) is_index = hasher.UpdateIndex(c2);
9330     } else {
9331       hasher.AddCharacter(c);
9332       if (is_index) is_index = hasher.UpdateIndex(c);
9333     }
9334   }
9335   *utf16_length_out = static_cast<int>(utf16_length);
9336   // Must set length here so that hash computation is correct.
9337   hasher.length_ = utf16_length;
9338   return hasher.GetHashField();
9339 }
9340
9341
9342 void String::PrintOn(FILE* file) {
9343   int length = this->length();
9344   for (int i = 0; i < length; i++) {
9345     PrintF(file, "%c", Get(i));
9346   }
9347 }
9348
9349
9350 static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) {
9351   int live_enum = map->EnumLength();
9352   if (live_enum == kInvalidEnumCacheSentinel) {
9353     live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
9354   }
9355   if (live_enum == 0) return descriptors->ClearEnumCache();
9356
9357   FixedArray* enum_cache = descriptors->GetEnumCache();
9358
9359   int to_trim = enum_cache->length() - live_enum;
9360   if (to_trim <= 0) return;
9361   RightTrimFixedArray<Heap::FROM_GC>(
9362       heap, descriptors->GetEnumCache(), to_trim);
9363
9364   if (!descriptors->HasEnumIndicesCache()) return;
9365   FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache();
9366   RightTrimFixedArray<Heap::FROM_GC>(heap, enum_indices_cache, to_trim);
9367 }
9368
9369
9370 static void TrimDescriptorArray(Heap* heap,
9371                                 Map* map,
9372                                 DescriptorArray* descriptors,
9373                                 int number_of_own_descriptors) {
9374   int number_of_descriptors = descriptors->number_of_descriptors_storage();
9375   int to_trim = number_of_descriptors - number_of_own_descriptors;
9376   if (to_trim == 0) return;
9377
9378   RightTrimFixedArray<Heap::FROM_GC>(
9379       heap, descriptors, to_trim * DescriptorArray::kDescriptorSize);
9380   descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
9381
9382   if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors);
9383   descriptors->Sort();
9384 }
9385
9386
9387 // Clear a possible back pointer in case the transition leads to a dead map.
9388 // Return true in case a back pointer has been cleared and false otherwise.
9389 static bool ClearBackPointer(Heap* heap, Map* target) {
9390   if (Marking::MarkBitFrom(target).Get()) return false;
9391   target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
9392   return true;
9393 }
9394
9395
9396 // TODO(mstarzinger): This method should be moved into MarkCompactCollector,
9397 // because it cannot be called from outside the GC and we already have methods
9398 // depending on the transitions layout in the GC anyways.
9399 void Map::ClearNonLiveTransitions(Heap* heap) {
9400   // If there are no transitions to be cleared, return.
9401   // TODO(verwaest) Should be an assert, otherwise back pointers are not
9402   // properly cleared.
9403   if (!HasTransitionArray()) return;
9404
9405   TransitionArray* t = transitions();
9406   MarkCompactCollector* collector = heap->mark_compact_collector();
9407
9408   int transition_index = 0;
9409
9410   DescriptorArray* descriptors = instance_descriptors();
9411   bool descriptors_owner_died = false;
9412
9413   // Compact all live descriptors to the left.
9414   for (int i = 0; i < t->number_of_transitions(); ++i) {
9415     Map* target = t->GetTarget(i);
9416     if (ClearBackPointer(heap, target)) {
9417       if (target->instance_descriptors() == descriptors) {
9418         descriptors_owner_died = true;
9419       }
9420     } else {
9421       if (i != transition_index) {
9422         Name* key = t->GetKey(i);
9423         t->SetKey(transition_index, key);
9424         Object** key_slot = t->GetKeySlot(transition_index);
9425         collector->RecordSlot(key_slot, key_slot, key);
9426         // Target slots do not need to be recorded since maps are not compacted.
9427         t->SetTarget(transition_index, t->GetTarget(i));
9428       }
9429       transition_index++;
9430     }
9431   }
9432
9433   // If there are no transitions to be cleared, return.
9434   // TODO(verwaest) Should be an assert, otherwise back pointers are not
9435   // properly cleared.
9436   if (transition_index == t->number_of_transitions()) return;
9437
9438   int number_of_own_descriptors = NumberOfOwnDescriptors();
9439
9440   if (descriptors_owner_died) {
9441     if (number_of_own_descriptors > 0) {
9442       TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors);
9443       ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
9444       set_owns_descriptors(true);
9445     } else {
9446       ASSERT(descriptors == GetHeap()->empty_descriptor_array());
9447     }
9448   }
9449
9450   int trim = t->number_of_transitions() - transition_index;
9451   if (trim > 0) {
9452     RightTrimFixedArray<Heap::FROM_GC>(heap, t, t->IsSimpleTransition()
9453         ? trim : trim * TransitionArray::kTransitionSize);
9454   }
9455 }
9456
9457
9458 int Map::Hash() {
9459   // For performance reasons we only hash the 3 most variable fields of a map:
9460   // constructor, prototype and bit_field2.
9461
9462   // Shift away the tag.
9463   int hash = (static_cast<uint32_t>(
9464         reinterpret_cast<uintptr_t>(constructor())) >> 2);
9465
9466   // XOR-ing the prototype and constructor directly yields too many zero bits
9467   // when the two pointers are close (which is fairly common).
9468   // To avoid this we shift the prototype 4 bits relatively to the constructor.
9469   hash ^= (static_cast<uint32_t>(
9470         reinterpret_cast<uintptr_t>(prototype())) << 2);
9471
9472   return hash ^ (hash >> 16) ^ bit_field2();
9473 }
9474
9475
9476 static bool CheckEquivalent(Map* first, Map* second) {
9477   return
9478     first->constructor() == second->constructor() &&
9479     first->prototype() == second->prototype() &&
9480     first->instance_type() == second->instance_type() &&
9481     first->bit_field() == second->bit_field() &&
9482     first->bit_field2() == second->bit_field2() &&
9483     first->is_observed() == second->is_observed() &&
9484     first->function_with_prototype() == second->function_with_prototype();
9485 }
9486
9487
9488 bool Map::EquivalentToForTransition(Map* other) {
9489   return CheckEquivalent(this, other);
9490 }
9491
9492
9493 bool Map::EquivalentToForNormalization(Map* other,
9494                                        PropertyNormalizationMode mode) {
9495   int properties = mode == CLEAR_INOBJECT_PROPERTIES
9496       ? 0 : other->inobject_properties();
9497   return CheckEquivalent(this, other) && inobject_properties() == properties;
9498 }
9499
9500
9501 void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) {
9502   for (int i = 0; i < count_of_code_ptr_entries(); i++) {
9503     int index = first_code_ptr_index() + i;
9504     v->VisitCodeEntry(reinterpret_cast<Address>(RawFieldOfElementAt(index)));
9505   }
9506   for (int i = 0; i < count_of_heap_ptr_entries(); i++) {
9507     int index = first_heap_ptr_index() + i;
9508     v->VisitPointer(RawFieldOfElementAt(index));
9509   }
9510 }
9511
9512
9513 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
9514   // Iterate over all fields in the body but take care in dealing with
9515   // the code entry.
9516   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
9517   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9518   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9519 }
9520
9521
9522 void JSFunction::MarkForOptimization() {
9523   ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
9524   ASSERT(!IsOptimized());
9525   ASSERT(shared()->allows_lazy_compilation() ||
9526          code()->optimizable());
9527   ASSERT(!shared()->is_generator());
9528   set_code_no_write_barrier(
9529       GetIsolate()->builtins()->builtin(Builtins::kCompileOptimized));
9530   // No write barrier required, since the builtin is part of the root set.
9531 }
9532
9533
9534 void JSFunction::MarkForConcurrentOptimization() {
9535   ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
9536   ASSERT(!IsOptimized());
9537   ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
9538   ASSERT(!shared()->is_generator());
9539   ASSERT(GetIsolate()->concurrent_recompilation_enabled());
9540   if (FLAG_trace_concurrent_recompilation) {
9541     PrintF("  ** Marking ");
9542     PrintName();
9543     PrintF(" for concurrent recompilation.\n");
9544   }
9545   set_code_no_write_barrier(
9546       GetIsolate()->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9547   // No write barrier required, since the builtin is part of the root set.
9548 }
9549
9550
9551 void JSFunction::MarkInOptimizationQueue() {
9552   // We can only arrive here via the concurrent-recompilation builtin.  If
9553   // break points were set, the code would point to the lazy-compile builtin.
9554   ASSERT(!GetIsolate()->DebuggerHasBreakPoints());
9555   ASSERT(IsMarkedForConcurrentOptimization() && !IsOptimized());
9556   ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
9557   ASSERT(GetIsolate()->concurrent_recompilation_enabled());
9558   if (FLAG_trace_concurrent_recompilation) {
9559     PrintF("  ** Queueing ");
9560     PrintName();
9561     PrintF(" for concurrent recompilation.\n");
9562   }
9563   set_code_no_write_barrier(
9564       GetIsolate()->builtins()->builtin(Builtins::kInOptimizationQueue));
9565   // No write barrier required, since the builtin is part of the root set.
9566 }
9567
9568
9569 void SharedFunctionInfo::AddToOptimizedCodeMap(
9570     Handle<SharedFunctionInfo> shared,
9571     Handle<Context> native_context,
9572     Handle<Code> code,
9573     Handle<FixedArray> literals,
9574     BailoutId osr_ast_id) {
9575   CALL_HEAP_FUNCTION_VOID(
9576       shared->GetIsolate(),
9577       shared->AddToOptimizedCodeMap(
9578           *native_context, *code, *literals, osr_ast_id));
9579 }
9580
9581
9582 MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context,
9583                                                        Code* code,
9584                                                        FixedArray* literals,
9585                                                        BailoutId osr_ast_id) {
9586   ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
9587   ASSERT(native_context->IsNativeContext());
9588   STATIC_ASSERT(kEntryLength == 4);
9589   Heap* heap = GetHeap();
9590   FixedArray* new_code_map;
9591   Object* value = optimized_code_map();
9592   Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
9593   if (value->IsSmi()) {
9594     // No optimized code map.
9595     ASSERT_EQ(0, Smi::cast(value)->value());
9596     // Create 3 entries per context {context, code, literals}.
9597     MaybeObject* maybe = heap->AllocateFixedArray(kInitialLength);
9598     if (!maybe->To(&new_code_map)) return maybe;
9599     new_code_map->set(kEntriesStart + kContextOffset, native_context);
9600     new_code_map->set(kEntriesStart + kCachedCodeOffset, code);
9601     new_code_map->set(kEntriesStart + kLiteralsOffset, literals);
9602     new_code_map->set(kEntriesStart + kOsrAstIdOffset, osr_ast_id_smi);
9603   } else {
9604     // Copy old map and append one new entry.
9605     FixedArray* old_code_map = FixedArray::cast(value);
9606     ASSERT_EQ(-1, SearchOptimizedCodeMap(native_context, osr_ast_id));
9607     int old_length = old_code_map->length();
9608     int new_length = old_length + kEntryLength;
9609     MaybeObject* maybe = old_code_map->CopySize(new_length);
9610     if (!maybe->To(&new_code_map)) return maybe;
9611     new_code_map->set(old_length + kContextOffset, native_context);
9612     new_code_map->set(old_length + kCachedCodeOffset, code);
9613     new_code_map->set(old_length + kLiteralsOffset, literals);
9614     new_code_map->set(old_length + kOsrAstIdOffset, osr_ast_id_smi);
9615     // Zap the old map for the sake of the heap verifier.
9616     if (Heap::ShouldZapGarbage()) {
9617       Object** data = old_code_map->data_start();
9618       MemsetPointer(data, heap->the_hole_value(), old_length);
9619     }
9620   }
9621 #ifdef DEBUG
9622   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9623     ASSERT(new_code_map->get(i + kContextOffset)->IsNativeContext());
9624     ASSERT(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9625     ASSERT(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9626            Code::OPTIMIZED_FUNCTION);
9627     ASSERT(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9628     ASSERT(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9629   }
9630 #endif
9631   set_optimized_code_map(new_code_map);
9632   return new_code_map;
9633 }
9634
9635
9636 FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) {
9637   ASSERT(index > kEntriesStart);
9638   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9639   if (!bound()) {
9640     FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
9641     ASSERT_NE(NULL, cached_literals);
9642     return cached_literals;
9643   }
9644   return NULL;
9645 }
9646
9647
9648 Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) {
9649   ASSERT(index > kEntriesStart);
9650   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9651   Code* code = Code::cast(code_map->get(index));
9652   ASSERT_NE(NULL, code);
9653   return code;
9654 }
9655
9656
9657 void SharedFunctionInfo::ClearOptimizedCodeMap() {
9658   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9659
9660   // If the next map link slot is already used then the function was
9661   // enqueued with code flushing and we remove it now.
9662   if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9663     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
9664     flusher->EvictOptimizedCodeMap(this);
9665   }
9666
9667   ASSERT(code_map->get(kNextMapIndex)->IsUndefined());
9668   set_optimized_code_map(Smi::FromInt(0));
9669 }
9670
9671
9672 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
9673                                                    const char* reason) {
9674   if (optimized_code_map()->IsSmi()) return;
9675
9676   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9677   int dst = kEntriesStart;
9678   int length = code_map->length();
9679   for (int src = kEntriesStart; src < length; src += kEntryLength) {
9680     ASSERT(code_map->get(src)->IsNativeContext());
9681     if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9682       // Evict the src entry by not copying it to the dst entry.
9683       if (FLAG_trace_opt) {
9684         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9685         ShortPrint();
9686         BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9687         if (osr.IsNone()) {
9688           PrintF("]\n");
9689         } else {
9690           PrintF(" (osr ast id %d)]\n", osr.ToInt());
9691         }
9692       }
9693     } else {
9694       // Keep the src entry by copying it to the dst entry.
9695       if (dst != src) {
9696         code_map->set(dst + kContextOffset,
9697                       code_map->get(src + kContextOffset));
9698         code_map->set(dst + kCachedCodeOffset,
9699                       code_map->get(src + kCachedCodeOffset));
9700         code_map->set(dst + kLiteralsOffset,
9701                       code_map->get(src + kLiteralsOffset));
9702         code_map->set(dst + kOsrAstIdOffset,
9703                       code_map->get(src + kOsrAstIdOffset));
9704       }
9705       dst += kEntryLength;
9706     }
9707   }
9708   if (dst != length) {
9709     // Always trim even when array is cleared because of heap verifier.
9710     RightTrimFixedArray<Heap::FROM_MUTATOR>(GetHeap(), code_map, length - dst);
9711     if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap();
9712   }
9713 }
9714
9715
9716 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
9717   FixedArray* code_map = FixedArray::cast(optimized_code_map());
9718   ASSERT(shrink_by % kEntryLength == 0);
9719   ASSERT(shrink_by <= code_map->length() - kEntriesStart);
9720   // Always trim even when array is cleared because of heap verifier.
9721   RightTrimFixedArray<Heap::FROM_GC>(GetHeap(), code_map, shrink_by);
9722   if (code_map->length() == kEntriesStart) {
9723     ClearOptimizedCodeMap();
9724   }
9725 }
9726
9727
9728 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) {
9729   if (object->IsGlobalObject()) return;
9730
9731   // Make sure prototypes are fast objects and their maps have the bit set
9732   // so they remain fast.
9733   if (!object->HasFastProperties()) {
9734     TransformToFastProperties(object, 0);
9735   }
9736 }
9737
9738
9739 static MUST_USE_RESULT MaybeObject* CacheInitialJSArrayMaps(
9740     Context* native_context, Map* initial_map) {
9741   // Replace all of the cached initial array maps in the native context with
9742   // the appropriate transitioned elements kind maps.
9743   Heap* heap = native_context->GetHeap();
9744   MaybeObject* maybe_maps =
9745       heap->AllocateFixedArrayWithHoles(kElementsKindCount, TENURED);
9746   FixedArray* maps;
9747   if (!maybe_maps->To(&maps)) return maybe_maps;
9748
9749   Map* current_map = initial_map;
9750   ElementsKind kind = current_map->elements_kind();
9751   ASSERT(kind == GetInitialFastElementsKind());
9752   maps->set(kind, current_map);
9753   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
9754        i < kFastElementsKindCount; ++i) {
9755     Map* new_map;
9756     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
9757     if (current_map->HasElementsTransition()) {
9758       new_map = current_map->elements_transition_map();
9759       ASSERT(new_map->elements_kind() == next_kind);
9760     } else {
9761       MaybeObject* maybe_new_map =
9762           current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION);
9763       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9764     }
9765     maps->set(next_kind, new_map);
9766     current_map = new_map;
9767   }
9768   native_context->set_js_array_maps(maps);
9769   return initial_map;
9770 }
9771
9772
9773 Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
9774                                        Handle<Map> initial_map) {
9775   CALL_HEAP_FUNCTION(native_context->GetIsolate(),
9776                      CacheInitialJSArrayMaps(*native_context, *initial_map),
9777                      Object);
9778 }
9779
9780
9781 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
9782                                       Handle<Object> value) {
9783   ASSERT(value->IsJSReceiver());
9784
9785   // First some logic for the map of the prototype to make sure it is in fast
9786   // mode.
9787   if (value->IsJSObject()) {
9788     JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
9789   }
9790
9791   // Now some logic for the maps of the objects that are created by using this
9792   // function as a constructor.
9793   if (function->has_initial_map()) {
9794     // If the function has allocated the initial map replace it with a
9795     // copy containing the new prototype.  Also complete any in-object
9796     // slack tracking that is in progress at this point because it is
9797     // still tracking the old copy.
9798     if (function->shared()->IsInobjectSlackTrackingInProgress()) {
9799       function->shared()->CompleteInobjectSlackTracking();
9800     }
9801     Handle<Map> new_map = Map::Copy(handle(function->initial_map()));
9802     new_map->set_prototype(*value);
9803
9804     // If the function is used as the global Array function, cache the
9805     // initial map (and transitioned versions) in the native context.
9806     Context* native_context = function->context()->native_context();
9807     Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX);
9808     if (array_function->IsJSFunction() &&
9809         *function == JSFunction::cast(array_function)) {
9810       CacheInitialJSArrayMaps(handle(native_context), new_map);
9811     }
9812
9813     function->set_initial_map(*new_map);
9814   } else {
9815     // Put the value in the initial map field until an initial map is
9816     // needed.  At that point, a new initial map is created and the
9817     // prototype is put into the initial map where it belongs.
9818     function->set_prototype_or_initial_map(*value);
9819   }
9820   function->GetHeap()->ClearInstanceofCache();
9821 }
9822
9823
9824 void JSFunction::SetPrototype(Handle<JSFunction> function,
9825                               Handle<Object> value) {
9826   ASSERT(function->should_have_prototype());
9827   Handle<Object> construct_prototype = value;
9828
9829   // If the value is not a JSReceiver, store the value in the map's
9830   // constructor field so it can be accessed.  Also, set the prototype
9831   // used for constructing objects to the original object prototype.
9832   // See ECMA-262 13.2.2.
9833   if (!value->IsJSReceiver()) {
9834     // Copy the map so this does not affect unrelated functions.
9835     // Remove map transitions because they point to maps with a
9836     // different prototype.
9837     Handle<Map> new_map = Map::Copy(handle(function->map()));
9838
9839     JSObject::MigrateToMap(function, new_map);
9840     new_map->set_constructor(*value);
9841     new_map->set_non_instance_prototype(true);
9842     Isolate* isolate = new_map->GetIsolate();
9843     construct_prototype = handle(
9844         isolate->context()->native_context()->initial_object_prototype(),
9845         isolate);
9846   } else {
9847     function->map()->set_non_instance_prototype(false);
9848   }
9849
9850   return SetInstancePrototype(function, construct_prototype);
9851 }
9852
9853
9854 void JSFunction::RemovePrototype() {
9855   Context* native_context = context()->native_context();
9856   Map* no_prototype_map = shared()->strict_mode() == SLOPPY
9857       ? native_context->sloppy_function_without_prototype_map()
9858       : native_context->strict_function_without_prototype_map();
9859
9860   if (map() == no_prototype_map) return;
9861
9862   ASSERT(map() == (shared()->strict_mode() == SLOPPY
9863                    ? native_context->sloppy_function_map()
9864                    : native_context->strict_function_map()));
9865
9866   set_map(no_prototype_map);
9867   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9868 }
9869
9870
9871 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
9872   if (function->has_initial_map()) return;
9873   Isolate* isolate = function->GetIsolate();
9874
9875   // First create a new map with the size and number of in-object properties
9876   // suggested by the function.
9877   InstanceType instance_type;
9878   int instance_size;
9879   int in_object_properties;
9880   if (function->shared()->is_generator()) {
9881     instance_type = JS_GENERATOR_OBJECT_TYPE;
9882     instance_size = JSGeneratorObject::kSize;
9883     in_object_properties = 0;
9884   } else {
9885     instance_type = JS_OBJECT_TYPE;
9886     instance_size = function->shared()->CalculateInstanceSize();
9887     in_object_properties = function->shared()->CalculateInObjectProperties();
9888   }
9889   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
9890
9891   // Fetch or allocate prototype.
9892   Handle<Object> prototype;
9893   if (function->has_instance_prototype()) {
9894     prototype = handle(function->instance_prototype(), isolate);
9895   } else {
9896     prototype = isolate->factory()->NewFunctionPrototype(function);
9897   }
9898   map->set_inobject_properties(in_object_properties);
9899   map->set_unused_property_fields(in_object_properties);
9900   map->set_prototype(*prototype);
9901   ASSERT(map->has_fast_object_elements());
9902
9903   if (!function->shared()->is_generator()) {
9904     function->shared()->StartInobjectSlackTracking(*map);
9905   }
9906
9907   // Finally link initial map and constructor function.
9908   function->set_initial_map(*map);
9909   map->set_constructor(*function);
9910 }
9911
9912
9913 void JSFunction::SetInstanceClassName(String* name) {
9914   shared()->set_instance_class_name(name);
9915 }
9916
9917
9918 void JSFunction::PrintName(FILE* out) {
9919   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
9920   PrintF(out, "%s", name.get());
9921 }
9922
9923
9924 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) {
9925   return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex));
9926 }
9927
9928
9929 // The filter is a pattern that matches function names in this way:
9930 //   "*"      all; the default
9931 //   "-"      all but the top-level function
9932 //   "-name"  all but the function "name"
9933 //   ""       only the top-level function
9934 //   "name"   only the function "name"
9935 //   "name*"  only functions starting with "name"
9936 bool JSFunction::PassesFilter(const char* raw_filter) {
9937   if (*raw_filter == '*') return true;
9938   String* name = shared()->DebugName();
9939   Vector<const char> filter = CStrVector(raw_filter);
9940   if (filter.length() == 0) return name->length() == 0;
9941   if (filter[0] == '-') {
9942     // Negative filter.
9943     if (filter.length() == 1) {
9944       return (name->length() != 0);
9945     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
9946       return false;
9947     }
9948     if (filter[filter.length() - 1] == '*' &&
9949         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
9950       return false;
9951     }
9952     return true;
9953
9954   } else if (name->IsUtf8EqualTo(filter)) {
9955     return true;
9956   }
9957   if (filter[filter.length() - 1] == '*' &&
9958       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
9959     return true;
9960   }
9961   return false;
9962 }
9963
9964
9965 MaybeObject* Oddball::Initialize(Heap* heap,
9966                                  const char* to_string,
9967                                  Object* to_number,
9968                                  byte kind) {
9969   String* internalized_to_string;
9970   { MaybeObject* maybe_string =
9971       heap->InternalizeUtf8String(
9972           CStrVector(to_string));
9973     if (!maybe_string->To(&internalized_to_string)) return maybe_string;
9974   }
9975   set_to_string(internalized_to_string);
9976   set_to_number(to_number);
9977   set_kind(kind);
9978   return this;
9979 }
9980
9981
9982 String* SharedFunctionInfo::DebugName() {
9983   Object* n = name();
9984   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
9985   return String::cast(n);
9986 }
9987
9988
9989 bool SharedFunctionInfo::HasSourceCode() {
9990   return !script()->IsUndefined() &&
9991          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
9992 }
9993
9994
9995 Handle<Object> SharedFunctionInfo::GetSourceCode() {
9996   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
9997   Handle<String> source(String::cast(Script::cast(script())->source()));
9998   return GetIsolate()->factory()->NewSubString(
9999       source, start_position(), end_position());
10000 }
10001
10002
10003 bool SharedFunctionInfo::IsInlineable() {
10004   // Check that the function has a script associated with it.
10005   if (!script()->IsScript()) return false;
10006   if (optimization_disabled()) return false;
10007   // If we never ran this (unlikely) then lets try to optimize it.
10008   if (code()->kind() != Code::FUNCTION) return true;
10009   return code()->optimizable();
10010 }
10011
10012
10013 int SharedFunctionInfo::SourceSize() {
10014   return end_position() - start_position();
10015 }
10016
10017
10018 int SharedFunctionInfo::CalculateInstanceSize() {
10019   int instance_size =
10020       JSObject::kHeaderSize +
10021       expected_nof_properties() * kPointerSize;
10022   if (instance_size > JSObject::kMaxInstanceSize) {
10023     instance_size = JSObject::kMaxInstanceSize;
10024   }
10025   return instance_size;
10026 }
10027
10028
10029 int SharedFunctionInfo::CalculateInObjectProperties() {
10030   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
10031 }
10032
10033
10034 // Support function for printing the source code to a StringStream
10035 // without any allocation in the heap.
10036 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
10037                                          int max_length) {
10038   // For some native functions there is no source.
10039   if (!HasSourceCode()) {
10040     accumulator->Add("<No Source>");
10041     return;
10042   }
10043
10044   // Get the source for the script which this function came from.
10045   // Don't use String::cast because we don't want more assertion errors while
10046   // we are already creating a stack dump.
10047   String* script_source =
10048       reinterpret_cast<String*>(Script::cast(script())->source());
10049
10050   if (!script_source->LooksValid()) {
10051     accumulator->Add("<Invalid Source>");
10052     return;
10053   }
10054
10055   if (!is_toplevel()) {
10056     accumulator->Add("function ");
10057     Object* name = this->name();
10058     if (name->IsString() && String::cast(name)->length() > 0) {
10059       accumulator->PrintName(name);
10060     }
10061   }
10062
10063   int len = end_position() - start_position();
10064   if (len <= max_length || max_length < 0) {
10065     accumulator->Put(script_source, start_position(), end_position());
10066   } else {
10067     accumulator->Put(script_source,
10068                      start_position(),
10069                      start_position() + max_length);
10070     accumulator->Add("...\n");
10071   }
10072 }
10073
10074
10075 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
10076   if (code->instruction_size() != recompiled->instruction_size()) return false;
10077   ByteArray* code_relocation = code->relocation_info();
10078   ByteArray* recompiled_relocation = recompiled->relocation_info();
10079   int length = code_relocation->length();
10080   if (length != recompiled_relocation->length()) return false;
10081   int compare = memcmp(code_relocation->GetDataStartAddress(),
10082                        recompiled_relocation->GetDataStartAddress(),
10083                        length);
10084   return compare == 0;
10085 }
10086
10087
10088 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
10089   ASSERT(!has_deoptimization_support());
10090   DisallowHeapAllocation no_allocation;
10091   Code* code = this->code();
10092   if (IsCodeEquivalent(code, recompiled)) {
10093     // Copy the deoptimization data from the recompiled code.
10094     code->set_deoptimization_data(recompiled->deoptimization_data());
10095     code->set_has_deoptimization_support(true);
10096   } else {
10097     // TODO(3025757): In case the recompiled isn't equivalent to the
10098     // old code, we have to replace it. We should try to avoid this
10099     // altogether because it flushes valuable type feedback by
10100     // effectively resetting all IC state.
10101     ReplaceCode(recompiled);
10102   }
10103   ASSERT(has_deoptimization_support());
10104 }
10105
10106
10107 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
10108   // Disable optimization for the shared function info and mark the
10109   // code as non-optimizable. The marker on the shared function info
10110   // is there because we flush non-optimized code thereby loosing the
10111   // non-optimizable information for the code. When the code is
10112   // regenerated and set on the shared function info it is marked as
10113   // non-optimizable if optimization is disabled for the shared
10114   // function info.
10115   set_optimization_disabled(true);
10116   set_bailout_reason(reason);
10117   // Code should be the lazy compilation stub or else unoptimized.  If the
10118   // latter, disable optimization for the code too.
10119   ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
10120   if (code()->kind() == Code::FUNCTION) {
10121     code()->set_optimizable(false);
10122   }
10123   PROFILE(GetIsolate(),
10124       LogExistingFunction(Handle<SharedFunctionInfo>(this),
10125                           Handle<Code>(code())));
10126   if (FLAG_trace_opt) {
10127     PrintF("[disabled optimization for ");
10128     ShortPrint();
10129     PrintF(", reason: %s]\n", GetBailoutReason(reason));
10130   }
10131 }
10132
10133
10134 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
10135   ASSERT(!id.IsNone());
10136   Code* unoptimized = code();
10137   DeoptimizationOutputData* data =
10138       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
10139   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
10140   USE(ignore);
10141   return true;  // Return true if there was no ASSERT.
10142 }
10143
10144
10145 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) {
10146   ASSERT(!IsInobjectSlackTrackingInProgress());
10147
10148   if (!FLAG_clever_optimizations) return;
10149
10150   // Only initiate the tracking the first time.
10151   if (live_objects_may_exist()) return;
10152   set_live_objects_may_exist(true);
10153
10154   // No tracking during the snapshot construction phase.
10155   if (Serializer::enabled()) return;
10156
10157   if (map->unused_property_fields() == 0) return;
10158
10159   // Nonzero counter is a leftover from the previous attempt interrupted
10160   // by GC, keep it.
10161   if (construction_count() == 0) {
10162     set_construction_count(kGenerousAllocationCount);
10163   }
10164   set_initial_map(map);
10165   Builtins* builtins = map->GetHeap()->isolate()->builtins();
10166   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
10167             construct_stub());
10168   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
10169 }
10170
10171
10172 // Called from GC, hence reinterpret_cast and unchecked accessors.
10173 void SharedFunctionInfo::DetachInitialMap() {
10174   Map* map = reinterpret_cast<Map*>(initial_map());
10175
10176   // Make the map remember to restore the link if it survives the GC.
10177   map->set_bit_field2(
10178       map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo));
10179
10180   // Undo state changes made by StartInobjectTracking (except the
10181   // construction_count). This way if the initial map does not survive the GC
10182   // then StartInobjectTracking will be called again the next time the
10183   // constructor is called. The countdown will continue and (possibly after
10184   // several more GCs) CompleteInobjectSlackTracking will eventually be called.
10185   Heap* heap = map->GetHeap();
10186   set_initial_map(heap->undefined_value());
10187   Builtins* builtins = heap->isolate()->builtins();
10188   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
10189             *RawField(this, kConstructStubOffset));
10190   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
10191   // It is safe to clear the flag: it will be set again if the map is live.
10192   set_live_objects_may_exist(false);
10193 }
10194
10195
10196 // Called from GC, hence reinterpret_cast and unchecked accessors.
10197 void SharedFunctionInfo::AttachInitialMap(Map* map) {
10198   map->set_bit_field2(
10199       map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo));
10200
10201   // Resume inobject slack tracking.
10202   set_initial_map(map);
10203   Builtins* builtins = map->GetHeap()->isolate()->builtins();
10204   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
10205             *RawField(this, kConstructStubOffset));
10206   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
10207   // The map survived the gc, so there may be objects referencing it.
10208   set_live_objects_may_exist(true);
10209 }
10210
10211
10212 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
10213   code()->ClearInlineCaches();
10214   set_ic_age(new_ic_age);
10215   if (code()->kind() == Code::FUNCTION) {
10216     code()->set_profiler_ticks(0);
10217     if (optimization_disabled() &&
10218         opt_count() >= FLAG_max_opt_count) {
10219       // Re-enable optimizations if they were disabled due to opt_count limit.
10220       set_optimization_disabled(false);
10221       code()->set_optimizable(true);
10222     }
10223     set_opt_count(0);
10224     set_deopt_count(0);
10225   }
10226 }
10227
10228
10229 static void GetMinInobjectSlack(Map* map, void* data) {
10230   int slack = map->unused_property_fields();
10231   if (*reinterpret_cast<int*>(data) > slack) {
10232     *reinterpret_cast<int*>(data) = slack;
10233   }
10234 }
10235
10236
10237 static void ShrinkInstanceSize(Map* map, void* data) {
10238   int slack = *reinterpret_cast<int*>(data);
10239   map->set_inobject_properties(map->inobject_properties() - slack);
10240   map->set_unused_property_fields(map->unused_property_fields() - slack);
10241   map->set_instance_size(map->instance_size() - slack * kPointerSize);
10242
10243   // Visitor id might depend on the instance size, recalculate it.
10244   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
10245 }
10246
10247
10248 void SharedFunctionInfo::CompleteInobjectSlackTracking() {
10249   ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
10250   Map* map = Map::cast(initial_map());
10251
10252   Heap* heap = map->GetHeap();
10253   set_initial_map(heap->undefined_value());
10254   Builtins* builtins = heap->isolate()->builtins();
10255   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
10256             construct_stub());
10257   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
10258
10259   int slack = map->unused_property_fields();
10260   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
10261   if (slack != 0) {
10262     // Resize the initial map and all maps in its transition tree.
10263     map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
10264
10265     // Give the correct expected_nof_properties to initial maps created later.
10266     ASSERT(expected_nof_properties() >= slack);
10267     set_expected_nof_properties(expected_nof_properties() - slack);
10268   }
10269 }
10270
10271
10272 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
10273                                                BailoutId osr_ast_id) {
10274   ASSERT(native_context->IsNativeContext());
10275   if (!FLAG_cache_optimized_code) return -1;
10276   Object* value = optimized_code_map();
10277   if (!value->IsSmi()) {
10278     FixedArray* optimized_code_map = FixedArray::cast(value);
10279     int length = optimized_code_map->length();
10280     Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
10281     for (int i = kEntriesStart; i < length; i += kEntryLength) {
10282       if (optimized_code_map->get(i + kContextOffset) == native_context &&
10283           optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
10284         return i + kCachedCodeOffset;
10285       }
10286     }
10287     if (FLAG_trace_opt) {
10288       PrintF("[didn't find optimized code in optimized code map for ");
10289       ShortPrint();
10290       PrintF("]\n");
10291     }
10292   }
10293   return -1;
10294 }
10295
10296
10297 #define DECLARE_TAG(ignore1, name, ignore2) name,
10298 const char* const VisitorSynchronization::kTags[
10299     VisitorSynchronization::kNumberOfSyncTags] = {
10300   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10301 };
10302 #undef DECLARE_TAG
10303
10304
10305 #define DECLARE_TAG(ignore1, ignore2, name) name,
10306 const char* const VisitorSynchronization::kTagNames[
10307     VisitorSynchronization::kNumberOfSyncTags] = {
10308   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10309 };
10310 #undef DECLARE_TAG
10311
10312
10313 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10314   ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
10315   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10316   Object* old_target = target;
10317   VisitPointer(&target);
10318   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10319 }
10320
10321
10322 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10323   ASSERT(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10324   Object* stub = rinfo->code_age_stub();
10325   if (stub) {
10326     VisitPointer(&stub);
10327   }
10328 }
10329
10330
10331 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10332   Object* code = Code::GetObjectFromEntryAddress(entry_address);
10333   Object* old_code = code;
10334   VisitPointer(&code);
10335   if (code != old_code) {
10336     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10337   }
10338 }
10339
10340
10341 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10342   ASSERT(rinfo->rmode() == RelocInfo::CELL);
10343   Object* cell = rinfo->target_cell();
10344   Object* old_cell = cell;
10345   VisitPointer(&cell);
10346   if (cell != old_cell) {
10347     rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10348   }
10349 }
10350
10351
10352 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10353   ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
10354           rinfo->IsPatchedReturnSequence()) ||
10355          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10356           rinfo->IsPatchedDebugBreakSlotSequence()));
10357   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
10358   Object* old_target = target;
10359   VisitPointer(&target);
10360   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10361 }
10362
10363
10364 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10365   ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10366   Object* p = rinfo->target_object();
10367   VisitPointer(&p);
10368 }
10369
10370
10371 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10372   Address p = rinfo->target_reference();
10373   VisitExternalReference(&p);
10374 }
10375
10376
10377 void Code::InvalidateRelocation() {
10378   set_relocation_info(GetHeap()->empty_byte_array());
10379 }
10380
10381
10382 void Code::InvalidateEmbeddedObjects() {
10383   Object* undefined = GetHeap()->undefined_value();
10384   Cell* undefined_cell = GetHeap()->undefined_cell();
10385   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10386                   RelocInfo::ModeMask(RelocInfo::CELL);
10387   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10388     RelocInfo::Mode mode = it.rinfo()->rmode();
10389     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10390       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10391     } else if (mode == RelocInfo::CELL) {
10392       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10393     }
10394   }
10395 }
10396
10397
10398 void Code::Relocate(intptr_t delta) {
10399   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10400     it.rinfo()->apply(delta);
10401   }
10402   CPU::FlushICache(instruction_start(), instruction_size());
10403 }
10404
10405
10406 void Code::CopyFrom(const CodeDesc& desc) {
10407   ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
10408
10409   // copy code
10410   CopyBytes(instruction_start(), desc.buffer,
10411             static_cast<size_t>(desc.instr_size));
10412
10413   // copy reloc info
10414   CopyBytes(relocation_start(),
10415             desc.buffer + desc.buffer_size - desc.reloc_size,
10416             static_cast<size_t>(desc.reloc_size));
10417
10418   // unbox handles and relocate
10419   intptr_t delta = instruction_start() - desc.buffer;
10420   int mode_mask = RelocInfo::kCodeTargetMask |
10421                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10422                   RelocInfo::ModeMask(RelocInfo::CELL) |
10423                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
10424                   RelocInfo::kApplyMask;
10425   // Needed to find target_object and runtime_entry on X64
10426   Assembler* origin = desc.origin;
10427   AllowDeferredHandleDereference embedding_raw_address;
10428   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10429     RelocInfo::Mode mode = it.rinfo()->rmode();
10430     if (mode == RelocInfo::EMBEDDED_OBJECT) {
10431       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10432       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
10433     } else if (mode == RelocInfo::CELL) {
10434       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
10435       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
10436     } else if (RelocInfo::IsCodeTarget(mode)) {
10437       // rewrite code handles in inline cache targets to direct
10438       // pointers to the first instruction in the code object
10439       Handle<Object> p = it.rinfo()->target_object_handle(origin);
10440       Code* code = Code::cast(*p);
10441       it.rinfo()->set_target_address(code->instruction_start(),
10442                                      SKIP_WRITE_BARRIER);
10443     } else if (RelocInfo::IsRuntimeEntry(mode)) {
10444       Address p = it.rinfo()->target_runtime_entry(origin);
10445       it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER);
10446     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10447       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10448       Code* code = Code::cast(*p);
10449       it.rinfo()->set_code_age_stub(code);
10450     } else {
10451       it.rinfo()->apply(delta);
10452     }
10453   }
10454   CPU::FlushICache(instruction_start(), instruction_size());
10455 }
10456
10457
10458 // Locate the source position which is closest to the address in the code. This
10459 // is using the source position information embedded in the relocation info.
10460 // The position returned is relative to the beginning of the script where the
10461 // source for this function is found.
10462 int Code::SourcePosition(Address pc) {
10463   int distance = kMaxInt;
10464   int position = RelocInfo::kNoPosition;  // Initially no position found.
10465   // Run through all the relocation info to find the best matching source
10466   // position. All the code needs to be considered as the sequence of the
10467   // instructions in the code does not necessarily follow the same order as the
10468   // source.
10469   RelocIterator it(this, RelocInfo::kPositionMask);
10470   while (!it.done()) {
10471     // Only look at positions after the current pc.
10472     if (it.rinfo()->pc() < pc) {
10473       // Get position and distance.
10474
10475       int dist = static_cast<int>(pc - it.rinfo()->pc());
10476       int pos = static_cast<int>(it.rinfo()->data());
10477       // If this position is closer than the current candidate or if it has the
10478       // same distance as the current candidate and the position is higher then
10479       // this position is the new candidate.
10480       if ((dist < distance) ||
10481           (dist == distance && pos > position)) {
10482         position = pos;
10483         distance = dist;
10484       }
10485     }
10486     it.next();
10487   }
10488   return position;
10489 }
10490
10491
10492 // Same as Code::SourcePosition above except it only looks for statement
10493 // positions.
10494 int Code::SourceStatementPosition(Address pc) {
10495   // First find the position as close as possible using all position
10496   // information.
10497   int position = SourcePosition(pc);
10498   // Now find the closest statement position before the position.
10499   int statement_position = 0;
10500   RelocIterator it(this, RelocInfo::kPositionMask);
10501   while (!it.done()) {
10502     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
10503       int p = static_cast<int>(it.rinfo()->data());
10504       if (statement_position < p && p <= position) {
10505         statement_position = p;
10506       }
10507     }
10508     it.next();
10509   }
10510   return statement_position;
10511 }
10512
10513
10514 SafepointEntry Code::GetSafepointEntry(Address pc) {
10515   SafepointTable table(this);
10516   return table.FindEntry(pc);
10517 }
10518
10519
10520 Object* Code::FindNthObject(int n, Map* match_map) {
10521   ASSERT(is_inline_cache_stub());
10522   DisallowHeapAllocation no_allocation;
10523   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10524   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10525     RelocInfo* info = it.rinfo();
10526     Object* object = info->target_object();
10527     if (object->IsHeapObject()) {
10528       if (HeapObject::cast(object)->map() == match_map) {
10529         if (--n == 0) return object;
10530       }
10531     }
10532   }
10533   return NULL;
10534 }
10535
10536
10537 AllocationSite* Code::FindFirstAllocationSite() {
10538   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
10539   return (result != NULL) ? AllocationSite::cast(result) : NULL;
10540 }
10541
10542
10543 Map* Code::FindFirstMap() {
10544   Object* result = FindNthObject(1, GetHeap()->meta_map());
10545   return (result != NULL) ? Map::cast(result) : NULL;
10546 }
10547
10548
10549 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
10550   ASSERT(is_inline_cache_stub() || is_handler());
10551   DisallowHeapAllocation no_allocation;
10552   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10553   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
10554   int current_pattern = 0;
10555   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10556     RelocInfo* info = it.rinfo();
10557     Object* object = info->target_object();
10558     if (object->IsHeapObject()) {
10559       Map* map = HeapObject::cast(object)->map();
10560       if (map == *pattern.find_[current_pattern]) {
10561         info->set_target_object(*pattern.replace_[current_pattern]);
10562         if (++current_pattern == pattern.count_) return;
10563       }
10564     }
10565   }
10566   UNREACHABLE();
10567 }
10568
10569
10570 void Code::FindAllMaps(MapHandleList* maps) {
10571   ASSERT(is_inline_cache_stub());
10572   DisallowHeapAllocation no_allocation;
10573   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10574   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10575     RelocInfo* info = it.rinfo();
10576     Object* object = info->target_object();
10577     if (object->IsMap()) maps->Add(handle(Map::cast(object)));
10578   }
10579 }
10580
10581
10582 void Code::FindAllTypes(TypeHandleList* types) {
10583   ASSERT(is_inline_cache_stub());
10584   DisallowHeapAllocation no_allocation;
10585   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10586   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10587     RelocInfo* info = it.rinfo();
10588     Object* object = info->target_object();
10589     if (object->IsMap()) {
10590       Handle<Map> map(Map::cast(object));
10591       types->Add(IC::MapToType<HeapType>(map, map->GetIsolate()));
10592     }
10593   }
10594 }
10595
10596
10597 Code* Code::FindFirstHandler() {
10598   ASSERT(is_inline_cache_stub());
10599   DisallowHeapAllocation no_allocation;
10600   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
10601   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10602     RelocInfo* info = it.rinfo();
10603     Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10604     if (code->kind() == Code::HANDLER) return code;
10605   }
10606   return NULL;
10607 }
10608
10609
10610 bool Code::FindHandlers(CodeHandleList* code_list, int length) {
10611   ASSERT(is_inline_cache_stub());
10612   DisallowHeapAllocation no_allocation;
10613   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
10614   int i = 0;
10615   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10616     if (i == length) return true;
10617     RelocInfo* info = it.rinfo();
10618     Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10619     // IC stubs with handlers never contain non-handler code objects before
10620     // handler targets.
10621     if (code->kind() != Code::HANDLER) break;
10622     code_list->Add(Handle<Code>(code));
10623     i++;
10624   }
10625   return i == length;
10626 }
10627
10628
10629 Name* Code::FindFirstName() {
10630   ASSERT(is_inline_cache_stub());
10631   DisallowHeapAllocation no_allocation;
10632   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10633   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10634     RelocInfo* info = it.rinfo();
10635     Object* object = info->target_object();
10636     if (object->IsName()) return Name::cast(object);
10637   }
10638   return NULL;
10639 }
10640
10641
10642 void Code::ClearInlineCaches() {
10643   ClearInlineCaches(NULL);
10644 }
10645
10646
10647 void Code::ClearInlineCaches(Code::Kind kind) {
10648   ClearInlineCaches(&kind);
10649 }
10650
10651
10652 void Code::ClearInlineCaches(Code::Kind* kind) {
10653   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10654              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
10655              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
10656   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10657     RelocInfo* info = it.rinfo();
10658     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10659     if (target->is_inline_cache_stub()) {
10660       if (kind == NULL || *kind == target->kind()) {
10661         IC::Clear(this->GetIsolate(), info->pc(),
10662                   info->host()->constant_pool());
10663       }
10664     }
10665   }
10666 }
10667
10668
10669 void Code::ClearTypeFeedbackInfo(Heap* heap) {
10670   if (kind() != FUNCTION) return;
10671   Object* raw_info = type_feedback_info();
10672   if (raw_info->IsTypeFeedbackInfo()) {
10673     FixedArray* feedback_vector =
10674         TypeFeedbackInfo::cast(raw_info)->feedback_vector();
10675     for (int i = 0; i < feedback_vector->length(); i++) {
10676       Object* obj = feedback_vector->get(i);
10677       if (!obj->IsAllocationSite()) {
10678         // TODO(mvstanton): Can't I avoid a write barrier for this sentinel?
10679         feedback_vector->set(i,
10680                              TypeFeedbackInfo::RawUninitializedSentinel(heap));
10681       }
10682     }
10683   }
10684 }
10685
10686
10687 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
10688   DisallowHeapAllocation no_gc;
10689   ASSERT(kind() == FUNCTION);
10690   BackEdgeTable back_edges(this, &no_gc);
10691   for (uint32_t i = 0; i < back_edges.length(); i++) {
10692     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
10693   }
10694   return BailoutId::None();
10695 }
10696
10697
10698 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
10699   DisallowHeapAllocation no_gc;
10700   ASSERT(kind() == FUNCTION);
10701   BackEdgeTable back_edges(this, &no_gc);
10702   for (uint32_t i = 0; i < back_edges.length(); i++) {
10703     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
10704   }
10705   UNREACHABLE();  // We expect to find the back edge.
10706   return 0;
10707 }
10708
10709
10710 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
10711   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
10712 }
10713
10714
10715 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
10716   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
10717       NO_MARKING_PARITY);
10718 }
10719
10720
10721 static Code::Age EffectiveAge(Code::Age age) {
10722   if (age == Code::kNotExecutedCodeAge) {
10723     // Treat that's never been executed as old immediately.
10724     age = Code::kIsOldCodeAge;
10725   } else if (age == Code::kExecutedOnceCodeAge) {
10726     // Pre-age code that has only been executed once.
10727     age = Code::kPreAgedCodeAge;
10728   }
10729   return age;
10730 }
10731
10732
10733 void Code::MakeOlder(MarkingParity current_parity) {
10734   byte* sequence = FindCodeAgeSequence();
10735   if (sequence != NULL) {
10736     Age age;
10737     MarkingParity code_parity;
10738     GetCodeAgeAndParity(sequence, &age, &code_parity);
10739     age = EffectiveAge(age);
10740     if (age != kLastCodeAge && code_parity != current_parity) {
10741       PatchPlatformCodeAge(GetIsolate(),
10742                            sequence,
10743                            static_cast<Age>(age + 1),
10744                            current_parity);
10745     }
10746   }
10747 }
10748
10749
10750 bool Code::IsOld() {
10751   return GetAge() >= kIsOldCodeAge;
10752 }
10753
10754
10755 byte* Code::FindCodeAgeSequence() {
10756   return FLAG_age_code &&
10757       prologue_offset() != Code::kPrologueOffsetNotSet &&
10758       (kind() == OPTIMIZED_FUNCTION ||
10759        (kind() == FUNCTION && !has_debug_break_slots()))
10760       ? instruction_start() + prologue_offset()
10761       : NULL;
10762 }
10763
10764
10765 Code::Age Code::GetAge() {
10766   return EffectiveAge(GetRawAge());
10767 }
10768
10769
10770 Code::Age Code::GetRawAge() {
10771   byte* sequence = FindCodeAgeSequence();
10772   if (sequence == NULL) {
10773     return kNoAgeCodeAge;
10774   }
10775   Age age;
10776   MarkingParity parity;
10777   GetCodeAgeAndParity(sequence, &age, &parity);
10778   return age;
10779 }
10780
10781
10782 void Code::GetCodeAgeAndParity(Code* code, Age* age,
10783                                MarkingParity* parity) {
10784   Isolate* isolate = code->GetIsolate();
10785   Builtins* builtins = isolate->builtins();
10786   Code* stub = NULL;
10787 #define HANDLE_CODE_AGE(AGE)                                            \
10788   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
10789   if (code == stub) {                                                   \
10790     *age = k##AGE##CodeAge;                                             \
10791     *parity = EVEN_MARKING_PARITY;                                      \
10792     return;                                                             \
10793   }                                                                     \
10794   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
10795   if (code == stub) {                                                   \
10796     *age = k##AGE##CodeAge;                                             \
10797     *parity = ODD_MARKING_PARITY;                                       \
10798     return;                                                             \
10799   }
10800   CODE_AGE_LIST(HANDLE_CODE_AGE)
10801 #undef HANDLE_CODE_AGE
10802   stub = *builtins->MarkCodeAsExecutedOnce();
10803   if (code == stub) {
10804     *age = kNotExecutedCodeAge;
10805     *parity = NO_MARKING_PARITY;
10806     return;
10807   }
10808   stub = *builtins->MarkCodeAsExecutedTwice();
10809   if (code == stub) {
10810     *age = kExecutedOnceCodeAge;
10811     *parity = NO_MARKING_PARITY;
10812     return;
10813   }
10814   UNREACHABLE();
10815 }
10816
10817
10818 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
10819   Builtins* builtins = isolate->builtins();
10820   switch (age) {
10821 #define HANDLE_CODE_AGE(AGE)                                            \
10822     case k##AGE##CodeAge: {                                             \
10823       Code* stub = parity == EVEN_MARKING_PARITY                        \
10824           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
10825           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
10826       return stub;                                                      \
10827     }
10828     CODE_AGE_LIST(HANDLE_CODE_AGE)
10829 #undef HANDLE_CODE_AGE
10830     case kNotExecutedCodeAge: {
10831       ASSERT(parity == NO_MARKING_PARITY);
10832       return *builtins->MarkCodeAsExecutedOnce();
10833     }
10834     case kExecutedOnceCodeAge: {
10835       ASSERT(parity == NO_MARKING_PARITY);
10836       return *builtins->MarkCodeAsExecutedTwice();
10837     }
10838     default:
10839       UNREACHABLE();
10840       break;
10841   }
10842   return NULL;
10843 }
10844
10845
10846 void Code::PrintDeoptLocation(FILE* out, int bailout_id) {
10847   const char* last_comment = NULL;
10848   int mask = RelocInfo::ModeMask(RelocInfo::COMMENT)
10849       | RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
10850   for (RelocIterator it(this, mask); !it.done(); it.next()) {
10851     RelocInfo* info = it.rinfo();
10852     if (info->rmode() == RelocInfo::COMMENT) {
10853       last_comment = reinterpret_cast<const char*>(info->data());
10854     } else if (last_comment != NULL) {
10855       if ((bailout_id == Deoptimizer::GetDeoptimizationId(
10856               GetIsolate(), info->target_address(), Deoptimizer::EAGER)) ||
10857           (bailout_id == Deoptimizer::GetDeoptimizationId(
10858               GetIsolate(), info->target_address(), Deoptimizer::SOFT))) {
10859         CHECK(RelocInfo::IsRuntimeEntry(info->rmode()));
10860         PrintF(out, "            %s\n", last_comment);
10861         return;
10862       }
10863     }
10864   }
10865 }
10866
10867
10868 bool Code::CanDeoptAt(Address pc) {
10869   DeoptimizationInputData* deopt_data =
10870       DeoptimizationInputData::cast(deoptimization_data());
10871   Address code_start_address = instruction_start();
10872   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
10873     if (deopt_data->Pc(i)->value() == -1) continue;
10874     Address address = code_start_address + deopt_data->Pc(i)->value();
10875     if (address == pc) return true;
10876   }
10877   return false;
10878 }
10879
10880
10881 // Identify kind of code.
10882 const char* Code::Kind2String(Kind kind) {
10883   switch (kind) {
10884 #define CASE(name) case name: return #name;
10885     CODE_KIND_LIST(CASE)
10886 #undef CASE
10887     case NUMBER_OF_KINDS: break;
10888   }
10889   UNREACHABLE();
10890   return NULL;
10891 }
10892
10893
10894 #ifdef ENABLE_DISASSEMBLER
10895
10896 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
10897   disasm::NameConverter converter;
10898   int deopt_count = DeoptCount();
10899   PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
10900   if (0 == deopt_count) return;
10901
10902   PrintF(out, "%6s  %6s  %6s %6s %12s\n", "index", "ast id", "argc", "pc",
10903          FLAG_print_code_verbose ? "commands" : "");
10904   for (int i = 0; i < deopt_count; i++) {
10905     PrintF(out, "%6d  %6d  %6d %6d",
10906            i,
10907            AstId(i).ToInt(),
10908            ArgumentsStackHeight(i)->value(),
10909            Pc(i)->value());
10910
10911     if (!FLAG_print_code_verbose) {
10912       PrintF(out, "\n");
10913       continue;
10914     }
10915     // Print details of the frame translation.
10916     int translation_index = TranslationIndex(i)->value();
10917     TranslationIterator iterator(TranslationByteArray(), translation_index);
10918     Translation::Opcode opcode =
10919         static_cast<Translation::Opcode>(iterator.Next());
10920     ASSERT(Translation::BEGIN == opcode);
10921     int frame_count = iterator.Next();
10922     int jsframe_count = iterator.Next();
10923     PrintF(out, "  %s {frame count=%d, js frame count=%d}\n",
10924            Translation::StringFor(opcode),
10925            frame_count,
10926            jsframe_count);
10927
10928     while (iterator.HasNext() &&
10929            Translation::BEGIN !=
10930            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
10931       PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
10932
10933       switch (opcode) {
10934         case Translation::BEGIN:
10935           UNREACHABLE();
10936           break;
10937
10938         case Translation::JS_FRAME: {
10939           int ast_id = iterator.Next();
10940           int function_id = iterator.Next();
10941           unsigned height = iterator.Next();
10942           PrintF(out, "{ast_id=%d, function=", ast_id);
10943           if (function_id != Translation::kSelfLiteralId) {
10944             Object* function = LiteralArray()->get(function_id);
10945             JSFunction::cast(function)->PrintName(out);
10946           } else {
10947             PrintF(out, "<self>");
10948           }
10949           PrintF(out, ", height=%u}", height);
10950           break;
10951         }
10952
10953         case Translation::COMPILED_STUB_FRAME: {
10954           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
10955           PrintF(out, "{kind=%d}", stub_kind);
10956           break;
10957         }
10958
10959         case Translation::ARGUMENTS_ADAPTOR_FRAME:
10960         case Translation::CONSTRUCT_STUB_FRAME: {
10961           int function_id = iterator.Next();
10962           JSFunction* function =
10963               JSFunction::cast(LiteralArray()->get(function_id));
10964           unsigned height = iterator.Next();
10965           PrintF(out, "{function=");
10966           function->PrintName(out);
10967           PrintF(out, ", height=%u}", height);
10968           break;
10969         }
10970
10971         case Translation::GETTER_STUB_FRAME:
10972         case Translation::SETTER_STUB_FRAME: {
10973           int function_id = iterator.Next();
10974           JSFunction* function =
10975               JSFunction::cast(LiteralArray()->get(function_id));
10976           PrintF(out, "{function=");
10977           function->PrintName(out);
10978           PrintF(out, "}");
10979           break;
10980         }
10981
10982         case Translation::REGISTER: {
10983           int reg_code = iterator.Next();
10984             PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
10985           break;
10986         }
10987
10988         case Translation::INT32_REGISTER: {
10989           int reg_code = iterator.Next();
10990           PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
10991           break;
10992         }
10993
10994         case Translation::UINT32_REGISTER: {
10995           int reg_code = iterator.Next();
10996           PrintF(out, "{input=%s (unsigned)}",
10997                  converter.NameOfCPURegister(reg_code));
10998           break;
10999         }
11000
11001         case Translation::DOUBLE_REGISTER: {
11002           int reg_code = iterator.Next();
11003           PrintF(out, "{input=%s}",
11004                  DoubleRegister::AllocationIndexToString(reg_code));
11005           break;
11006         }
11007
11008         case Translation::FLOAT32x4_REGISTER: {
11009           int reg_code = iterator.Next();
11010           PrintF(out, "{input=%s}",
11011                  SIMD128Register::AllocationIndexToString(reg_code));
11012           break;
11013         }
11014
11015         case Translation::INT32x4_REGISTER: {
11016           int reg_code = iterator.Next();
11017           PrintF(out, "{input=%s}",
11018                  SIMD128Register::AllocationIndexToString(reg_code));
11019           break;
11020         }
11021
11022         case Translation::STACK_SLOT: {
11023           int input_slot_index = iterator.Next();
11024           PrintF(out, "{input=%d}", input_slot_index);
11025           break;
11026         }
11027
11028         case Translation::INT32_STACK_SLOT: {
11029           int input_slot_index = iterator.Next();
11030           PrintF(out, "{input=%d}", input_slot_index);
11031           break;
11032         }
11033
11034         case Translation::UINT32_STACK_SLOT: {
11035           int input_slot_index = iterator.Next();
11036           PrintF(out, "{input=%d (unsigned)}", input_slot_index);
11037           break;
11038         }
11039
11040         case Translation::DOUBLE_STACK_SLOT: {
11041           int input_slot_index = iterator.Next();
11042           PrintF(out, "{input=%d}", input_slot_index);
11043           break;
11044         }
11045
11046         case Translation::FLOAT32x4_STACK_SLOT: {
11047           int input_slot_index = iterator.Next();
11048           PrintF(out, "{input=%d}", input_slot_index);
11049           break;
11050         }
11051
11052         case Translation::INT32x4_STACK_SLOT: {
11053           int input_slot_index = iterator.Next();
11054           PrintF(out, "{input=%d}", input_slot_index);
11055           break;
11056         }
11057
11058         case Translation::LITERAL: {
11059           unsigned literal_index = iterator.Next();
11060           PrintF(out, "{literal_id=%u}", literal_index);
11061           break;
11062         }
11063
11064         case Translation::DUPLICATED_OBJECT: {
11065           int object_index = iterator.Next();
11066           PrintF(out, "{object_index=%d}", object_index);
11067           break;
11068         }
11069
11070         case Translation::ARGUMENTS_OBJECT:
11071         case Translation::CAPTURED_OBJECT: {
11072           int args_length = iterator.Next();
11073           PrintF(out, "{length=%d}", args_length);
11074           break;
11075         }
11076       }
11077       PrintF(out, "\n");
11078     }
11079   }
11080 }
11081
11082
11083 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
11084   PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
11085          this->DeoptPoints());
11086   if (this->DeoptPoints() == 0) return;
11087
11088   PrintF(out, "%6s  %8s  %s\n", "ast id", "pc", "state");
11089   for (int i = 0; i < this->DeoptPoints(); i++) {
11090     int pc_and_state = this->PcAndState(i)->value();
11091     PrintF(out, "%6d  %8d  %s\n",
11092            this->AstId(i).ToInt(),
11093            FullCodeGenerator::PcField::decode(pc_and_state),
11094            FullCodeGenerator::State2String(
11095                FullCodeGenerator::StateField::decode(pc_and_state)));
11096   }
11097 }
11098
11099
11100 const char* Code::ICState2String(InlineCacheState state) {
11101   switch (state) {
11102     case UNINITIALIZED: return "UNINITIALIZED";
11103     case PREMONOMORPHIC: return "PREMONOMORPHIC";
11104     case MONOMORPHIC: return "MONOMORPHIC";
11105     case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
11106     case POLYMORPHIC: return "POLYMORPHIC";
11107     case MEGAMORPHIC: return "MEGAMORPHIC";
11108     case GENERIC: return "GENERIC";
11109     case DEBUG_STUB: return "DEBUG_STUB";
11110   }
11111   UNREACHABLE();
11112   return NULL;
11113 }
11114
11115
11116 const char* Code::StubType2String(StubType type) {
11117   switch (type) {
11118     case NORMAL: return "NORMAL";
11119     case FAST: return "FAST";
11120   }
11121   UNREACHABLE();  // keep the compiler happy
11122   return NULL;
11123 }
11124
11125
11126 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
11127   PrintF(out, "extra_ic_state = ");
11128   const char* name = NULL;
11129   switch (kind) {
11130     case STORE_IC:
11131     case KEYED_STORE_IC:
11132       if (extra == STRICT) name = "STRICT";
11133       break;
11134     default:
11135       break;
11136   }
11137   if (name != NULL) {
11138     PrintF(out, "%s\n", name);
11139   } else {
11140     PrintF(out, "%d\n", extra);
11141   }
11142 }
11143
11144
11145 void Code::Disassemble(const char* name, FILE* out) {
11146   PrintF(out, "kind = %s\n", Kind2String(kind()));
11147   if (has_major_key()) {
11148     PrintF(out, "major_key = %s\n",
11149            CodeStub::MajorName(CodeStub::GetMajorKey(this), true));
11150   }
11151   if (is_inline_cache_stub()) {
11152     PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
11153     PrintExtraICState(out, kind(), extra_ic_state());
11154     if (ic_state() == MONOMORPHIC) {
11155       PrintF(out, "type = %s\n", StubType2String(type()));
11156     }
11157     if (is_compare_ic_stub()) {
11158       ASSERT(major_key() == CodeStub::CompareIC);
11159       CompareIC::State left_state, right_state, handler_state;
11160       Token::Value op;
11161       ICCompareStub::DecodeMinorKey(stub_info(), &left_state, &right_state,
11162                                     &handler_state, &op);
11163       PrintF(out, "compare_state = %s*%s -> %s\n",
11164              CompareIC::GetStateName(left_state),
11165              CompareIC::GetStateName(right_state),
11166              CompareIC::GetStateName(handler_state));
11167       PrintF(out, "compare_operation = %s\n", Token::Name(op));
11168     }
11169   }
11170   if ((name != NULL) && (name[0] != '\0')) {
11171     PrintF(out, "name = %s\n", name);
11172   }
11173   if (kind() == OPTIMIZED_FUNCTION) {
11174     PrintF(out, "stack_slots = %d\n", stack_slots());
11175   }
11176
11177   PrintF(out, "Instructions (size = %d)\n", instruction_size());
11178   Disassembler::Decode(out, this);
11179   PrintF(out, "\n");
11180
11181   if (kind() == FUNCTION) {
11182     DeoptimizationOutputData* data =
11183         DeoptimizationOutputData::cast(this->deoptimization_data());
11184     data->DeoptimizationOutputDataPrint(out);
11185   } else if (kind() == OPTIMIZED_FUNCTION) {
11186     DeoptimizationInputData* data =
11187         DeoptimizationInputData::cast(this->deoptimization_data());
11188     data->DeoptimizationInputDataPrint(out);
11189   }
11190   PrintF(out, "\n");
11191
11192   if (is_crankshafted()) {
11193     SafepointTable table(this);
11194     PrintF(out, "Safepoints (size = %u)\n", table.size());
11195     for (unsigned i = 0; i < table.length(); i++) {
11196       unsigned pc_offset = table.GetPcOffset(i);
11197       PrintF(out, "%p  %4d  ", (instruction_start() + pc_offset), pc_offset);
11198       table.PrintEntry(i, out);
11199       PrintF(out, " (sp -> fp)");
11200       SafepointEntry entry = table.GetEntry(i);
11201       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
11202         PrintF(out, "  %6d", entry.deoptimization_index());
11203       } else {
11204         PrintF(out, "  <none>");
11205       }
11206       if (entry.argument_count() > 0) {
11207         PrintF(out, " argc: %d", entry.argument_count());
11208       }
11209       PrintF(out, "\n");
11210     }
11211     PrintF(out, "\n");
11212   } else if (kind() == FUNCTION) {
11213     unsigned offset = back_edge_table_offset();
11214     // If there is no back edge table, the "table start" will be at or after
11215     // (due to alignment) the end of the instruction stream.
11216     if (static_cast<int>(offset) < instruction_size()) {
11217       DisallowHeapAllocation no_gc;
11218       BackEdgeTable back_edges(this, &no_gc);
11219
11220       PrintF(out, "Back edges (size = %u)\n", back_edges.length());
11221       PrintF(out, "ast_id  pc_offset  loop_depth\n");
11222
11223       for (uint32_t i = 0; i < back_edges.length(); i++) {
11224         PrintF(out, "%6d  %9u  %10u\n", back_edges.ast_id(i).ToInt(),
11225                                         back_edges.pc_offset(i),
11226                                         back_edges.loop_depth(i));
11227       }
11228
11229       PrintF(out, "\n");
11230     }
11231 #ifdef OBJECT_PRINT
11232     if (!type_feedback_info()->IsUndefined()) {
11233       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out);
11234       PrintF(out, "\n");
11235     }
11236 #endif
11237   }
11238
11239   PrintF(out, "RelocInfo (size = %d)\n", relocation_size());
11240   for (RelocIterator it(this); !it.done(); it.next()) {
11241     it.rinfo()->Print(GetIsolate(), out);
11242   }
11243   PrintF(out, "\n");
11244 }
11245 #endif  // ENABLE_DISASSEMBLER
11246
11247
11248 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
11249     Handle<JSObject> object,
11250     int capacity,
11251     int length,
11252     SetFastElementsCapacitySmiMode smi_mode) {
11253   // We should never end in here with a pixel or external array.
11254   ASSERT(!object->HasExternalArrayElements());
11255
11256   // Allocate a new fast elements backing store.
11257   Handle<FixedArray> new_elements =
11258       object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
11259
11260   ElementsKind elements_kind = object->GetElementsKind();
11261   ElementsKind new_elements_kind;
11262   // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
11263   // or if it's allowed and the old elements array contained only SMIs.
11264   bool has_fast_smi_elements =
11265       (smi_mode == kForceSmiElements) ||
11266       ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements());
11267   if (has_fast_smi_elements) {
11268     if (IsHoleyElementsKind(elements_kind)) {
11269       new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
11270     } else {
11271       new_elements_kind = FAST_SMI_ELEMENTS;
11272     }
11273   } else {
11274     if (IsHoleyElementsKind(elements_kind)) {
11275       new_elements_kind = FAST_HOLEY_ELEMENTS;
11276     } else {
11277       new_elements_kind = FAST_ELEMENTS;
11278     }
11279   }
11280   Handle<FixedArrayBase> old_elements(object->elements());
11281   ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
11282   accessor->CopyElements(object, new_elements, elements_kind);
11283
11284   if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
11285     Handle<Map> new_map = (new_elements_kind != elements_kind)
11286         ? GetElementsTransitionMap(object, new_elements_kind)
11287         : handle(object->map());
11288     object->ValidateElements();
11289     object->set_map_and_elements(*new_map, *new_elements);
11290
11291     // Transition through the allocation site as well if present.
11292     JSObject::UpdateAllocationSite(object, new_elements_kind);
11293   } else {
11294     Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11295     parameter_map->set(1, *new_elements);
11296   }
11297
11298   if (FLAG_trace_elements_transitions) {
11299     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11300                             object->GetElementsKind(), new_elements);
11301   }
11302
11303   if (object->IsJSArray()) {
11304     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11305   }
11306   return new_elements;
11307 }
11308
11309
11310 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object,
11311                                                       int capacity,
11312                                                       int length) {
11313   // We should never end in here with a pixel or external array.
11314   ASSERT(!object->HasExternalArrayElements());
11315
11316   Handle<FixedArrayBase> elems =
11317       object->GetIsolate()->factory()->NewFixedDoubleArray(capacity);
11318
11319   ElementsKind elements_kind = object->GetElementsKind();
11320   CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS);
11321   ElementsKind new_elements_kind = elements_kind;
11322   if (IsHoleyElementsKind(elements_kind)) {
11323     new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
11324   } else {
11325     new_elements_kind = FAST_DOUBLE_ELEMENTS;
11326   }
11327
11328   Handle<Map> new_map = GetElementsTransitionMap(object, new_elements_kind);
11329
11330   Handle<FixedArrayBase> old_elements(object->elements());
11331   ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
11332   accessor->CopyElements(object, elems, elements_kind);
11333
11334   object->ValidateElements();
11335   object->set_map_and_elements(*new_map, *elems);
11336
11337   if (FLAG_trace_elements_transitions) {
11338     PrintElementsTransition(stdout, object, elements_kind, old_elements,
11339                             object->GetElementsKind(), elems);
11340   }
11341
11342   if (object->IsJSArray()) {
11343     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11344   }
11345 }
11346
11347
11348 // static
11349 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11350   ASSERT(capacity >= 0);
11351   array->GetIsolate()->factory()->NewJSArrayStorage(
11352       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11353 }
11354
11355
11356 void JSArray::Expand(Handle<JSArray> array, int required_size) {
11357   ElementsAccessor* accessor = array->GetElementsAccessor();
11358   accessor->SetCapacityAndLength(array, required_size, required_size);
11359 }
11360
11361
11362 // Returns false if the passed-in index is marked non-configurable,
11363 // which will cause the ES5 truncation operation to halt, and thus
11364 // no further old values need be collected.
11365 static bool GetOldValue(Isolate* isolate,
11366                         Handle<JSObject> object,
11367                         uint32_t index,
11368                         List<Handle<Object> >* old_values,
11369                         List<uint32_t>* indices) {
11370   PropertyAttributes attributes =
11371       JSReceiver::GetLocalElementAttribute(object, index);
11372   ASSERT(attributes != ABSENT);
11373   if (attributes == DONT_DELETE) return false;
11374   Handle<Object> value;
11375   if (object->GetLocalElementAccessorPair(index) != NULL) {
11376     value = Handle<Object>::cast(isolate->factory()->the_hole_value());
11377   } else {
11378     value = Object::GetElementNoExceptionThrown(isolate, object, index);
11379   }
11380   old_values->Add(value);
11381   indices->Add(index);
11382   return true;
11383 }
11384
11385 static void EnqueueSpliceRecord(Handle<JSArray> object,
11386                                 uint32_t index,
11387                                 Handle<JSArray> deleted,
11388                                 uint32_t add_count) {
11389   Isolate* isolate = object->GetIsolate();
11390   HandleScope scope(isolate);
11391   Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
11392   Handle<Object> add_count_object =
11393       isolate->factory()->NewNumberFromUint(add_count);
11394
11395   Handle<Object> args[] =
11396       { object, index_object, deleted, add_count_object };
11397
11398   bool threw;
11399   Execution::Call(isolate,
11400                   Handle<JSFunction>(isolate->observers_enqueue_splice()),
11401                   isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
11402                   &threw);
11403   ASSERT(!threw);
11404 }
11405
11406
11407 static void BeginPerformSplice(Handle<JSArray> object) {
11408   Isolate* isolate = object->GetIsolate();
11409   HandleScope scope(isolate);
11410   Handle<Object> args[] = { object };
11411
11412   bool threw;
11413   Execution::Call(isolate,
11414                   Handle<JSFunction>(isolate->observers_begin_perform_splice()),
11415                   isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
11416                   &threw);
11417   ASSERT(!threw);
11418 }
11419
11420
11421 static void EndPerformSplice(Handle<JSArray> object) {
11422   Isolate* isolate = object->GetIsolate();
11423   HandleScope scope(isolate);
11424   Handle<Object> args[] = { object };
11425
11426   bool threw;
11427   Execution::Call(isolate,
11428                   Handle<JSFunction>(isolate->observers_end_perform_splice()),
11429                   isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
11430                   &threw);
11431   ASSERT(!threw);
11432 }
11433
11434
11435 Handle<Object> JSArray::SetElementsLength(Handle<JSArray> array,
11436                                           Handle<Object> new_length_handle) {
11437   // We should never end in here with a pixel or external array.
11438   ASSERT(array->AllowsSetElementsLength());
11439   if (!array->map()->is_observed()) {
11440     return array->GetElementsAccessor()->SetLength(array, new_length_handle);
11441   }
11442
11443   Isolate* isolate = array->GetIsolate();
11444   List<uint32_t> indices;
11445   List<Handle<Object> > old_values;
11446   Handle<Object> old_length_handle(array->length(), isolate);
11447   uint32_t old_length = 0;
11448   CHECK(old_length_handle->ToArrayIndex(&old_length));
11449   uint32_t new_length = 0;
11450   CHECK(new_length_handle->ToArrayIndex(&new_length));
11451
11452   static const PropertyAttributes kNoAttrFilter = NONE;
11453   int num_elements = array->NumberOfLocalElements(kNoAttrFilter);
11454   if (num_elements > 0) {
11455     if (old_length == static_cast<uint32_t>(num_elements)) {
11456       // Simple case for arrays without holes.
11457       for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
11458         if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
11459       }
11460     } else {
11461       // For sparse arrays, only iterate over existing elements.
11462       // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
11463       // the to-be-removed indices twice.
11464       Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
11465       array->GetLocalElementKeys(*keys, kNoAttrFilter);
11466       while (num_elements-- > 0) {
11467         uint32_t index = NumberToUint32(keys->get(num_elements));
11468         if (index < new_length) break;
11469         if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
11470       }
11471     }
11472   }
11473
11474   Handle<Object> hresult =
11475       array->GetElementsAccessor()->SetLength(array, new_length_handle);
11476   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, hresult, hresult);
11477
11478   CHECK(array->length()->ToArrayIndex(&new_length));
11479   if (old_length == new_length) return hresult;
11480
11481   BeginPerformSplice(array);
11482
11483   for (int i = 0; i < indices.length(); ++i) {
11484     // For deletions where the property was an accessor, old_values[i]
11485     // will be the hole, which instructs EnqueueChangeRecord to elide
11486     // the "oldValue" property.
11487     JSObject::EnqueueChangeRecord(
11488         array, "delete", isolate->factory()->Uint32ToString(indices[i]),
11489         old_values[i]);
11490   }
11491   JSObject::EnqueueChangeRecord(
11492       array, "update", isolate->factory()->length_string(),
11493       old_length_handle);
11494
11495   EndPerformSplice(array);
11496
11497   uint32_t index = Min(old_length, new_length);
11498   uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11499   uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11500   Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11501   if (delete_count > 0) {
11502     for (int i = indices.length() - 1; i >= 0; i--) {
11503       // Skip deletions where the property was an accessor, leaving holes
11504       // in the array of old values.
11505       if (old_values[i]->IsTheHole()) continue;
11506       JSObject::SetElement(deleted, indices[i] - index, old_values[i], NONE,
11507                            SLOPPY);
11508     }
11509
11510     SetProperty(deleted, isolate->factory()->length_string(),
11511                 isolate->factory()->NewNumberFromUint(delete_count),
11512                 NONE, SLOPPY);
11513   }
11514
11515   EnqueueSpliceRecord(array, index, deleted, add_count);
11516
11517   return hresult;
11518 }
11519
11520
11521 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map,
11522                                         Handle<Object> prototype) {
11523   FixedArray* cache = map->GetPrototypeTransitions();
11524   int number_of_transitions = map->NumberOfProtoTransitions();
11525   const int proto_offset =
11526       kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
11527   const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
11528   const int step = kProtoTransitionElementsPerEntry;
11529   for (int i = 0; i < number_of_transitions; i++) {
11530     if (cache->get(proto_offset + i * step) == *prototype) {
11531       Object* result = cache->get(map_offset + i * step);
11532       return Handle<Map>(Map::cast(result));
11533     }
11534   }
11535   return Handle<Map>();
11536 }
11537
11538
11539 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
11540                                         Handle<Object> prototype,
11541                                         Handle<Map> target_map) {
11542   ASSERT(target_map->IsMap());
11543   ASSERT(HeapObject::cast(*prototype)->map()->IsMap());
11544   // Don't cache prototype transition if this map is shared.
11545   if (map->is_shared() || !FLAG_cache_prototype_transitions) return map;
11546
11547   const int step = kProtoTransitionElementsPerEntry;
11548   const int header = kProtoTransitionHeaderSize;
11549
11550   Handle<FixedArray> cache(map->GetPrototypeTransitions());
11551   int capacity = (cache->length() - header) / step;
11552   int transitions = map->NumberOfProtoTransitions() + 1;
11553
11554   if (transitions > capacity) {
11555     if (capacity > kMaxCachedPrototypeTransitions) return map;
11556
11557     // Grow array by factor 2 over and above what we need.
11558     Factory* factory = map->GetIsolate()->factory();
11559     cache = factory->CopySizeFixedArray(cache, transitions * 2 * step + header);
11560
11561     CALL_AND_RETRY_OR_DIE(map->GetIsolate(),
11562                           map->SetPrototypeTransitions(*cache),
11563                           break,
11564                           return Handle<Map>());
11565   }
11566
11567   // Reload number of transitions as GC might shrink them.
11568   int last = map->NumberOfProtoTransitions();
11569   int entry = header + last * step;
11570
11571   cache->set(entry + kProtoTransitionPrototypeOffset, *prototype);
11572   cache->set(entry + kProtoTransitionMapOffset, *target_map);
11573   map->SetNumberOfProtoTransitions(last + 1);
11574
11575   return map;
11576 }
11577
11578
11579 void Map::ZapTransitions() {
11580   TransitionArray* transition_array = transitions();
11581   // TODO(mstarzinger): Temporarily use a slower version instead of the faster
11582   // MemsetPointer to investigate a crasher. Switch back to MemsetPointer.
11583   Object** data = transition_array->data_start();
11584   Object* the_hole = GetHeap()->the_hole_value();
11585   int length = transition_array->length();
11586   for (int i = 0; i < length; i++) {
11587     data[i] = the_hole;
11588   }
11589 }
11590
11591
11592 void Map::ZapPrototypeTransitions() {
11593   FixedArray* proto_transitions = GetPrototypeTransitions();
11594   MemsetPointer(proto_transitions->data_start(),
11595                 GetHeap()->the_hole_value(),
11596                 proto_transitions->length());
11597 }
11598
11599
11600 void Map::AddDependentCompilationInfo(DependentCode::DependencyGroup group,
11601                                       CompilationInfo* info) {
11602   Handle<DependentCode> dep(dependent_code());
11603   Handle<DependentCode> codes =
11604       DependentCode::Insert(dep, group, info->object_wrapper());
11605   if (*codes != dependent_code()) set_dependent_code(*codes);
11606   info->dependencies(group)->Add(Handle<HeapObject>(this), info->zone());
11607 }
11608
11609
11610 void Map::AddDependentCode(DependentCode::DependencyGroup group,
11611                            Handle<Code> code) {
11612   Handle<DependentCode> codes = DependentCode::Insert(
11613       Handle<DependentCode>(dependent_code()), group, code);
11614   if (*codes != dependent_code()) set_dependent_code(*codes);
11615 }
11616
11617
11618 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
11619   Recompute(entries);
11620 }
11621
11622
11623 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
11624   start_indexes_[0] = 0;
11625   for (int g = 1; g <= kGroupCount; g++) {
11626     int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
11627     start_indexes_[g] = start_indexes_[g - 1] + count;
11628   }
11629 }
11630
11631
11632 DependentCode* DependentCode::ForObject(Handle<HeapObject> object,
11633                                         DependencyGroup group) {
11634   AllowDeferredHandleDereference dependencies_are_safe;
11635   if (group == DependentCode::kPropertyCellChangedGroup) {
11636     return Handle<PropertyCell>::cast(object)->dependent_code();
11637   } else if (group == DependentCode::kAllocationSiteTenuringChangedGroup ||
11638       group == DependentCode::kAllocationSiteTransitionChangedGroup) {
11639     return Handle<AllocationSite>::cast(object)->dependent_code();
11640   }
11641   return Handle<Map>::cast(object)->dependent_code();
11642 }
11643
11644
11645 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
11646                                             DependencyGroup group,
11647                                             Handle<Object> object) {
11648   GroupStartIndexes starts(*entries);
11649   int start = starts.at(group);
11650   int end = starts.at(group + 1);
11651   int number_of_entries = starts.number_of_entries();
11652   // Check for existing entry to avoid duplicates.
11653   for (int i = start; i < end; i++) {
11654     if (entries->object_at(i) == *object) return entries;
11655   }
11656   if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
11657     Factory* factory = entries->GetIsolate()->factory();
11658     int capacity = kCodesStartIndex + number_of_entries + 1;
11659     if (capacity > 5) capacity = capacity * 5 / 4;
11660     Handle<DependentCode> new_entries = Handle<DependentCode>::cast(
11661         factory->CopySizeFixedArray(entries, capacity, TENURED));
11662     // The number of codes can change after GC.
11663     starts.Recompute(*entries);
11664     start = starts.at(group);
11665     end = starts.at(group + 1);
11666     number_of_entries = starts.number_of_entries();
11667     for (int i = 0; i < number_of_entries; i++) {
11668       entries->clear_at(i);
11669     }
11670     // If the old fixed array was empty, we need to reset counters of the
11671     // new array.
11672     if (number_of_entries == 0) {
11673       for (int g = 0; g < kGroupCount; g++) {
11674         new_entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
11675       }
11676     }
11677     entries = new_entries;
11678   }
11679   entries->ExtendGroup(group);
11680   entries->set_object_at(end, *object);
11681   entries->set_number_of_entries(group, end + 1 - start);
11682   return entries;
11683 }
11684
11685
11686 void DependentCode::UpdateToFinishedCode(DependencyGroup group,
11687                                          CompilationInfo* info,
11688                                          Code* code) {
11689   DisallowHeapAllocation no_gc;
11690   AllowDeferredHandleDereference get_object_wrapper;
11691   Foreign* info_wrapper = *info->object_wrapper();
11692   GroupStartIndexes starts(this);
11693   int start = starts.at(group);
11694   int end = starts.at(group + 1);
11695   for (int i = start; i < end; i++) {
11696     if (object_at(i) == info_wrapper) {
11697       set_object_at(i, code);
11698       break;
11699     }
11700   }
11701
11702 #ifdef DEBUG
11703   for (int i = start; i < end; i++) {
11704     ASSERT(is_code_at(i) || compilation_info_at(i) != info);
11705   }
11706 #endif
11707 }
11708
11709
11710 void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
11711                                           CompilationInfo* info) {
11712   DisallowHeapAllocation no_allocation;
11713   AllowDeferredHandleDereference get_object_wrapper;
11714   Foreign* info_wrapper = *info->object_wrapper();
11715   GroupStartIndexes starts(this);
11716   int start = starts.at(group);
11717   int end = starts.at(group + 1);
11718   // Find compilation info wrapper.
11719   int info_pos = -1;
11720   for (int i = start; i < end; i++) {
11721     if (object_at(i) == info_wrapper) {
11722       info_pos = i;
11723       break;
11724     }
11725   }
11726   if (info_pos == -1) return;  // Not found.
11727   int gap = info_pos;
11728   // Use the last of each group to fill the gap in the previous group.
11729   for (int i = group; i < kGroupCount; i++) {
11730     int last_of_group = starts.at(i + 1) - 1;
11731     ASSERT(last_of_group >= gap);
11732     if (last_of_group == gap) continue;
11733     copy(last_of_group, gap);
11734     gap = last_of_group;
11735   }
11736   ASSERT(gap == starts.number_of_entries() - 1);
11737   clear_at(gap);  // Clear last gap.
11738   set_number_of_entries(group, end - start - 1);
11739
11740 #ifdef DEBUG
11741   for (int i = start; i < end - 1; i++) {
11742     ASSERT(is_code_at(i) || compilation_info_at(i) != info);
11743   }
11744 #endif
11745 }
11746
11747
11748 bool DependentCode::Contains(DependencyGroup group, Code* code) {
11749   GroupStartIndexes starts(this);
11750   int start = starts.at(group);
11751   int end = starts.at(group + 1);
11752   for (int i = start; i < end; i++) {
11753     if (object_at(i) == code) return true;
11754   }
11755   return false;
11756 }
11757
11758
11759 bool DependentCode::MarkCodeForDeoptimization(
11760     Isolate* isolate,
11761     DependentCode::DependencyGroup group) {
11762   DisallowHeapAllocation no_allocation_scope;
11763   DependentCode::GroupStartIndexes starts(this);
11764   int start = starts.at(group);
11765   int end = starts.at(group + 1);
11766   int code_entries = starts.number_of_entries();
11767   if (start == end) return false;
11768
11769   // Mark all the code that needs to be deoptimized.
11770   bool marked = false;
11771   for (int i = start; i < end; i++) {
11772     if (is_code_at(i)) {
11773       Code* code = code_at(i);
11774       if (!code->marked_for_deoptimization()) {
11775         code->set_marked_for_deoptimization(true);
11776         marked = true;
11777       }
11778     } else {
11779       CompilationInfo* info = compilation_info_at(i);
11780       info->AbortDueToDependencyChange();
11781     }
11782   }
11783   // Compact the array by moving all subsequent groups to fill in the new holes.
11784   for (int src = end, dst = start; src < code_entries; src++, dst++) {
11785     copy(src, dst);
11786   }
11787   // Now the holes are at the end of the array, zap them for heap-verifier.
11788   int removed = end - start;
11789   for (int i = code_entries - removed; i < code_entries; i++) {
11790     clear_at(i);
11791   }
11792   set_number_of_entries(group, 0);
11793   return marked;
11794 }
11795
11796
11797 void DependentCode::DeoptimizeDependentCodeGroup(
11798     Isolate* isolate,
11799     DependentCode::DependencyGroup group) {
11800   ASSERT(AllowCodeDependencyChange::IsAllowed());
11801   DisallowHeapAllocation no_allocation_scope;
11802   bool marked = MarkCodeForDeoptimization(isolate, group);
11803
11804   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
11805 }
11806
11807
11808 Handle<Object> JSObject::SetPrototype(Handle<JSObject> object,
11809                                       Handle<Object> value,
11810                                       bool skip_hidden_prototypes) {
11811 #ifdef DEBUG
11812   int size = object->Size();
11813 #endif
11814
11815   Isolate* isolate = object->GetIsolate();
11816   Heap* heap = isolate->heap();
11817   // Silently ignore the change if value is not a JSObject or null.
11818   // SpiderMonkey behaves this way.
11819   if (!value->IsJSReceiver() && !value->IsNull()) return value;
11820
11821   // From 8.6.2 Object Internal Methods
11822   // ...
11823   // In addition, if [[Extensible]] is false the value of the [[Class]] and
11824   // [[Prototype]] internal properties of the object may not be modified.
11825   // ...
11826   // Implementation specific extensions that modify [[Class]], [[Prototype]]
11827   // or [[Extensible]] must not violate the invariants defined in the preceding
11828   // paragraph.
11829   if (!object->map()->is_extensible()) {
11830     Handle<Object> args[] = { object };
11831     Handle<Object> error = isolate->factory()->NewTypeError(
11832         "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args)));
11833     isolate->Throw(*error);
11834     return Handle<Object>();
11835   }
11836
11837   // Before we can set the prototype we need to be sure
11838   // prototype cycles are prevented.
11839   // It is sufficient to validate that the receiver is not in the new prototype
11840   // chain.
11841   for (Object* pt = *value;
11842        pt != heap->null_value();
11843        pt = pt->GetPrototype(isolate)) {
11844     if (JSReceiver::cast(pt) == *object) {
11845       // Cycle detected.
11846       Handle<Object> error = isolate->factory()->NewError(
11847           "cyclic_proto", HandleVector<Object>(NULL, 0));
11848       isolate->Throw(*error);
11849       return Handle<Object>();
11850     }
11851   }
11852
11853   bool dictionary_elements_in_chain =
11854       object->map()->DictionaryElementsInPrototypeChainOnly();
11855   Handle<JSObject> real_receiver = object;
11856
11857   if (skip_hidden_prototypes) {
11858     // Find the first object in the chain whose prototype object is not
11859     // hidden and set the new prototype on that object.
11860     Object* current_proto = real_receiver->GetPrototype();
11861     while (current_proto->IsJSObject() &&
11862           JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
11863       real_receiver = handle(JSObject::cast(current_proto), isolate);
11864       current_proto = current_proto->GetPrototype(isolate);
11865     }
11866   }
11867
11868   // Set the new prototype of the object.
11869   Handle<Map> map(real_receiver->map());
11870
11871   // Nothing to do if prototype is already set.
11872   if (map->prototype() == *value) return value;
11873
11874   if (value->IsJSObject()) {
11875     JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
11876   }
11877
11878   Handle<Map> new_map = Map::GetPrototypeTransition(map, value);
11879   if (new_map.is_null()) {
11880     new_map = Map::Copy(map);
11881     Map::PutPrototypeTransition(map, value, new_map);
11882     new_map->set_prototype(*value);
11883   }
11884   ASSERT(new_map->prototype() == *value);
11885   JSObject::MigrateToMap(real_receiver, new_map);
11886
11887   if (!dictionary_elements_in_chain &&
11888       new_map->DictionaryElementsInPrototypeChainOnly()) {
11889     // If the prototype chain didn't previously have element callbacks, then
11890     // KeyedStoreICs need to be cleared to ensure any that involve this
11891     // map go generic.
11892     object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
11893   }
11894
11895   heap->ClearInstanceofCache();
11896   ASSERT(size == object->Size());
11897   return value;
11898 }
11899
11900
11901 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
11902                                         Arguments* args,
11903                                         uint32_t first_arg,
11904                                         uint32_t arg_count,
11905                                         EnsureElementsMode mode) {
11906   // Elements in |Arguments| are ordered backwards (because they're on the
11907   // stack), but the method that's called here iterates over them in forward
11908   // direction.
11909   return EnsureCanContainElements(
11910       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
11911 }
11912
11913
11914 AccessorPair* JSObject::GetLocalPropertyAccessorPair(Name* name) {
11915   uint32_t index = 0;
11916   if (name->AsArrayIndex(&index)) {
11917     return GetLocalElementAccessorPair(index);
11918   }
11919
11920   LookupResult lookup(GetIsolate());
11921   LocalLookupRealNamedProperty(name, &lookup);
11922
11923   if (lookup.IsPropertyCallbacks() &&
11924       lookup.GetCallbackObject()->IsAccessorPair()) {
11925     return AccessorPair::cast(lookup.GetCallbackObject());
11926   }
11927   return NULL;
11928 }
11929
11930
11931 AccessorPair* JSObject::GetLocalElementAccessorPair(uint32_t index) {
11932   if (IsJSGlobalProxy()) {
11933     Object* proto = GetPrototype();
11934     if (proto->IsNull()) return NULL;
11935     ASSERT(proto->IsJSGlobalObject());
11936     return JSObject::cast(proto)->GetLocalElementAccessorPair(index);
11937   }
11938
11939   // Check for lookup interceptor.
11940   if (HasIndexedInterceptor()) return NULL;
11941
11942   return GetElementsAccessor()->GetAccessorPair(this, this, index);
11943 }
11944
11945
11946 Handle<Object> JSObject::SetElementWithInterceptor(
11947     Handle<JSObject> object,
11948     uint32_t index,
11949     Handle<Object> value,
11950     PropertyAttributes attributes,
11951     StrictMode strict_mode,
11952     bool check_prototype,
11953     SetPropertyMode set_mode) {
11954   Isolate* isolate = object->GetIsolate();
11955
11956   // Make sure that the top context does not change when doing
11957   // callbacks or interceptor calls.
11958   AssertNoContextChange ncc(isolate);
11959
11960   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
11961   if (!interceptor->setter()->IsUndefined()) {
11962     v8::IndexedPropertySetterCallback setter =
11963         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
11964     LOG(isolate,
11965         ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
11966     PropertyCallbackArguments args(isolate, interceptor->data(), *object,
11967                                    *object);
11968     v8::Handle<v8::Value> result =
11969         args.Call(setter, index, v8::Utils::ToLocal(value));
11970     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
11971     if (!result.IsEmpty()) return value;
11972   }
11973
11974   return SetElementWithoutInterceptor(object, index, value, attributes,
11975                                       strict_mode,
11976                                       check_prototype,
11977                                       set_mode);
11978 }
11979
11980
11981 MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
11982                                               Object* structure,
11983                                               uint32_t index,
11984                                               Object* holder) {
11985   Isolate* isolate = GetIsolate();
11986   ASSERT(!structure->IsForeign());
11987
11988   // api style callbacks.
11989   if (structure->IsExecutableAccessorInfo()) {
11990     Handle<ExecutableAccessorInfo> data(
11991         ExecutableAccessorInfo::cast(structure));
11992     Object* fun_obj = data->getter();
11993     v8::AccessorGetterCallback call_fun =
11994         v8::ToCData<v8::AccessorGetterCallback>(fun_obj);
11995     if (call_fun == NULL) return isolate->heap()->undefined_value();
11996     HandleScope scope(isolate);
11997     Handle<JSObject> self(JSObject::cast(receiver));
11998     Handle<JSObject> holder_handle(JSObject::cast(holder));
11999     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12000     Handle<String> key = isolate->factory()->NumberToString(number);
12001     LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
12002     PropertyCallbackArguments
12003         args(isolate, data->data(), *self, *holder_handle);
12004     v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
12005     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
12006     if (result.IsEmpty()) return isolate->heap()->undefined_value();
12007     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12008     result_internal->VerifyApiCallResultType();
12009     return *result_internal;
12010   }
12011
12012   // __defineGetter__ callback
12013   if (structure->IsAccessorPair()) {
12014     Object* getter = AccessorPair::cast(structure)->getter();
12015     if (getter->IsSpecFunction()) {
12016       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12017       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
12018     }
12019     // Getter is not a function.
12020     return isolate->heap()->undefined_value();
12021   }
12022
12023   if (structure->IsDeclaredAccessorInfo()) {
12024     return GetDeclaredAccessorProperty(receiver,
12025                                        DeclaredAccessorInfo::cast(structure),
12026                                        isolate);
12027   }
12028
12029   UNREACHABLE();
12030   return NULL;
12031 }
12032
12033
12034 Handle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
12035                                                 Handle<Object> structure,
12036                                                 uint32_t index,
12037                                                 Handle<Object> value,
12038                                                 Handle<JSObject> holder,
12039                                                 StrictMode strict_mode) {
12040   Isolate* isolate = object->GetIsolate();
12041
12042   // We should never get here to initialize a const with the hole
12043   // value since a const declaration would conflict with the setter.
12044   ASSERT(!value->IsTheHole());
12045
12046   // To accommodate both the old and the new api we switch on the
12047   // data structure used to store the callbacks.  Eventually foreign
12048   // callbacks should be phased out.
12049   ASSERT(!structure->IsForeign());
12050
12051   if (structure->IsExecutableAccessorInfo()) {
12052     // api style callbacks
12053     Handle<ExecutableAccessorInfo> data =
12054         Handle<ExecutableAccessorInfo>::cast(structure);
12055     Object* call_obj = data->setter();
12056     v8::AccessorSetterCallback call_fun =
12057         v8::ToCData<v8::AccessorSetterCallback>(call_obj);
12058     if (call_fun == NULL) return value;
12059     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12060     Handle<String> key(isolate->factory()->NumberToString(number));
12061     LOG(isolate, ApiNamedPropertyAccess("store", *object, *key));
12062     PropertyCallbackArguments
12063         args(isolate, data->data(), *object, *holder);
12064     args.Call(call_fun,
12065               v8::Utils::ToLocal(key),
12066               v8::Utils::ToLocal(value));
12067     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
12068     return value;
12069   }
12070
12071   if (structure->IsAccessorPair()) {
12072     Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
12073     if (setter->IsSpecFunction()) {
12074       // TODO(rossberg): nicer would be to cast to some JSCallable here...
12075       return SetPropertyWithDefinedSetter(
12076           object, Handle<JSReceiver>::cast(setter), value);
12077     } else {
12078       if (strict_mode == SLOPPY) return value;
12079       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
12080       Handle<Object> args[2] = { key, holder };
12081       Handle<Object> error = isolate->factory()->NewTypeError(
12082           "no_setter_in_callback", HandleVector(args, 2));
12083       isolate->Throw(*error);
12084       return Handle<Object>();
12085     }
12086   }
12087
12088   // TODO(dcarney): Handle correctly.
12089   if (structure->IsDeclaredAccessorInfo()) return value;
12090
12091   UNREACHABLE();
12092   return Handle<Object>();
12093 }
12094
12095
12096 bool JSObject::HasFastArgumentsElements() {
12097   Heap* heap = GetHeap();
12098   if (!elements()->IsFixedArray()) return false;
12099   FixedArray* elements = FixedArray::cast(this->elements());
12100   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12101     return false;
12102   }
12103   FixedArray* arguments = FixedArray::cast(elements->get(1));
12104   return !arguments->IsDictionary();
12105 }
12106
12107
12108 bool JSObject::HasDictionaryArgumentsElements() {
12109   Heap* heap = GetHeap();
12110   if (!elements()->IsFixedArray()) return false;
12111   FixedArray* elements = FixedArray::cast(this->elements());
12112   if (elements->map() != heap->sloppy_arguments_elements_map()) {
12113     return false;
12114   }
12115   FixedArray* arguments = FixedArray::cast(elements->get(1));
12116   return arguments->IsDictionary();
12117 }
12118
12119
12120 // Adding n elements in fast case is O(n*n).
12121 // Note: revisit design to have dual undefined values to capture absent
12122 // elements.
12123 Handle<Object> JSObject::SetFastElement(Handle<JSObject> object,
12124                                         uint32_t index,
12125                                         Handle<Object> value,
12126                                         StrictMode strict_mode,
12127                                         bool check_prototype) {
12128   ASSERT(object->HasFastSmiOrObjectElements() ||
12129          object->HasFastArgumentsElements());
12130
12131   Isolate* isolate = object->GetIsolate();
12132
12133   // Array optimizations rely on the prototype lookups of Array objects always
12134   // returning undefined. If there is a store to the initial prototype object,
12135   // make sure all of these optimizations are invalidated.
12136   if (isolate->is_initial_object_prototype(*object) ||
12137       isolate->is_initial_array_prototype(*object)) {
12138     object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate,
12139         DependentCode::kElementsCantBeAddedGroup);
12140   }
12141
12142   Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12143   if (backing_store->map() ==
12144       isolate->heap()->sloppy_arguments_elements_map()) {
12145     backing_store = handle(FixedArray::cast(backing_store->get(1)));
12146   } else {
12147     backing_store = EnsureWritableFastElements(object);
12148   }
12149   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12150
12151   if (check_prototype &&
12152       (index >= capacity || backing_store->get(index)->IsTheHole())) {
12153     bool found;
12154     Handle<Object> result = SetElementWithCallbackSetterInPrototypes(
12155         object, index, value, &found, strict_mode);
12156     if (found) return result;
12157   }
12158
12159   uint32_t new_capacity = capacity;
12160   // Check if the length property of this object needs to be updated.
12161   uint32_t array_length = 0;
12162   bool must_update_array_length = false;
12163   bool introduces_holes = true;
12164   if (object->IsJSArray()) {
12165     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12166     introduces_holes = index > array_length;
12167     if (index >= array_length) {
12168       must_update_array_length = true;
12169       array_length = index + 1;
12170     }
12171   } else {
12172     introduces_holes = index >= capacity;
12173   }
12174
12175   // If the array is growing, and it's not growth by a single element at the
12176   // end, make sure that the ElementsKind is HOLEY.
12177   ElementsKind elements_kind = object->GetElementsKind();
12178   if (introduces_holes &&
12179       IsFastElementsKind(elements_kind) &&
12180       !IsFastHoleyElementsKind(elements_kind)) {
12181     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12182     TransitionElementsKind(object, transitioned_kind);
12183   }
12184
12185   // Check if the capacity of the backing store needs to be increased, or if
12186   // a transition to slow elements is necessary.
12187   if (index >= capacity) {
12188     bool convert_to_slow = true;
12189     if ((index - capacity) < kMaxGap) {
12190       new_capacity = NewElementsCapacity(index + 1);
12191       ASSERT(new_capacity > index);
12192       if (!object->ShouldConvertToSlowElements(new_capacity)) {
12193         convert_to_slow = false;
12194       }
12195     }
12196     if (convert_to_slow) {
12197       NormalizeElements(object);
12198       return SetDictionaryElement(object, index, value, NONE, strict_mode,
12199                                   check_prototype);
12200     }
12201   }
12202   // Convert to fast double elements if appropriate.
12203   if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12204     // Consider fixing the boilerplate as well if we have one.
12205     ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
12206         ? FAST_HOLEY_DOUBLE_ELEMENTS
12207         : FAST_DOUBLE_ELEMENTS;
12208
12209     UpdateAllocationSite(object, to_kind);
12210
12211     SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12212     FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12213     object->ValidateElements();
12214     return value;
12215   }
12216   // Change elements kind from Smi-only to generic FAST if necessary.
12217   if (object->HasFastSmiElements() && !value->IsSmi()) {
12218     ElementsKind kind = object->HasFastHoleyElements()
12219         ? FAST_HOLEY_ELEMENTS
12220         : FAST_ELEMENTS;
12221
12222     UpdateAllocationSite(object, kind);
12223     Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12224     JSObject::MigrateToMap(object, new_map);
12225     ASSERT(IsFastObjectElementsKind(object->GetElementsKind()));
12226   }
12227   // Increase backing store capacity if that's been decided previously.
12228   if (new_capacity != capacity) {
12229     SetFastElementsCapacitySmiMode smi_mode =
12230         value->IsSmi() && object->HasFastSmiElements()
12231             ? kAllowSmiElements
12232             : kDontAllowSmiElements;
12233     Handle<FixedArray> new_elements =
12234         SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12235                                          smi_mode);
12236     new_elements->set(index, *value);
12237     object->ValidateElements();
12238     return value;
12239   }
12240
12241   // Finally, set the new element and length.
12242   ASSERT(object->elements()->IsFixedArray());
12243   backing_store->set(index, *value);
12244   if (must_update_array_length) {
12245     Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12246   }
12247   return value;
12248 }
12249
12250
12251 Handle<Object> JSObject::SetDictionaryElement(Handle<JSObject> object,
12252                                               uint32_t index,
12253                                               Handle<Object> value,
12254                                               PropertyAttributes attributes,
12255                                               StrictMode strict_mode,
12256                                               bool check_prototype,
12257                                               SetPropertyMode set_mode) {
12258   ASSERT(object->HasDictionaryElements() ||
12259          object->HasDictionaryArgumentsElements());
12260   Isolate* isolate = object->GetIsolate();
12261
12262   // Insert element in the dictionary.
12263   Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12264   bool is_arguments =
12265       (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12266   Handle<SeededNumberDictionary> dictionary(is_arguments
12267     ? SeededNumberDictionary::cast(elements->get(1))
12268     : SeededNumberDictionary::cast(*elements));
12269
12270   int entry = dictionary->FindEntry(index);
12271   if (entry != SeededNumberDictionary::kNotFound) {
12272     Handle<Object> element(dictionary->ValueAt(entry), isolate);
12273     PropertyDetails details = dictionary->DetailsAt(entry);
12274     if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
12275       return SetElementWithCallback(object, element, index, value, object,
12276                                     strict_mode);
12277     } else {
12278       dictionary->UpdateMaxNumberKey(index);
12279       // If a value has not been initialized we allow writing to it even if it
12280       // is read-only (a declared const that has not been initialized).  If a
12281       // value is being defined we skip attribute checks completely.
12282       if (set_mode == DEFINE_PROPERTY) {
12283         details = PropertyDetails(
12284             attributes, NORMAL, details.dictionary_index());
12285         dictionary->DetailsAtPut(entry, details);
12286       } else if (details.IsReadOnly() && !element->IsTheHole()) {
12287         if (strict_mode == SLOPPY) {
12288           return isolate->factory()->undefined_value();
12289         } else {
12290           Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12291           Handle<Object> args[2] = { number, object };
12292           Handle<Object> error =
12293               isolate->factory()->NewTypeError("strict_read_only_property",
12294                                                HandleVector(args, 2));
12295           isolate->Throw(*error);
12296           return Handle<Object>();
12297         }
12298       }
12299       // Elements of the arguments object in slow mode might be slow aliases.
12300       if (is_arguments && element->IsAliasedArgumentsEntry()) {
12301         Handle<AliasedArgumentsEntry> entry =
12302             Handle<AliasedArgumentsEntry>::cast(element);
12303         Handle<Context> context(Context::cast(elements->get(0)));
12304         int context_index = entry->aliased_context_slot();
12305         ASSERT(!context->get(context_index)->IsTheHole());
12306         context->set(context_index, *value);
12307         // For elements that are still writable we keep slow aliasing.
12308         if (!details.IsReadOnly()) value = element;
12309       }
12310       dictionary->ValueAtPut(entry, *value);
12311     }
12312   } else {
12313     // Index not already used. Look for an accessor in the prototype chain.
12314     // Can cause GC!
12315     if (check_prototype) {
12316       bool found;
12317       Handle<Object> result = SetElementWithCallbackSetterInPrototypes(object,
12318           index, value, &found, strict_mode);
12319       if (found) return result;
12320     }
12321
12322     // When we set the is_extensible flag to false we always force the
12323     // element into dictionary mode (and force them to stay there).
12324     if (!object->map()->is_extensible()) {
12325       if (strict_mode == SLOPPY) {
12326         return isolate->factory()->undefined_value();
12327       } else {
12328         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12329         Handle<String> name = isolate->factory()->NumberToString(number);
12330         Handle<Object> args[1] = { name };
12331         Handle<Object> error =
12332             isolate->factory()->NewTypeError("object_not_extensible",
12333                                              HandleVector(args, 1));
12334         isolate->Throw(*error);
12335         return Handle<Object>();
12336       }
12337     }
12338
12339     PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
12340     Handle<SeededNumberDictionary> new_dictionary =
12341         SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
12342                                                details);
12343     if (*dictionary != *new_dictionary) {
12344       if (is_arguments) {
12345         elements->set(1, *new_dictionary);
12346       } else {
12347         object->set_elements(*new_dictionary);
12348       }
12349       dictionary = new_dictionary;
12350     }
12351   }
12352
12353   // Update the array length if this JSObject is an array.
12354   if (object->IsJSArray()) {
12355     JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index,
12356                                           value);
12357   }
12358
12359   // Attempt to put this object back in fast case.
12360   if (object->ShouldConvertToFastElements()) {
12361     uint32_t new_length = 0;
12362     if (object->IsJSArray()) {
12363       CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length));
12364     } else {
12365       new_length = dictionary->max_number_key() + 1;
12366     }
12367     SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays
12368         ? kAllowSmiElements
12369         : kDontAllowSmiElements;
12370     bool has_smi_only_elements = false;
12371     bool should_convert_to_fast_double_elements =
12372         object->ShouldConvertToFastDoubleElements(&has_smi_only_elements);
12373     if (has_smi_only_elements) {
12374       smi_mode = kForceSmiElements;
12375     }
12376
12377     if (should_convert_to_fast_double_elements) {
12378       SetFastDoubleElementsCapacityAndLength(object, new_length, new_length);
12379     } else {
12380       SetFastElementsCapacityAndLength(object, new_length, new_length,
12381                                        smi_mode);
12382     }
12383     object->ValidateElements();
12384 #ifdef DEBUG
12385     if (FLAG_trace_normalization) {
12386       PrintF("Object elements are fast case again:\n");
12387       object->Print();
12388     }
12389 #endif
12390   }
12391   return value;
12392 }
12393
12394 Handle<Object> JSObject::SetFastDoubleElement(
12395     Handle<JSObject> object,
12396     uint32_t index,
12397     Handle<Object> value,
12398     StrictMode strict_mode,
12399     bool check_prototype) {
12400   ASSERT(object->HasFastDoubleElements());
12401
12402   Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12403   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
12404
12405   // If storing to an element that isn't in the array, pass the store request
12406   // up the prototype chain before storing in the receiver's elements.
12407   if (check_prototype &&
12408       (index >= elms_length ||
12409        Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
12410     bool found;
12411     Handle<Object> result = SetElementWithCallbackSetterInPrototypes(object,
12412         index, value, &found, strict_mode);
12413     if (found) return result;
12414   }
12415
12416   // If the value object is not a heap number, switch to fast elements and try
12417   // again.
12418   bool value_is_smi = value->IsSmi();
12419   bool introduces_holes = true;
12420   uint32_t length = elms_length;
12421   if (object->IsJSArray()) {
12422     CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length));
12423     introduces_holes = index > length;
12424   } else {
12425     introduces_holes = index >= elms_length;
12426   }
12427
12428   if (!value->IsNumber()) {
12429     SetFastElementsCapacityAndLength(object, elms_length, length,
12430                                      kDontAllowSmiElements);
12431     Handle<Object> result = SetFastElement(object, index, value, strict_mode,
12432                                            check_prototype);
12433     RETURN_IF_EMPTY_HANDLE_VALUE(object->GetIsolate(), result,
12434                                  Handle<Object>());
12435     object->ValidateElements();
12436     return result;
12437   }
12438
12439   double double_value = value_is_smi
12440       ? static_cast<double>(Handle<Smi>::cast(value)->value())
12441       : Handle<HeapNumber>::cast(value)->value();
12442
12443   // If the array is growing, and it's not growth by a single element at the
12444   // end, make sure that the ElementsKind is HOLEY.
12445   ElementsKind elements_kind = object->GetElementsKind();
12446   if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
12447     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12448     TransitionElementsKind(object, transitioned_kind);
12449   }
12450
12451   // Check whether there is extra space in the fixed array.
12452   if (index < elms_length) {
12453     Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
12454     elms->set(index, double_value);
12455     if (object->IsJSArray()) {
12456       // Update the length of the array if needed.
12457       uint32_t array_length = 0;
12458       CHECK(
12459           Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12460       if (index >= array_length) {
12461         Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12462       }
12463     }
12464     return value;
12465   }
12466
12467   // Allow gap in fast case.
12468   if ((index - elms_length) < kMaxGap) {
12469     // Try allocating extra space.
12470     int new_capacity = NewElementsCapacity(index+1);
12471     if (!object->ShouldConvertToSlowElements(new_capacity)) {
12472       ASSERT(static_cast<uint32_t>(new_capacity) > index);
12473       SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
12474       FixedDoubleArray::cast(object->elements())->set(index, double_value);
12475       object->ValidateElements();
12476       return value;
12477     }
12478   }
12479
12480   // Otherwise default to slow case.
12481   ASSERT(object->HasFastDoubleElements());
12482   ASSERT(object->map()->has_fast_double_elements());
12483   ASSERT(object->elements()->IsFixedDoubleArray() ||
12484          object->elements()->length() == 0);
12485
12486   NormalizeElements(object);
12487   ASSERT(object->HasDictionaryElements());
12488   return SetElement(object, index, value, NONE, strict_mode, check_prototype);
12489 }
12490
12491
12492 Handle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12493                                       uint32_t index,
12494                                       Handle<Object> value,
12495                                       PropertyAttributes attributes,
12496                                       StrictMode strict_mode) {
12497   if (object->IsJSProxy()) {
12498     return JSProxy::SetElementWithHandler(
12499         Handle<JSProxy>::cast(object), object, index, value, strict_mode);
12500   }
12501   return JSObject::SetElement(
12502       Handle<JSObject>::cast(object), index, value, attributes, strict_mode);
12503 }
12504
12505
12506 Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
12507                                        uint32_t index,
12508                                        Handle<Object> value,
12509                                        StrictMode strict_mode) {
12510   ASSERT(!object->HasExternalArrayElements());
12511   return JSObject::SetElement(object, index, value, NONE, strict_mode, false);
12512 }
12513
12514
12515 Handle<Object> JSObject::SetElement(Handle<JSObject> object,
12516                                     uint32_t index,
12517                                     Handle<Object> value,
12518                                     PropertyAttributes attributes,
12519                                     StrictMode strict_mode,
12520                                     bool check_prototype,
12521                                     SetPropertyMode set_mode) {
12522   Isolate* isolate = object->GetIsolate();
12523
12524   if (object->HasExternalArrayElements() ||
12525       object->HasFixedTypedArrayElements()) {
12526     // TODO(ningxin): Throw an error if setting a Float32x4Array element
12527     // while the value is not Float32x4Object.
12528     if (!value->IsNumber() && !value->IsFloat32x4() &&
12529         !value->IsInt32x4() && !value->IsUndefined()) {
12530       bool has_exception;
12531       Handle<Object> number =
12532           Execution::ToNumber(isolate, value, &has_exception);
12533       if (has_exception) return Handle<Object>();
12534       value = number;
12535     }
12536   }
12537
12538   // Check access rights if needed.
12539   if (object->IsAccessCheckNeeded()) {
12540     if (!isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_SET)) {
12541       isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET);
12542       RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
12543       return value;
12544     }
12545   }
12546
12547   if (object->IsJSGlobalProxy()) {
12548     Handle<Object> proto(object->GetPrototype(), isolate);
12549     if (proto->IsNull()) return value;
12550     ASSERT(proto->IsJSGlobalObject());
12551     return SetElement(Handle<JSObject>::cast(proto), index, value, attributes,
12552                       strict_mode,
12553                       check_prototype,
12554                       set_mode);
12555   }
12556
12557   // Don't allow element properties to be redefined for external arrays.
12558   if ((object->HasExternalArrayElements() ||
12559           object->HasFixedTypedArrayElements()) &&
12560       set_mode == DEFINE_PROPERTY) {
12561     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12562     Handle<Object> args[] = { object, number };
12563     Handle<Object> error = isolate->factory()->NewTypeError(
12564         "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
12565     isolate->Throw(*error);
12566     return Handle<Object>();
12567   }
12568
12569   // Normalize the elements to enable attributes on the property.
12570   if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
12571     Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
12572     // Make sure that we never go back to fast case.
12573     dictionary->set_requires_slow_elements();
12574   }
12575
12576   if (!object->map()->is_observed()) {
12577     return object->HasIndexedInterceptor()
12578       ? SetElementWithInterceptor(object, index, value, attributes, strict_mode,
12579                                   check_prototype,
12580                                    set_mode)
12581       : SetElementWithoutInterceptor(object, index, value, attributes,
12582                                      strict_mode,
12583                                      check_prototype,
12584                                      set_mode);
12585   }
12586
12587   PropertyAttributes old_attributes =
12588       JSReceiver::GetLocalElementAttribute(object, index);
12589   Handle<Object> old_value = isolate->factory()->the_hole_value();
12590   Handle<Object> old_length_handle;
12591   Handle<Object> new_length_handle;
12592
12593   if (old_attributes != ABSENT) {
12594     if (object->GetLocalElementAccessorPair(index) == NULL) {
12595       old_value = Object::GetElementNoExceptionThrown(isolate, object, index);
12596     }
12597   } else if (object->IsJSArray()) {
12598     // Store old array length in case adding an element grows the array.
12599     old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
12600                                isolate);
12601   }
12602
12603   // Check for lookup interceptor
12604   Handle<Object> result = object->HasIndexedInterceptor()
12605     ? SetElementWithInterceptor(object, index, value, attributes, strict_mode,
12606                                 check_prototype,
12607                                 set_mode)
12608     : SetElementWithoutInterceptor(object, index, value, attributes,
12609                                    strict_mode,
12610                                    check_prototype,
12611                                    set_mode);
12612   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
12613
12614   Handle<String> name = isolate->factory()->Uint32ToString(index);
12615   PropertyAttributes new_attributes = GetLocalElementAttribute(object, index);
12616   if (old_attributes == ABSENT) {
12617     if (object->IsJSArray() &&
12618         !old_length_handle->SameValue(
12619             Handle<JSArray>::cast(object)->length())) {
12620       new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
12621                                  isolate);
12622       uint32_t old_length = 0;
12623       uint32_t new_length = 0;
12624       CHECK(old_length_handle->ToArrayIndex(&old_length));
12625       CHECK(new_length_handle->ToArrayIndex(&new_length));
12626
12627       BeginPerformSplice(Handle<JSArray>::cast(object));
12628       EnqueueChangeRecord(object, "add", name, old_value);
12629       EnqueueChangeRecord(object, "update", isolate->factory()->length_string(),
12630                           old_length_handle);
12631       EndPerformSplice(Handle<JSArray>::cast(object));
12632       Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12633       EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length, deleted,
12634                           new_length - old_length);
12635     } else {
12636       EnqueueChangeRecord(object, "add", name, old_value);
12637     }
12638   } else if (old_value->IsTheHole()) {
12639     EnqueueChangeRecord(object, "reconfigure", name, old_value);
12640   } else {
12641     Handle<Object> new_value =
12642         Object::GetElementNoExceptionThrown(isolate, object, index);
12643     bool value_changed = !old_value->SameValue(*new_value);
12644     if (old_attributes != new_attributes) {
12645       if (!value_changed) old_value = isolate->factory()->the_hole_value();
12646       EnqueueChangeRecord(object, "reconfigure", name, old_value);
12647     } else if (value_changed) {
12648       EnqueueChangeRecord(object, "update", name, old_value);
12649     }
12650   }
12651
12652   return result;
12653 }
12654
12655
12656 Handle<Object> JSObject::SetElementWithoutInterceptor(
12657     Handle<JSObject> object,
12658     uint32_t index,
12659     Handle<Object> value,
12660     PropertyAttributes attributes,
12661     StrictMode strict_mode,
12662     bool check_prototype,
12663     SetPropertyMode set_mode) {
12664   ASSERT(object->HasDictionaryElements() ||
12665          object->HasDictionaryArgumentsElements() ||
12666          (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
12667   Isolate* isolate = object->GetIsolate();
12668   if (FLAG_trace_external_array_abuse &&
12669       IsExternalArrayElementsKind(object->GetElementsKind())) {
12670     CheckArrayAbuse(*object, "external elements write", index);
12671   }
12672   if (FLAG_trace_js_array_abuse &&
12673       !IsExternalArrayElementsKind(object->GetElementsKind())) {
12674     if (object->IsJSArray()) {
12675       CheckArrayAbuse(*object, "elements write", index, true);
12676     }
12677   }
12678   switch (object->GetElementsKind()) {
12679     case FAST_SMI_ELEMENTS:
12680     case FAST_ELEMENTS:
12681     case FAST_HOLEY_SMI_ELEMENTS:
12682     case FAST_HOLEY_ELEMENTS:
12683       return SetFastElement(object, index, value, strict_mode, check_prototype);
12684     case FAST_DOUBLE_ELEMENTS:
12685     case FAST_HOLEY_DOUBLE_ELEMENTS:
12686       return SetFastDoubleElement(object, index, value, strict_mode,
12687                                   check_prototype);
12688
12689 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
12690     case EXTERNAL_##TYPE##_ELEMENTS: {                                        \
12691       Handle<External##Type##Array> array(                                    \
12692           External##Type##Array::cast(object->elements()));                   \
12693       return External##Type##Array::SetValue(array, index, value);            \
12694     }                                                                         \
12695     case TYPE##_ELEMENTS: {                                                   \
12696       Handle<Fixed##Type##Array> array(                                       \
12697           Fixed##Type##Array::cast(object->elements()));                      \
12698       return Fixed##Type##Array::SetValue(array, index, value);               \
12699     }
12700
12701     TYPED_ARRAYS(TYPED_ARRAY_CASE)
12702
12703 #undef TYPED_ARRAY_CASE
12704
12705     case DICTIONARY_ELEMENTS:
12706       return SetDictionaryElement(object, index, value, attributes, strict_mode,
12707                                   check_prototype,
12708                                   set_mode);
12709     case SLOPPY_ARGUMENTS_ELEMENTS: {
12710       Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
12711       uint32_t length = parameter_map->length();
12712       Handle<Object> probe = index < length - 2 ?
12713           Handle<Object>(parameter_map->get(index + 2), isolate) :
12714           Handle<Object>();
12715       if (!probe.is_null() && !probe->IsTheHole()) {
12716         Handle<Context> context(Context::cast(parameter_map->get(0)));
12717         int context_index = Handle<Smi>::cast(probe)->value();
12718         ASSERT(!context->get(context_index)->IsTheHole());
12719         context->set(context_index, *value);
12720         // Redefining attributes of an aliased element destroys fast aliasing.
12721         if (set_mode == SET_PROPERTY || attributes == NONE) return value;
12722         parameter_map->set_the_hole(index + 2);
12723         // For elements that are still writable we re-establish slow aliasing.
12724         if ((attributes & READ_ONLY) == 0) {
12725           value = Handle<Object>::cast(
12726               isolate->factory()->NewAliasedArgumentsEntry(context_index));
12727         }
12728       }
12729       Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
12730       if (arguments->IsDictionary()) {
12731         return SetDictionaryElement(object, index, value, attributes,
12732                                     strict_mode,
12733                                     check_prototype,
12734                                     set_mode);
12735       } else {
12736         return SetFastElement(object, index, value, strict_mode,
12737                               check_prototype);
12738       }
12739     }
12740   }
12741   // All possible cases have been handled above. Add a return to avoid the
12742   // complaints from the compiler.
12743   UNREACHABLE();
12744   return isolate->factory()->null_value();
12745 }
12746
12747
12748 const double AllocationSite::kPretenureRatio = 0.85;
12749
12750
12751 void AllocationSite::ResetPretenureDecision() {
12752   set_pretenure_decision(kUndecided);
12753   set_memento_found_count(0);
12754   set_memento_create_count(0);
12755 }
12756
12757
12758 PretenureFlag AllocationSite::GetPretenureMode() {
12759   PretenureDecision mode = pretenure_decision();
12760   // Zombie objects "decide" to be untenured.
12761   return mode == kTenure ? TENURED : NOT_TENURED;
12762 }
12763
12764
12765 bool AllocationSite::IsNestedSite() {
12766   ASSERT(FLAG_trace_track_allocation_sites);
12767   Object* current = GetHeap()->allocation_sites_list();
12768   while (current->IsAllocationSite()) {
12769     AllocationSite* current_site = AllocationSite::cast(current);
12770     if (current_site->nested_site() == this) {
12771       return true;
12772     }
12773     current = current_site->weak_next();
12774   }
12775   return false;
12776 }
12777
12778
12779 void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
12780                                               ElementsKind to_kind) {
12781   Isolate* isolate = site->GetIsolate();
12782
12783   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
12784     Handle<JSArray> transition_info =
12785         handle(JSArray::cast(site->transition_info()));
12786     ElementsKind kind = transition_info->GetElementsKind();
12787     // if kind is holey ensure that to_kind is as well.
12788     if (IsHoleyElementsKind(kind)) {
12789       to_kind = GetHoleyElementsKind(to_kind);
12790     }
12791     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12792       // If the array is huge, it's not likely to be defined in a local
12793       // function, so we shouldn't make new instances of it very often.
12794       uint32_t length = 0;
12795       CHECK(transition_info->length()->ToArrayIndex(&length));
12796       if (length <= kMaximumArrayBytesToPretransition) {
12797         if (FLAG_trace_track_allocation_sites) {
12798           bool is_nested = site->IsNestedSite();
12799           PrintF(
12800               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
12801               reinterpret_cast<void*>(*site),
12802               is_nested ? "(nested)" : "",
12803               ElementsKindToString(kind),
12804               ElementsKindToString(to_kind));
12805         }
12806         JSObject::TransitionElementsKind(transition_info, to_kind);
12807         site->dependent_code()->DeoptimizeDependentCodeGroup(
12808             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12809       }
12810     }
12811   } else {
12812     ElementsKind kind = site->GetElementsKind();
12813     // if kind is holey ensure that to_kind is as well.
12814     if (IsHoleyElementsKind(kind)) {
12815       to_kind = GetHoleyElementsKind(to_kind);
12816     }
12817     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12818       if (FLAG_trace_track_allocation_sites) {
12819         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
12820                reinterpret_cast<void*>(*site),
12821                ElementsKindToString(kind),
12822                ElementsKindToString(to_kind));
12823       }
12824       site->SetElementsKind(to_kind);
12825       site->dependent_code()->DeoptimizeDependentCodeGroup(
12826           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12827     }
12828   }
12829 }
12830
12831
12832 // static
12833 void AllocationSite::AddDependentCompilationInfo(Handle<AllocationSite> site,
12834                                                  Reason reason,
12835                                                  CompilationInfo* info) {
12836   DependentCode::DependencyGroup group = site->ToDependencyGroup(reason);
12837   Handle<DependentCode> dep(site->dependent_code());
12838   Handle<DependentCode> codes =
12839       DependentCode::Insert(dep, group, info->object_wrapper());
12840   if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
12841   info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
12842 }
12843
12844
12845 void JSObject::UpdateAllocationSite(Handle<JSObject> object,
12846                                     ElementsKind to_kind) {
12847   if (!object->IsJSArray()) return;
12848
12849   Heap* heap = object->GetHeap();
12850   if (!heap->InNewSpace(*object)) return;
12851
12852   Handle<AllocationSite> site;
12853   {
12854     DisallowHeapAllocation no_allocation;
12855     // Check if there is potentially a memento behind the object. If
12856     // the last word of the momento is on another page we return
12857     // immediatelly.
12858     Address object_address = object->address();
12859     Address memento_address = object_address + JSArray::kSize;
12860     Address last_memento_word_address = memento_address + kPointerSize;
12861     if (!NewSpacePage::OnSamePage(object_address,
12862                                   last_memento_word_address)) {
12863       return;
12864     }
12865
12866     // Either object is the last object in the new space, or there is another
12867     // object of at least word size (the header map word) following it, so
12868     // suffices to compare ptr and top here.
12869     Address top = heap->NewSpaceTop();
12870     ASSERT(memento_address == top ||
12871            memento_address + HeapObject::kHeaderSize <= top);
12872     if (memento_address == top) return;
12873
12874     HeapObject* candidate = HeapObject::FromAddress(memento_address);
12875     if (candidate->map() != heap->allocation_memento_map()) return;
12876
12877     AllocationMemento* memento = AllocationMemento::cast(candidate);
12878     if (!memento->IsValid()) return;
12879
12880     // Walk through to the Allocation Site
12881     site = handle(memento->GetAllocationSite());
12882   }
12883   AllocationSite::DigestTransitionFeedback(site, to_kind);
12884 }
12885
12886
12887 void JSObject::TransitionElementsKind(Handle<JSObject> object,
12888                                       ElementsKind to_kind) {
12889   ElementsKind from_kind = object->map()->elements_kind();
12890
12891   if (IsFastHoleyElementsKind(from_kind)) {
12892     to_kind = GetHoleyElementsKind(to_kind);
12893   }
12894
12895   if (from_kind == to_kind) return;
12896   // Don't update the site if to_kind isn't fast
12897   if (IsFastElementsKind(to_kind)) {
12898     UpdateAllocationSite(object, to_kind);
12899   }
12900
12901   Isolate* isolate = object->GetIsolate();
12902   if (object->elements() == isolate->heap()->empty_fixed_array() ||
12903       (IsFastSmiOrObjectElementsKind(from_kind) &&
12904        IsFastSmiOrObjectElementsKind(to_kind)) ||
12905       (from_kind == FAST_DOUBLE_ELEMENTS &&
12906        to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
12907     ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
12908     // No change is needed to the elements() buffer, the transition
12909     // only requires a map change.
12910     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
12911     MigrateToMap(object, new_map);
12912     if (FLAG_trace_elements_transitions) {
12913       Handle<FixedArrayBase> elms(object->elements());
12914       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
12915     }
12916     return;
12917   }
12918
12919   Handle<FixedArrayBase> elms(object->elements());
12920   uint32_t capacity = static_cast<uint32_t>(elms->length());
12921   uint32_t length = capacity;
12922
12923   if (object->IsJSArray()) {
12924     Object* raw_length = Handle<JSArray>::cast(object)->length();
12925     if (raw_length->IsUndefined()) {
12926       // If length is undefined, then JSArray is being initialized and has no
12927       // elements, assume a length of zero.
12928       length = 0;
12929     } else {
12930       CHECK(raw_length->ToArrayIndex(&length));
12931     }
12932   }
12933
12934   if (IsFastSmiElementsKind(from_kind) &&
12935       IsFastDoubleElementsKind(to_kind)) {
12936     SetFastDoubleElementsCapacityAndLength(object, capacity, length);
12937     object->ValidateElements();
12938     return;
12939   }
12940
12941   if (IsFastDoubleElementsKind(from_kind) &&
12942       IsFastObjectElementsKind(to_kind)) {
12943     SetFastElementsCapacityAndLength(object, capacity, length,
12944                                      kDontAllowSmiElements);
12945     object->ValidateElements();
12946     return;
12947   }
12948
12949   // This method should never be called for any other case than the ones
12950   // handled above.
12951   UNREACHABLE();
12952 }
12953
12954
12955 // static
12956 bool Map::IsValidElementsTransition(ElementsKind from_kind,
12957                                     ElementsKind to_kind) {
12958   // Transitions can't go backwards.
12959   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
12960     return false;
12961   }
12962
12963   // Transitions from HOLEY -> PACKED are not allowed.
12964   return !IsFastHoleyElementsKind(from_kind) ||
12965       IsFastHoleyElementsKind(to_kind);
12966 }
12967
12968
12969 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array,
12970                                            uint32_t index,
12971                                            Handle<Object> value) {
12972   CALL_HEAP_FUNCTION_VOID(array->GetIsolate(),
12973                           array->JSArrayUpdateLengthFromIndex(index, *value));
12974 }
12975
12976
12977 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
12978                                                    Object* value) {
12979   uint32_t old_len = 0;
12980   CHECK(length()->ToArrayIndex(&old_len));
12981   // Check to see if we need to update the length. For now, we make
12982   // sure that the length stays within 32-bits (unsigned).
12983   if (index >= old_len && index != 0xffffffff) {
12984     Object* len;
12985     { MaybeObject* maybe_len =
12986           GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
12987       if (!maybe_len->ToObject(&len)) return maybe_len;
12988     }
12989     set_length(len);
12990   }
12991   return value;
12992 }
12993
12994
12995 Handle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object,
12996                                                    Handle<Object> receiver,
12997                                                    uint32_t index) {
12998   Isolate* isolate = object->GetIsolate();
12999
13000   // Make sure that the top context does not change when doing
13001   // callbacks or interceptor calls.
13002   AssertNoContextChange ncc(isolate);
13003
13004   Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate);
13005   if (!interceptor->getter()->IsUndefined()) {
13006     v8::IndexedPropertyGetterCallback getter =
13007         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
13008     LOG(isolate,
13009         ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
13010     PropertyCallbackArguments
13011         args(isolate, interceptor->data(), *receiver, *object);
13012     v8::Handle<v8::Value> result = args.Call(getter, index);
13013     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
13014     if (!result.IsEmpty()) {
13015       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13016       result_internal->VerifyApiCallResultType();
13017       // Rebox handle before return.
13018       return Handle<Object>(*result_internal, isolate);
13019     }
13020   }
13021
13022   ElementsAccessor* handler = object->GetElementsAccessor();
13023   Handle<Object> result = handler->Get(receiver,  object, index);
13024   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
13025   if (!result->IsTheHole()) return result;
13026
13027   Handle<Object> proto(object->GetPrototype(), isolate);
13028   if (proto->IsNull()) return isolate->factory()->undefined_value();
13029   return Object::GetElementWithReceiver(isolate, proto, receiver, index);
13030 }
13031
13032
13033 bool JSObject::HasDenseElements() {
13034   int capacity = 0;
13035   int used = 0;
13036   GetElementsCapacityAndUsage(&capacity, &used);
13037   return (capacity == 0) || (used > (capacity / 2));
13038 }
13039
13040
13041 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
13042   *capacity = 0;
13043   *used = 0;
13044
13045   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
13046   FixedArray* backing_store = NULL;
13047   switch (GetElementsKind()) {
13048     case SLOPPY_ARGUMENTS_ELEMENTS:
13049       backing_store_base =
13050           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
13051       backing_store = FixedArray::cast(backing_store_base);
13052       if (backing_store->IsDictionary()) {
13053         SeededNumberDictionary* dictionary =
13054             SeededNumberDictionary::cast(backing_store);
13055         *capacity = dictionary->Capacity();
13056         *used = dictionary->NumberOfElements();
13057         break;
13058       }
13059       // Fall through.
13060     case FAST_SMI_ELEMENTS:
13061     case FAST_ELEMENTS:
13062       if (IsJSArray()) {
13063         *capacity = backing_store_base->length();
13064         *used = Smi::cast(JSArray::cast(this)->length())->value();
13065         break;
13066       }
13067       // Fall through if packing is not guaranteed.
13068     case FAST_HOLEY_SMI_ELEMENTS:
13069     case FAST_HOLEY_ELEMENTS:
13070       backing_store = FixedArray::cast(backing_store_base);
13071       *capacity = backing_store->length();
13072       for (int i = 0; i < *capacity; ++i) {
13073         if (!backing_store->get(i)->IsTheHole()) ++(*used);
13074       }
13075       break;
13076     case DICTIONARY_ELEMENTS: {
13077       SeededNumberDictionary* dictionary = element_dictionary();
13078       *capacity = dictionary->Capacity();
13079       *used = dictionary->NumberOfElements();
13080       break;
13081     }
13082     case FAST_DOUBLE_ELEMENTS:
13083       if (IsJSArray()) {
13084         *capacity = backing_store_base->length();
13085         *used = Smi::cast(JSArray::cast(this)->length())->value();
13086         break;
13087       }
13088       // Fall through if packing is not guaranteed.
13089     case FAST_HOLEY_DOUBLE_ELEMENTS: {
13090       *capacity = elements()->length();
13091       if (*capacity == 0) break;
13092       FixedDoubleArray * elms = FixedDoubleArray::cast(elements());
13093       for (int i = 0; i < *capacity; i++) {
13094         if (!elms->is_the_hole(i)) ++(*used);
13095       }
13096       break;
13097     }
13098
13099 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
13100     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
13101     case TYPE##_ELEMENTS:                                                    \
13102
13103     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13104 #undef TYPED_ARRAY_CASE
13105     {
13106       // External arrays are considered 100% used.
13107       FixedArrayBase* external_array = FixedArrayBase::cast(elements());
13108       *capacity = external_array->length();
13109       *used = external_array->length();
13110       break;
13111     }
13112   }
13113 }
13114
13115
13116 bool JSObject::WouldConvertToSlowElements(Handle<Object> key) {
13117   uint32_t index;
13118   if (HasFastElements() && key->ToArrayIndex(&index)) {
13119     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
13120     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
13121     if (index >= capacity) {
13122       if ((index - capacity) >= kMaxGap) return true;
13123       uint32_t new_capacity = NewElementsCapacity(index + 1);
13124       return ShouldConvertToSlowElements(new_capacity);
13125     }
13126   }
13127   return false;
13128 }
13129
13130
13131 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
13132   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
13133                 kMaxUncheckedFastElementsLength);
13134   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
13135       (new_capacity <= kMaxUncheckedFastElementsLength &&
13136        GetHeap()->InNewSpace(this))) {
13137     return false;
13138   }
13139   // If the fast-case backing storage takes up roughly three times as
13140   // much space (in machine words) as a dictionary backing storage
13141   // would, the object should have slow elements.
13142   int old_capacity = 0;
13143   int used_elements = 0;
13144   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
13145   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
13146       SeededNumberDictionary::kEntrySize;
13147   return 3 * dictionary_size <= new_capacity;
13148 }
13149
13150
13151 bool JSObject::ShouldConvertToFastElements() {
13152   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
13153   // If the elements are sparse, we should not go back to fast case.
13154   if (!HasDenseElements()) return false;
13155   // An object requiring access checks is never allowed to have fast
13156   // elements.  If it had fast elements we would skip security checks.
13157   if (IsAccessCheckNeeded()) return false;
13158   // Observed objects may not go to fast mode because they rely on map checks,
13159   // and for fast element accesses we sometimes check element kinds only.
13160   if (map()->is_observed()) return false;
13161
13162   FixedArray* elements = FixedArray::cast(this->elements());
13163   SeededNumberDictionary* dictionary = NULL;
13164   if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) {
13165     dictionary = SeededNumberDictionary::cast(elements->get(1));
13166   } else {
13167     dictionary = SeededNumberDictionary::cast(elements);
13168   }
13169   // If an element has been added at a very high index in the elements
13170   // dictionary, we cannot go back to fast case.
13171   if (dictionary->requires_slow_elements()) return false;
13172   // If the dictionary backing storage takes up roughly half as much
13173   // space (in machine words) as a fast-case backing storage would,
13174   // the object should have fast elements.
13175   uint32_t array_size = 0;
13176   if (IsJSArray()) {
13177     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
13178   } else {
13179     array_size = dictionary->max_number_key();
13180   }
13181   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
13182       SeededNumberDictionary::kEntrySize;
13183   return 2 * dictionary_size >= array_size;
13184 }
13185
13186
13187 bool JSObject::ShouldConvertToFastDoubleElements(
13188     bool* has_smi_only_elements) {
13189   *has_smi_only_elements = false;
13190   if (HasSloppyArgumentsElements()) return false;
13191   if (FLAG_unbox_double_arrays) {
13192     ASSERT(HasDictionaryElements());
13193     SeededNumberDictionary* dictionary = element_dictionary();
13194     bool found_double = false;
13195     for (int i = 0; i < dictionary->Capacity(); i++) {
13196       Object* key = dictionary->KeyAt(i);
13197       if (key->IsNumber()) {
13198         Object* value = dictionary->ValueAt(i);
13199         if (!value->IsNumber()) return false;
13200         if (!value->IsSmi()) {
13201           found_double = true;
13202         }
13203       }
13204     }
13205     *has_smi_only_elements = !found_double;
13206     return found_double;
13207   } else {
13208     return false;
13209   }
13210 }
13211
13212
13213 // Certain compilers request function template instantiation when they
13214 // see the definition of the other template functions in the
13215 // class. This requires us to have the template functions put
13216 // together, so even though this function belongs in objects-debug.cc,
13217 // we keep it here instead to satisfy certain compilers.
13218 #ifdef OBJECT_PRINT
13219 template<typename Shape, typename Key>
13220 void Dictionary<Shape, Key>::Print(FILE* out) {
13221   int capacity = HashTable<Shape, Key>::Capacity();
13222   for (int i = 0; i < capacity; i++) {
13223     Object* k = HashTable<Shape, Key>::KeyAt(i);
13224     if (HashTable<Shape, Key>::IsKey(k)) {
13225       PrintF(out, " ");
13226       if (k->IsString()) {
13227         String::cast(k)->StringPrint(out);
13228       } else {
13229         k->ShortPrint(out);
13230       }
13231       PrintF(out, ": ");
13232       ValueAt(i)->ShortPrint(out);
13233       PrintF(out, "\n");
13234     }
13235   }
13236 }
13237 #endif
13238
13239
13240 template<typename Shape, typename Key>
13241 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
13242   int pos = 0;
13243   int capacity = HashTable<Shape, Key>::Capacity();
13244   DisallowHeapAllocation no_gc;
13245   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
13246   for (int i = 0; i < capacity; i++) {
13247     Object* k =  Dictionary<Shape, Key>::KeyAt(i);
13248     if (Dictionary<Shape, Key>::IsKey(k)) {
13249       elements->set(pos++, ValueAt(i), mode);
13250     }
13251   }
13252   ASSERT(pos == elements->length());
13253 }
13254
13255
13256 InterceptorInfo* JSObject::GetNamedInterceptor() {
13257   ASSERT(map()->has_named_interceptor());
13258   JSFunction* constructor = JSFunction::cast(map()->constructor());
13259   ASSERT(constructor->shared()->IsApiFunction());
13260   Object* result =
13261       constructor->shared()->get_api_func_data()->named_property_handler();
13262   return InterceptorInfo::cast(result);
13263 }
13264
13265
13266 InterceptorInfo* JSObject::GetIndexedInterceptor() {
13267   ASSERT(map()->has_indexed_interceptor());
13268   JSFunction* constructor = JSFunction::cast(map()->constructor());
13269   ASSERT(constructor->shared()->IsApiFunction());
13270   Object* result =
13271       constructor->shared()->get_api_func_data()->indexed_property_handler();
13272   return InterceptorInfo::cast(result);
13273 }
13274
13275
13276 Handle<Object> JSObject::GetPropertyPostInterceptor(
13277     Handle<JSObject> object,
13278     Handle<Object> receiver,
13279     Handle<Name> name,
13280     PropertyAttributes* attributes) {
13281   // Check local property in holder, ignore interceptor.
13282   Isolate* isolate = object->GetIsolate();
13283   LookupResult lookup(isolate);
13284   object->LocalLookupRealNamedProperty(*name, &lookup);
13285   Handle<Object> result;
13286   if (lookup.IsFound()) {
13287     result = GetProperty(object, receiver, &lookup, name, attributes);
13288   } else {
13289     // Continue searching via the prototype chain.
13290     Handle<Object> prototype(object->GetPrototype(), isolate);
13291     *attributes = ABSENT;
13292     if (prototype->IsNull()) return isolate->factory()->undefined_value();
13293     result = GetPropertyWithReceiver(prototype, receiver, name, attributes);
13294   }
13295   return result;
13296 }
13297
13298
13299 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
13300     Object* receiver,
13301     Name* name,
13302     PropertyAttributes* attributes) {
13303   // Check local property in holder, ignore interceptor.
13304   LookupResult result(GetIsolate());
13305   LocalLookupRealNamedProperty(name, &result);
13306   if (result.IsFound()) {
13307     return GetProperty(receiver, &result, name, attributes);
13308   }
13309   return GetHeap()->undefined_value();
13310 }
13311
13312
13313 Handle<Object> JSObject::GetPropertyWithInterceptor(
13314     Handle<JSObject> object,
13315     Handle<Object> receiver,
13316     Handle<Name> name,
13317     PropertyAttributes* attributes) {
13318   Isolate* isolate = object->GetIsolate();
13319
13320   // TODO(rossberg): Support symbols in the API.
13321   if (name->IsSymbol()) return isolate->factory()->undefined_value();
13322
13323   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor(), isolate);
13324   Handle<String> name_string = Handle<String>::cast(name);
13325
13326   if (!interceptor->getter()->IsUndefined()) {
13327     v8::NamedPropertyGetterCallback getter =
13328         v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
13329     LOG(isolate,
13330         ApiNamedPropertyAccess("interceptor-named-get", *object, *name));
13331     PropertyCallbackArguments
13332         args(isolate, interceptor->data(), *receiver, *object);
13333     v8::Handle<v8::Value> result =
13334         args.Call(getter, v8::Utils::ToLocal(name_string));
13335     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
13336     if (!result.IsEmpty()) {
13337       *attributes = NONE;
13338       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13339       result_internal->VerifyApiCallResultType();
13340       // Rebox handle to escape this scope.
13341       return handle(*result_internal, isolate);
13342     }
13343   }
13344
13345   return GetPropertyPostInterceptor(object, receiver, name, attributes);
13346 }
13347
13348
13349 bool JSObject::HasRealNamedProperty(Handle<JSObject> object,
13350                                     Handle<Name> key) {
13351   Isolate* isolate = object->GetIsolate();
13352   SealHandleScope shs(isolate);
13353   // Check access rights if needed.
13354   if (object->IsAccessCheckNeeded()) {
13355     if (!isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_HAS)) {
13356       isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
13357       return false;
13358     }
13359   }
13360
13361   LookupResult result(isolate);
13362   object->LocalLookupRealNamedProperty(*key, &result);
13363   return result.IsFound() && !result.IsInterceptor();
13364 }
13365
13366
13367 bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) {
13368   Isolate* isolate = object->GetIsolate();
13369   HandleScope scope(isolate);
13370   // Check access rights if needed.
13371   if (object->IsAccessCheckNeeded()) {
13372     if (!isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_HAS)) {
13373       isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
13374       return false;
13375     }
13376   }
13377
13378   if (object->IsJSGlobalProxy()) {
13379     HandleScope scope(isolate);
13380     Handle<Object> proto(object->GetPrototype(), isolate);
13381     if (proto->IsNull()) return false;
13382     ASSERT(proto->IsJSGlobalObject());
13383     return HasRealElementProperty(Handle<JSObject>::cast(proto), index);
13384   }
13385
13386   return GetElementAttributeWithoutInterceptor(
13387              object, object, index, false) != ABSENT;
13388 }
13389
13390
13391 bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
13392                                             Handle<Name> key) {
13393   Isolate* isolate = object->GetIsolate();
13394   SealHandleScope shs(isolate);
13395   // Check access rights if needed.
13396   if (object->IsAccessCheckNeeded()) {
13397     if (!isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_HAS)) {
13398       isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
13399       return false;
13400     }
13401   }
13402
13403   LookupResult result(isolate);
13404   object->LocalLookupRealNamedProperty(*key, &result);
13405   return result.IsPropertyCallbacks();
13406 }
13407
13408
13409 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
13410   if (HasFastProperties()) {
13411     Map* map = this->map();
13412     if (filter == NONE) return map->NumberOfOwnDescriptors();
13413     if (filter & DONT_ENUM) {
13414       int result = map->EnumLength();
13415       if (result != kInvalidEnumCacheSentinel) return result;
13416     }
13417     return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
13418   }
13419   return property_dictionary()->NumberOfElementsFilterAttributes(filter);
13420 }
13421
13422
13423 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
13424   Object* temp = get(i);
13425   set(i, get(j));
13426   set(j, temp);
13427   if (this != numbers) {
13428     temp = numbers->get(i);
13429     numbers->set(i, Smi::cast(numbers->get(j)));
13430     numbers->set(j, Smi::cast(temp));
13431   }
13432 }
13433
13434
13435 static void InsertionSortPairs(FixedArray* content,
13436                                FixedArray* numbers,
13437                                int len) {
13438   for (int i = 1; i < len; i++) {
13439     int j = i;
13440     while (j > 0 &&
13441            (NumberToUint32(numbers->get(j - 1)) >
13442             NumberToUint32(numbers->get(j)))) {
13443       content->SwapPairs(numbers, j - 1, j);
13444       j--;
13445     }
13446   }
13447 }
13448
13449
13450 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
13451   // In-place heap sort.
13452   ASSERT(content->length() == numbers->length());
13453
13454   // Bottom-up max-heap construction.
13455   for (int i = 1; i < len; ++i) {
13456     int child_index = i;
13457     while (child_index > 0) {
13458       int parent_index = ((child_index + 1) >> 1) - 1;
13459       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13460       uint32_t child_value = NumberToUint32(numbers->get(child_index));
13461       if (parent_value < child_value) {
13462         content->SwapPairs(numbers, parent_index, child_index);
13463       } else {
13464         break;
13465       }
13466       child_index = parent_index;
13467     }
13468   }
13469
13470   // Extract elements and create sorted array.
13471   for (int i = len - 1; i > 0; --i) {
13472     // Put max element at the back of the array.
13473     content->SwapPairs(numbers, 0, i);
13474     // Sift down the new top element.
13475     int parent_index = 0;
13476     while (true) {
13477       int child_index = ((parent_index + 1) << 1) - 1;
13478       if (child_index >= i) break;
13479       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
13480       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
13481       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13482       if (child_index + 1 >= i || child1_value > child2_value) {
13483         if (parent_value > child1_value) break;
13484         content->SwapPairs(numbers, parent_index, child_index);
13485         parent_index = child_index;
13486       } else {
13487         if (parent_value > child2_value) break;
13488         content->SwapPairs(numbers, parent_index, child_index + 1);
13489         parent_index = child_index + 1;
13490       }
13491     }
13492   }
13493 }
13494
13495
13496 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
13497 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
13498   ASSERT(this->length() == numbers->length());
13499   // For small arrays, simply use insertion sort.
13500   if (len <= 10) {
13501     InsertionSortPairs(this, numbers, len);
13502     return;
13503   }
13504   // Check the range of indices.
13505   uint32_t min_index = NumberToUint32(numbers->get(0));
13506   uint32_t max_index = min_index;
13507   uint32_t i;
13508   for (i = 1; i < len; i++) {
13509     if (NumberToUint32(numbers->get(i)) < min_index) {
13510       min_index = NumberToUint32(numbers->get(i));
13511     } else if (NumberToUint32(numbers->get(i)) > max_index) {
13512       max_index = NumberToUint32(numbers->get(i));
13513     }
13514   }
13515   if (max_index - min_index + 1 == len) {
13516     // Indices form a contiguous range, unless there are duplicates.
13517     // Do an in-place linear time sort assuming distinct numbers, but
13518     // avoid hanging in case they are not.
13519     for (i = 0; i < len; i++) {
13520       uint32_t p;
13521       uint32_t j = 0;
13522       // While the current element at i is not at its correct position p,
13523       // swap the elements at these two positions.
13524       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
13525              j++ < len) {
13526         SwapPairs(numbers, i, p);
13527       }
13528     }
13529   } else {
13530     HeapSortPairs(this, numbers, len);
13531     return;
13532   }
13533 }
13534
13535
13536 // Fill in the names of local properties into the supplied storage. The main
13537 // purpose of this function is to provide reflection information for the object
13538 // mirrors.
13539 void JSObject::GetLocalPropertyNames(
13540     FixedArray* storage, int index, PropertyAttributes filter) {
13541   ASSERT(storage->length() >= (NumberOfLocalProperties(filter) - index));
13542   if (HasFastProperties()) {
13543     int real_size = map()->NumberOfOwnDescriptors();
13544     DescriptorArray* descs = map()->instance_descriptors();
13545     for (int i = 0; i < real_size; i++) {
13546       if ((descs->GetDetails(i).attributes() & filter) == 0 &&
13547           !FilterKey(descs->GetKey(i), filter)) {
13548         storage->set(index++, descs->GetKey(i));
13549       }
13550     }
13551   } else {
13552     property_dictionary()->CopyKeysTo(storage,
13553                                       index,
13554                                       filter,
13555                                       NameDictionary::UNSORTED);
13556   }
13557 }
13558
13559
13560 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
13561   return GetLocalElementKeys(NULL, filter);
13562 }
13563
13564
13565 int JSObject::NumberOfEnumElements() {
13566   // Fast case for objects with no elements.
13567   if (!IsJSValue() && HasFastObjectElements()) {
13568     uint32_t length = IsJSArray() ?
13569         static_cast<uint32_t>(
13570             Smi::cast(JSArray::cast(this)->length())->value()) :
13571         static_cast<uint32_t>(FixedArray::cast(elements())->length());
13572     if (length == 0) return 0;
13573   }
13574   // Compute the number of enumerable elements.
13575   return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
13576 }
13577
13578
13579 int JSObject::GetLocalElementKeys(FixedArray* storage,
13580                                   PropertyAttributes filter) {
13581   int counter = 0;
13582   switch (GetElementsKind()) {
13583     case FAST_SMI_ELEMENTS:
13584     case FAST_ELEMENTS:
13585     case FAST_HOLEY_SMI_ELEMENTS:
13586     case FAST_HOLEY_ELEMENTS: {
13587       int length = IsJSArray() ?
13588           Smi::cast(JSArray::cast(this)->length())->value() :
13589           FixedArray::cast(elements())->length();
13590       for (int i = 0; i < length; i++) {
13591         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
13592           if (storage != NULL) {
13593             storage->set(counter, Smi::FromInt(i));
13594           }
13595           counter++;
13596         }
13597       }
13598       ASSERT(!storage || storage->length() >= counter);
13599       break;
13600     }
13601     case FAST_DOUBLE_ELEMENTS:
13602     case FAST_HOLEY_DOUBLE_ELEMENTS: {
13603       int length = IsJSArray() ?
13604           Smi::cast(JSArray::cast(this)->length())->value() :
13605           FixedDoubleArray::cast(elements())->length();
13606       for (int i = 0; i < length; i++) {
13607         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
13608           if (storage != NULL) {
13609             storage->set(counter, Smi::FromInt(i));
13610           }
13611           counter++;
13612         }
13613       }
13614       ASSERT(!storage || storage->length() >= counter);
13615       break;
13616     }
13617
13618 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
13619     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
13620     case TYPE##_ELEMENTS:                                                    \
13621
13622     TYPED_ARRAYS(TYPED_ARRAY_CASE)
13623 #undef TYPED_ARRAY_CASE
13624     {
13625       int length = FixedArrayBase::cast(elements())->length();
13626       while (counter < length) {
13627         if (storage != NULL) {
13628           storage->set(counter, Smi::FromInt(counter));
13629         }
13630         counter++;
13631       }
13632       ASSERT(!storage || storage->length() >= counter);
13633       break;
13634     }
13635
13636     case DICTIONARY_ELEMENTS: {
13637       if (storage != NULL) {
13638         element_dictionary()->CopyKeysTo(storage,
13639                                          filter,
13640                                          SeededNumberDictionary::SORTED);
13641       }
13642       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
13643       break;
13644     }
13645     case SLOPPY_ARGUMENTS_ELEMENTS: {
13646       FixedArray* parameter_map = FixedArray::cast(elements());
13647       int mapped_length = parameter_map->length() - 2;
13648       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
13649       if (arguments->IsDictionary()) {
13650         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
13651         // will insert in storage starting at index 0.
13652         SeededNumberDictionary* dictionary =
13653             SeededNumberDictionary::cast(arguments);
13654         if (storage != NULL) {
13655           dictionary->CopyKeysTo(
13656               storage, filter, SeededNumberDictionary::UNSORTED);
13657         }
13658         counter += dictionary->NumberOfElementsFilterAttributes(filter);
13659         for (int i = 0; i < mapped_length; ++i) {
13660           if (!parameter_map->get(i + 2)->IsTheHole()) {
13661             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13662             ++counter;
13663           }
13664         }
13665         if (storage != NULL) storage->SortPairs(storage, counter);
13666
13667       } else {
13668         int backing_length = arguments->length();
13669         int i = 0;
13670         for (; i < mapped_length; ++i) {
13671           if (!parameter_map->get(i + 2)->IsTheHole()) {
13672             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13673             ++counter;
13674           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
13675             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13676             ++counter;
13677           }
13678         }
13679         for (; i < backing_length; ++i) {
13680           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13681           ++counter;
13682         }
13683       }
13684       break;
13685     }
13686   }
13687
13688   if (this->IsJSValue()) {
13689     Object* val = JSValue::cast(this)->value();
13690     if (val->IsString()) {
13691       String* str = String::cast(val);
13692       if (storage) {
13693         for (int i = 0; i < str->length(); i++) {
13694           storage->set(counter + i, Smi::FromInt(i));
13695         }
13696       }
13697       counter += str->length();
13698     }
13699   }
13700   ASSERT(!storage || storage->length() == counter);
13701   return counter;
13702 }
13703
13704
13705 int JSObject::GetEnumElementKeys(FixedArray* storage) {
13706   return GetLocalElementKeys(storage,
13707                              static_cast<PropertyAttributes>(DONT_ENUM));
13708 }
13709
13710
13711 // StringKey simply carries a string object as key.
13712 class StringKey : public HashTableKey {
13713  public:
13714   explicit StringKey(String* string) :
13715       string_(string),
13716       hash_(HashForObject(string)) { }
13717
13718   bool IsMatch(Object* string) {
13719     // We know that all entries in a hash table had their hash keys created.
13720     // Use that knowledge to have fast failure.
13721     if (hash_ != HashForObject(string)) {
13722       return false;
13723     }
13724     return string_->Equals(String::cast(string));
13725   }
13726
13727   uint32_t Hash() { return hash_; }
13728
13729   uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
13730
13731   Object* AsObject(Heap* heap) { return string_; }
13732
13733   String* string_;
13734   uint32_t hash_;
13735 };
13736
13737
13738 // StringSharedKeys are used as keys in the eval cache.
13739 class StringSharedKey : public HashTableKey {
13740  public:
13741   StringSharedKey(String* source,
13742                   SharedFunctionInfo* shared,
13743                   StrictMode strict_mode,
13744                   int scope_position)
13745       : source_(source),
13746         shared_(shared),
13747         strict_mode_(strict_mode),
13748         scope_position_(scope_position) { }
13749
13750   bool IsMatch(Object* other) {
13751     if (!other->IsFixedArray()) return false;
13752     FixedArray* other_array = FixedArray::cast(other);
13753     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13754     if (shared != shared_) return false;
13755     int strict_unchecked = Smi::cast(other_array->get(2))->value();
13756     ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
13757     StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
13758     if (strict_mode != strict_mode_) return false;
13759     int scope_position = Smi::cast(other_array->get(3))->value();
13760     if (scope_position != scope_position_) return false;
13761     String* source = String::cast(other_array->get(1));
13762     return source->Equals(source_);
13763   }
13764
13765   static uint32_t StringSharedHashHelper(String* source,
13766                                          SharedFunctionInfo* shared,
13767                                          StrictMode strict_mode,
13768                                          int scope_position) {
13769     uint32_t hash = source->Hash();
13770     if (shared->HasSourceCode()) {
13771       // Instead of using the SharedFunctionInfo pointer in the hash
13772       // code computation, we use a combination of the hash of the
13773       // script source code and the start position of the calling scope.
13774       // We do this to ensure that the cache entries can survive garbage
13775       // collection.
13776       Script* script = Script::cast(shared->script());
13777       hash ^= String::cast(script->source())->Hash();
13778       if (strict_mode == STRICT) hash ^= 0x8000;
13779       hash += scope_position;
13780     }
13781     return hash;
13782   }
13783
13784   uint32_t Hash() {
13785     return StringSharedHashHelper(
13786         source_, shared_, strict_mode_, scope_position_);
13787   }
13788
13789   uint32_t HashForObject(Object* obj) {
13790     FixedArray* other_array = FixedArray::cast(obj);
13791     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13792     String* source = String::cast(other_array->get(1));
13793     int strict_unchecked = Smi::cast(other_array->get(2))->value();
13794     ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
13795     StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
13796     int scope_position = Smi::cast(other_array->get(3))->value();
13797     return StringSharedHashHelper(
13798         source, shared, strict_mode, scope_position);
13799   }
13800
13801   MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) {
13802     Object* obj;
13803     { MaybeObject* maybe_obj = heap->AllocateFixedArray(4);
13804       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
13805     }
13806     FixedArray* other_array = FixedArray::cast(obj);
13807     other_array->set(0, shared_);
13808     other_array->set(1, source_);
13809     other_array->set(2, Smi::FromInt(strict_mode_));
13810     other_array->set(3, Smi::FromInt(scope_position_));
13811     return other_array;
13812   }
13813
13814  private:
13815   String* source_;
13816   SharedFunctionInfo* shared_;
13817   StrictMode strict_mode_;
13818   int scope_position_;
13819 };
13820
13821
13822 // RegExpKey carries the source and flags of a regular expression as key.
13823 class RegExpKey : public HashTableKey {
13824  public:
13825   RegExpKey(String* string, JSRegExp::Flags flags)
13826       : string_(string),
13827         flags_(Smi::FromInt(flags.value())) { }
13828
13829   // Rather than storing the key in the hash table, a pointer to the
13830   // stored value is stored where the key should be.  IsMatch then
13831   // compares the search key to the found object, rather than comparing
13832   // a key to a key.
13833   bool IsMatch(Object* obj) {
13834     FixedArray* val = FixedArray::cast(obj);
13835     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
13836         && (flags_ == val->get(JSRegExp::kFlagsIndex));
13837   }
13838
13839   uint32_t Hash() { return RegExpHash(string_, flags_); }
13840
13841   Object* AsObject(Heap* heap) {
13842     // Plain hash maps, which is where regexp keys are used, don't
13843     // use this function.
13844     UNREACHABLE();
13845     return NULL;
13846   }
13847
13848   uint32_t HashForObject(Object* obj) {
13849     FixedArray* val = FixedArray::cast(obj);
13850     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
13851                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
13852   }
13853
13854   static uint32_t RegExpHash(String* string, Smi* flags) {
13855     return string->Hash() + flags->value();
13856   }
13857
13858   String* string_;
13859   Smi* flags_;
13860 };
13861
13862
13863 MaybeObject* OneByteStringKey::AsObject(Heap* heap) {
13864   if (hash_field_ == 0) Hash();
13865   return heap->AllocateOneByteInternalizedString(string_, hash_field_);
13866 }
13867
13868
13869 MaybeObject* TwoByteStringKey::AsObject(Heap* heap) {
13870   if (hash_field_ == 0) Hash();
13871   return heap->AllocateTwoByteInternalizedString(string_, hash_field_);
13872 }
13873
13874
13875 template<>
13876 const uint8_t* SubStringKey<uint8_t>::GetChars() {
13877   return string_->IsSeqOneByteString()
13878       ? SeqOneByteString::cast(*string_)->GetChars()
13879       : ExternalAsciiString::cast(*string_)->GetChars();
13880 }
13881
13882
13883 template<>
13884 const uint16_t* SubStringKey<uint16_t>::GetChars() {
13885   return string_->IsSeqTwoByteString()
13886       ? SeqTwoByteString::cast(*string_)->GetChars()
13887       : ExternalTwoByteString::cast(*string_)->GetChars();
13888 }
13889
13890
13891 template<>
13892 MaybeObject* SubStringKey<uint8_t>::AsObject(Heap* heap) {
13893   if (hash_field_ == 0) Hash();
13894   Vector<const uint8_t> chars(GetChars() + from_, length_);
13895   return heap->AllocateOneByteInternalizedString(chars, hash_field_);
13896 }
13897
13898
13899 template<>
13900 MaybeObject* SubStringKey<uint16_t>::AsObject(
13901     Heap* heap) {
13902   if (hash_field_ == 0) Hash();
13903   Vector<const uint16_t> chars(GetChars() + from_, length_);
13904   return heap->AllocateTwoByteInternalizedString(chars, hash_field_);
13905 }
13906
13907
13908 template<>
13909 bool SubStringKey<uint8_t>::IsMatch(Object* string) {
13910   Vector<const uint8_t> chars(GetChars() + from_, length_);
13911   return String::cast(string)->IsOneByteEqualTo(chars);
13912 }
13913
13914
13915 template<>
13916 bool SubStringKey<uint16_t>::IsMatch(Object* string) {
13917   Vector<const uint16_t> chars(GetChars() + from_, length_);
13918   return String::cast(string)->IsTwoByteEqualTo(chars);
13919 }
13920
13921
13922 template class SubStringKey<uint8_t>;
13923 template class SubStringKey<uint16_t>;
13924
13925
13926 // InternalizedStringKey carries a string/internalized-string object as key.
13927 class InternalizedStringKey : public HashTableKey {
13928  public:
13929   explicit InternalizedStringKey(String* string)
13930       : string_(string) { }
13931
13932   bool IsMatch(Object* string) {
13933     return String::cast(string)->Equals(string_);
13934   }
13935
13936   uint32_t Hash() { return string_->Hash(); }
13937
13938   uint32_t HashForObject(Object* other) {
13939     return String::cast(other)->Hash();
13940   }
13941
13942   MaybeObject* AsObject(Heap* heap) {
13943     // Attempt to flatten the string, so that internalized strings will most
13944     // often be flat strings.
13945     string_ = string_->TryFlattenGetString();
13946     // Internalize the string if possible.
13947     Map* map = heap->InternalizedStringMapForString(string_);
13948     if (map != NULL) {
13949       string_->set_map_no_write_barrier(map);
13950       ASSERT(string_->IsInternalizedString());
13951       return string_;
13952     }
13953     // Otherwise allocate a new internalized string.
13954     return heap->AllocateInternalizedStringImpl(
13955         string_, string_->length(), string_->hash_field());
13956   }
13957
13958   static uint32_t StringHash(Object* obj) {
13959     return String::cast(obj)->Hash();
13960   }
13961
13962   String* string_;
13963 };
13964
13965
13966 template<typename Shape, typename Key>
13967 void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
13968   IteratePointers(v, 0, kElementsStartOffset);
13969 }
13970
13971
13972 template<typename Shape, typename Key>
13973 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
13974   IteratePointers(v,
13975                   kElementsStartOffset,
13976                   kHeaderSize + length() * kPointerSize);
13977 }
13978
13979
13980 template<typename Shape, typename Key>
13981 MaybeObject* HashTable<Shape, Key>::Allocate(Heap* heap,
13982                                              int at_least_space_for,
13983                                              MinimumCapacity capacity_option,
13984                                              PretenureFlag pretenure) {
13985   ASSERT(!capacity_option || IS_POWER_OF_TWO(at_least_space_for));
13986   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
13987                      ? at_least_space_for
13988                      : ComputeCapacity(at_least_space_for);
13989   if (capacity > HashTable::kMaxCapacity) {
13990     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
13991   }
13992
13993   Object* obj;
13994   { MaybeObject* maybe_obj =
13995         heap-> AllocateHashTable(EntryToIndex(capacity), pretenure);
13996     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
13997   }
13998   HashTable::cast(obj)->SetNumberOfElements(0);
13999   HashTable::cast(obj)->SetNumberOfDeletedElements(0);
14000   HashTable::cast(obj)->SetCapacity(capacity);
14001   return obj;
14002 }
14003
14004
14005 // Find entry for key otherwise return kNotFound.
14006 int NameDictionary::FindEntry(Name* key) {
14007   if (!key->IsUniqueName()) {
14008     return HashTable<NameDictionaryShape, Name*>::FindEntry(key);
14009   }
14010
14011   // Optimized for unique names. Knowledge of the key type allows:
14012   // 1. Move the check if the key is unique out of the loop.
14013   // 2. Avoid comparing hash codes in unique-to-unique comparison.
14014   // 3. Detect a case when a dictionary key is not unique but the key is.
14015   //    In case of positive result the dictionary key may be replaced by the
14016   //    internalized string with minimal performance penalty. It gives a chance
14017   //    to perform further lookups in code stubs (and significant performance
14018   //    boost a certain style of code).
14019
14020   // EnsureCapacity will guarantee the hash table is never full.
14021   uint32_t capacity = Capacity();
14022   uint32_t entry = FirstProbe(key->Hash(), capacity);
14023   uint32_t count = 1;
14024
14025   while (true) {
14026     int index = EntryToIndex(entry);
14027     Object* element = get(index);
14028     if (element->IsUndefined()) break;  // Empty entry.
14029     if (key == element) return entry;
14030     if (!element->IsUniqueName() &&
14031         !element->IsTheHole() &&
14032         Name::cast(element)->Equals(key)) {
14033       // Replace a key that is a non-internalized string by the equivalent
14034       // internalized string for faster further lookups.
14035       set(index, key);
14036       return entry;
14037     }
14038     ASSERT(element->IsTheHole() || !Name::cast(element)->Equals(key));
14039     entry = NextProbe(entry, count++, capacity);
14040   }
14041   return kNotFound;
14042 }
14043
14044
14045 template<typename Shape, typename Key>
14046 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
14047   ASSERT(NumberOfElements() < new_table->Capacity());
14048
14049   DisallowHeapAllocation no_gc;
14050   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
14051
14052   // Copy prefix to new array.
14053   for (int i = kPrefixStartIndex;
14054        i < kPrefixStartIndex + Shape::kPrefixSize;
14055        i++) {
14056     new_table->set(i, get(i), mode);
14057   }
14058
14059   // Rehash the elements.
14060   int capacity = Capacity();
14061   for (int i = 0; i < capacity; i++) {
14062     uint32_t from_index = EntryToIndex(i);
14063     Object* k = get(from_index);
14064     if (IsKey(k)) {
14065       uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k);
14066       uint32_t insertion_index =
14067           EntryToIndex(new_table->FindInsertionEntry(hash));
14068       for (int j = 0; j < Shape::kEntrySize; j++) {
14069         new_table->set(insertion_index + j, get(from_index + j), mode);
14070       }
14071     }
14072   }
14073   new_table->SetNumberOfElements(NumberOfElements());
14074   new_table->SetNumberOfDeletedElements(0);
14075   return new_table;
14076 }
14077
14078
14079 template<typename Shape, typename Key>
14080 uint32_t HashTable<Shape, Key>::EntryForProbe(Key key,
14081                                               Object* k,
14082                                               int probe,
14083                                               uint32_t expected) {
14084   uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k);
14085   uint32_t capacity = Capacity();
14086   uint32_t entry = FirstProbe(hash, capacity);
14087   for (int i = 1; i < probe; i++) {
14088     if (entry == expected) return expected;
14089     entry = NextProbe(entry, i, capacity);
14090   }
14091   return entry;
14092 }
14093
14094
14095 template<typename Shape, typename Key>
14096 void HashTable<Shape, Key>::Swap(uint32_t entry1,
14097                                  uint32_t entry2,
14098                                  WriteBarrierMode mode) {
14099   int index1 = EntryToIndex(entry1);
14100   int index2 = EntryToIndex(entry2);
14101   Object* temp[Shape::kEntrySize];
14102   for (int j = 0; j < Shape::kEntrySize; j++) {
14103     temp[j] = get(index1 + j);
14104   }
14105   for (int j = 0; j < Shape::kEntrySize; j++) {
14106     set(index1 + j, get(index2 + j), mode);
14107   }
14108   for (int j = 0; j < Shape::kEntrySize; j++) {
14109     set(index2 + j, temp[j], mode);
14110   }
14111 }
14112
14113
14114 template<typename Shape, typename Key>
14115 void HashTable<Shape, Key>::Rehash(Key key) {
14116   DisallowHeapAllocation no_gc;
14117   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
14118   uint32_t capacity = Capacity();
14119   bool done = false;
14120   for (int probe = 1; !done; probe++) {
14121     // All elements at entries given by one of the first _probe_ probes
14122     // are placed correctly. Other elements might need to be moved.
14123     done = true;
14124     for (uint32_t current = 0; current < capacity; current++) {
14125       Object* current_key = get(EntryToIndex(current));
14126       if (IsKey(current_key)) {
14127         uint32_t target = EntryForProbe(key, current_key, probe, current);
14128         if (current == target) continue;
14129         Object* target_key = get(EntryToIndex(target));
14130         if (!IsKey(target_key) ||
14131             EntryForProbe(key, target_key, probe, target) != target) {
14132           // Put the current element into the correct position.
14133           Swap(current, target, mode);
14134           // The other element will be processed on the next iteration.
14135           current--;
14136         } else {
14137           // The place for the current element is occupied. Leave the element
14138           // for the next probe.
14139           done = false;
14140         }
14141       }
14142     }
14143   }
14144 }
14145
14146
14147 template<typename Shape, typename Key>
14148 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n,
14149                                                    Key key,
14150                                                    PretenureFlag pretenure) {
14151   int capacity = Capacity();
14152   int nof = NumberOfElements() + n;
14153   int nod = NumberOfDeletedElements();
14154   // Return if:
14155   //   50% is still free after adding n elements and
14156   //   at most 50% of the free elements are deleted elements.
14157   if (nod <= (capacity - nof) >> 1) {
14158     int needed_free = nof >> 1;
14159     if (nof + needed_free <= capacity) return this;
14160   }
14161
14162   const int kMinCapacityForPretenure = 256;
14163   bool should_pretenure = pretenure == TENURED ||
14164       ((capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this));
14165   Object* obj;
14166   { MaybeObject* maybe_obj =
14167         Allocate(GetHeap(),
14168                  nof * 2,
14169                  USE_DEFAULT_MINIMUM_CAPACITY,
14170                  should_pretenure ? TENURED : NOT_TENURED);
14171     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
14172   }
14173
14174   return Rehash(HashTable::cast(obj), key);
14175 }
14176
14177
14178 template<typename Shape, typename Key>
14179 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
14180   int capacity = Capacity();
14181   int nof = NumberOfElements();
14182
14183   // Shrink to fit the number of elements if only a quarter of the
14184   // capacity is filled with elements.
14185   if (nof > (capacity >> 2)) return this;
14186   // Allocate a new dictionary with room for at least the current
14187   // number of elements. The allocation method will make sure that
14188   // there is extra room in the dictionary for additions. Don't go
14189   // lower than room for 16 elements.
14190   int at_least_room_for = nof;
14191   if (at_least_room_for < 16) return this;
14192
14193   const int kMinCapacityForPretenure = 256;
14194   bool pretenure =
14195       (at_least_room_for > kMinCapacityForPretenure) &&
14196       !GetHeap()->InNewSpace(this);
14197   Object* obj;
14198   { MaybeObject* maybe_obj =
14199         Allocate(GetHeap(),
14200                  at_least_room_for,
14201                  USE_DEFAULT_MINIMUM_CAPACITY,
14202                  pretenure ? TENURED : NOT_TENURED);
14203     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
14204   }
14205
14206   return Rehash(HashTable::cast(obj), key);
14207 }
14208
14209
14210 template<typename Shape, typename Key>
14211 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
14212   uint32_t capacity = Capacity();
14213   uint32_t entry = FirstProbe(hash, capacity);
14214   uint32_t count = 1;
14215   // EnsureCapacity will guarantee the hash table is never full.
14216   while (true) {
14217     Object* element = KeyAt(entry);
14218     if (element->IsUndefined() || element->IsTheHole()) break;
14219     entry = NextProbe(entry, count++, capacity);
14220   }
14221   return entry;
14222 }
14223
14224
14225 // Force instantiation of template instances class.
14226 // Please note this list is compiler dependent.
14227
14228 template class HashTable<StringTableShape, HashTableKey*>;
14229
14230 template class HashTable<CompilationCacheShape, HashTableKey*>;
14231
14232 template class HashTable<MapCacheShape, HashTableKey*>;
14233
14234 template class HashTable<ObjectHashTableShape<1>, Object*>;
14235
14236 template class HashTable<ObjectHashTableShape<2>, Object*>;
14237
14238 template class HashTable<WeakHashTableShape<2>, Object*>;
14239
14240 template class Dictionary<NameDictionaryShape, Name*>;
14241
14242 template class Dictionary<SeededNumberDictionaryShape, uint32_t>;
14243
14244 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>;
14245
14246 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
14247     Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure);
14248
14249 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
14250     Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure);
14251
14252 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::
14253     Allocate(Heap* heap, int n, PretenureFlag pretenure);
14254
14255 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut(
14256     uint32_t, Object*);
14257
14258 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
14259     AtPut(uint32_t, Object*);
14260
14261 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
14262     SlowReverseLookup(Object* value);
14263
14264 template Object* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
14265     SlowReverseLookup(Object* value);
14266
14267 template Object* Dictionary<NameDictionaryShape, Name*>::SlowReverseLookup(
14268     Object*);
14269
14270 template void Dictionary<SeededNumberDictionaryShape, uint32_t>::CopyKeysTo(
14271     FixedArray*,
14272     PropertyAttributes,
14273     Dictionary<SeededNumberDictionaryShape, uint32_t>::SortMode);
14274
14275 template Object* Dictionary<NameDictionaryShape, Name*>::DeleteProperty(
14276     int, JSObject::DeleteMode);
14277
14278 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
14279     DeleteProperty(int, JSObject::DeleteMode);
14280
14281 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Shrink(Name* n);
14282
14283 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink(
14284     uint32_t);
14285
14286 template void Dictionary<NameDictionaryShape, Name*>::CopyKeysTo(
14287     FixedArray*,
14288     int,
14289     PropertyAttributes,
14290     Dictionary<NameDictionaryShape, Name*>::SortMode);
14291
14292 template int
14293 Dictionary<NameDictionaryShape, Name*>::NumberOfElementsFilterAttributes(
14294     PropertyAttributes);
14295
14296 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Add(
14297     Name*, Object*, PropertyDetails);
14298
14299 template MaybeObject*
14300 Dictionary<NameDictionaryShape, Name*>::GenerateNewEnumerationIndices();
14301
14302 template int
14303 Dictionary<SeededNumberDictionaryShape, uint32_t>::
14304     NumberOfElementsFilterAttributes(PropertyAttributes);
14305
14306 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Add(
14307     uint32_t, Object*, PropertyDetails);
14308
14309 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::Add(
14310     uint32_t, Object*, PropertyDetails);
14311
14312 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
14313     EnsureCapacity(int, uint32_t);
14314
14315 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
14316     EnsureCapacity(int, uint32_t);
14317
14318 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::
14319     EnsureCapacity(int, Name*);
14320
14321 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
14322     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
14323
14324 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
14325     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
14326
14327 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::AddEntry(
14328     Name*, Object*, PropertyDetails, uint32_t);
14329
14330 template
14331 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements();
14332
14333 template
14334 int Dictionary<NameDictionaryShape, Name*>::NumberOfEnumElements();
14335
14336 template
14337 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
14338
14339
14340 Handle<Object> JSObject::PrepareSlowElementsForSort(
14341     Handle<JSObject> object, uint32_t limit) {
14342   CALL_HEAP_FUNCTION(object->GetIsolate(),
14343                      object->PrepareSlowElementsForSort(limit),
14344                      Object);
14345 }
14346
14347
14348 // Collates undefined and unexisting elements below limit from position
14349 // zero of the elements. The object stays in Dictionary mode.
14350 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
14351   ASSERT(HasDictionaryElements());
14352   // Must stay in dictionary mode, either because of requires_slow_elements,
14353   // or because we are not going to sort (and therefore compact) all of the
14354   // elements.
14355   SeededNumberDictionary* dict = element_dictionary();
14356   HeapNumber* result_double = NULL;
14357   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
14358     // Allocate space for result before we start mutating the object.
14359     Object* new_double;
14360     { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0);
14361       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
14362     }
14363     result_double = HeapNumber::cast(new_double);
14364   }
14365
14366   Object* obj;
14367   { MaybeObject* maybe_obj =
14368         SeededNumberDictionary::Allocate(GetHeap(), dict->NumberOfElements());
14369     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
14370   }
14371   SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj);
14372
14373   DisallowHeapAllocation no_alloc;
14374
14375   uint32_t pos = 0;
14376   uint32_t undefs = 0;
14377   int capacity = dict->Capacity();
14378   for (int i = 0; i < capacity; i++) {
14379     Object* k = dict->KeyAt(i);
14380     if (dict->IsKey(k)) {
14381       ASSERT(k->IsNumber());
14382       ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
14383       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
14384       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
14385       Object* value = dict->ValueAt(i);
14386       PropertyDetails details = dict->DetailsAt(i);
14387       if (details.type() == CALLBACKS || details.IsReadOnly()) {
14388         // Bail out and do the sorting of undefineds and array holes in JS.
14389         // Also bail out if the element is not supposed to be moved.
14390         return Smi::FromInt(-1);
14391       }
14392       uint32_t key = NumberToUint32(k);
14393       // In the following we assert that adding the entry to the new dictionary
14394       // does not cause GC.  This is the case because we made sure to allocate
14395       // the dictionary big enough above, so it need not grow.
14396       if (key < limit) {
14397         if (value->IsUndefined()) {
14398           undefs++;
14399         } else {
14400           if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14401             // Adding an entry with the key beyond smi-range requires
14402             // allocation. Bailout.
14403             return Smi::FromInt(-1);
14404           }
14405           new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
14406           pos++;
14407         }
14408       } else {
14409         if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
14410           // Adding an entry with the key beyond smi-range requires
14411           // allocation. Bailout.
14412           return Smi::FromInt(-1);
14413         }
14414         new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
14415       }
14416     }
14417   }
14418
14419   uint32_t result = pos;
14420   PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0);
14421   Heap* heap = GetHeap();
14422   while (undefs > 0) {
14423     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14424       // Adding an entry with the key beyond smi-range requires
14425       // allocation. Bailout.
14426       return Smi::FromInt(-1);
14427     }
14428     new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
14429         ToObjectUnchecked();
14430     pos++;
14431     undefs--;
14432   }
14433
14434   set_elements(new_dict);
14435
14436   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
14437     return Smi::FromInt(static_cast<int>(result));
14438   }
14439
14440   ASSERT_NE(NULL, result_double);
14441   result_double->set_value(static_cast<double>(result));
14442   return result_double;
14443 }
14444
14445
14446 // Collects all defined (non-hole) and non-undefined (array) elements at
14447 // the start of the elements array.
14448 // If the object is in dictionary mode, it is converted to fast elements
14449 // mode.
14450 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
14451                                                 uint32_t limit) {
14452   Isolate* isolate = object->GetIsolate();
14453   if (object->HasSloppyArgumentsElements() ||
14454       object->map()->is_observed()) {
14455     return handle(Smi::FromInt(-1), isolate);
14456   }
14457
14458   if (object->HasDictionaryElements()) {
14459     // Convert to fast elements containing only the existing properties.
14460     // Ordering is irrelevant, since we are going to sort anyway.
14461     Handle<SeededNumberDictionary> dict(object->element_dictionary());
14462     if (object->IsJSArray() || dict->requires_slow_elements() ||
14463         dict->max_number_key() >= limit) {
14464       return JSObject::PrepareSlowElementsForSort(object, limit);
14465     }
14466     // Convert to fast elements.
14467
14468     Handle<Map> new_map =
14469         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
14470
14471     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
14472         NOT_TENURED: TENURED;
14473     Handle<FixedArray> fast_elements =
14474         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
14475     dict->CopyValuesTo(*fast_elements);
14476     object->ValidateElements();
14477
14478     object->set_map_and_elements(*new_map, *fast_elements);
14479   } else if (object->HasExternalArrayElements() ||
14480              object->HasFixedTypedArrayElements()) {
14481     // Typed arrays cannot have holes or undefined elements.
14482     return handle(Smi::FromInt(
14483         FixedArrayBase::cast(object->elements())->length()), isolate);
14484   } else if (!object->HasFastDoubleElements()) {
14485     EnsureWritableFastElements(object);
14486   }
14487   ASSERT(object->HasFastSmiOrObjectElements() ||
14488          object->HasFastDoubleElements());
14489
14490   // Collect holes at the end, undefined before that and the rest at the
14491   // start, and return the number of non-hole, non-undefined values.
14492
14493   Handle<FixedArrayBase> elements_base(object->elements());
14494   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
14495   if (limit > elements_length) {
14496     limit = elements_length ;
14497   }
14498   if (limit == 0) {
14499     return handle(Smi::FromInt(0), isolate);
14500   }
14501
14502   uint32_t result = 0;
14503   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
14504     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
14505     // Split elements into defined and the_hole, in that order.
14506     unsigned int holes = limit;
14507     // Assume most arrays contain no holes and undefined values, so minimize the
14508     // number of stores of non-undefined, non-the-hole values.
14509     for (unsigned int i = 0; i < holes; i++) {
14510       if (elements->is_the_hole(i)) {
14511         holes--;
14512       } else {
14513         continue;
14514       }
14515       // Position i needs to be filled.
14516       while (holes > i) {
14517         if (elements->is_the_hole(holes)) {
14518           holes--;
14519         } else {
14520           elements->set(i, elements->get_scalar(holes));
14521           break;
14522         }
14523       }
14524     }
14525     result = holes;
14526     while (holes < limit) {
14527       elements->set_the_hole(holes);
14528       holes++;
14529     }
14530   } else {
14531     FixedArray* elements = FixedArray::cast(*elements_base);
14532     DisallowHeapAllocation no_gc;
14533
14534     // Split elements into defined, undefined and the_hole, in that order.  Only
14535     // count locations for undefined and the hole, and fill them afterwards.
14536     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
14537     unsigned int undefs = limit;
14538     unsigned int holes = limit;
14539     // Assume most arrays contain no holes and undefined values, so minimize the
14540     // number of stores of non-undefined, non-the-hole values.
14541     for (unsigned int i = 0; i < undefs; i++) {
14542       Object* current = elements->get(i);
14543       if (current->IsTheHole()) {
14544         holes--;
14545         undefs--;
14546       } else if (current->IsUndefined()) {
14547         undefs--;
14548       } else {
14549         continue;
14550       }
14551       // Position i needs to be filled.
14552       while (undefs > i) {
14553         current = elements->get(undefs);
14554         if (current->IsTheHole()) {
14555           holes--;
14556           undefs--;
14557         } else if (current->IsUndefined()) {
14558           undefs--;
14559         } else {
14560           elements->set(i, current, write_barrier);
14561           break;
14562         }
14563       }
14564     }
14565     result = undefs;
14566     while (undefs < holes) {
14567       elements->set_undefined(undefs);
14568       undefs++;
14569     }
14570     while (holes < limit) {
14571       elements->set_the_hole(holes);
14572       holes++;
14573     }
14574   }
14575
14576   return isolate->factory()->NewNumberFromUint(result);
14577 }
14578
14579
14580 ExternalArrayType JSTypedArray::type() {
14581   switch (elements()->map()->instance_type()) {
14582 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
14583     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
14584     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
14585       return kExternal##Type##Array;
14586
14587     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
14588 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
14589
14590     default:
14591       UNREACHABLE();
14592       return static_cast<ExternalArrayType>(-1);
14593   }
14594 }
14595
14596
14597 size_t JSTypedArray::element_size() {
14598   switch (elements()->map()->instance_type()) {
14599 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)          \
14600     case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
14601       return size;
14602
14603     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
14604 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
14605
14606     default:
14607       UNREACHABLE();
14608       return 0;
14609   }
14610 }
14611
14612
14613 Object* ExternalUint8ClampedArray::SetValue(uint32_t index, Object* value) {
14614   uint8_t clamped_value = 0;
14615   if (index < static_cast<uint32_t>(length())) {
14616     if (value->IsSmi()) {
14617       int int_value = Smi::cast(value)->value();
14618       if (int_value < 0) {
14619         clamped_value = 0;
14620       } else if (int_value > 255) {
14621         clamped_value = 255;
14622       } else {
14623         clamped_value = static_cast<uint8_t>(int_value);
14624       }
14625     } else if (value->IsHeapNumber()) {
14626       double double_value = HeapNumber::cast(value)->value();
14627       if (!(double_value > 0)) {
14628         // NaN and less than zero clamp to zero.
14629         clamped_value = 0;
14630       } else if (double_value > 255) {
14631         // Greater than 255 clamp to 255.
14632         clamped_value = 255;
14633       } else {
14634         // Other doubles are rounded to the nearest integer.
14635         clamped_value = static_cast<uint8_t>(lrint(double_value));
14636       }
14637     } else {
14638       // Clamp undefined to zero (default). All other types have been
14639       // converted to a number type further up in the call chain.
14640       ASSERT(value->IsUndefined());
14641     }
14642     set(index, clamped_value);
14643   }
14644   return Smi::FromInt(clamped_value);
14645 }
14646
14647
14648 Handle<Object> ExternalUint8ClampedArray::SetValue(
14649     Handle<ExternalUint8ClampedArray> array,
14650     uint32_t index,
14651     Handle<Object> value) {
14652   return Handle<Object>(array->SetValue(index, *value), array->GetIsolate());
14653 }
14654
14655
14656 template<typename ExternalArrayClass, typename ValueType>
14657 static MaybeObject* ExternalArrayIntSetter(Heap* heap,
14658                                            ExternalArrayClass* receiver,
14659                                            uint32_t index,
14660                                            Object* value) {
14661   ValueType cast_value = 0;
14662   if (index < static_cast<uint32_t>(receiver->length())) {
14663     if (value->IsSmi()) {
14664       int int_value = Smi::cast(value)->value();
14665       cast_value = static_cast<ValueType>(int_value);
14666     } else if (value->IsHeapNumber()) {
14667       double double_value = HeapNumber::cast(value)->value();
14668       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
14669     } else {
14670       // Clamp undefined to zero (default). All other types have been
14671       // converted to a number type further up in the call chain.
14672       ASSERT(value->IsUndefined());
14673     }
14674     receiver->set(index, cast_value);
14675   }
14676   return heap->NumberFromInt32(cast_value);
14677 }
14678
14679
14680 Handle<Object> ExternalInt8Array::SetValue(Handle<ExternalInt8Array> array,
14681                                            uint32_t index,
14682                                            Handle<Object> value) {
14683   CALL_HEAP_FUNCTION(array->GetIsolate(),
14684                      array->SetValue(index, *value),
14685                      Object);
14686 }
14687
14688
14689 MaybeObject* ExternalInt8Array::SetValue(uint32_t index, Object* value) {
14690   return ExternalArrayIntSetter<ExternalInt8Array, int8_t>
14691       (GetHeap(), this, index, value);
14692 }
14693
14694
14695 Handle<Object> ExternalUint8Array::SetValue(
14696     Handle<ExternalUint8Array> array,
14697     uint32_t index,
14698     Handle<Object> value) {
14699   CALL_HEAP_FUNCTION(array->GetIsolate(),
14700                      array->SetValue(index, *value),
14701                      Object);
14702 }
14703
14704
14705 MaybeObject* ExternalUint8Array::SetValue(uint32_t index,
14706                                                  Object* value) {
14707   return ExternalArrayIntSetter<ExternalUint8Array, uint8_t>
14708       (GetHeap(), this, index, value);
14709 }
14710
14711
14712 Handle<Object> ExternalInt16Array::SetValue(
14713     Handle<ExternalInt16Array> array,
14714     uint32_t index,
14715     Handle<Object> value) {
14716   CALL_HEAP_FUNCTION(array->GetIsolate(),
14717                      array->SetValue(index, *value),
14718                      Object);
14719 }
14720
14721
14722 MaybeObject* ExternalInt16Array::SetValue(uint32_t index,
14723                                           Object* value) {
14724   return ExternalArrayIntSetter<ExternalInt16Array, int16_t>
14725       (GetHeap(), this, index, value);
14726 }
14727
14728
14729 Handle<Object> ExternalUint16Array::SetValue(
14730     Handle<ExternalUint16Array> array,
14731     uint32_t index,
14732     Handle<Object> value) {
14733   CALL_HEAP_FUNCTION(array->GetIsolate(),
14734                      array->SetValue(index, *value),
14735                      Object);
14736 }
14737
14738
14739 MaybeObject* ExternalUint16Array::SetValue(uint32_t index,
14740                                                   Object* value) {
14741   return ExternalArrayIntSetter<ExternalUint16Array, uint16_t>
14742       (GetHeap(), this, index, value);
14743 }
14744
14745
14746 Handle<Object> ExternalInt32Array::SetValue(Handle<ExternalInt32Array> array,
14747                                           uint32_t index,
14748                                           Handle<Object> value) {
14749   CALL_HEAP_FUNCTION(array->GetIsolate(),
14750                      array->SetValue(index, *value),
14751                      Object);
14752 }
14753
14754
14755 MaybeObject* ExternalInt32Array::SetValue(uint32_t index, Object* value) {
14756   return ExternalArrayIntSetter<ExternalInt32Array, int32_t>
14757       (GetHeap(), this, index, value);
14758 }
14759
14760
14761 Handle<Object> ExternalUint32Array::SetValue(
14762     Handle<ExternalUint32Array> array,
14763     uint32_t index,
14764     Handle<Object> value) {
14765   CALL_HEAP_FUNCTION(array->GetIsolate(),
14766                      array->SetValue(index, *value),
14767                      Object);
14768 }
14769
14770
14771 MaybeObject* ExternalUint32Array::SetValue(uint32_t index, Object* value) {
14772   uint32_t cast_value = 0;
14773   Heap* heap = GetHeap();
14774   if (index < static_cast<uint32_t>(length())) {
14775     if (value->IsSmi()) {
14776       int int_value = Smi::cast(value)->value();
14777       cast_value = static_cast<uint32_t>(int_value);
14778     } else if (value->IsHeapNumber()) {
14779       double double_value = HeapNumber::cast(value)->value();
14780       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
14781     } else {
14782       // Clamp undefined to zero (default). All other types have been
14783       // converted to a number type further up in the call chain.
14784       ASSERT(value->IsUndefined());
14785     }
14786     set(index, cast_value);
14787   }
14788   return heap->NumberFromUint32(cast_value);
14789 }
14790
14791
14792 Handle<Object> ExternalFloat32Array::SetValue(
14793     Handle<ExternalFloat32Array> array,
14794     uint32_t index,
14795     Handle<Object> value) {
14796   CALL_HEAP_FUNCTION(array->GetIsolate(),
14797                      array->SetValue(index, *value),
14798                      Object);
14799 }
14800
14801
14802 MaybeObject* ExternalFloat32Array::SetValue(uint32_t index, Object* value) {
14803   float cast_value = static_cast<float>(OS::nan_value());
14804   Heap* heap = GetHeap();
14805   if (index < static_cast<uint32_t>(length())) {
14806     if (value->IsSmi()) {
14807       int int_value = Smi::cast(value)->value();
14808       cast_value = static_cast<float>(int_value);
14809     } else if (value->IsHeapNumber()) {
14810       double double_value = HeapNumber::cast(value)->value();
14811       cast_value = static_cast<float>(double_value);
14812     } else {
14813       // Clamp undefined to NaN (default). All other types have been
14814       // converted to a number type further up in the call chain.
14815       ASSERT(value->IsUndefined());
14816     }
14817     set(index, cast_value);
14818   }
14819   return heap->AllocateHeapNumber(cast_value);
14820 }
14821
14822
14823 Handle<Object> ExternalFloat64Array::SetValue(
14824     Handle<ExternalFloat64Array> array,
14825     uint32_t index,
14826     Handle<Object> value) {
14827   CALL_HEAP_FUNCTION(array->GetIsolate(),
14828                      array->SetValue(index, *value),
14829                      Object);
14830 }
14831
14832
14833 MaybeObject* ExternalFloat64Array::SetValue(uint32_t index, Object* value) {
14834   double double_value = OS::nan_value();
14835   Heap* heap = GetHeap();
14836   if (index < static_cast<uint32_t>(length())) {
14837     if (value->IsSmi()) {
14838       int int_value = Smi::cast(value)->value();
14839       double_value = static_cast<double>(int_value);
14840     } else if (value->IsHeapNumber()) {
14841       double_value = HeapNumber::cast(value)->value();
14842     } else {
14843       // Clamp undefined to NaN (default). All other types have been
14844       // converted to a number type further up in the call chain.
14845       ASSERT(value->IsUndefined());
14846     }
14847     set(index, double_value);
14848   }
14849   return heap->AllocateHeapNumber(double_value);
14850 }
14851
14852
14853 Handle<Object> ExternalFloat32x4Array::SetValue(
14854     Handle<ExternalFloat32x4Array> array,
14855     uint32_t index,
14856     Handle<Object> value) {
14857   CALL_HEAP_FUNCTION(array->GetIsolate(),
14858                      array->SetValue(index, *value),
14859                      Object);
14860 }
14861
14862
14863 MaybeObject* ExternalFloat32x4Array::SetValue(uint32_t index, Object* value) {
14864   float32x4_value_t cast_value;
14865   cast_value.storage[0] = static_cast<float>(OS::nan_value());
14866   cast_value.storage[1] = static_cast<float>(OS::nan_value());
14867   cast_value.storage[2] = static_cast<float>(OS::nan_value());
14868   cast_value.storage[3] = static_cast<float>(OS::nan_value());
14869   Heap* heap = GetHeap();
14870   if (index < static_cast<uint32_t>(length())) {
14871     if (value->IsFloat32x4()) {
14872       cast_value = Float32x4::cast(value)->value();
14873     } else {
14874       // Clamp undefined to NaN (default). All other types have been
14875       // converted to a number type further up in the call chain.
14876       ASSERT(value->IsUndefined());
14877     }
14878     set(index, cast_value);
14879   }
14880   return heap->AllocateFloat32x4(cast_value);
14881 }
14882
14883
14884 Handle<Object> ExternalInt32x4Array::SetValue(
14885     Handle<ExternalInt32x4Array> array, uint32_t index, Handle<Object> value) {
14886   CALL_HEAP_FUNCTION(array->GetIsolate(),
14887                      array->SetValue(index, *value),
14888                      Object);
14889 }
14890
14891
14892 MaybeObject* ExternalInt32x4Array::SetValue(uint32_t index, Object* value) {
14893   int32x4_value_t cast_value;
14894   cast_value.storage[0] = 0;
14895   cast_value.storage[1] = 0;
14896   cast_value.storage[2] = 0;
14897   cast_value.storage[3] = 0;
14898   Heap* heap = GetHeap();
14899   if (index < static_cast<uint32_t>(length())) {
14900     if (value->IsInt32x4()) {
14901       cast_value = Int32x4::cast(value)->value();
14902     } else {
14903       // Clamp undefined to zero (default). All other types have been
14904       // converted to a number type further up in the call chain.
14905       ASSERT(value->IsUndefined());
14906     }
14907     set(index, cast_value);
14908   }
14909   return heap->AllocateInt32x4(cast_value);
14910 }
14911
14912
14913 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
14914   ASSERT(!HasFastProperties());
14915   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
14916   return PropertyCell::cast(value);
14917 }
14918
14919
14920 Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell(
14921     Handle<JSGlobalObject> global,
14922     Handle<Name> name) {
14923   ASSERT(!global->HasFastProperties());
14924   int entry = global->property_dictionary()->FindEntry(*name);
14925   if (entry == NameDictionary::kNotFound) {
14926     Isolate* isolate = global->GetIsolate();
14927     Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(
14928         isolate->factory()->the_hole_value());
14929     PropertyDetails details(NONE, NORMAL, 0);
14930     details = details.AsDeleted();
14931     Handle<NameDictionary> dictionary = NameDictionaryAdd(
14932         handle(global->property_dictionary()), name, cell, details);
14933     global->set_properties(*dictionary);
14934     return cell;
14935   } else {
14936     Object* value = global->property_dictionary()->ValueAt(entry);
14937     ASSERT(value->IsPropertyCell());
14938     return handle(PropertyCell::cast(value));
14939   }
14940 }
14941
14942
14943 MaybeObject* StringTable::LookupString(String* string, Object** s) {
14944   InternalizedStringKey key(string);
14945   return LookupKey(&key, s);
14946 }
14947
14948
14949 // This class is used for looking up two character strings in the string table.
14950 // If we don't have a hit we don't want to waste much time so we unroll the
14951 // string hash calculation loop here for speed.  Doesn't work if the two
14952 // characters form a decimal integer, since such strings have a different hash
14953 // algorithm.
14954 class TwoCharHashTableKey : public HashTableKey {
14955  public:
14956   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
14957     : c1_(c1), c2_(c2) {
14958     // Char 1.
14959     uint32_t hash = seed;
14960     hash += c1;
14961     hash += hash << 10;
14962     hash ^= hash >> 6;
14963     // Char 2.
14964     hash += c2;
14965     hash += hash << 10;
14966     hash ^= hash >> 6;
14967     // GetHash.
14968     hash += hash << 3;
14969     hash ^= hash >> 11;
14970     hash += hash << 15;
14971     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
14972     hash_ = hash;
14973 #ifdef DEBUG
14974     // If this assert fails then we failed to reproduce the two-character
14975     // version of the string hashing algorithm above.  One reason could be
14976     // that we were passed two digits as characters, since the hash
14977     // algorithm is different in that case.
14978     uint16_t chars[2] = {c1, c2};
14979     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
14980     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
14981     ASSERT_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
14982 #endif
14983   }
14984
14985   bool IsMatch(Object* o) {
14986     if (!o->IsString()) return false;
14987     String* other = String::cast(o);
14988     if (other->length() != 2) return false;
14989     if (other->Get(0) != c1_) return false;
14990     return other->Get(1) == c2_;
14991   }
14992
14993   uint32_t Hash() { return hash_; }
14994   uint32_t HashForObject(Object* key) {
14995     if (!key->IsString()) return 0;
14996     return String::cast(key)->Hash();
14997   }
14998
14999   Object* AsObject(Heap* heap) {
15000     // The TwoCharHashTableKey is only used for looking in the string
15001     // table, not for adding to it.
15002     UNREACHABLE();
15003     return NULL;
15004   }
15005
15006  private:
15007   uint16_t c1_;
15008   uint16_t c2_;
15009   uint32_t hash_;
15010 };
15011
15012
15013 bool StringTable::LookupStringIfExists(String* string, String** result) {
15014   InternalizedStringKey key(string);
15015   int entry = FindEntry(&key);
15016   if (entry == kNotFound) {
15017     return false;
15018   } else {
15019     *result = String::cast(KeyAt(entry));
15020     ASSERT(StringShape(*result).IsInternalized());
15021     return true;
15022   }
15023 }
15024
15025
15026 bool StringTable::LookupTwoCharsStringIfExists(uint16_t c1,
15027                                                uint16_t c2,
15028                                                String** result) {
15029   TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed());
15030   int entry = FindEntry(&key);
15031   if (entry == kNotFound) {
15032     return false;
15033   } else {
15034     *result = String::cast(KeyAt(entry));
15035     ASSERT(StringShape(*result).IsInternalized());
15036     return true;
15037   }
15038 }
15039
15040
15041 MaybeObject* StringTable::LookupKey(HashTableKey* key, Object** s) {
15042   int entry = FindEntry(key);
15043
15044   // String already in table.
15045   if (entry != kNotFound) {
15046     *s = KeyAt(entry);
15047     return this;
15048   }
15049
15050   // Adding new string. Grow table if needed.
15051   Object* obj;
15052   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
15053     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15054   }
15055
15056   // Create string object.
15057   Object* string;
15058   { MaybeObject* maybe_string = key->AsObject(GetHeap());
15059     if (!maybe_string->ToObject(&string)) return maybe_string;
15060   }
15061
15062   // If the string table grew as part of EnsureCapacity, obj is not
15063   // the current string table and therefore we cannot use
15064   // StringTable::cast here.
15065   StringTable* table = reinterpret_cast<StringTable*>(obj);
15066
15067   // Add the new string and return it along with the string table.
15068   entry = table->FindInsertionEntry(key->Hash());
15069   table->set(EntryToIndex(entry), string);
15070   table->ElementAdded();
15071   *s = string;
15072   return table;
15073 }
15074
15075
15076 Object* CompilationCacheTable::Lookup(String* src, Context* context) {
15077   SharedFunctionInfo* shared = context->closure()->shared();
15078   StringSharedKey key(src,
15079                       shared,
15080                       FLAG_use_strict ? STRICT : SLOPPY,
15081                       RelocInfo::kNoPosition);
15082   int entry = FindEntry(&key);
15083   if (entry == kNotFound) return GetHeap()->undefined_value();
15084   return get(EntryToIndex(entry) + 1);
15085 }
15086
15087
15088 Object* CompilationCacheTable::LookupEval(String* src,
15089                                           Context* context,
15090                                           StrictMode strict_mode,
15091                                           int scope_position) {
15092   StringSharedKey key(src,
15093                       context->closure()->shared(),
15094                       strict_mode,
15095                       scope_position);
15096   int entry = FindEntry(&key);
15097   if (entry == kNotFound) return GetHeap()->undefined_value();
15098   return get(EntryToIndex(entry) + 1);
15099 }
15100
15101
15102 Object* CompilationCacheTable::LookupRegExp(String* src,
15103                                             JSRegExp::Flags flags) {
15104   RegExpKey key(src, flags);
15105   int entry = FindEntry(&key);
15106   if (entry == kNotFound) return GetHeap()->undefined_value();
15107   return get(EntryToIndex(entry) + 1);
15108 }
15109
15110
15111 MaybeObject* CompilationCacheTable::Put(String* src,
15112                                         Context* context,
15113                                         Object* value) {
15114   SharedFunctionInfo* shared = context->closure()->shared();
15115   StringSharedKey key(src,
15116                       shared,
15117                       FLAG_use_strict ? STRICT : SLOPPY,
15118                       RelocInfo::kNoPosition);
15119   CompilationCacheTable* cache;
15120   MaybeObject* maybe_cache = EnsureCapacity(1, &key);
15121   if (!maybe_cache->To(&cache)) return maybe_cache;
15122
15123   Object* k;
15124   MaybeObject* maybe_k = key.AsObject(GetHeap());
15125   if (!maybe_k->To(&k)) return maybe_k;
15126
15127   int entry = cache->FindInsertionEntry(key.Hash());
15128   cache->set(EntryToIndex(entry), k);
15129   cache->set(EntryToIndex(entry) + 1, value);
15130   cache->ElementAdded();
15131   return cache;
15132 }
15133
15134
15135 MaybeObject* CompilationCacheTable::PutEval(String* src,
15136                                             Context* context,
15137                                             SharedFunctionInfo* value,
15138                                             int scope_position) {
15139   StringSharedKey key(src,
15140                       context->closure()->shared(),
15141                       value->strict_mode(),
15142                       scope_position);
15143   Object* obj;
15144   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
15145     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15146   }
15147
15148   CompilationCacheTable* cache =
15149       reinterpret_cast<CompilationCacheTable*>(obj);
15150   int entry = cache->FindInsertionEntry(key.Hash());
15151
15152   Object* k;
15153   { MaybeObject* maybe_k = key.AsObject(GetHeap());
15154     if (!maybe_k->ToObject(&k)) return maybe_k;
15155   }
15156
15157   cache->set(EntryToIndex(entry), k);
15158   cache->set(EntryToIndex(entry) + 1, value);
15159   cache->ElementAdded();
15160   return cache;
15161 }
15162
15163
15164 MaybeObject* CompilationCacheTable::PutRegExp(String* src,
15165                                               JSRegExp::Flags flags,
15166                                               FixedArray* value) {
15167   RegExpKey key(src, flags);
15168   Object* obj;
15169   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
15170     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15171   }
15172
15173   CompilationCacheTable* cache =
15174       reinterpret_cast<CompilationCacheTable*>(obj);
15175   int entry = cache->FindInsertionEntry(key.Hash());
15176   // We store the value in the key slot, and compare the search key
15177   // to the stored value with a custon IsMatch function during lookups.
15178   cache->set(EntryToIndex(entry), value);
15179   cache->set(EntryToIndex(entry) + 1, value);
15180   cache->ElementAdded();
15181   return cache;
15182 }
15183
15184
15185 void CompilationCacheTable::Remove(Object* value) {
15186   Object* the_hole_value = GetHeap()->the_hole_value();
15187   for (int entry = 0, size = Capacity(); entry < size; entry++) {
15188     int entry_index = EntryToIndex(entry);
15189     int value_index = entry_index + 1;
15190     if (get(value_index) == value) {
15191       NoWriteBarrierSet(this, entry_index, the_hole_value);
15192       NoWriteBarrierSet(this, value_index, the_hole_value);
15193       ElementRemoved();
15194     }
15195   }
15196   return;
15197 }
15198
15199
15200 // StringsKey used for HashTable where key is array of internalized strings.
15201 class StringsKey : public HashTableKey {
15202  public:
15203   explicit StringsKey(FixedArray* strings) : strings_(strings) { }
15204
15205   bool IsMatch(Object* strings) {
15206     FixedArray* o = FixedArray::cast(strings);
15207     int len = strings_->length();
15208     if (o->length() != len) return false;
15209     for (int i = 0; i < len; i++) {
15210       if (o->get(i) != strings_->get(i)) return false;
15211     }
15212     return true;
15213   }
15214
15215   uint32_t Hash() { return HashForObject(strings_); }
15216
15217   uint32_t HashForObject(Object* obj) {
15218     FixedArray* strings = FixedArray::cast(obj);
15219     int len = strings->length();
15220     uint32_t hash = 0;
15221     for (int i = 0; i < len; i++) {
15222       hash ^= String::cast(strings->get(i))->Hash();
15223     }
15224     return hash;
15225   }
15226
15227   Object* AsObject(Heap* heap) { return strings_; }
15228
15229  private:
15230   FixedArray* strings_;
15231 };
15232
15233
15234 Object* MapCache::Lookup(FixedArray* array) {
15235   StringsKey key(array);
15236   int entry = FindEntry(&key);
15237   if (entry == kNotFound) return GetHeap()->undefined_value();
15238   return get(EntryToIndex(entry) + 1);
15239 }
15240
15241
15242 MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
15243   StringsKey key(array);
15244   Object* obj;
15245   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
15246     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15247   }
15248
15249   MapCache* cache = reinterpret_cast<MapCache*>(obj);
15250   int entry = cache->FindInsertionEntry(key.Hash());
15251   cache->set(EntryToIndex(entry), array);
15252   cache->set(EntryToIndex(entry) + 1, value);
15253   cache->ElementAdded();
15254   return cache;
15255 }
15256
15257
15258 template<typename Shape, typename Key>
15259 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap,
15260                                               int at_least_space_for,
15261                                               PretenureFlag pretenure) {
15262   Object* obj;
15263   { MaybeObject* maybe_obj =
15264       HashTable<Shape, Key>::Allocate(
15265           heap,
15266           at_least_space_for,
15267           USE_DEFAULT_MINIMUM_CAPACITY,
15268           pretenure);
15269     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15270   }
15271   // Initialize the next enumeration index.
15272   Dictionary<Shape, Key>::cast(obj)->
15273       SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
15274   return obj;
15275 }
15276
15277
15278 void NameDictionary::DoGenerateNewEnumerationIndices(
15279     Handle<NameDictionary> dictionary) {
15280   CALL_HEAP_FUNCTION_VOID(dictionary->GetIsolate(),
15281                           dictionary->GenerateNewEnumerationIndices());
15282 }
15283
15284 template<typename Shape, typename Key>
15285 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
15286   Heap* heap = Dictionary<Shape, Key>::GetHeap();
15287   int length = HashTable<Shape, Key>::NumberOfElements();
15288
15289   // Allocate and initialize iteration order array.
15290   Object* obj;
15291   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
15292     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15293   }
15294   FixedArray* iteration_order = FixedArray::cast(obj);
15295   for (int i = 0; i < length; i++) {
15296     iteration_order->set(i, Smi::FromInt(i));
15297   }
15298
15299   // Allocate array with enumeration order.
15300   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
15301     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15302   }
15303   FixedArray* enumeration_order = FixedArray::cast(obj);
15304
15305   // Fill the enumeration order array with property details.
15306   int capacity = HashTable<Shape, Key>::Capacity();
15307   int pos = 0;
15308   for (int i = 0; i < capacity; i++) {
15309     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
15310       int index = DetailsAt(i).dictionary_index();
15311       enumeration_order->set(pos++, Smi::FromInt(index));
15312     }
15313   }
15314
15315   // Sort the arrays wrt. enumeration order.
15316   iteration_order->SortPairs(enumeration_order, enumeration_order->length());
15317
15318   // Overwrite the enumeration_order with the enumeration indices.
15319   for (int i = 0; i < length; i++) {
15320     int index = Smi::cast(iteration_order->get(i))->value();
15321     int enum_index = PropertyDetails::kInitialIndex + i;
15322     enumeration_order->set(index, Smi::FromInt(enum_index));
15323   }
15324
15325   // Update the dictionary with new indices.
15326   capacity = HashTable<Shape, Key>::Capacity();
15327   pos = 0;
15328   for (int i = 0; i < capacity; i++) {
15329     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
15330       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
15331       PropertyDetails details = DetailsAt(i);
15332       PropertyDetails new_details = PropertyDetails(
15333           details.attributes(), details.type(), enum_index);
15334       DetailsAtPut(i, new_details);
15335     }
15336   }
15337
15338   // Set the next enumeration index.
15339   SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
15340   return this;
15341 }
15342
15343 template<typename Shape, typename Key>
15344 MaybeObject* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
15345   // Check whether there are enough enumeration indices to add n elements.
15346   if (Shape::kIsEnumerable &&
15347       !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
15348     // If not, we generate new indices for the properties.
15349     Object* result;
15350     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
15351       if (!maybe_result->ToObject(&result)) return maybe_result;
15352     }
15353   }
15354   return HashTable<Shape, Key>::EnsureCapacity(n, key);
15355 }
15356
15357
15358 template<typename Shape, typename Key>
15359 Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
15360                                                JSReceiver::DeleteMode mode) {
15361   Heap* heap = Dictionary<Shape, Key>::GetHeap();
15362   PropertyDetails details = DetailsAt(entry);
15363   // Ignore attributes if forcing a deletion.
15364   if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
15365     return heap->false_value();
15366   }
15367   SetEntry(entry, heap->the_hole_value(), heap->the_hole_value());
15368   HashTable<Shape, Key>::ElementRemoved();
15369   return heap->true_value();
15370 }
15371
15372
15373 template<typename Shape, typename Key>
15374 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
15375   return HashTable<Shape, Key>::Shrink(key);
15376 }
15377
15378
15379 template<typename Shape, typename Key>
15380 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
15381   int entry = this->FindEntry(key);
15382
15383   // If the entry is present set the value;
15384   if (entry != Dictionary<Shape, Key>::kNotFound) {
15385     ValueAtPut(entry, value);
15386     return this;
15387   }
15388
15389   // Check whether the dictionary should be extended.
15390   Object* obj;
15391   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
15392     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15393   }
15394
15395   Object* k;
15396   { MaybeObject* maybe_k = Shape::AsObject(this->GetHeap(), key);
15397     if (!maybe_k->ToObject(&k)) return maybe_k;
15398   }
15399   PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
15400
15401   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
15402       Dictionary<Shape, Key>::Hash(key));
15403 }
15404
15405
15406 template<typename Shape, typename Key>
15407 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
15408                                          Object* value,
15409                                          PropertyDetails details) {
15410   // Valdate key is absent.
15411   SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
15412   // Check whether the dictionary should be extended.
15413   Object* obj;
15414   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
15415     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15416   }
15417
15418   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
15419       Dictionary<Shape, Key>::Hash(key));
15420 }
15421
15422
15423 // Add a key, value pair to the dictionary.
15424 template<typename Shape, typename Key>
15425 MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key,
15426                                               Object* value,
15427                                               PropertyDetails details,
15428                                               uint32_t hash) {
15429   // Compute the key object.
15430   Object* k;
15431   { MaybeObject* maybe_k = Shape::AsObject(this->GetHeap(), key);
15432     if (!maybe_k->ToObject(&k)) return maybe_k;
15433   }
15434
15435   uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
15436   // Insert element at empty or deleted entry
15437   if (!details.IsDeleted() &&
15438       details.dictionary_index() == 0 &&
15439       Shape::kIsEnumerable) {
15440     // Assign an enumeration index to the property and update
15441     // SetNextEnumerationIndex.
15442     int index = NextEnumerationIndex();
15443     details = PropertyDetails(details.attributes(), details.type(), index);
15444     SetNextEnumerationIndex(index + 1);
15445   }
15446   SetEntry(entry, k, value, details);
15447   ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() ||
15448           Dictionary<Shape, Key>::KeyAt(entry)->IsName()));
15449   HashTable<Shape, Key>::ElementAdded();
15450   return this;
15451 }
15452
15453
15454 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
15455   // If the dictionary requires slow elements an element has already
15456   // been added at a high index.
15457   if (requires_slow_elements()) return;
15458   // Check if this index is high enough that we should require slow
15459   // elements.
15460   if (key > kRequiresSlowElementsLimit) {
15461     set_requires_slow_elements();
15462     return;
15463   }
15464   // Update max key value.
15465   Object* max_index_object = get(kMaxNumberKeyIndex);
15466   if (!max_index_object->IsSmi() || max_number_key() < key) {
15467     FixedArray::set(kMaxNumberKeyIndex,
15468                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
15469   }
15470 }
15471
15472 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
15473     Handle<SeededNumberDictionary> dictionary,
15474     uint32_t key,
15475     Handle<Object> value,
15476     PropertyDetails details) {
15477   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
15478                      dictionary->AddNumberEntry(key, *value, details),
15479                      SeededNumberDictionary);
15480 }
15481
15482 MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key,
15483                                                     Object* value,
15484                                                     PropertyDetails details) {
15485   UpdateMaxNumberKey(key);
15486   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
15487   return Add(key, value, details);
15488 }
15489
15490
15491 MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key,
15492                                                       Object* value) {
15493   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
15494   return Add(key, value, PropertyDetails(NONE, NORMAL, 0));
15495 }
15496
15497
15498 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) {
15499   UpdateMaxNumberKey(key);
15500   return AtPut(key, value);
15501 }
15502
15503
15504 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key,
15505                                                    Object* value) {
15506   return AtPut(key, value);
15507 }
15508
15509
15510 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
15511     Handle<SeededNumberDictionary> dictionary,
15512     uint32_t index,
15513     Handle<Object> value,
15514     PropertyDetails details) {
15515   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
15516                      dictionary->Set(index, *value, details),
15517                      SeededNumberDictionary);
15518 }
15519
15520
15521 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
15522     Handle<UnseededNumberDictionary> dictionary,
15523     uint32_t index,
15524     Handle<Object> value) {
15525   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
15526                      dictionary->Set(index, *value),
15527                      UnseededNumberDictionary);
15528 }
15529
15530
15531 MaybeObject* SeededNumberDictionary::Set(uint32_t key,
15532                                          Object* value,
15533                                          PropertyDetails details) {
15534   int entry = FindEntry(key);
15535   if (entry == kNotFound) return AddNumberEntry(key, value, details);
15536   // Preserve enumeration index.
15537   details = PropertyDetails(details.attributes(),
15538                             details.type(),
15539                             DetailsAt(entry).dictionary_index());
15540   MaybeObject* maybe_object_key =
15541       SeededNumberDictionaryShape::AsObject(GetHeap(), key);
15542   Object* object_key;
15543   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
15544   SetEntry(entry, object_key, value, details);
15545   return this;
15546 }
15547
15548
15549 MaybeObject* UnseededNumberDictionary::Set(uint32_t key,
15550                                            Object* value) {
15551   int entry = FindEntry(key);
15552   if (entry == kNotFound) return AddNumberEntry(key, value);
15553   MaybeObject* maybe_object_key =
15554       UnseededNumberDictionaryShape::AsObject(GetHeap(), key);
15555   Object* object_key;
15556   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
15557   SetEntry(entry, object_key, value);
15558   return this;
15559 }
15560
15561
15562
15563 template<typename Shape, typename Key>
15564 int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
15565     PropertyAttributes filter) {
15566   int capacity = HashTable<Shape, Key>::Capacity();
15567   int result = 0;
15568   for (int i = 0; i < capacity; i++) {
15569     Object* k = HashTable<Shape, Key>::KeyAt(i);
15570     if (HashTable<Shape, Key>::IsKey(k) && !FilterKey(k, filter)) {
15571       PropertyDetails details = DetailsAt(i);
15572       if (details.IsDeleted()) continue;
15573       PropertyAttributes attr = details.attributes();
15574       if ((attr & filter) == 0) result++;
15575     }
15576   }
15577   return result;
15578 }
15579
15580
15581 template<typename Shape, typename Key>
15582 int Dictionary<Shape, Key>::NumberOfEnumElements() {
15583   return NumberOfElementsFilterAttributes(
15584       static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC));
15585 }
15586
15587
15588 template<typename Shape, typename Key>
15589 void Dictionary<Shape, Key>::CopyKeysTo(
15590     FixedArray* storage,
15591     PropertyAttributes filter,
15592     typename Dictionary<Shape, Key>::SortMode sort_mode) {
15593   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter));
15594   int capacity = HashTable<Shape, Key>::Capacity();
15595   int index = 0;
15596   for (int i = 0; i < capacity; i++) {
15597      Object* k = HashTable<Shape, Key>::KeyAt(i);
15598      if (HashTable<Shape, Key>::IsKey(k) && !FilterKey(k, filter)) {
15599        PropertyDetails details = DetailsAt(i);
15600        if (details.IsDeleted()) continue;
15601        PropertyAttributes attr = details.attributes();
15602        if ((attr & filter) == 0) storage->set(index++, k);
15603      }
15604   }
15605   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
15606     storage->SortPairs(storage, index);
15607   }
15608   ASSERT(storage->length() >= index);
15609 }
15610
15611
15612 struct EnumIndexComparator {
15613   explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { }
15614   bool operator() (Smi* a, Smi* b) {
15615     PropertyDetails da(dict->DetailsAt(a->value()));
15616     PropertyDetails db(dict->DetailsAt(b->value()));
15617     return da.dictionary_index() < db.dictionary_index();
15618   }
15619   NameDictionary* dict;
15620 };
15621
15622
15623 void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
15624   int length = storage->length();
15625   int capacity = Capacity();
15626   int properties = 0;
15627   for (int i = 0; i < capacity; i++) {
15628      Object* k = KeyAt(i);
15629      if (IsKey(k) && !k->IsSymbol()) {
15630        PropertyDetails details = DetailsAt(i);
15631        if (details.IsDeleted() || details.IsDontEnum()) continue;
15632        storage->set(properties, Smi::FromInt(i));
15633        properties++;
15634        if (properties == length) break;
15635      }
15636   }
15637   EnumIndexComparator cmp(this);
15638   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
15639   std::sort(start, start + length, cmp);
15640   for (int i = 0; i < length; i++) {
15641     int index = Smi::cast(storage->get(i))->value();
15642     storage->set(i, KeyAt(index));
15643   }
15644 }
15645
15646
15647 template<typename Shape, typename Key>
15648 void Dictionary<Shape, Key>::CopyKeysTo(
15649     FixedArray* storage,
15650     int index,
15651     PropertyAttributes filter,
15652     typename Dictionary<Shape, Key>::SortMode sort_mode) {
15653   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter));
15654   int capacity = HashTable<Shape, Key>::Capacity();
15655   for (int i = 0; i < capacity; i++) {
15656     Object* k = HashTable<Shape, Key>::KeyAt(i);
15657     if (HashTable<Shape, Key>::IsKey(k) && !FilterKey(k, filter)) {
15658       PropertyDetails details = DetailsAt(i);
15659       if (details.IsDeleted()) continue;
15660       PropertyAttributes attr = details.attributes();
15661       if ((attr & filter) == 0) storage->set(index++, k);
15662     }
15663   }
15664   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
15665     storage->SortPairs(storage, index);
15666   }
15667   ASSERT(storage->length() >= index);
15668 }
15669
15670
15671 // Backwards lookup (slow).
15672 template<typename Shape, typename Key>
15673 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
15674   int capacity = HashTable<Shape, Key>::Capacity();
15675   for (int i = 0; i < capacity; i++) {
15676     Object* k =  HashTable<Shape, Key>::KeyAt(i);
15677     if (Dictionary<Shape, Key>::IsKey(k)) {
15678       Object* e = ValueAt(i);
15679       if (e->IsPropertyCell()) {
15680         e = PropertyCell::cast(e)->value();
15681       }
15682       if (e == value) return k;
15683     }
15684   }
15685   Heap* heap = Dictionary<Shape, Key>::GetHeap();
15686   return heap->undefined_value();
15687 }
15688
15689
15690 MaybeObject* NameDictionary::TransformPropertiesToFastFor(
15691     JSObject* obj, int unused_property_fields) {
15692   // Make sure we preserve dictionary representation if there are too many
15693   // descriptors.
15694   int number_of_elements = NumberOfElements();
15695   if (number_of_elements > kMaxNumberOfDescriptors) return obj;
15696
15697   if (number_of_elements != NextEnumerationIndex()) {
15698     MaybeObject* maybe_result = GenerateNewEnumerationIndices();
15699     if (maybe_result->IsFailure()) return maybe_result;
15700   }
15701
15702   int instance_descriptor_length = 0;
15703   int number_of_fields = 0;
15704
15705   Heap* heap = GetHeap();
15706
15707   // Compute the length of the instance descriptor.
15708   int capacity = Capacity();
15709   for (int i = 0; i < capacity; i++) {
15710     Object* k = KeyAt(i);
15711     if (IsKey(k)) {
15712       Object* value = ValueAt(i);
15713       PropertyType type = DetailsAt(i).type();
15714       ASSERT(type != FIELD);
15715       instance_descriptor_length++;
15716       if (type == NORMAL && !value->IsJSFunction()) {
15717         number_of_fields += 1;
15718       }
15719     }
15720   }
15721
15722   int inobject_props = obj->map()->inobject_properties();
15723
15724   // Allocate new map.
15725   Map* new_map;
15726   MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
15727   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
15728   new_map->set_dictionary_map(false);
15729
15730   if (instance_descriptor_length == 0) {
15731     ASSERT_LE(unused_property_fields, inobject_props);
15732     // Transform the object.
15733     new_map->set_unused_property_fields(inobject_props);
15734     obj->set_map(new_map);
15735     obj->set_properties(heap->empty_fixed_array());
15736     // Check that it really works.
15737     ASSERT(obj->HasFastProperties());
15738     return obj;
15739   }
15740
15741   // Allocate the instance descriptor.
15742   DescriptorArray* descriptors;
15743   MaybeObject* maybe_descriptors =
15744       DescriptorArray::Allocate(GetIsolate(), instance_descriptor_length);
15745   if (!maybe_descriptors->To(&descriptors)) {
15746     return maybe_descriptors;
15747   }
15748
15749   DescriptorArray::WhitenessWitness witness(descriptors);
15750
15751   int number_of_allocated_fields =
15752       number_of_fields + unused_property_fields - inobject_props;
15753   if (number_of_allocated_fields < 0) {
15754     // There is enough inobject space for all fields (including unused).
15755     number_of_allocated_fields = 0;
15756     unused_property_fields = inobject_props - number_of_fields;
15757   }
15758
15759   // Allocate the fixed array for the fields.
15760   FixedArray* fields;
15761   MaybeObject* maybe_fields =
15762       heap->AllocateFixedArray(number_of_allocated_fields);
15763   if (!maybe_fields->To(&fields)) return maybe_fields;
15764
15765   // Fill in the instance descriptor and the fields.
15766   int current_offset = 0;
15767   for (int i = 0; i < capacity; i++) {
15768     Object* k = KeyAt(i);
15769     if (IsKey(k)) {
15770       Object* value = ValueAt(i);
15771       Name* key;
15772       if (k->IsSymbol()) {
15773         key = Symbol::cast(k);
15774       } else {
15775         // Ensure the key is a unique name before writing into the
15776         // instance descriptor.
15777         MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
15778         if (!maybe_key->To(&key)) return maybe_key;
15779       }
15780
15781       PropertyDetails details = DetailsAt(i);
15782       int enumeration_index = details.dictionary_index();
15783       PropertyType type = details.type();
15784
15785       if (value->IsJSFunction()) {
15786         ConstantDescriptor d(key, value, details.attributes());
15787         descriptors->Set(enumeration_index - 1, &d, witness);
15788       } else if (type == NORMAL) {
15789         if (current_offset < inobject_props) {
15790           obj->InObjectPropertyAtPut(current_offset,
15791                                      value,
15792                                      UPDATE_WRITE_BARRIER);
15793         } else {
15794           int offset = current_offset - inobject_props;
15795           fields->set(offset, value);
15796         }
15797         FieldDescriptor d(key,
15798                           current_offset++,
15799                           details.attributes(),
15800                           // TODO(verwaest): value->OptimalRepresentation();
15801                           Representation::Tagged());
15802         descriptors->Set(enumeration_index - 1, &d, witness);
15803       } else if (type == CALLBACKS) {
15804         CallbacksDescriptor d(key,
15805                               value,
15806                               details.attributes());
15807         descriptors->Set(enumeration_index - 1, &d, witness);
15808       } else {
15809         UNREACHABLE();
15810       }
15811     }
15812   }
15813   ASSERT(current_offset == number_of_fields);
15814
15815   descriptors->Sort();
15816
15817   new_map->InitializeDescriptors(descriptors);
15818   new_map->set_unused_property_fields(unused_property_fields);
15819
15820   // Transform the object.
15821   obj->set_map(new_map);
15822
15823   obj->set_properties(fields);
15824   ASSERT(obj->IsJSObject());
15825
15826   // Check that it really works.
15827   ASSERT(obj->HasFastProperties());
15828
15829   return obj;
15830 }
15831
15832
15833 Handle<ObjectHashSet> ObjectHashSet::EnsureCapacity(
15834     Handle<ObjectHashSet> table,
15835     int n,
15836     Handle<Object> key,
15837     PretenureFlag pretenure) {
15838   Handle<HashTable<ObjectHashTableShape<1>, Object*> > table_base = table;
15839   CALL_HEAP_FUNCTION(table_base->GetIsolate(),
15840                      table_base->EnsureCapacity(n, *key, pretenure),
15841                      ObjectHashSet);
15842 }
15843
15844
15845 Handle<ObjectHashSet> ObjectHashSet::Shrink(Handle<ObjectHashSet> table,
15846                                             Handle<Object> key) {
15847   Handle<HashTable<ObjectHashTableShape<1>, Object*> > table_base = table;
15848   CALL_HEAP_FUNCTION(table_base->GetIsolate(),
15849                      table_base->Shrink(*key),
15850                      ObjectHashSet);
15851 }
15852
15853
15854 bool ObjectHashSet::Contains(Object* key) {
15855   ASSERT(IsKey(key));
15856
15857   // If the object does not have an identity hash, it was never used as a key.
15858   Object* hash = key->GetHash();
15859   if (hash->IsUndefined()) return false;
15860
15861   return (FindEntry(key) != kNotFound);
15862 }
15863
15864
15865 Handle<ObjectHashSet> ObjectHashSet::Add(Handle<ObjectHashSet> table,
15866                                          Handle<Object> key) {
15867   ASSERT(table->IsKey(*key));
15868
15869   // Make sure the key object has an identity hash code.
15870   Handle<Object> object_hash = Object::GetOrCreateHash(key,
15871                                                        table->GetIsolate());
15872
15873   int entry = table->FindEntry(*key);
15874
15875   // Check whether key is already present.
15876   if (entry != kNotFound) return table;
15877
15878   // Check whether the hash set should be extended and add entry.
15879   Handle<ObjectHashSet> new_table =
15880       ObjectHashSet::EnsureCapacity(table, 1, key);
15881   entry = new_table->FindInsertionEntry(Smi::cast(*object_hash)->value());
15882   new_table->set(EntryToIndex(entry), *key);
15883   new_table->ElementAdded();
15884   return new_table;
15885 }
15886
15887
15888 Handle<ObjectHashSet> ObjectHashSet::Remove(Handle<ObjectHashSet> table,
15889                                             Handle<Object> key) {
15890   ASSERT(table->IsKey(*key));
15891
15892   // If the object does not have an identity hash, it was never used as a key.
15893   if (key->GetHash()->IsUndefined()) return table;
15894
15895   int entry = table->FindEntry(*key);
15896
15897   // Check whether key is actually present.
15898   if (entry == kNotFound) return table;
15899
15900   // Remove entry and try to shrink this hash set.
15901   table->set_the_hole(EntryToIndex(entry));
15902   table->ElementRemoved();
15903
15904   return ObjectHashSet::Shrink(table, key);
15905 }
15906
15907
15908 Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity(
15909     Handle<ObjectHashTable> table,
15910     int n,
15911     Handle<Object> key,
15912     PretenureFlag pretenure) {
15913   Handle<HashTable<ObjectHashTableShape<2>, Object*> > table_base = table;
15914   CALL_HEAP_FUNCTION(table_base->GetIsolate(),
15915                      table_base->EnsureCapacity(n, *key, pretenure),
15916                      ObjectHashTable);
15917 }
15918
15919
15920 Handle<ObjectHashTable> ObjectHashTable::Shrink(
15921     Handle<ObjectHashTable> table, Handle<Object> key) {
15922   Handle<HashTable<ObjectHashTableShape<2>, Object*> > table_base = table;
15923   CALL_HEAP_FUNCTION(table_base->GetIsolate(),
15924                      table_base->Shrink(*key),
15925                      ObjectHashTable);
15926 }
15927
15928
15929 Object* ObjectHashTable::Lookup(Object* key) {
15930   ASSERT(IsKey(key));
15931
15932   // If the object does not have an identity hash, it was never used as a key.
15933   Object* hash = key->GetHash();
15934   if (hash->IsUndefined()) {
15935     return GetHeap()->the_hole_value();
15936   }
15937   int entry = FindEntry(key);
15938   if (entry == kNotFound) return GetHeap()->the_hole_value();
15939   return get(EntryToIndex(entry) + 1);
15940 }
15941
15942
15943 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
15944                                              Handle<Object> key,
15945                                              Handle<Object> value) {
15946   ASSERT(table->IsKey(*key));
15947
15948   Isolate* isolate = table->GetIsolate();
15949
15950   // Make sure the key object has an identity hash code.
15951   Handle<Object> hash = Object::GetOrCreateHash(key, isolate);
15952
15953   int entry = table->FindEntry(*key);
15954
15955   // Check whether to perform removal operation.
15956   if (value->IsTheHole()) {
15957     if (entry == kNotFound) return table;
15958     table->RemoveEntry(entry);
15959     return Shrink(table, key);
15960   }
15961
15962   // Key is already in table, just overwrite value.
15963   if (entry != kNotFound) {
15964     table->set(EntryToIndex(entry) + 1, *value);
15965     return table;
15966   }
15967
15968   // Check whether the hash table should be extended.
15969   table = EnsureCapacity(table, 1, key);
15970   table->AddEntry(table->FindInsertionEntry(Handle<Smi>::cast(hash)->value()),
15971                   *key,
15972                   *value);
15973   return table;
15974 }
15975
15976
15977 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
15978   set(EntryToIndex(entry), key);
15979   set(EntryToIndex(entry) + 1, value);
15980   ElementAdded();
15981 }
15982
15983
15984 void ObjectHashTable::RemoveEntry(int entry) {
15985   set_the_hole(EntryToIndex(entry));
15986   set_the_hole(EntryToIndex(entry) + 1);
15987   ElementRemoved();
15988 }
15989
15990
15991 Object* WeakHashTable::Lookup(Object* key) {
15992   ASSERT(IsKey(key));
15993   int entry = FindEntry(key);
15994   if (entry == kNotFound) return GetHeap()->the_hole_value();
15995   return get(EntryToValueIndex(entry));
15996 }
15997
15998
15999 MaybeObject* WeakHashTable::Put(Object* key, Object* value) {
16000   ASSERT(IsKey(key));
16001   int entry = FindEntry(key);
16002   // Key is already in table, just overwrite value.
16003   if (entry != kNotFound) {
16004     set(EntryToValueIndex(entry), value);
16005     return this;
16006   }
16007
16008   // Check whether the hash table should be extended.
16009   Object* obj;
16010   { MaybeObject* maybe_obj = EnsureCapacity(1, key, TENURED);
16011     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
16012   }
16013   WeakHashTable* table = WeakHashTable::cast(obj);
16014   table->AddEntry(table->FindInsertionEntry(Hash(key)), key, value);
16015   return table;
16016 }
16017
16018
16019 void WeakHashTable::AddEntry(int entry, Object* key, Object* value) {
16020   set(EntryToIndex(entry), key);
16021   set(EntryToValueIndex(entry), value);
16022   ElementAdded();
16023 }
16024
16025
16026 DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator(
16027     DeclaredAccessorDescriptor* descriptor)
16028     : array_(descriptor->serialized_data()->GetDataStartAddress()),
16029       length_(descriptor->serialized_data()->length()),
16030       offset_(0) {
16031 }
16032
16033
16034 const DeclaredAccessorDescriptorData*
16035   DeclaredAccessorDescriptorIterator::Next() {
16036   ASSERT(offset_ < length_);
16037   uint8_t* ptr = &array_[offset_];
16038   ASSERT(reinterpret_cast<uintptr_t>(ptr) % sizeof(uintptr_t) == 0);
16039   const DeclaredAccessorDescriptorData* data =
16040       reinterpret_cast<const DeclaredAccessorDescriptorData*>(ptr);
16041   offset_ += sizeof(*data);
16042   ASSERT(offset_ <= length_);
16043   return data;
16044 }
16045
16046
16047 Handle<DeclaredAccessorDescriptor> DeclaredAccessorDescriptor::Create(
16048     Isolate* isolate,
16049     const DeclaredAccessorDescriptorData& descriptor,
16050     Handle<DeclaredAccessorDescriptor> previous) {
16051   int previous_length =
16052       previous.is_null() ? 0 : previous->serialized_data()->length();
16053   int length = sizeof(descriptor) + previous_length;
16054   Handle<ByteArray> serialized_descriptor =
16055       isolate->factory()->NewByteArray(length);
16056   Handle<DeclaredAccessorDescriptor> value =
16057       isolate->factory()->NewDeclaredAccessorDescriptor();
16058   value->set_serialized_data(*serialized_descriptor);
16059   // Copy in the data.
16060   {
16061     DisallowHeapAllocation no_allocation;
16062     uint8_t* array = serialized_descriptor->GetDataStartAddress();
16063     if (previous_length != 0) {
16064       uint8_t* previous_array =
16065           previous->serialized_data()->GetDataStartAddress();
16066       OS::MemCopy(array, previous_array, previous_length);
16067       array += previous_length;
16068     }
16069     ASSERT(reinterpret_cast<uintptr_t>(array) % sizeof(uintptr_t) == 0);
16070     DeclaredAccessorDescriptorData* data =
16071         reinterpret_cast<DeclaredAccessorDescriptorData*>(array);
16072     *data = descriptor;
16073   }
16074   return value;
16075 }
16076
16077
16078 #ifdef ENABLE_DEBUGGER_SUPPORT
16079 // Check if there is a break point at this code position.
16080 bool DebugInfo::HasBreakPoint(int code_position) {
16081   // Get the break point info object for this code position.
16082   Object* break_point_info = GetBreakPointInfo(code_position);
16083
16084   // If there is no break point info object or no break points in the break
16085   // point info object there is no break point at this code position.
16086   if (break_point_info->IsUndefined()) return false;
16087   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
16088 }
16089
16090
16091 // Get the break point info object for this code position.
16092 Object* DebugInfo::GetBreakPointInfo(int code_position) {
16093   // Find the index of the break point info object for this code position.
16094   int index = GetBreakPointInfoIndex(code_position);
16095
16096   // Return the break point info object if any.
16097   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
16098   return BreakPointInfo::cast(break_points()->get(index));
16099 }
16100
16101
16102 // Clear a break point at the specified code position.
16103 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
16104                                 int code_position,
16105                                 Handle<Object> break_point_object) {
16106   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16107                                   debug_info->GetIsolate());
16108   if (break_point_info->IsUndefined()) return;
16109   BreakPointInfo::ClearBreakPoint(
16110       Handle<BreakPointInfo>::cast(break_point_info),
16111       break_point_object);
16112 }
16113
16114
16115 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
16116                               int code_position,
16117                               int source_position,
16118                               int statement_position,
16119                               Handle<Object> break_point_object) {
16120   Isolate* isolate = debug_info->GetIsolate();
16121   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
16122                                   isolate);
16123   if (!break_point_info->IsUndefined()) {
16124     BreakPointInfo::SetBreakPoint(
16125         Handle<BreakPointInfo>::cast(break_point_info),
16126         break_point_object);
16127     return;
16128   }
16129
16130   // Adding a new break point for a code position which did not have any
16131   // break points before. Try to find a free slot.
16132   int index = kNoBreakPointInfo;
16133   for (int i = 0; i < debug_info->break_points()->length(); i++) {
16134     if (debug_info->break_points()->get(i)->IsUndefined()) {
16135       index = i;
16136       break;
16137     }
16138   }
16139   if (index == kNoBreakPointInfo) {
16140     // No free slot - extend break point info array.
16141     Handle<FixedArray> old_break_points =
16142         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
16143     Handle<FixedArray> new_break_points =
16144         isolate->factory()->NewFixedArray(
16145             old_break_points->length() +
16146             Debug::kEstimatedNofBreakPointsInFunction);
16147
16148     debug_info->set_break_points(*new_break_points);
16149     for (int i = 0; i < old_break_points->length(); i++) {
16150       new_break_points->set(i, old_break_points->get(i));
16151     }
16152     index = old_break_points->length();
16153   }
16154   ASSERT(index != kNoBreakPointInfo);
16155
16156   // Allocate new BreakPointInfo object and set the break point.
16157   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
16158       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
16159   new_break_point_info->set_code_position(Smi::FromInt(code_position));
16160   new_break_point_info->set_source_position(Smi::FromInt(source_position));
16161   new_break_point_info->
16162       set_statement_position(Smi::FromInt(statement_position));
16163   new_break_point_info->set_break_point_objects(
16164       isolate->heap()->undefined_value());
16165   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
16166   debug_info->break_points()->set(index, *new_break_point_info);
16167 }
16168
16169
16170 // Get the break point objects for a code position.
16171 Object* DebugInfo::GetBreakPointObjects(int code_position) {
16172   Object* break_point_info = GetBreakPointInfo(code_position);
16173   if (break_point_info->IsUndefined()) {
16174     return GetHeap()->undefined_value();
16175   }
16176   return BreakPointInfo::cast(break_point_info)->break_point_objects();
16177 }
16178
16179
16180 // Get the total number of break points.
16181 int DebugInfo::GetBreakPointCount() {
16182   if (break_points()->IsUndefined()) return 0;
16183   int count = 0;
16184   for (int i = 0; i < break_points()->length(); i++) {
16185     if (!break_points()->get(i)->IsUndefined()) {
16186       BreakPointInfo* break_point_info =
16187           BreakPointInfo::cast(break_points()->get(i));
16188       count += break_point_info->GetBreakPointCount();
16189     }
16190   }
16191   return count;
16192 }
16193
16194
16195 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
16196                                       Handle<Object> break_point_object) {
16197   Heap* heap = debug_info->GetHeap();
16198   if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
16199   for (int i = 0; i < debug_info->break_points()->length(); i++) {
16200     if (!debug_info->break_points()->get(i)->IsUndefined()) {
16201       Handle<BreakPointInfo> break_point_info =
16202           Handle<BreakPointInfo>(BreakPointInfo::cast(
16203               debug_info->break_points()->get(i)));
16204       if (BreakPointInfo::HasBreakPointObject(break_point_info,
16205                                               break_point_object)) {
16206         return *break_point_info;
16207       }
16208     }
16209   }
16210   return heap->undefined_value();
16211 }
16212
16213
16214 // Find the index of the break point info object for the specified code
16215 // position.
16216 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
16217   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
16218   for (int i = 0; i < break_points()->length(); i++) {
16219     if (!break_points()->get(i)->IsUndefined()) {
16220       BreakPointInfo* break_point_info =
16221           BreakPointInfo::cast(break_points()->get(i));
16222       if (break_point_info->code_position()->value() == code_position) {
16223         return i;
16224       }
16225     }
16226   }
16227   return kNoBreakPointInfo;
16228 }
16229
16230
16231 // Remove the specified break point object.
16232 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
16233                                      Handle<Object> break_point_object) {
16234   Isolate* isolate = break_point_info->GetIsolate();
16235   // If there are no break points just ignore.
16236   if (break_point_info->break_point_objects()->IsUndefined()) return;
16237   // If there is a single break point clear it if it is the same.
16238   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16239     if (break_point_info->break_point_objects() == *break_point_object) {
16240       break_point_info->set_break_point_objects(
16241           isolate->heap()->undefined_value());
16242     }
16243     return;
16244   }
16245   // If there are multiple break points shrink the array
16246   ASSERT(break_point_info->break_point_objects()->IsFixedArray());
16247   Handle<FixedArray> old_array =
16248       Handle<FixedArray>(
16249           FixedArray::cast(break_point_info->break_point_objects()));
16250   Handle<FixedArray> new_array =
16251       isolate->factory()->NewFixedArray(old_array->length() - 1);
16252   int found_count = 0;
16253   for (int i = 0; i < old_array->length(); i++) {
16254     if (old_array->get(i) == *break_point_object) {
16255       ASSERT(found_count == 0);
16256       found_count++;
16257     } else {
16258       new_array->set(i - found_count, old_array->get(i));
16259     }
16260   }
16261   // If the break point was found in the list change it.
16262   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
16263 }
16264
16265
16266 // Add the specified break point object.
16267 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
16268                                    Handle<Object> break_point_object) {
16269   Isolate* isolate = break_point_info->GetIsolate();
16270
16271   // If there was no break point objects before just set it.
16272   if (break_point_info->break_point_objects()->IsUndefined()) {
16273     break_point_info->set_break_point_objects(*break_point_object);
16274     return;
16275   }
16276   // If the break point object is the same as before just ignore.
16277   if (break_point_info->break_point_objects() == *break_point_object) return;
16278   // If there was one break point object before replace with array.
16279   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16280     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
16281     array->set(0, break_point_info->break_point_objects());
16282     array->set(1, *break_point_object);
16283     break_point_info->set_break_point_objects(*array);
16284     return;
16285   }
16286   // If there was more than one break point before extend array.
16287   Handle<FixedArray> old_array =
16288       Handle<FixedArray>(
16289           FixedArray::cast(break_point_info->break_point_objects()));
16290   Handle<FixedArray> new_array =
16291       isolate->factory()->NewFixedArray(old_array->length() + 1);
16292   for (int i = 0; i < old_array->length(); i++) {
16293     // If the break point was there before just ignore.
16294     if (old_array->get(i) == *break_point_object) return;
16295     new_array->set(i, old_array->get(i));
16296   }
16297   // Add the new break point.
16298   new_array->set(old_array->length(), *break_point_object);
16299   break_point_info->set_break_point_objects(*new_array);
16300 }
16301
16302
16303 bool BreakPointInfo::HasBreakPointObject(
16304     Handle<BreakPointInfo> break_point_info,
16305     Handle<Object> break_point_object) {
16306   // No break point.
16307   if (break_point_info->break_point_objects()->IsUndefined()) return false;
16308   // Single break point.
16309   if (!break_point_info->break_point_objects()->IsFixedArray()) {
16310     return break_point_info->break_point_objects() == *break_point_object;
16311   }
16312   // Multiple break points.
16313   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
16314   for (int i = 0; i < array->length(); i++) {
16315     if (array->get(i) == *break_point_object) {
16316       return true;
16317     }
16318   }
16319   return false;
16320 }
16321
16322
16323 // Get the number of break points.
16324 int BreakPointInfo::GetBreakPointCount() {
16325   // No break point.
16326   if (break_point_objects()->IsUndefined()) return 0;
16327   // Single break point.
16328   if (!break_point_objects()->IsFixedArray()) return 1;
16329   // Multiple break points.
16330   return FixedArray::cast(break_point_objects())->length();
16331 }
16332 #endif  // ENABLE_DEBUGGER_SUPPORT
16333
16334
16335 Object* JSDate::GetField(Object* object, Smi* index) {
16336   return JSDate::cast(object)->DoGetField(
16337       static_cast<FieldIndex>(index->value()));
16338 }
16339
16340
16341 Object* JSDate::DoGetField(FieldIndex index) {
16342   ASSERT(index != kDateValue);
16343
16344   DateCache* date_cache = GetIsolate()->date_cache();
16345
16346   if (index < kFirstUncachedField) {
16347     Object* stamp = cache_stamp();
16348     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
16349       // Since the stamp is not NaN, the value is also not NaN.
16350       int64_t local_time_ms =
16351           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
16352       SetLocalFields(local_time_ms, date_cache);
16353     }
16354     switch (index) {
16355       case kYear: return year();
16356       case kMonth: return month();
16357       case kDay: return day();
16358       case kWeekday: return weekday();
16359       case kHour: return hour();
16360       case kMinute: return min();
16361       case kSecond: return sec();
16362       default: UNREACHABLE();
16363     }
16364   }
16365
16366   if (index >= kFirstUTCField) {
16367     return GetUTCField(index, value()->Number(), date_cache);
16368   }
16369
16370   double time = value()->Number();
16371   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
16372
16373   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
16374   int days = DateCache::DaysFromTime(local_time_ms);
16375
16376   if (index == kDays) return Smi::FromInt(days);
16377
16378   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16379   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
16380   ASSERT(index == kTimeInDay);
16381   return Smi::FromInt(time_in_day_ms);
16382 }
16383
16384
16385 Object* JSDate::GetUTCField(FieldIndex index,
16386                             double value,
16387                             DateCache* date_cache) {
16388   ASSERT(index >= kFirstUTCField);
16389
16390   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
16391
16392   int64_t time_ms = static_cast<int64_t>(value);
16393
16394   if (index == kTimezoneOffset) {
16395     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
16396   }
16397
16398   int days = DateCache::DaysFromTime(time_ms);
16399
16400   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
16401
16402   if (index <= kDayUTC) {
16403     int year, month, day;
16404     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16405     if (index == kYearUTC) return Smi::FromInt(year);
16406     if (index == kMonthUTC) return Smi::FromInt(month);
16407     ASSERT(index == kDayUTC);
16408     return Smi::FromInt(day);
16409   }
16410
16411   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
16412   switch (index) {
16413     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
16414     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
16415     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
16416     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
16417     case kDaysUTC: return Smi::FromInt(days);
16418     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
16419     default: UNREACHABLE();
16420   }
16421
16422   UNREACHABLE();
16423   return NULL;
16424 }
16425
16426
16427 void JSDate::SetValue(Object* value, bool is_value_nan) {
16428   set_value(value);
16429   if (is_value_nan) {
16430     HeapNumber* nan = GetIsolate()->heap()->nan_value();
16431     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
16432     set_year(nan, SKIP_WRITE_BARRIER);
16433     set_month(nan, SKIP_WRITE_BARRIER);
16434     set_day(nan, SKIP_WRITE_BARRIER);
16435     set_hour(nan, SKIP_WRITE_BARRIER);
16436     set_min(nan, SKIP_WRITE_BARRIER);
16437     set_sec(nan, SKIP_WRITE_BARRIER);
16438     set_weekday(nan, SKIP_WRITE_BARRIER);
16439   } else {
16440     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
16441   }
16442 }
16443
16444
16445 void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) {
16446   int days = DateCache::DaysFromTime(local_time_ms);
16447   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16448   int year, month, day;
16449   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16450   int weekday = date_cache->Weekday(days);
16451   int hour = time_in_day_ms / (60 * 60 * 1000);
16452   int min = (time_in_day_ms / (60 * 1000)) % 60;
16453   int sec = (time_in_day_ms / 1000) % 60;
16454   set_cache_stamp(date_cache->stamp());
16455   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
16456   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
16457   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
16458   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
16459   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
16460   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
16461   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
16462 }
16463
16464
16465 void JSArrayBuffer::Neuter() {
16466   ASSERT(is_external());
16467   set_backing_store(NULL);
16468   set_byte_length(Smi::FromInt(0));
16469 }
16470
16471
16472 void JSArrayBufferView::NeuterView() {
16473   set_byte_offset(Smi::FromInt(0));
16474   set_byte_length(Smi::FromInt(0));
16475 }
16476
16477
16478 void JSDataView::Neuter() {
16479   NeuterView();
16480 }
16481
16482
16483 void JSTypedArray::Neuter() {
16484   NeuterView();
16485   set_length(Smi::FromInt(0));
16486   set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
16487 }
16488
16489
16490 static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) {
16491   switch (elements_kind) {
16492 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
16493     case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
16494
16495     TYPED_ARRAYS(TYPED_ARRAY_CASE)
16496 #undef TYPED_ARRAY_CASE
16497
16498     default:
16499       UNREACHABLE();
16500       return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
16501   }
16502 }
16503
16504
16505 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
16506     Handle<JSTypedArray> typed_array) {
16507
16508   Handle<Map> map(typed_array->map());
16509   Isolate* isolate = typed_array->GetIsolate();
16510
16511   ASSERT(IsFixedTypedArrayElementsKind(map->elements_kind()));
16512
16513   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
16514   Handle<FixedTypedArrayBase> fixed_typed_array(
16515       FixedTypedArrayBase::cast(typed_array->elements()));
16516   Runtime::SetupArrayBufferAllocatingData(isolate, buffer,
16517       fixed_typed_array->DataSize(), false);
16518   memcpy(buffer->backing_store(),
16519          fixed_typed_array->DataPtr(),
16520          fixed_typed_array->DataSize());
16521   Handle<ExternalArray> new_elements =
16522       isolate->factory()->NewExternalArray(
16523           fixed_typed_array->length(), typed_array->type(),
16524           static_cast<uint8_t*>(buffer->backing_store()));
16525   Handle<Map> new_map = JSObject::GetElementsTransitionMap(
16526           typed_array,
16527           FixedToExternalElementsKind(map->elements_kind()));
16528
16529   buffer->set_weak_first_view(*typed_array);
16530   ASSERT(typed_array->weak_next() == isolate->heap()->undefined_value());
16531   typed_array->set_buffer(*buffer);
16532   typed_array->set_map_and_elements(*new_map, *new_elements);
16533
16534   return buffer;
16535 }
16536
16537
16538 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
16539   Handle<Object> result(buffer(), GetIsolate());
16540   if (*result != Smi::FromInt(0)) {
16541     ASSERT(IsExternalArrayElementsKind(map()->elements_kind()));
16542     return Handle<JSArrayBuffer>::cast(result);
16543   }
16544   Handle<JSTypedArray> self(this);
16545   return MaterializeArrayBuffer(self);
16546 }
16547
16548
16549 HeapType* PropertyCell::type() {
16550   return static_cast<HeapType*>(type_raw());
16551 }
16552
16553
16554 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) {
16555   ASSERT(IsPropertyCell());
16556   set_type_raw(type, ignored);
16557 }
16558
16559
16560 Handle<HeapType> PropertyCell::UpdatedType(Handle<PropertyCell> cell,
16561                                            Handle<Object> value) {
16562   Isolate* isolate = cell->GetIsolate();
16563   Handle<HeapType> old_type(cell->type(), isolate);
16564   // TODO(2803): Do not track ConsString as constant because they cannot be
16565   // embedded into code.
16566   Handle<HeapType> new_type = value->IsConsString() || value->IsTheHole()
16567       ? HeapType::Any(isolate) : HeapType::Constant(value, isolate);
16568
16569   if (new_type->Is(old_type)) {
16570     return old_type;
16571   }
16572
16573   cell->dependent_code()->DeoptimizeDependentCodeGroup(
16574       isolate, DependentCode::kPropertyCellChangedGroup);
16575
16576   if (old_type->Is(HeapType::None()) || old_type->Is(HeapType::Undefined())) {
16577     return new_type;
16578   }
16579
16580   return HeapType::Any(isolate);
16581 }
16582
16583
16584 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell,
16585                                      Handle<Object> value) {
16586   cell->set_value(*value);
16587   if (!HeapType::Any()->Is(cell->type())) {
16588     Handle<HeapType> new_type = UpdatedType(cell, value);
16589     cell->set_type(*new_type);
16590   }
16591 }
16592
16593
16594 void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) {
16595   Handle<DependentCode> dep(dependent_code());
16596   Handle<DependentCode> codes =
16597       DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup,
16598                             info->object_wrapper());
16599   if (*codes != dependent_code()) set_dependent_code(*codes);
16600   info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
16601       Handle<HeapObject>(this), info->zone());
16602 }
16603
16604
16605 const char* GetBailoutReason(BailoutReason reason) {
16606   ASSERT(reason < kLastErrorMessage);
16607 #define ERROR_MESSAGES_TEXTS(C, T) T,
16608   static const char* error_messages_[] = {
16609       ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16610   };
16611 #undef ERROR_MESSAGES_TEXTS
16612   return error_messages_[reason];
16613 }
16614
16615
16616 } }  // namespace v8::internal