1// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/v8.h"
6
7#include "src/accessors.h"
8#include "src/allocation-site-scopes.h"
9#include "src/api.h"
10#include "src/arguments.h"
11#include "src/base/bits.h"
12#include "src/bootstrapper.h"
13#include "src/code-stubs.h"
14#include "src/codegen.h"
15#include "src/cpu-profiler.h"
16#include "src/date.h"
17#include "src/debug.h"
18#include "src/deoptimizer.h"
19#include "src/elements.h"
20#include "src/execution.h"
21#include "src/field-index-inl.h"
22#include "src/field-index.h"
23#include "src/full-codegen.h"
24#include "src/heap/mark-compact.h"
25#include "src/heap/objects-visiting-inl.h"
26#include "src/hydrogen.h"
27#include "src/ic/ic.h"
28#include "src/isolate-inl.h"
29#include "src/log.h"
30#include "src/lookup.h"
31#include "src/macro-assembler.h"
32#include "src/objects-inl.h"
33#include "src/prototype.h"
34#include "src/safepoint-table.h"
35#include "src/string-search.h"
36#include "src/string-stream.h"
37#include "src/utils.h"
38
39#ifdef ENABLE_DISASSEMBLER
40#include "src/disasm.h"
41#include "src/disassembler.h"
42#endif
43
44namespace v8 {
45namespace internal {
46
47Handle<HeapType> Object::OptimalType(Isolate* isolate,
48                                     Representation representation) {
49  if (representation.IsNone()) return HeapType::None(isolate);
50  if (FLAG_track_field_types) {
51    if (representation.IsHeapObject() && IsHeapObject()) {
52      // We can track only JavaScript objects with stable maps.
53      Handle<Map> map(HeapObject::cast(this)->map(), isolate);
54      if (map->is_stable() &&
55          map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
56          map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) {
57        return HeapType::Class(map, isolate);
58      }
59    }
60  }
61  return HeapType::Any(isolate);
62}
63
64
65MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
66                                         Handle<Object> object,
67                                         Handle<Context> native_context) {
68  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
69  Handle<JSFunction> constructor;
70  if (object->IsNumber()) {
71    constructor = handle(native_context->number_function(), isolate);
72  } else if (object->IsBoolean()) {
73    constructor = handle(native_context->boolean_function(), isolate);
74  } else if (object->IsString()) {
75    constructor = handle(native_context->string_function(), isolate);
76  } else if (object->IsSymbol()) {
77    constructor = handle(native_context->symbol_function(), isolate);
78  } else {
79    return MaybeHandle<JSReceiver>();
80  }
81  Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
82  Handle<JSValue>::cast(result)->set_value(*object);
83  return result;
84}
85
86
87bool Object::BooleanValue() {
88  if (IsBoolean()) return IsTrue();
89  if (IsSmi()) return Smi::cast(this)->value() != 0;
90  if (IsUndefined() || IsNull()) return false;
91  if (IsUndetectableObject()) return false;   // Undetectable object is false.
92  if (IsString()) return String::cast(this)->length() != 0;
93  if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
94  return true;
95}
96
97
98bool Object::IsCallable() const {
99  const Object* fun = this;
100  while (fun->IsJSFunctionProxy()) {
101    fun = JSFunctionProxy::cast(fun)->call_trap();
102  }
103  return fun->IsJSFunction() ||
104         (fun->IsHeapObject() &&
105          HeapObject::cast(fun)->map()->has_instance_call_handler());
106}
107
108
109MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
110  for (; it->IsFound(); it->Next()) {
111    switch (it->state()) {
112      case LookupIterator::NOT_FOUND:
113      case LookupIterator::TRANSITION:
114        UNREACHABLE();
115      case LookupIterator::JSPROXY:
116        return JSProxy::GetPropertyWithHandler(it->GetHolder<JSProxy>(),
117                                               it->GetReceiver(), it->name());
118      case LookupIterator::INTERCEPTOR: {
119        MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithInterceptor(
120            it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
121        if (!maybe_result.is_null()) return maybe_result;
122        if (it->isolate()->has_pending_exception()) return maybe_result;
123        break;
124      }
125      case LookupIterator::ACCESS_CHECK:
126        if (it->HasAccess(v8::ACCESS_GET)) break;
127        return JSObject::GetPropertyWithFailedAccessCheck(it);
128      case LookupIterator::ACCESSOR:
129        return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
130                                       it->GetHolder<JSObject>(),
131                                       it->GetAccessors());
132      case LookupIterator::DATA:
133        return it->GetDataValue();
134    }
135  }
136  return it->factory()->undefined_value();
137}
138
139
140Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
141                                         Handle<Name> key) {
142  LookupIterator it(object, key,
143                    LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
144  return GetDataProperty(&it);
145}
146
147
148Handle<Object> JSObject::GetDataProperty(LookupIterator* it) {
149  for (; it->IsFound(); it->Next()) {
150    switch (it->state()) {
151      case LookupIterator::INTERCEPTOR:
152      case LookupIterator::NOT_FOUND:
153      case LookupIterator::TRANSITION:
154        UNREACHABLE();
155      case LookupIterator::ACCESS_CHECK:
156        if (it->HasAccess(v8::ACCESS_GET)) continue;
157      // Fall through.
158      case LookupIterator::JSPROXY:
159        it->NotFound();
160        return it->isolate()->factory()->undefined_value();
161      case LookupIterator::ACCESSOR:
162        // TODO(verwaest): For now this doesn't call into
163        // ExecutableAccessorInfo, since clients don't need it. Update once
164        // relevant.
165        it->NotFound();
166        return it->isolate()->factory()->undefined_value();
167      case LookupIterator::DATA:
168        return it->GetDataValue();
169    }
170  }
171  return it->isolate()->factory()->undefined_value();
172}
173
174
175bool Object::ToInt32(int32_t* value) {
176  if (IsSmi()) {
177    *value = Smi::cast(this)->value();
178    return true;
179  }
180  if (IsHeapNumber()) {
181    double num = HeapNumber::cast(this)->value();
182    if (FastI2D(FastD2I(num)) == num) {
183      *value = FastD2I(num);
184      return true;
185    }
186  }
187  return false;
188}
189
190
191bool Object::ToUint32(uint32_t* value) {
192  if (IsSmi()) {
193    int num = Smi::cast(this)->value();
194    if (num >= 0) {
195      *value = static_cast<uint32_t>(num);
196      return true;
197    }
198  }
199  if (IsHeapNumber()) {
200    double num = HeapNumber::cast(this)->value();
201    if (num >= 0 && FastUI2D(FastD2UI(num)) == num) {
202      *value = FastD2UI(num);
203      return true;
204    }
205  }
206  return false;
207}
208
209
210bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
211  if (!object->IsHeapObject()) return false;
212  return IsTemplateFor(HeapObject::cast(object)->map());
213}
214
215
216bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
217  // There is a constraint on the object; check.
218  if (!map->IsJSObjectMap()) return false;
219  // Fetch the constructor function of the object.
220  Object* cons_obj = map->constructor();
221  if (!cons_obj->IsJSFunction()) return false;
222  JSFunction* fun = JSFunction::cast(cons_obj);
223  // Iterate through the chain of inheriting function templates to
224  // see if the required one occurs.
225  for (Object* type = fun->shared()->function_data();
226       type->IsFunctionTemplateInfo();
227       type = FunctionTemplateInfo::cast(type)->parent_template()) {
228    if (type == this) return true;
229  }
230  // Didn't find the required type in the inheritance chain.
231  return false;
232}
233
234
235template<typename To>
236static inline To* CheckedCast(void *from) {
237  uintptr_t temp = reinterpret_cast<uintptr_t>(from);
238  DCHECK(temp % sizeof(To) == 0);
239  return reinterpret_cast<To*>(temp);
240}
241
242
243static Handle<Object> PerformCompare(const BitmaskCompareDescriptor& descriptor,
244                                     char* ptr,
245                                     Isolate* isolate) {
246  uint32_t bitmask = descriptor.bitmask;
247  uint32_t compare_value = descriptor.compare_value;
248  uint32_t value;
249  switch (descriptor.size) {
250    case 1:
251      value = static_cast<uint32_t>(*CheckedCast<uint8_t>(ptr));
252      compare_value &= 0xff;
253      bitmask &= 0xff;
254      break;
255    case 2:
256      value = static_cast<uint32_t>(*CheckedCast<uint16_t>(ptr));
257      compare_value &= 0xffff;
258      bitmask &= 0xffff;
259      break;
260    case 4:
261      value = *CheckedCast<uint32_t>(ptr);
262      break;
263    default:
264      UNREACHABLE();
265      return isolate->factory()->undefined_value();
266  }
267  return isolate->factory()->ToBoolean(
268      (bitmask & value) == (bitmask & compare_value));
269}
270
271
272static Handle<Object> PerformCompare(const PointerCompareDescriptor& descriptor,
273                                     char* ptr,
274                                     Isolate* isolate) {
275  uintptr_t compare_value =
276      reinterpret_cast<uintptr_t>(descriptor.compare_value);
277  uintptr_t value = *CheckedCast<uintptr_t>(ptr);
278  return isolate->factory()->ToBoolean(compare_value == value);
279}
280
281
282static Handle<Object> GetPrimitiveValue(
283    const PrimitiveValueDescriptor& descriptor,
284    char* ptr,
285    Isolate* isolate) {
286  int32_t int32_value = 0;
287  switch (descriptor.data_type) {
288    case kDescriptorInt8Type:
289      int32_value = *CheckedCast<int8_t>(ptr);
290      break;
291    case kDescriptorUint8Type:
292      int32_value = *CheckedCast<uint8_t>(ptr);
293      break;
294    case kDescriptorInt16Type:
295      int32_value = *CheckedCast<int16_t>(ptr);
296      break;
297    case kDescriptorUint16Type:
298      int32_value = *CheckedCast<uint16_t>(ptr);
299      break;
300    case kDescriptorInt32Type:
301      int32_value = *CheckedCast<int32_t>(ptr);
302      break;
303    case kDescriptorUint32Type: {
304      uint32_t value = *CheckedCast<uint32_t>(ptr);
305      AllowHeapAllocation allow_gc;
306      return isolate->factory()->NewNumberFromUint(value);
307    }
308    case kDescriptorBoolType: {
309      uint8_t byte = *CheckedCast<uint8_t>(ptr);
310      return isolate->factory()->ToBoolean(
311          byte & (0x1 << descriptor.bool_offset));
312    }
313    case kDescriptorFloatType: {
314      float value = *CheckedCast<float>(ptr);
315      AllowHeapAllocation allow_gc;
316      return isolate->factory()->NewNumber(value);
317    }
318    case kDescriptorDoubleType: {
319      double value = *CheckedCast<double>(ptr);
320      AllowHeapAllocation allow_gc;
321      return isolate->factory()->NewNumber(value);
322    }
323  }
324  AllowHeapAllocation allow_gc;
325  return isolate->factory()->NewNumberFromInt(int32_value);
326}
327
328
329static Handle<Object> GetDeclaredAccessorProperty(
330    Handle<Object> receiver,
331    Handle<DeclaredAccessorInfo> info,
332    Isolate* isolate) {
333  DisallowHeapAllocation no_gc;
334  char* current = reinterpret_cast<char*>(*receiver);
335  DeclaredAccessorDescriptorIterator iterator(info->descriptor());
336  while (true) {
337    const DeclaredAccessorDescriptorData* data = iterator.Next();
338    switch (data->type) {
339      case kDescriptorReturnObject: {
340        DCHECK(iterator.Complete());
341        current = *CheckedCast<char*>(current);
342        return handle(*CheckedCast<Object*>(current), isolate);
343      }
344      case kDescriptorPointerDereference:
345        DCHECK(!iterator.Complete());
346        current = *reinterpret_cast<char**>(current);
347        break;
348      case kDescriptorPointerShift:
349        DCHECK(!iterator.Complete());
350        current += data->pointer_shift_descriptor.byte_offset;
351        break;
352      case kDescriptorObjectDereference: {
353        DCHECK(!iterator.Complete());
354        Object* object = CheckedCast<Object>(current);
355        int field = data->object_dereference_descriptor.internal_field;
356        Object* smi = JSObject::cast(object)->GetInternalField(field);
357        DCHECK(smi->IsSmi());
358        current = reinterpret_cast<char*>(smi);
359        break;
360      }
361      case kDescriptorBitmaskCompare:
362        DCHECK(iterator.Complete());
363        return PerformCompare(data->bitmask_compare_descriptor,
364                              current,
365                              isolate);
366      case kDescriptorPointerCompare:
367        DCHECK(iterator.Complete());
368        return PerformCompare(data->pointer_compare_descriptor,
369                              current,
370                              isolate);
371      case kDescriptorPrimitiveValue:
372        DCHECK(iterator.Complete());
373        return GetPrimitiveValue(data->primitive_value_descriptor,
374                                 current,
375                                 isolate);
376    }
377  }
378  UNREACHABLE();
379  return isolate->factory()->undefined_value();
380}
381
382
383Handle<FixedArray> JSObject::EnsureWritableFastElements(
384    Handle<JSObject> object) {
385  DCHECK(object->HasFastSmiOrObjectElements());
386  Isolate* isolate = object->GetIsolate();
387  Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
388  if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
389  Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
390      elems, isolate->factory()->fixed_array_map());
391  object->set_elements(*writable_elems);
392  isolate->counters()->cow_arrays_converted()->Increment();
393  return writable_elems;
394}
395
396
397MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
398                                                    Handle<Object> receiver,
399                                                    Handle<Name> name) {
400  Isolate* isolate = proxy->GetIsolate();
401
402  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
403  if (name->IsSymbol()) return isolate->factory()->undefined_value();
404
405  Handle<Object> args[] = { receiver, name };
406  return CallTrap(
407      proxy, "get",  isolate->derived_get_trap(), arraysize(args), args);
408}
409
410
411MaybeHandle<Object> Object::GetPropertyWithAccessor(Handle<Object> receiver,
412                                                    Handle<Name> name,
413                                                    Handle<JSObject> holder,
414                                                    Handle<Object> structure) {
415  Isolate* isolate = name->GetIsolate();
416  DCHECK(!structure->IsForeign());
417  // api style callbacks.
418  if (structure->IsAccessorInfo()) {
419    Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
420    if (!info->IsCompatibleReceiver(*receiver)) {
421      Handle<Object> args[2] = { name, receiver };
422      THROW_NEW_ERROR(isolate,
423                      NewTypeError("incompatible_method_receiver",
424                                   HandleVector(args, arraysize(args))),
425                      Object);
426    }
427    if (structure->IsDeclaredAccessorInfo()) {
428      return GetDeclaredAccessorProperty(
429          receiver,
430          Handle<DeclaredAccessorInfo>::cast(structure),
431          isolate);
432    }
433
434    Handle<ExecutableAccessorInfo> data =
435        Handle<ExecutableAccessorInfo>::cast(structure);
436    v8::AccessorNameGetterCallback call_fun =
437        v8::ToCData<v8::AccessorNameGetterCallback>(data->getter());
438    if (call_fun == NULL) return isolate->factory()->undefined_value();
439
440    LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
441    PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
442    v8::Handle<v8::Value> result =
443        args.Call(call_fun, v8::Utils::ToLocal(name));
444    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
445    if (result.IsEmpty()) {
446      return isolate->factory()->undefined_value();
447    }
448    Handle<Object> return_value = v8::Utils::OpenHandle(*result);
449    return_value->VerifyApiCallResultType();
450    // Rebox handle before return.
451    return handle(*return_value, isolate);
452  }
453
454  // __defineGetter__ callback
455  Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
456                        isolate);
457  if (getter->IsSpecFunction()) {
458    // TODO(rossberg): nicer would be to cast to some JSCallable here...
459    return Object::GetPropertyWithDefinedGetter(
460        receiver, Handle<JSReceiver>::cast(getter));
461  }
462  // Getter is not a function.
463  return isolate->factory()->undefined_value();
464}
465
466
467bool AccessorInfo::IsCompatibleReceiverType(Isolate* isolate,
468                                            Handle<AccessorInfo> info,
469                                            Handle<HeapType> type) {
470  if (!info->HasExpectedReceiverType()) return true;
471  Handle<Map> map = IC::TypeToMap(*type, isolate);
472  if (!map->IsJSObjectMap()) return false;
473  return FunctionTemplateInfo::cast(info->expected_receiver_type())
474      ->IsTemplateFor(*map);
475}
476
477
478MaybeHandle<Object> Object::SetPropertyWithAccessor(
479    Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
480    Handle<JSObject> holder, Handle<Object> structure, StrictMode strict_mode) {
481  Isolate* isolate = name->GetIsolate();
482
483  // We should never get here to initialize a const with the hole
484  // value since a const declaration would conflict with the setter.
485  DCHECK(!structure->IsForeign());
486  if (structure->IsExecutableAccessorInfo()) {
487    // Don't call executable accessor setters with non-JSObject receivers.
488    if (!receiver->IsJSObject()) return value;
489    // api style callbacks
490    ExecutableAccessorInfo* info = ExecutableAccessorInfo::cast(*structure);
491    if (!info->IsCompatibleReceiver(*receiver)) {
492      Handle<Object> args[2] = { name, receiver };
493      THROW_NEW_ERROR(isolate,
494                      NewTypeError("incompatible_method_receiver",
495                                   HandleVector(args, arraysize(args))),
496                      Object);
497    }
498    Object* call_obj = info->setter();
499    v8::AccessorNameSetterCallback call_fun =
500        v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
501    if (call_fun == NULL) return value;
502    LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
503    PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder);
504    args.Call(call_fun,
505              v8::Utils::ToLocal(name),
506              v8::Utils::ToLocal(value));
507    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
508    return value;
509  }
510
511  if (structure->IsAccessorPair()) {
512    Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
513    if (setter->IsSpecFunction()) {
514      // TODO(rossberg): nicer would be to cast to some JSCallable here...
515      return SetPropertyWithDefinedSetter(
516          receiver, Handle<JSReceiver>::cast(setter), value);
517    } else {
518      if (strict_mode == SLOPPY) return value;
519      Handle<Object> args[2] = { name, holder };
520      THROW_NEW_ERROR(
521          isolate, NewTypeError("no_setter_in_callback", HandleVector(args, 2)),
522          Object);
523    }
524  }
525
526  // TODO(dcarney): Handle correctly.
527  if (structure->IsDeclaredAccessorInfo()) {
528    return value;
529  }
530
531  UNREACHABLE();
532  return MaybeHandle<Object>();
533}
534
535
536MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
537    Handle<Object> receiver,
538    Handle<JSReceiver> getter) {
539  Isolate* isolate = getter->GetIsolate();
540  Debug* debug = isolate->debug();
541  // Handle stepping into a getter if step into is active.
542  // TODO(rossberg): should this apply to getters that are function proxies?
543  if (debug->StepInActive() && getter->IsJSFunction()) {
544    debug->HandleStepIn(
545        Handle<JSFunction>::cast(getter), Handle<Object>::null(), 0, false);
546  }
547
548  return Execution::Call(isolate, getter, receiver, 0, NULL, true);
549}
550
551
552MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
553    Handle<Object> receiver,
554    Handle<JSReceiver> setter,
555    Handle<Object> value) {
556  Isolate* isolate = setter->GetIsolate();
557
558  Debug* debug = isolate->debug();
559  // Handle stepping into a setter if step into is active.
560  // TODO(rossberg): should this apply to getters that are function proxies?
561  if (debug->StepInActive() && setter->IsJSFunction()) {
562    debug->HandleStepIn(
563        Handle<JSFunction>::cast(setter), Handle<Object>::null(), 0, false);
564  }
565
566  Handle<Object> argv[] = { value };
567  RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver,
568                                               arraysize(argv), argv, true),
569                      Object);
570  return value;
571}
572
573
574static bool FindAllCanReadHolder(LookupIterator* it) {
575  for (; it->IsFound(); it->Next()) {
576    if (it->state() == LookupIterator::ACCESSOR) {
577      Handle<Object> accessors = it->GetAccessors();
578      if (accessors->IsAccessorInfo()) {
579        if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
580      }
581    }
582  }
583  return false;
584}
585
586
587MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
588    LookupIterator* it) {
589  Handle<JSObject> checked = it->GetHolder<JSObject>();
590  if (FindAllCanReadHolder(it)) {
591    return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
592                                   it->GetHolder<JSObject>(),
593                                   it->GetAccessors());
594  }
595  it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET);
596  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
597  return it->factory()->undefined_value();
598}
599
600
601Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
602    LookupIterator* it) {
603  Handle<JSObject> checked = it->GetHolder<JSObject>();
604  if (FindAllCanReadHolder(it))
605    return maybe(it->property_details().attributes());
606  it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
607  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
608                                      Maybe<PropertyAttributes>());
609  return maybe(ABSENT);
610}
611
612
613static bool FindAllCanWriteHolder(LookupIterator* it) {
614  for (; it->IsFound(); it->Next()) {
615    if (it->state() == LookupIterator::ACCESSOR) {
616      Handle<Object> accessors = it->GetAccessors();
617      if (accessors->IsAccessorInfo()) {
618        if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
619      }
620    }
621  }
622  return false;
623}
624
625
626MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
627    LookupIterator* it, Handle<Object> value, StrictMode strict_mode) {
628  Handle<JSObject> checked = it->GetHolder<JSObject>();
629  if (FindAllCanWriteHolder(it)) {
630    return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
631                                   it->GetHolder<JSObject>(),
632                                   it->GetAccessors(), strict_mode);
633  }
634
635  it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_SET);
636  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
637  return value;
638}
639
640
641void JSObject::SetNormalizedProperty(Handle<JSObject> object,
642                                     Handle<Name> name,
643                                     Handle<Object> value,
644                                     PropertyDetails details) {
645  DCHECK(!object->HasFastProperties());
646  Handle<NameDictionary> property_dictionary(object->property_dictionary());
647
648  if (!name->IsUniqueName()) {
649    name = object->GetIsolate()->factory()->InternalizeString(
650        Handle<String>::cast(name));
651  }
652
653  int entry = property_dictionary->FindEntry(name);
654  if (entry == NameDictionary::kNotFound) {
655    Handle<Object> store_value = value;
656    if (object->IsGlobalObject()) {
657      store_value = object->GetIsolate()->factory()->NewPropertyCell(value);
658    }
659
660    property_dictionary = NameDictionary::Add(
661        property_dictionary, name, store_value, details);
662    object->set_properties(*property_dictionary);
663    return;
664  }
665
666  PropertyDetails original_details = property_dictionary->DetailsAt(entry);
667  int enumeration_index;
668  // Preserve the enumeration index unless the property was deleted.
669  if (original_details.IsDeleted()) {
670    enumeration_index = property_dictionary->NextEnumerationIndex();
671    property_dictionary->SetNextEnumerationIndex(enumeration_index + 1);
672  } else {
673    enumeration_index = original_details.dictionary_index();
674    DCHECK(enumeration_index > 0);
675  }
676
677  details = PropertyDetails(
678      details.attributes(), details.type(), enumeration_index);
679
680  if (object->IsGlobalObject()) {
681    Handle<PropertyCell> cell(
682        PropertyCell::cast(property_dictionary->ValueAt(entry)));
683    PropertyCell::SetValueInferType(cell, value);
684    // Please note we have to update the property details.
685    property_dictionary->DetailsAtPut(entry, details);
686  } else {
687    property_dictionary->SetEntry(entry, name, value, details);
688  }
689}
690
691
692Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
693                                                  Handle<Name> name,
694                                                  DeleteMode mode) {
695  DCHECK(!object->HasFastProperties());
696  Isolate* isolate = object->GetIsolate();
697  Handle<NameDictionary> dictionary(object->property_dictionary());
698  int entry = dictionary->FindEntry(name);
699  if (entry != NameDictionary::kNotFound) {
700    // If we have a global object set the cell to the hole.
701    if (object->IsGlobalObject()) {
702      PropertyDetails details = dictionary->DetailsAt(entry);
703      if (!details.IsConfigurable()) {
704        if (mode != FORCE_DELETION) return isolate->factory()->false_value();
705        // When forced to delete global properties, we have to make a
706        // map change to invalidate any ICs that think they can load
707        // from the non-configurable cell without checking if it contains
708        // the hole value.
709        Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
710        DCHECK(new_map->is_dictionary_map());
711        JSObject::MigrateToMap(object, new_map);
712      }
713      Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
714      Handle<Object> value = isolate->factory()->the_hole_value();
715      PropertyCell::SetValueInferType(cell, value);
716      dictionary->DetailsAtPut(entry, details.AsDeleted());
717    } else {
718      Handle<Object> deleted(
719          NameDictionary::DeleteProperty(dictionary, entry, mode));
720      if (*deleted == isolate->heap()->true_value()) {
721        Handle<NameDictionary> new_properties =
722            NameDictionary::Shrink(dictionary, name);
723        object->set_properties(*new_properties);
724      }
725      return deleted;
726    }
727  }
728  return isolate->factory()->true_value();
729}
730
731
732bool JSObject::IsDirty() {
733  Object* cons_obj = map()->constructor();
734  if (!cons_obj->IsJSFunction())
735    return true;
736  JSFunction* fun = JSFunction::cast(cons_obj);
737  if (!fun->shared()->IsApiFunction())
738    return true;
739  // If the object is fully fast case and has the same map it was
740  // created with then no changes can have been made to it.
741  return map() != fun->initial_map()
742      || !HasFastObjectElements()
743      || !HasFastProperties();
744}
745
746
747MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
748                                                   Handle<Object> object,
749                                                   Handle<Object> receiver,
750                                                   uint32_t index) {
751  if (object->IsUndefined()) {
752    // TODO(verwaest): Why is this check here?
753    UNREACHABLE();
754    return isolate->factory()->undefined_value();
755  }
756
757  // Iterate up the prototype chain until an element is found or the null
758  // prototype is encountered.
759  for (PrototypeIterator iter(isolate, object,
760                              object->IsJSProxy() || object->IsJSObject()
761                                  ? PrototypeIterator::START_AT_RECEIVER
762                                  : PrototypeIterator::START_AT_PROTOTYPE);
763       !iter.IsAtEnd(); iter.Advance()) {
764    if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
765      return JSProxy::GetElementWithHandler(
766          Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
767          index);
768    }
769
770    // Inline the case for JSObjects. Doing so significantly improves the
771    // performance of fetching elements where checking the prototype chain is
772    // necessary.
773    Handle<JSObject> js_object =
774        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
775
776    // Check access rights if needed.
777    if (js_object->IsAccessCheckNeeded()) {
778      if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
779        isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
780        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
781        return isolate->factory()->undefined_value();
782      }
783    }
784
785    if (js_object->HasIndexedInterceptor()) {
786      return JSObject::GetElementWithInterceptor(js_object, receiver, index);
787    }
788
789    if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
790      Handle<Object> result;
791      ASSIGN_RETURN_ON_EXCEPTION(
792          isolate, result,
793          js_object->GetElementsAccessor()->Get(receiver, js_object, index),
794          Object);
795      if (!result->IsTheHole()) return result;
796    }
797  }
798
799  return isolate->factory()->undefined_value();
800}
801
802
803Map* Object::GetRootMap(Isolate* isolate) {
804  DisallowHeapAllocation no_alloc;
805  if (IsSmi()) {
806    Context* context = isolate->context()->native_context();
807    return context->number_function()->initial_map();
808  }
809
810  HeapObject* heap_object = HeapObject::cast(this);
811
812  // The object is either a number, a string, a boolean,
813  // a real JS object, or a Harmony proxy.
814  if (heap_object->IsJSReceiver()) {
815    return heap_object->map();
816  }
817  Context* context = isolate->context()->native_context();
818
819  if (heap_object->IsHeapNumber()) {
820    return context->number_function()->initial_map();
821  }
822  if (heap_object->IsString()) {
823    return context->string_function()->initial_map();
824  }
825  if (heap_object->IsSymbol()) {
826    return context->symbol_function()->initial_map();
827  }
828  if (heap_object->IsBoolean()) {
829    return context->boolean_function()->initial_map();
830  }
831  return isolate->heap()->null_value()->map();
832}
833
834
835Object* Object::GetHash() {
836  // The object is either a number, a name, an odd-ball,
837  // a real JS object, or a Harmony proxy.
838  if (IsNumber()) {
839    uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
840    return Smi::FromInt(hash & Smi::kMaxValue);
841  }
842  if (IsName()) {
843    uint32_t hash = Name::cast(this)->Hash();
844    return Smi::FromInt(hash);
845  }
846  if (IsOddball()) {
847    uint32_t hash = Oddball::cast(this)->to_string()->Hash();
848    return Smi::FromInt(hash);
849  }
850
851  DCHECK(IsJSReceiver());
852  return JSReceiver::cast(this)->GetIdentityHash();
853}
854
855
856Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
857  Handle<Object> hash(object->GetHash(), isolate);
858  if (hash->IsSmi()) return Handle<Smi>::cast(hash);
859
860  DCHECK(object->IsJSReceiver());
861  return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
862}
863
864
865bool Object::SameValue(Object* other) {
866  if (other == this) return true;
867
868  // The object is either a number, a name, an odd-ball,
869  // a real JS object, or a Harmony proxy.
870  if (IsNumber() && other->IsNumber()) {
871    double this_value = Number();
872    double other_value = other->Number();
873    bool equal = this_value == other_value;
874    // SameValue(NaN, NaN) is true.
875    if (!equal) return std::isnan(this_value) && std::isnan(other_value);
876    // SameValue(0.0, -0.0) is false.
877    return (this_value != 0) || ((1 / this_value) == (1 / other_value));
878  }
879  if (IsString() && other->IsString()) {
880    return String::cast(this)->Equals(String::cast(other));
881  }
882  return false;
883}
884
885
886bool Object::SameValueZero(Object* other) {
887  if (other == this) return true;
888
889  // The object is either a number, a name, an odd-ball,
890  // a real JS object, or a Harmony proxy.
891  if (IsNumber() && other->IsNumber()) {
892    double this_value = Number();
893    double other_value = other->Number();
894    // +0 == -0 is true
895    return this_value == other_value
896        || (std::isnan(this_value) && std::isnan(other_value));
897  }
898  if (IsString() && other->IsString()) {
899    return String::cast(this)->Equals(String::cast(other));
900  }
901  return false;
902}
903
904
905void Object::ShortPrint(FILE* out) {
906  OFStream os(out);
907  os << Brief(this);
908}
909
910
911void Object::ShortPrint(StringStream* accumulator) {
912  OStringStream os;
913  os << Brief(this);
914  accumulator->Add(os.c_str());
915}
916
917
918OStream& operator<<(OStream& os, const Brief& v) {
919  if (v.value->IsSmi()) {
920    Smi::cast(v.value)->SmiPrint(os);
921  } else {
922    // TODO(svenpanne) Const-correct HeapObjectShortPrint!
923    HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
924    obj->HeapObjectShortPrint(os);
925  }
926  return os;
927}
928
929
930void Smi::SmiPrint(OStream& os) const {  // NOLINT
931  os << value();
932}
933
934
935// Should a word be prefixed by 'a' or 'an' in order to read naturally in
936// English?  Returns false for non-ASCII or words that don't start with
937// a capital letter.  The a/an rule follows pronunciation in English.
938// We don't use the BBC's overcorrect "an historic occasion" though if
939// you speak a dialect you may well say "an 'istoric occasion".
940static bool AnWord(String* str) {
941  if (str->length() == 0) return false;  // A nothing.
942  int c0 = str->Get(0);
943  int c1 = str->length() > 1 ? str->Get(1) : 0;
944  if (c0 == 'U') {
945    if (c1 > 'Z') {
946      return true;  // An Umpire, but a UTF8String, a U.
947    }
948  } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
949    return true;    // An Ape, an ABCBook.
950  } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
951           (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
952            c0 == 'S' || c0 == 'X')) {
953    return true;    // An MP3File, an M.
954  }
955  return false;
956}
957
958
959Handle<String> String::SlowFlatten(Handle<ConsString> cons,
960                                   PretenureFlag pretenure) {
961  DCHECK(AllowHeapAllocation::IsAllowed());
962  DCHECK(cons->second()->length() != 0);
963  Isolate* isolate = cons->GetIsolate();
964  int length = cons->length();
965  PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
966                                                            : TENURED;
967  Handle<SeqString> result;
968  if (cons->IsOneByteRepresentation()) {
969    Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
970        length, tenure).ToHandleChecked();
971    DisallowHeapAllocation no_gc;
972    WriteToFlat(*cons, flat->GetChars(), 0, length);
973    result = flat;
974  } else {
975    Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
976        length, tenure).ToHandleChecked();
977    DisallowHeapAllocation no_gc;
978    WriteToFlat(*cons, flat->GetChars(), 0, length);
979    result = flat;
980  }
981  cons->set_first(*result);
982  cons->set_second(isolate->heap()->empty_string());
983  DCHECK(result->IsFlat());
984  return result;
985}
986
987
988
989bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
990  // Externalizing twice leaks the external resource, so it's
991  // prohibited by the API.
992  DCHECK(!this->IsExternalString());
993#ifdef ENABLE_SLOW_DCHECKS
994  if (FLAG_enable_slow_asserts) {
995    // Assert that the resource and the string are equivalent.
996    DCHECK(static_cast<size_t>(this->length()) == resource->length());
997    ScopedVector<uc16> smart_chars(this->length());
998    String::WriteToFlat(this, smart_chars.start(), 0, this->length());
999    DCHECK(memcmp(smart_chars.start(),
1000                  resource->data(),
1001                  resource->length() * sizeof(smart_chars[0])) == 0);
1002  }
1003#endif  // DEBUG
1004  int size = this->Size();  // Byte size of the original string.
1005  // Abort if size does not allow in-place conversion.
1006  if (size < ExternalString::kShortSize) return false;
1007  Heap* heap = GetHeap();
1008  bool is_one_byte = this->IsOneByteRepresentation();
1009  bool is_internalized = this->IsInternalizedString();
1010
1011  // Morph the string to an external string by replacing the map and
1012  // reinitializing the fields.  This won't work if the space the existing
1013  // string occupies is too small for a regular  external string.
1014  // Instead, we resort to a short external string instead, omitting
1015  // the field caching the address of the backing store.  When we encounter
1016  // short external strings in generated code, we need to bailout to runtime.
1017  Map* new_map;
1018  if (size < ExternalString::kSize) {
1019    new_map = is_internalized
1020        ? (is_one_byte
1021           ? heap->short_external_internalized_string_with_one_byte_data_map()
1022           : heap->short_external_internalized_string_map())
1023        : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
1024                       : heap->short_external_string_map());
1025  } else {
1026    new_map = is_internalized
1027        ? (is_one_byte
1028           ? heap->external_internalized_string_with_one_byte_data_map()
1029           : heap->external_internalized_string_map())
1030        : (is_one_byte ? heap->external_string_with_one_byte_data_map()
1031                       : heap->external_string_map());
1032  }
1033
1034  // Byte size of the external String object.
1035  int new_size = this->SizeFromMap(new_map);
1036  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1037
1038  // We are storing the new map using release store after creating a filler for
1039  // the left-over space to avoid races with the sweeper thread.
1040  this->synchronized_set_map(new_map);
1041
1042  ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
1043  self->set_resource(resource);
1044  if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1045
1046  heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1047  return true;
1048}
1049
1050
1051bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
1052  // Externalizing twice leaks the external resource, so it's
1053  // prohibited by the API.
1054  DCHECK(!this->IsExternalString());
1055#ifdef ENABLE_SLOW_DCHECKS
1056  if (FLAG_enable_slow_asserts) {
1057    // Assert that the resource and the string are equivalent.
1058    DCHECK(static_cast<size_t>(this->length()) == resource->length());
1059    if (this->IsTwoByteRepresentation()) {
1060      ScopedVector<uint16_t> smart_chars(this->length());
1061      String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1062      DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
1063    }
1064    ScopedVector<char> smart_chars(this->length());
1065    String::WriteToFlat(this, smart_chars.start(), 0, this->length());
1066    DCHECK(memcmp(smart_chars.start(),
1067                  resource->data(),
1068                  resource->length() * sizeof(smart_chars[0])) == 0);
1069  }
1070#endif  // DEBUG
1071  int size = this->Size();  // Byte size of the original string.
1072  // Abort if size does not allow in-place conversion.
1073  if (size < ExternalString::kShortSize) return false;
1074  Heap* heap = GetHeap();
1075  bool is_internalized = this->IsInternalizedString();
1076
1077  // Morph the string to an external string by replacing the map and
1078  // reinitializing the fields.  This won't work if the space the existing
1079  // string occupies is too small for a regular  external string.
1080  // Instead, we resort to a short external string instead, omitting
1081  // the field caching the address of the backing store.  When we encounter
1082  // short external strings in generated code, we need to bailout to runtime.
1083  Map* new_map;
1084  if (size < ExternalString::kSize) {
1085    new_map = is_internalized
1086                  ? heap->short_external_one_byte_internalized_string_map()
1087                  : heap->short_external_one_byte_string_map();
1088  } else {
1089    new_map = is_internalized
1090                  ? heap->external_one_byte_internalized_string_map()
1091                  : heap->external_one_byte_string_map();
1092  }
1093
1094  // Byte size of the external String object.
1095  int new_size = this->SizeFromMap(new_map);
1096  heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
1097
1098  // We are storing the new map using release store after creating a filler for
1099  // the left-over space to avoid races with the sweeper thread.
1100  this->synchronized_set_map(new_map);
1101
1102  ExternalOneByteString* self = ExternalOneByteString::cast(this);
1103  self->set_resource(resource);
1104  if (is_internalized) self->Hash();  // Force regeneration of the hash value.
1105
1106  heap->AdjustLiveBytes(this->address(), new_size - size, Heap::FROM_MUTATOR);
1107  return true;
1108}
1109
1110
1111void String::StringShortPrint(StringStream* accumulator) {
1112  int len = length();
1113  if (len > kMaxShortPrintLength) {
1114    accumulator->Add("<Very long string[%u]>", len);
1115    return;
1116  }
1117
1118  if (!LooksValid()) {
1119    accumulator->Add("<Invalid String>");
1120    return;
1121  }
1122
1123  ConsStringIteratorOp op;
1124  StringCharacterStream stream(this, &op);
1125
1126  bool truncated = false;
1127  if (len > kMaxShortPrintLength) {
1128    len = kMaxShortPrintLength;
1129    truncated = true;
1130  }
1131  bool one_byte = true;
1132  for (int i = 0; i < len; i++) {
1133    uint16_t c = stream.GetNext();
1134
1135    if (c < 32 || c >= 127) {
1136      one_byte = false;
1137    }
1138  }
1139  stream.Reset(this);
1140  if (one_byte) {
1141    accumulator->Add("<String[%u]: ", length());
1142    for (int i = 0; i < len; i++) {
1143      accumulator->Put(static_cast<char>(stream.GetNext()));
1144    }
1145    accumulator->Put('>');
1146  } else {
1147    // Backslash indicates that the string contains control
1148    // characters and that backslashes are therefore escaped.
1149    accumulator->Add("<String[%u]\\: ", length());
1150    for (int i = 0; i < len; i++) {
1151      uint16_t c = stream.GetNext();
1152      if (c == '\n') {
1153        accumulator->Add("\\n");
1154      } else if (c == '\r') {
1155        accumulator->Add("\\r");
1156      } else if (c == '\\') {
1157        accumulator->Add("\\\\");
1158      } else if (c < 32 || c > 126) {
1159        accumulator->Add("\\x%02x", c);
1160      } else {
1161        accumulator->Put(static_cast<char>(c));
1162      }
1163    }
1164    if (truncated) {
1165      accumulator->Put('.');
1166      accumulator->Put('.');
1167      accumulator->Put('.');
1168    }
1169    accumulator->Put('>');
1170  }
1171  return;
1172}
1173
1174
1175void String::PrintUC16(OStream& os, int start, int end) {  // NOLINT
1176  if (end < 0) end = length();
1177  ConsStringIteratorOp op;
1178  StringCharacterStream stream(this, &op, start);
1179  for (int i = start; i < end && stream.HasMore(); i++) {
1180    os << AsUC16(stream.GetNext());
1181  }
1182}
1183
1184
1185void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1186  switch (map()->instance_type()) {
1187    case JS_ARRAY_TYPE: {
1188      double length = JSArray::cast(this)->length()->IsUndefined()
1189          ? 0
1190          : JSArray::cast(this)->length()->Number();
1191      accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1192      break;
1193    }
1194    case JS_WEAK_MAP_TYPE: {
1195      accumulator->Add("<JS WeakMap>");
1196      break;
1197    }
1198    case JS_WEAK_SET_TYPE: {
1199      accumulator->Add("<JS WeakSet>");
1200      break;
1201    }
1202    case JS_REGEXP_TYPE: {
1203      accumulator->Add("<JS RegExp>");
1204      break;
1205    }
1206    case JS_FUNCTION_TYPE: {
1207      JSFunction* function = JSFunction::cast(this);
1208      Object* fun_name = function->shared()->DebugName();
1209      bool printed = false;
1210      if (fun_name->IsString()) {
1211        String* str = String::cast(fun_name);
1212        if (str->length() > 0) {
1213          accumulator->Add("<JS Function ");
1214          accumulator->Put(str);
1215          printed = true;
1216        }
1217      }
1218      if (!printed) {
1219        accumulator->Add("<JS Function");
1220      }
1221      accumulator->Add(" (SharedFunctionInfo %p)",
1222                       reinterpret_cast<void*>(function->shared()));
1223      accumulator->Put('>');
1224      break;
1225    }
1226    case JS_GENERATOR_OBJECT_TYPE: {
1227      accumulator->Add("<JS Generator>");
1228      break;
1229    }
1230    case JS_MODULE_TYPE: {
1231      accumulator->Add("<JS Module>");
1232      break;
1233    }
1234    // All other JSObjects are rather similar to each other (JSObject,
1235    // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1236    default: {
1237      Map* map_of_this = map();
1238      Heap* heap = GetHeap();
1239      Object* constructor = map_of_this->constructor();
1240      bool printed = false;
1241      if (constructor->IsHeapObject() &&
1242          !heap->Contains(HeapObject::cast(constructor))) {
1243        accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1244      } else {
1245        bool global_object = IsJSGlobalProxy();
1246        if (constructor->IsJSFunction()) {
1247          if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1248            accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1249          } else {
1250            Object* constructor_name =
1251                JSFunction::cast(constructor)->shared()->name();
1252            if (constructor_name->IsString()) {
1253              String* str = String::cast(constructor_name);
1254              if (str->length() > 0) {
1255                bool vowel = AnWord(str);
1256                accumulator->Add("<%sa%s ",
1257                       global_object ? "Global Object: " : "",
1258                       vowel ? "n" : "");
1259                accumulator->Put(str);
1260                accumulator->Add(" with %smap %p",
1261                    map_of_this->is_deprecated() ? "deprecated " : "",
1262                    map_of_this);
1263                printed = true;
1264              }
1265            }
1266          }
1267        }
1268        if (!printed) {
1269          accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1270        }
1271      }
1272      if (IsJSValue()) {
1273        accumulator->Add(" value = ");
1274        JSValue::cast(this)->value()->ShortPrint(accumulator);
1275      }
1276      accumulator->Put('>');
1277      break;
1278    }
1279  }
1280}
1281
1282
1283void JSObject::PrintElementsTransition(
1284    FILE* file, Handle<JSObject> object,
1285    ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
1286    ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
1287  if (from_kind != to_kind) {
1288    OFStream os(file);
1289    os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
1290       << ElementsKindToString(to_kind) << "] in ";
1291    JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
1292    PrintF(file, " for ");
1293    object->ShortPrint(file);
1294    PrintF(file, " from ");
1295    from_elements->ShortPrint(file);
1296    PrintF(file, " to ");
1297    to_elements->ShortPrint(file);
1298    PrintF(file, "\n");
1299  }
1300}
1301
1302
1303void Map::PrintGeneralization(FILE* file,
1304                              const char* reason,
1305                              int modify_index,
1306                              int split,
1307                              int descriptors,
1308                              bool constant_to_field,
1309                              Representation old_representation,
1310                              Representation new_representation,
1311                              HeapType* old_field_type,
1312                              HeapType* new_field_type) {
1313  OFStream os(file);
1314  os << "[generalizing ";
1315  constructor_name()->PrintOn(file);
1316  os << "] ";
1317  Name* name = instance_descriptors()->GetKey(modify_index);
1318  if (name->IsString()) {
1319    String::cast(name)->PrintOn(file);
1320  } else {
1321    os << "{symbol " << static_cast<void*>(name) << "}";
1322  }
1323  os << ":";
1324  if (constant_to_field) {
1325    os << "c";
1326  } else {
1327    os << old_representation.Mnemonic() << "{";
1328    old_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1329    os << "}";
1330  }
1331  os << "->" << new_representation.Mnemonic() << "{";
1332  new_field_type->PrintTo(os, HeapType::SEMANTIC_DIM);
1333  os << "} (";
1334  if (strlen(reason) > 0) {
1335    os << reason;
1336  } else {
1337    os << "+" << (descriptors - split) << " maps";
1338  }
1339  os << ") [";
1340  JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
1341  os << "]\n";
1342}
1343
1344
1345void JSObject::PrintInstanceMigration(FILE* file,
1346                                      Map* original_map,
1347                                      Map* new_map) {
1348  PrintF(file, "[migrating ");
1349  map()->constructor_name()->PrintOn(file);
1350  PrintF(file, "] ");
1351  DescriptorArray* o = original_map->instance_descriptors();
1352  DescriptorArray* n = new_map->instance_descriptors();
1353  for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
1354    Representation o_r = o->GetDetails(i).representation();
1355    Representation n_r = n->GetDetails(i).representation();
1356    if (!o_r.Equals(n_r)) {
1357      String::cast(o->GetKey(i))->PrintOn(file);
1358      PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
1359    } else if (o->GetDetails(i).type() == CONSTANT &&
1360               n->GetDetails(i).type() == FIELD) {
1361      Name* name = o->GetKey(i);
1362      if (name->IsString()) {
1363        String::cast(name)->PrintOn(file);
1364      } else {
1365        PrintF(file, "{symbol %p}", static_cast<void*>(name));
1366      }
1367      PrintF(file, " ");
1368    }
1369  }
1370  PrintF(file, "\n");
1371}
1372
1373
1374void HeapObject::HeapObjectShortPrint(OStream& os) {  // NOLINT
1375  Heap* heap = GetHeap();
1376  if (!heap->Contains(this)) {
1377    os << "!!!INVALID POINTER!!!";
1378    return;
1379  }
1380  if (!heap->Contains(map())) {
1381    os << "!!!INVALID MAP!!!";
1382    return;
1383  }
1384
1385  os << this << " ";
1386
1387  if (IsString()) {
1388    HeapStringAllocator allocator;
1389    StringStream accumulator(&allocator);
1390    String::cast(this)->StringShortPrint(&accumulator);
1391    os << accumulator.ToCString().get();
1392    return;
1393  }
1394  if (IsJSObject()) {
1395    HeapStringAllocator allocator;
1396    StringStream accumulator(&allocator);
1397    JSObject::cast(this)->JSObjectShortPrint(&accumulator);
1398    os << accumulator.ToCString().get();
1399    return;
1400  }
1401  switch (map()->instance_type()) {
1402    case MAP_TYPE:
1403      os << "<Map(elements=" << Map::cast(this)->elements_kind() << ")>";
1404      break;
1405    case FIXED_ARRAY_TYPE:
1406      os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
1407      break;
1408    case FIXED_DOUBLE_ARRAY_TYPE:
1409      os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
1410         << "]>";
1411      break;
1412    case BYTE_ARRAY_TYPE:
1413      os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
1414      break;
1415    case FREE_SPACE_TYPE:
1416      os << "<FreeSpace[" << FreeSpace::cast(this)->Size() << "]>";
1417      break;
1418#define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
1419  case EXTERNAL_##TYPE##_ARRAY_TYPE:                                          \
1420    os << "<External" #Type "Array["                                          \
1421       << External##Type##Array::cast(this)->length() << "]>";                \
1422    break;                                                                    \
1423  case FIXED_##TYPE##_ARRAY_TYPE:                                             \
1424    os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
1425       << "]>";                                                               \
1426    break;
1427
1428    TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
1429#undef TYPED_ARRAY_SHORT_PRINT
1430
1431    case SHARED_FUNCTION_INFO_TYPE: {
1432      SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
1433      SmartArrayPointer<char> debug_name =
1434          shared->DebugName()->ToCString();
1435      if (debug_name[0] != 0) {
1436        os << "<SharedFunctionInfo " << debug_name.get() << ">";
1437      } else {
1438        os << "<SharedFunctionInfo>";
1439      }
1440      break;
1441    }
1442    case JS_MESSAGE_OBJECT_TYPE:
1443      os << "<JSMessageObject>";
1444      break;
1445#define MAKE_STRUCT_CASE(NAME, Name, name) \
1446  case NAME##_TYPE:                        \
1447    os << "<" #Name ">";                   \
1448    break;
1449  STRUCT_LIST(MAKE_STRUCT_CASE)
1450#undef MAKE_STRUCT_CASE
1451    case CODE_TYPE: {
1452      Code* code = Code::cast(this);
1453      os << "<Code: " << Code::Kind2String(code->kind()) << ">";
1454      break;
1455    }
1456    case ODDBALL_TYPE: {
1457      if (IsUndefined()) {
1458        os << "<undefined>";
1459      } else if (IsTheHole()) {
1460        os << "<the hole>";
1461      } else if (IsNull()) {
1462        os << "<null>";
1463      } else if (IsTrue()) {
1464        os << "<true>";
1465      } else if (IsFalse()) {
1466        os << "<false>";
1467      } else {
1468        os << "<Odd Oddball>";
1469      }
1470      break;
1471    }
1472    case SYMBOL_TYPE: {
1473      Symbol* symbol = Symbol::cast(this);
1474      os << "<Symbol: " << symbol->Hash();
1475      if (!symbol->name()->IsUndefined()) {
1476        os << " ";
1477        HeapStringAllocator allocator;
1478        StringStream accumulator(&allocator);
1479        String::cast(symbol->name())->StringShortPrint(&accumulator);
1480        os << accumulator.ToCString().get();
1481      }
1482      os << ">";
1483      break;
1484    }
1485    case HEAP_NUMBER_TYPE: {
1486      os << "<Number: ";
1487      HeapNumber::cast(this)->HeapNumberPrint(os);
1488      os << ">";
1489      break;
1490    }
1491    case MUTABLE_HEAP_NUMBER_TYPE: {
1492      os << "<MutableNumber: ";
1493      HeapNumber::cast(this)->HeapNumberPrint(os);
1494      os << '>';
1495      break;
1496    }
1497    case JS_PROXY_TYPE:
1498      os << "<JSProxy>";
1499      break;
1500    case JS_FUNCTION_PROXY_TYPE:
1501      os << "<JSFunctionProxy>";
1502      break;
1503    case FOREIGN_TYPE:
1504      os << "<Foreign>";
1505      break;
1506    case CELL_TYPE: {
1507      os << "Cell for ";
1508      HeapStringAllocator allocator;
1509      StringStream accumulator(&allocator);
1510      Cell::cast(this)->value()->ShortPrint(&accumulator);
1511      os << accumulator.ToCString().get();
1512      break;
1513    }
1514    case PROPERTY_CELL_TYPE: {
1515      os << "PropertyCell for ";
1516      HeapStringAllocator allocator;
1517      StringStream accumulator(&allocator);
1518      PropertyCell::cast(this)->value()->ShortPrint(&accumulator);
1519      os << accumulator.ToCString().get();
1520      break;
1521    }
1522    default:
1523      os << "<Other heap object (" << map()->instance_type() << ")>";
1524      break;
1525  }
1526}
1527
1528
1529void HeapObject::Iterate(ObjectVisitor* v) {
1530  // Handle header
1531  IteratePointer(v, kMapOffset);
1532  // Handle object body
1533  Map* m = map();
1534  IterateBody(m->instance_type(), SizeFromMap(m), v);
1535}
1536
1537
1538void HeapObject::IterateBody(InstanceType type, int object_size,
1539                             ObjectVisitor* v) {
1540  // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1541  // During GC, the map pointer field is encoded.
1542  if (type < FIRST_NONSTRING_TYPE) {
1543    switch (type & kStringRepresentationMask) {
1544      case kSeqStringTag:
1545        break;
1546      case kConsStringTag:
1547        ConsString::BodyDescriptor::IterateBody(this, v);
1548        break;
1549      case kSlicedStringTag:
1550        SlicedString::BodyDescriptor::IterateBody(this, v);
1551        break;
1552      case kExternalStringTag:
1553        if ((type & kStringEncodingMask) == kOneByteStringTag) {
1554          reinterpret_cast<ExternalOneByteString*>(this)
1555              ->ExternalOneByteStringIterateBody(v);
1556        } else {
1557          reinterpret_cast<ExternalTwoByteString*>(this)->
1558              ExternalTwoByteStringIterateBody(v);
1559        }
1560        break;
1561    }
1562    return;
1563  }
1564
1565  switch (type) {
1566    case FIXED_ARRAY_TYPE:
1567      FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1568      break;
1569    case CONSTANT_POOL_ARRAY_TYPE:
1570      reinterpret_cast<ConstantPoolArray*>(this)->ConstantPoolIterateBody(v);
1571      break;
1572    case FIXED_DOUBLE_ARRAY_TYPE:
1573      break;
1574    case JS_OBJECT_TYPE:
1575    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1576    case JS_GENERATOR_OBJECT_TYPE:
1577    case JS_MODULE_TYPE:
1578    case JS_VALUE_TYPE:
1579    case JS_DATE_TYPE:
1580    case JS_ARRAY_TYPE:
1581    case JS_ARRAY_BUFFER_TYPE:
1582    case JS_TYPED_ARRAY_TYPE:
1583    case JS_DATA_VIEW_TYPE:
1584    case JS_SET_TYPE:
1585    case JS_MAP_TYPE:
1586    case JS_SET_ITERATOR_TYPE:
1587    case JS_MAP_ITERATOR_TYPE:
1588    case JS_WEAK_MAP_TYPE:
1589    case JS_WEAK_SET_TYPE:
1590    case JS_REGEXP_TYPE:
1591    case JS_GLOBAL_PROXY_TYPE:
1592    case JS_GLOBAL_OBJECT_TYPE:
1593    case JS_BUILTINS_OBJECT_TYPE:
1594    case JS_MESSAGE_OBJECT_TYPE:
1595      JSObject::BodyDescriptor::IterateBody(this, object_size, v);
1596      break;
1597    case JS_FUNCTION_TYPE:
1598      reinterpret_cast<JSFunction*>(this)
1599          ->JSFunctionIterateBody(object_size, v);
1600      break;
1601    case ODDBALL_TYPE:
1602      Oddball::BodyDescriptor::IterateBody(this, v);
1603      break;
1604    case JS_PROXY_TYPE:
1605      JSProxy::BodyDescriptor::IterateBody(this, v);
1606      break;
1607    case JS_FUNCTION_PROXY_TYPE:
1608      JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
1609      break;
1610    case FOREIGN_TYPE:
1611      reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
1612      break;
1613    case MAP_TYPE:
1614      Map::BodyDescriptor::IterateBody(this, v);
1615      break;
1616    case CODE_TYPE:
1617      reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1618      break;
1619    case CELL_TYPE:
1620      Cell::BodyDescriptor::IterateBody(this, v);
1621      break;
1622    case PROPERTY_CELL_TYPE:
1623      PropertyCell::BodyDescriptor::IterateBody(this, v);
1624      break;
1625    case SYMBOL_TYPE:
1626      Symbol::BodyDescriptor::IterateBody(this, v);
1627      break;
1628
1629    case HEAP_NUMBER_TYPE:
1630    case MUTABLE_HEAP_NUMBER_TYPE:
1631    case FILLER_TYPE:
1632    case BYTE_ARRAY_TYPE:
1633    case FREE_SPACE_TYPE:
1634      break;
1635
1636#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
1637    case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
1638    case FIXED_##TYPE##_ARRAY_TYPE:                                            \
1639      break;
1640
1641    TYPED_ARRAYS(TYPED_ARRAY_CASE)
1642#undef TYPED_ARRAY_CASE
1643
1644    case SHARED_FUNCTION_INFO_TYPE: {
1645      SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
1646      break;
1647    }
1648
1649#define MAKE_STRUCT_CASE(NAME, Name, name) \
1650        case NAME##_TYPE:
1651      STRUCT_LIST(MAKE_STRUCT_CASE)
1652#undef MAKE_STRUCT_CASE
1653      if (type == ALLOCATION_SITE_TYPE) {
1654        AllocationSite::BodyDescriptor::IterateBody(this, v);
1655      } else {
1656        StructBodyDescriptor::IterateBody(this, object_size, v);
1657      }
1658      break;
1659    default:
1660      PrintF("Unknown type: %d\n", type);
1661      UNREACHABLE();
1662  }
1663}
1664
1665
1666bool HeapNumber::HeapNumberBooleanValue() {
1667  return DoubleToBoolean(value());
1668}
1669
1670
1671void HeapNumber::HeapNumberPrint(OStream& os) {  // NOLINT
1672  os << value();
1673}
1674
1675
1676String* JSReceiver::class_name() {
1677  if (IsJSFunction() || IsJSFunctionProxy()) {
1678    return GetHeap()->Function_string();
1679  }
1680  if (map()->constructor()->IsJSFunction()) {
1681    JSFunction* constructor = JSFunction::cast(map()->constructor());
1682    return String::cast(constructor->shared()->instance_class_name());
1683  }
1684  // If the constructor is not present, return "Object".
1685  return GetHeap()->Object_string();
1686}
1687
1688
1689String* Map::constructor_name() {
1690  if (constructor()->IsJSFunction()) {
1691    JSFunction* constructor = JSFunction::cast(this->constructor());
1692    String* name = String::cast(constructor->shared()->name());
1693    if (name->length() > 0) return name;
1694    String* inferred_name = constructor->shared()->inferred_name();
1695    if (inferred_name->length() > 0) return inferred_name;
1696    Object* proto = prototype();
1697    if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1698  }
1699  // TODO(rossberg): what about proxies?
1700  // If the constructor is not present, return "Object".
1701  return GetHeap()->Object_string();
1702}
1703
1704
1705String* JSReceiver::constructor_name() {
1706  return map()->constructor_name();
1707}
1708
1709
1710MaybeHandle<Map> Map::CopyWithField(Handle<Map> map,
1711                                    Handle<Name> name,
1712                                    Handle<HeapType> type,
1713                                    PropertyAttributes attributes,
1714                                    Representation representation,
1715                                    TransitionFlag flag) {
1716  DCHECK(DescriptorArray::kNotFound ==
1717         map->instance_descriptors()->Search(
1718             *name, map->NumberOfOwnDescriptors()));
1719
1720  // Ensure the descriptor array does not get too big.
1721  if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1722    return MaybeHandle<Map>();
1723  }
1724
1725  Isolate* isolate = map->GetIsolate();
1726
1727  // Compute the new index for new field.
1728  int index = map->NextFreePropertyIndex();
1729
1730  if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1731    representation = Representation::Tagged();
1732    type = HeapType::Any(isolate);
1733  }
1734
1735  FieldDescriptor new_field_desc(name, index, type, attributes, representation);
1736  Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
1737  int unused_property_fields = new_map->unused_property_fields() - 1;
1738  if (unused_property_fields < 0) {
1739    unused_property_fields += JSObject::kFieldsAdded;
1740  }
1741  new_map->set_unused_property_fields(unused_property_fields);
1742  return new_map;
1743}
1744
1745
1746MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
1747                                       Handle<Name> name,
1748                                       Handle<Object> constant,
1749                                       PropertyAttributes attributes,
1750                                       TransitionFlag flag) {
1751  // Ensure the descriptor array does not get too big.
1752  if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1753    return MaybeHandle<Map>();
1754  }
1755
1756  // Allocate new instance descriptors with (name, constant) added.
1757  ConstantDescriptor new_constant_desc(name, constant, attributes);
1758  return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1759}
1760
1761
1762void JSObject::AddSlowProperty(Handle<JSObject> object,
1763                               Handle<Name> name,
1764                               Handle<Object> value,
1765                               PropertyAttributes attributes) {
1766  DCHECK(!object->HasFastProperties());
1767  Isolate* isolate = object->GetIsolate();
1768  Handle<NameDictionary> dict(object->property_dictionary());
1769  if (object->IsGlobalObject()) {
1770    // In case name is an orphaned property reuse the cell.
1771    int entry = dict->FindEntry(name);
1772    if (entry != NameDictionary::kNotFound) {
1773      Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry)));
1774      PropertyCell::SetValueInferType(cell, value);
1775      // Assign an enumeration index to the property and update
1776      // SetNextEnumerationIndex.
1777      int index = dict->NextEnumerationIndex();
1778      PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
1779      dict->SetNextEnumerationIndex(index + 1);
1780      dict->SetEntry(entry, name, cell, details);
1781      return;
1782    }
1783    Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value);
1784    PropertyCell::SetValueInferType(cell, value);
1785    value = cell;
1786  }
1787  PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
1788  Handle<NameDictionary> result =
1789      NameDictionary::Add(dict, name, value, details);
1790  if (*dict != *result) object->set_properties(*result);
1791}
1792
1793
1794Context* JSObject::GetCreationContext() {
1795  Object* constructor = this->map()->constructor();
1796  JSFunction* function;
1797  if (!constructor->IsJSFunction()) {
1798    // Functions have null as a constructor,
1799    // but any JSFunction knows its context immediately.
1800    function = JSFunction::cast(this);
1801  } else {
1802    function = JSFunction::cast(constructor);
1803  }
1804
1805  return function->context()->native_context();
1806}
1807
1808
1809void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
1810                                   const char* type_str,
1811                                   Handle<Name> name,
1812                                   Handle<Object> old_value) {
1813  DCHECK(!object->IsJSGlobalProxy());
1814  DCHECK(!object->IsJSGlobalObject());
1815  Isolate* isolate = object->GetIsolate();
1816  HandleScope scope(isolate);
1817  Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
1818  Handle<Object> args[] = { type, object, name, old_value };
1819  int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
1820
1821  Execution::Call(isolate,
1822                  Handle<JSFunction>(isolate->observers_notify_change()),
1823                  isolate->factory()->undefined_value(),
1824                  argc, args).Assert();
1825}
1826
1827
1828const char* Representation::Mnemonic() const {
1829  switch (kind_) {
1830    case kNone: return "v";
1831    case kTagged: return "t";
1832    case kSmi: return "s";
1833    case kDouble: return "d";
1834    case kInteger32: return "i";
1835    case kHeapObject: return "h";
1836    case kExternal: return "x";
1837    default:
1838      UNREACHABLE();
1839      return NULL;
1840  }
1841}
1842
1843
1844bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
1845                                 int target_inobject, int target_unused,
1846                                 int* old_number_of_fields) {
1847  // If fields were added (or removed), rewrite the instance.
1848  *old_number_of_fields = NumberOfFields();
1849  DCHECK(target_number_of_fields >= *old_number_of_fields);
1850  if (target_number_of_fields != *old_number_of_fields) return true;
1851
1852  // If smi descriptors were replaced by double descriptors, rewrite.
1853  DescriptorArray* old_desc = instance_descriptors();
1854  DescriptorArray* new_desc = target->instance_descriptors();
1855  int limit = NumberOfOwnDescriptors();
1856  for (int i = 0; i < limit; i++) {
1857    if (new_desc->GetDetails(i).representation().IsDouble() !=
1858        old_desc->GetDetails(i).representation().IsDouble()) {
1859      return true;
1860    }
1861  }
1862
1863  // If no fields were added, and no inobject properties were removed, setting
1864  // the map is sufficient.
1865  if (target_inobject == inobject_properties()) return false;
1866  // In-object slack tracking may have reduced the object size of the new map.
1867  // In that case, succeed if all existing fields were inobject, and they still
1868  // fit within the new inobject size.
1869  DCHECK(target_inobject < inobject_properties());
1870  if (target_number_of_fields <= target_inobject) {
1871    DCHECK(target_number_of_fields + target_unused == target_inobject);
1872    return false;
1873  }
1874  // Otherwise, properties will need to be moved to the backing store.
1875  return true;
1876}
1877
1878
1879void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) {
1880  Isolate* isolate = parent->GetIsolate();
1881  Handle<Name> name = isolate->factory()->elements_transition_symbol();
1882  ConnectTransition(parent, child, name, FULL_TRANSITION);
1883}
1884
1885
1886void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
1887  if (object->map() == *new_map) return;
1888  if (object->HasFastProperties()) {
1889    if (!new_map->is_dictionary_map()) {
1890      Handle<Map> old_map(object->map());
1891      MigrateFastToFast(object, new_map);
1892      if (old_map->is_prototype_map()) {
1893        // Clear out the old descriptor array to avoid problems to sharing
1894        // the descriptor array without using an explicit.
1895        old_map->InitializeDescriptors(
1896            old_map->GetHeap()->empty_descriptor_array());
1897        // Ensure that no transition was inserted for prototype migrations.
1898        DCHECK(!old_map->HasTransitionArray());
1899        DCHECK(new_map->GetBackPointer()->IsUndefined());
1900      }
1901    } else {
1902      MigrateFastToSlow(object, new_map, 0);
1903    }
1904  } else {
1905    // For slow-to-fast migrations JSObject::TransformToFastProperties()
1906    // must be used instead.
1907    CHECK(new_map->is_dictionary_map());
1908
1909    // Slow-to-slow migration is trivial.
1910    object->set_map(*new_map);
1911  }
1912}
1913
1914
1915// To migrate a fast instance to a fast map:
1916// - First check whether the instance needs to be rewritten. If not, simply
1917//   change the map.
1918// - Otherwise, allocate a fixed array large enough to hold all fields, in
1919//   addition to unused space.
1920// - Copy all existing properties in, in the following order: backing store
1921//   properties, unused fields, inobject properties.
1922// - If all allocation succeeded, commit the state atomically:
1923//   * Copy inobject properties from the backing store back into the object.
1924//   * Trim the difference in instance size of the object. This also cleanly
1925//     frees inobject properties that moved to the backing store.
1926//   * If there are properties left in the backing store, trim of the space used
1927//     to temporarily store the inobject properties.
1928//   * If there are properties left in the backing store, install the backing
1929//     store.
1930void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
1931  Isolate* isolate = object->GetIsolate();
1932  Handle<Map> old_map(object->map());
1933  int old_number_of_fields;
1934  int number_of_fields = new_map->NumberOfFields();
1935  int inobject = new_map->inobject_properties();
1936  int unused = new_map->unused_property_fields();
1937
1938  // Nothing to do if no functions were converted to fields and no smis were
1939  // converted to doubles.
1940  if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
1941                                       unused, &old_number_of_fields)) {
1942    object->synchronized_set_map(*new_map);
1943    return;
1944  }
1945
1946  int total_size = number_of_fields + unused;
1947  int external = total_size - inobject;
1948
1949  if (number_of_fields != old_number_of_fields &&
1950      new_map->GetBackPointer() == *old_map) {
1951    PropertyDetails details = new_map->GetLastDescriptorDetails();
1952
1953    if (old_map->unused_property_fields() > 0) {
1954      if (details.representation().IsDouble()) {
1955        Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1956        FieldIndex index =
1957            FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
1958        object->FastPropertyAtPut(index, *value);
1959      }
1960      object->synchronized_set_map(*new_map);
1961      return;
1962    }
1963
1964    DCHECK(number_of_fields == old_number_of_fields + 1);
1965    // This migration is a transition from a map that has run out out property
1966    // space. Therefore it could be done by extending the backing store.
1967    Handle<FixedArray> old_storage = handle(object->properties(), isolate);
1968    Handle<FixedArray> new_storage =
1969        FixedArray::CopySize(old_storage, external);
1970
1971    // Properly initialize newly added property.
1972    Handle<Object> value;
1973    if (details.representation().IsDouble()) {
1974      value = isolate->factory()->NewHeapNumber(0, MUTABLE);
1975    } else {
1976      value = isolate->factory()->uninitialized_value();
1977    }
1978    DCHECK(details.type() == FIELD);
1979    int target_index = details.field_index() - inobject;
1980    DCHECK(target_index >= 0);  // Must be a backing store index.
1981    new_storage->set(target_index, *value);
1982
1983    // From here on we cannot fail and we shouldn't GC anymore.
1984    DisallowHeapAllocation no_allocation;
1985
1986    // Set the new property value and do the map transition.
1987    object->set_properties(*new_storage);
1988    object->synchronized_set_map(*new_map);
1989    return;
1990  }
1991  Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
1992
1993  Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
1994  Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
1995  int old_nof = old_map->NumberOfOwnDescriptors();
1996  int new_nof = new_map->NumberOfOwnDescriptors();
1997
1998  // This method only supports generalizing instances to at least the same
1999  // number of properties.
2000  DCHECK(old_nof <= new_nof);
2001
2002  for (int i = 0; i < old_nof; i++) {
2003    PropertyDetails details = new_descriptors->GetDetails(i);
2004    if (details.type() != FIELD) continue;
2005    PropertyDetails old_details = old_descriptors->GetDetails(i);
2006    if (old_details.type() == CALLBACKS) {
2007      DCHECK(details.representation().IsTagged());
2008      continue;
2009    }
2010    DCHECK(old_details.type() == CONSTANT ||
2011           old_details.type() == FIELD);
2012    Object* raw_value = old_details.type() == CONSTANT
2013        ? old_descriptors->GetValue(i)
2014        : object->RawFastPropertyAt(FieldIndex::ForDescriptor(*old_map, i));
2015    Handle<Object> value(raw_value, isolate);
2016    if (!old_details.representation().IsDouble() &&
2017        details.representation().IsDouble()) {
2018      if (old_details.representation().IsNone()) {
2019        value = handle(Smi::FromInt(0), isolate);
2020      }
2021      value = Object::NewStorageFor(isolate, value, details.representation());
2022    } else if (old_details.representation().IsDouble() &&
2023               !details.representation().IsDouble()) {
2024      value = Object::WrapForRead(isolate, value, old_details.representation());
2025    }
2026    DCHECK(!(details.representation().IsDouble() && value->IsSmi()));
2027    int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2028    if (target_index < 0) target_index += total_size;
2029    array->set(target_index, *value);
2030  }
2031
2032  for (int i = old_nof; i < new_nof; i++) {
2033    PropertyDetails details = new_descriptors->GetDetails(i);
2034    if (details.type() != FIELD) continue;
2035    Handle<Object> value;
2036    if (details.representation().IsDouble()) {
2037      value = isolate->factory()->NewHeapNumber(0, MUTABLE);
2038    } else {
2039      value = isolate->factory()->uninitialized_value();
2040    }
2041    int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2042    if (target_index < 0) target_index += total_size;
2043    array->set(target_index, *value);
2044  }
2045
2046  // From here on we cannot fail and we shouldn't GC anymore.
2047  DisallowHeapAllocation no_allocation;
2048
2049  // Copy (real) inobject properties. If necessary, stop at number_of_fields to
2050  // avoid overwriting |one_pointer_filler_map|.
2051  int limit = Min(inobject, number_of_fields);
2052  for (int i = 0; i < limit; i++) {
2053    FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
2054    object->FastPropertyAtPut(index, array->get(external + i));
2055  }
2056
2057  Heap* heap = isolate->heap();
2058
2059  // If there are properties in the new backing store, trim it to the correct
2060  // size and install the backing store into the object.
2061  if (external > 0) {
2062    heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, inobject);
2063    object->set_properties(*array);
2064  }
2065
2066  // Create filler object past the new instance size.
2067  int new_instance_size = new_map->instance_size();
2068  int instance_size_delta = old_map->instance_size() - new_instance_size;
2069  DCHECK(instance_size_delta >= 0);
2070
2071  if (instance_size_delta > 0) {
2072    Address address = object->address();
2073    heap->CreateFillerObjectAt(
2074        address + new_instance_size, instance_size_delta);
2075    heap->AdjustLiveBytes(address, -instance_size_delta, Heap::FROM_MUTATOR);
2076  }
2077
2078  // We are storing the new map using release store after creating a filler for
2079  // the left-over space to avoid races with the sweeper thread.
2080  object->synchronized_set_map(*new_map);
2081}
2082
2083
2084void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object,
2085                                             int modify_index,
2086                                             Representation new_representation,
2087                                             Handle<HeapType> new_field_type) {
2088  Handle<Map> new_map = Map::GeneralizeRepresentation(
2089      handle(object->map()), modify_index, new_representation, new_field_type,
2090      FORCE_FIELD);
2091  MigrateToMap(object, new_map);
2092}
2093
2094
2095int Map::NumberOfFields() {
2096  DescriptorArray* descriptors = instance_descriptors();
2097  int result = 0;
2098  for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2099    if (descriptors->GetDetails(i).type() == FIELD) result++;
2100  }
2101  return result;
2102}
2103
2104
2105Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
2106                                                  int modify_index,
2107                                                  StoreMode store_mode,
2108                                                  PropertyAttributes attributes,
2109                                                  const char* reason) {
2110  Isolate* isolate = map->GetIsolate();
2111  Handle<Map> new_map = Copy(map);
2112
2113  DescriptorArray* descriptors = new_map->instance_descriptors();
2114  int length = descriptors->number_of_descriptors();
2115  for (int i = 0; i < length; i++) {
2116    descriptors->SetRepresentation(i, Representation::Tagged());
2117    if (descriptors->GetDetails(i).type() == FIELD) {
2118      descriptors->SetValue(i, HeapType::Any());
2119    }
2120  }
2121
2122  // Unless the instance is being migrated, ensure that modify_index is a field.
2123  PropertyDetails details = descriptors->GetDetails(modify_index);
2124  if (store_mode == FORCE_FIELD &&
2125      (details.type() != FIELD || details.attributes() != attributes)) {
2126    int field_index = details.type() == FIELD ? details.field_index()
2127                                              : new_map->NumberOfFields();
2128    FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
2129                      field_index, attributes, Representation::Tagged());
2130    descriptors->Replace(modify_index, &d);
2131    if (details.type() != FIELD) {
2132      int unused_property_fields = new_map->unused_property_fields() - 1;
2133      if (unused_property_fields < 0) {
2134        unused_property_fields += JSObject::kFieldsAdded;
2135      }
2136      new_map->set_unused_property_fields(unused_property_fields);
2137    }
2138  } else {
2139    DCHECK(details.attributes() == attributes);
2140  }
2141
2142  if (FLAG_trace_generalization) {
2143    HeapType* field_type = (details.type() == FIELD)
2144        ? map->instance_descriptors()->GetFieldType(modify_index)
2145        : NULL;
2146    map->PrintGeneralization(stdout, reason, modify_index,
2147                        new_map->NumberOfOwnDescriptors(),
2148                        new_map->NumberOfOwnDescriptors(),
2149                        details.type() == CONSTANT && store_mode == FORCE_FIELD,
2150                        details.representation(), Representation::Tagged(),
2151                        field_type, HeapType::Any());
2152  }
2153  return new_map;
2154}
2155
2156
2157// static
2158Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
2159                                                  int modify_index,
2160                                                  StoreMode store_mode,
2161                                                  const char* reason) {
2162  PropertyDetails details =
2163      map->instance_descriptors()->GetDetails(modify_index);
2164  return CopyGeneralizeAllRepresentations(map, modify_index, store_mode,
2165                                          details.attributes(), reason);
2166}
2167
2168
2169void Map::DeprecateTransitionTree() {
2170  if (is_deprecated()) return;
2171  if (HasTransitionArray()) {
2172    TransitionArray* transitions = this->transitions();
2173    for (int i = 0; i < transitions->number_of_transitions(); i++) {
2174      transitions->GetTarget(i)->DeprecateTransitionTree();
2175    }
2176  }
2177  deprecate();
2178  dependent_code()->DeoptimizeDependentCodeGroup(
2179      GetIsolate(), DependentCode::kTransitionGroup);
2180  NotifyLeafMapLayoutChange();
2181}
2182
2183
2184// Invalidates a transition target at |key|, and installs |new_descriptors| over
2185// the current instance_descriptors to ensure proper sharing of descriptor
2186// arrays.
2187void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors) {
2188  if (HasTransitionArray()) {
2189    TransitionArray* transitions = this->transitions();
2190    int transition = transitions->Search(key);
2191    if (transition != TransitionArray::kNotFound) {
2192      transitions->GetTarget(transition)->DeprecateTransitionTree();
2193    }
2194  }
2195
2196  // Don't overwrite the empty descriptor array.
2197  if (NumberOfOwnDescriptors() == 0) return;
2198
2199  DescriptorArray* to_replace = instance_descriptors();
2200  Map* current = this;
2201  GetHeap()->incremental_marking()->RecordWrites(to_replace);
2202  while (current->instance_descriptors() == to_replace) {
2203    current->SetEnumLength(kInvalidEnumCacheSentinel);
2204    current->set_instance_descriptors(new_descriptors);
2205    Object* next = current->GetBackPointer();
2206    if (next->IsUndefined()) break;
2207    current = Map::cast(next);
2208  }
2209
2210  set_owns_descriptors(false);
2211}
2212
2213
2214Map* Map::FindRootMap() {
2215  Map* result = this;
2216  while (true) {
2217    Object* back = result->GetBackPointer();
2218    if (back->IsUndefined()) return result;
2219    result = Map::cast(back);
2220  }
2221}
2222
2223
2224Map* Map::FindLastMatchMap(int verbatim,
2225                           int length,
2226                           DescriptorArray* descriptors) {
2227  DisallowHeapAllocation no_allocation;
2228
2229  // This can only be called on roots of transition trees.
2230  DCHECK(GetBackPointer()->IsUndefined());
2231
2232  Map* current = this;
2233
2234  for (int i = verbatim; i < length; i++) {
2235    if (!current->HasTransitionArray()) break;
2236    Name* name = descriptors->GetKey(i);
2237    TransitionArray* transitions = current->transitions();
2238    int transition = transitions->Search(name);
2239    if (transition == TransitionArray::kNotFound) break;
2240
2241    Map* next = transitions->GetTarget(transition);
2242    DescriptorArray* next_descriptors = next->instance_descriptors();
2243
2244    PropertyDetails details = descriptors->GetDetails(i);
2245    PropertyDetails next_details = next_descriptors->GetDetails(i);
2246    if (details.type() != next_details.type()) break;
2247    if (details.attributes() != next_details.attributes()) break;
2248    if (!details.representation().Equals(next_details.representation())) break;
2249    if (next_details.type() == FIELD) {
2250      if (!descriptors->GetFieldType(i)->NowIs(
2251              next_descriptors->GetFieldType(i))) break;
2252    } else {
2253      if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break;
2254    }
2255
2256    current = next;
2257  }
2258  return current;
2259}
2260
2261
2262Map* Map::FindFieldOwner(int descriptor) {
2263  DisallowHeapAllocation no_allocation;
2264  DCHECK_EQ(FIELD, instance_descriptors()->GetDetails(descriptor).type());
2265  Map* result = this;
2266  while (true) {
2267    Object* back = result->GetBackPointer();
2268    if (back->IsUndefined()) break;
2269    Map* parent = Map::cast(back);
2270    if (parent->NumberOfOwnDescriptors() <= descriptor) break;
2271    result = parent;
2272  }
2273  return result;
2274}
2275
2276
2277void Map::UpdateFieldType(int descriptor, Handle<Name> name,
2278                          Handle<HeapType> new_type) {
2279  DisallowHeapAllocation no_allocation;
2280  PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
2281  if (details.type() != FIELD) return;
2282  if (HasTransitionArray()) {
2283    TransitionArray* transitions = this->transitions();
2284    for (int i = 0; i < transitions->number_of_transitions(); ++i) {
2285      transitions->GetTarget(i)->UpdateFieldType(descriptor, name, new_type);
2286    }
2287  }
2288  // Skip if already updated the shared descriptor.
2289  if (instance_descriptors()->GetFieldType(descriptor) == *new_type) return;
2290  FieldDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor),
2291                    new_type, details.attributes(), details.representation());
2292  instance_descriptors()->Replace(descriptor, &d);
2293}
2294
2295
2296// static
2297Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> type1,
2298                                          Handle<HeapType> type2,
2299                                          Isolate* isolate) {
2300  static const int kMaxClassesPerFieldType = 5;
2301  if (type1->NowIs(type2)) return type2;
2302  if (type2->NowIs(type1)) return type1;
2303  if (type1->NowStable() && type2->NowStable()) {
2304    Handle<HeapType> type = HeapType::Union(type1, type2, isolate);
2305    if (type->NumClasses() <= kMaxClassesPerFieldType) {
2306      DCHECK(type->NowStable());
2307      DCHECK(type1->NowIs(type));
2308      DCHECK(type2->NowIs(type));
2309      return type;
2310    }
2311  }
2312  return HeapType::Any(isolate);
2313}
2314
2315
2316// static
2317void Map::GeneralizeFieldType(Handle<Map> map,
2318                              int modify_index,
2319                              Handle<HeapType> new_field_type) {
2320  Isolate* isolate = map->GetIsolate();
2321
2322  // Check if we actually need to generalize the field type at all.
2323  Handle<HeapType> old_field_type(
2324      map->instance_descriptors()->GetFieldType(modify_index), isolate);
2325  if (new_field_type->NowIs(old_field_type)) {
2326    DCHECK(Map::GeneralizeFieldType(old_field_type,
2327                                    new_field_type,
2328                                    isolate)->NowIs(old_field_type));
2329    return;
2330  }
2331
2332  // Determine the field owner.
2333  Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
2334  Handle<DescriptorArray> descriptors(
2335      field_owner->instance_descriptors(), isolate);
2336  DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
2337
2338  // Determine the generalized new field type.
2339  new_field_type = Map::GeneralizeFieldType(
2340      old_field_type, new_field_type, isolate);
2341
2342  PropertyDetails details = descriptors->GetDetails(modify_index);
2343  Handle<Name> name(descriptors->GetKey(modify_index));
2344  field_owner->UpdateFieldType(modify_index, name, new_field_type);
2345  field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
2346      isolate, DependentCode::kFieldTypeGroup);
2347
2348  if (FLAG_trace_generalization) {
2349    map->PrintGeneralization(
2350        stdout, "field type generalization",
2351        modify_index, map->NumberOfOwnDescriptors(),
2352        map->NumberOfOwnDescriptors(), false,
2353        details.representation(), details.representation(),
2354        *old_field_type, *new_field_type);
2355  }
2356}
2357
2358
2359// Generalize the representation of the descriptor at |modify_index|.
2360// This method rewrites the transition tree to reflect the new change. To avoid
2361// high degrees over polymorphism, and to stabilize quickly, on every rewrite
2362// the new type is deduced by merging the current type with any potential new
2363// (partial) version of the type in the transition tree.
2364// To do this, on each rewrite:
2365// - Search the root of the transition tree using FindRootMap.
2366// - Find |target_map|, the newest matching version of this map using the keys
2367//   in the |old_map|'s descriptor array to walk the transition tree.
2368// - Merge/generalize the descriptor array of the |old_map| and |target_map|.
2369// - Generalize the |modify_index| descriptor using |new_representation| and
2370//   |new_field_type|.
2371// - Walk the tree again starting from the root towards |target_map|. Stop at
2372//   |split_map|, the first map who's descriptor array does not match the merged
2373//   descriptor array.
2374// - If |target_map| == |split_map|, |target_map| is in the expected state.
2375//   Return it.
2376// - Otherwise, invalidate the outdated transition target from |target_map|, and
2377//   replace its transition tree with a new branch for the updated descriptors.
2378Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
2379                                          int modify_index,
2380                                          Representation new_representation,
2381                                          Handle<HeapType> new_field_type,
2382                                          StoreMode store_mode) {
2383  Isolate* isolate = old_map->GetIsolate();
2384
2385  Handle<DescriptorArray> old_descriptors(
2386      old_map->instance_descriptors(), isolate);
2387  int old_nof = old_map->NumberOfOwnDescriptors();
2388  PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2389  Representation old_representation = old_details.representation();
2390
2391  // It's fine to transition from None to anything but double without any
2392  // modification to the object, because the default uninitialized value for
2393  // representation None can be overwritten by both smi and tagged values.
2394  // Doubles, however, would require a box allocation.
2395  if (old_representation.IsNone() &&
2396      !new_representation.IsNone() &&
2397      !new_representation.IsDouble()) {
2398    DCHECK(old_details.type() == FIELD);
2399    DCHECK(old_descriptors->GetFieldType(modify_index)->NowIs(
2400            HeapType::None()));
2401    if (FLAG_trace_generalization) {
2402      old_map->PrintGeneralization(
2403          stdout, "uninitialized field",
2404          modify_index, old_map->NumberOfOwnDescriptors(),
2405          old_map->NumberOfOwnDescriptors(), false,
2406          old_representation, new_representation,
2407          old_descriptors->GetFieldType(modify_index), *new_field_type);
2408    }
2409    old_descriptors->SetRepresentation(modify_index, new_representation);
2410    old_descriptors->SetValue(modify_index, *new_field_type);
2411    return old_map;
2412  }
2413
2414  // Check the state of the root map.
2415  Handle<Map> root_map(old_map->FindRootMap(), isolate);
2416  if (!old_map->EquivalentToForTransition(*root_map)) {
2417    return CopyGeneralizeAllRepresentations(
2418        old_map, modify_index, store_mode, "not equivalent");
2419  }
2420  int root_nof = root_map->NumberOfOwnDescriptors();
2421  if (modify_index < root_nof) {
2422    PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2423    if ((old_details.type() != FIELD && store_mode == FORCE_FIELD) ||
2424        (old_details.type() == FIELD &&
2425         (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
2426          !new_representation.fits_into(old_details.representation())))) {
2427      return CopyGeneralizeAllRepresentations(
2428          old_map, modify_index, store_mode, "root modification");
2429    }
2430  }
2431
2432  Handle<Map> target_map = root_map;
2433  for (int i = root_nof; i < old_nof; ++i) {
2434    int j = target_map->SearchTransition(old_descriptors->GetKey(i));
2435    if (j == TransitionArray::kNotFound) break;
2436    Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
2437    Handle<DescriptorArray> tmp_descriptors = handle(
2438        tmp_map->instance_descriptors(), isolate);
2439
2440    // Check if target map is incompatible.
2441    PropertyDetails old_details = old_descriptors->GetDetails(i);
2442    PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2443    PropertyType old_type = old_details.type();
2444    PropertyType tmp_type = tmp_details.type();
2445    if (tmp_details.attributes() != old_details.attributes() ||
2446        ((tmp_type == CALLBACKS || old_type == CALLBACKS) &&
2447         (tmp_type != old_type ||
2448          tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) {
2449      return CopyGeneralizeAllRepresentations(
2450          old_map, modify_index, store_mode, "incompatible");
2451    }
2452    Representation old_representation = old_details.representation();
2453    Representation tmp_representation = tmp_details.representation();
2454    if (!old_representation.fits_into(tmp_representation) ||
2455        (!new_representation.fits_into(tmp_representation) &&
2456         modify_index == i)) {
2457      break;
2458    }
2459    if (tmp_type == FIELD) {
2460      // Generalize the field type as necessary.
2461      Handle<HeapType> old_field_type = (old_type == FIELD)
2462          ? handle(old_descriptors->GetFieldType(i), isolate)
2463          : old_descriptors->GetValue(i)->OptimalType(
2464              isolate, tmp_representation);
2465      if (modify_index == i) {
2466        old_field_type = GeneralizeFieldType(
2467            new_field_type, old_field_type, isolate);
2468      }
2469      GeneralizeFieldType(tmp_map, i, old_field_type);
2470    } else if (tmp_type == CONSTANT) {
2471      if (old_type != CONSTANT ||
2472          old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) {
2473        break;
2474      }
2475    } else {
2476      DCHECK_EQ(tmp_type, old_type);
2477      DCHECK_EQ(tmp_descriptors->GetValue(i), old_descriptors->GetValue(i));
2478    }
2479    target_map = tmp_map;
2480  }
2481
2482  // Directly change the map if the target map is more general.
2483  Handle<DescriptorArray> target_descriptors(
2484      target_map->instance_descriptors(), isolate);
2485  int target_nof = target_map->NumberOfOwnDescriptors();
2486  if (target_nof == old_nof &&
2487      (store_mode != FORCE_FIELD ||
2488       target_descriptors->GetDetails(modify_index).type() == FIELD)) {
2489    DCHECK(modify_index < target_nof);
2490    DCHECK(new_representation.fits_into(
2491            target_descriptors->GetDetails(modify_index).representation()));
2492    DCHECK(target_descriptors->GetDetails(modify_index).type() != FIELD ||
2493           new_field_type->NowIs(
2494               target_descriptors->GetFieldType(modify_index)));
2495    return target_map;
2496  }
2497
2498  // Find the last compatible target map in the transition tree.
2499  for (int i = target_nof; i < old_nof; ++i) {
2500    int j = target_map->SearchTransition(old_descriptors->GetKey(i));
2501    if (j == TransitionArray::kNotFound) break;
2502    Handle<Map> tmp_map(target_map->GetTransition(j), isolate);
2503    Handle<DescriptorArray> tmp_descriptors(
2504        tmp_map->instance_descriptors(), isolate);
2505
2506    // Check if target map is compatible.
2507    PropertyDetails old_details = old_descriptors->GetDetails(i);
2508    PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
2509    if (tmp_details.attributes() != old_details.attributes() ||
2510        ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) &&
2511         (tmp_details.type() != old_details.type() ||
2512          tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) {
2513      return CopyGeneralizeAllRepresentations(
2514          old_map, modify_index, store_mode, "incompatible");
2515    }
2516    target_map = tmp_map;
2517  }
2518  target_nof = target_map->NumberOfOwnDescriptors();
2519  target_descriptors = handle(target_map->instance_descriptors(), isolate);
2520
2521  // Allocate a new descriptor array large enough to hold the required
2522  // descriptors, with minimally the exact same size as the old descriptor
2523  // array.
2524  int new_slack = Max(
2525      old_nof, old_descriptors->number_of_descriptors()) - old_nof;
2526  Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
2527      isolate, old_nof, new_slack);
2528  DCHECK(new_descriptors->length() > target_descriptors->length() ||
2529         new_descriptors->NumberOfSlackDescriptors() > 0 ||
2530         new_descriptors->number_of_descriptors() ==
2531         old_descriptors->number_of_descriptors());
2532  DCHECK(new_descriptors->number_of_descriptors() == old_nof);
2533
2534  // 0 -> |root_nof|
2535  int current_offset = 0;
2536  for (int i = 0; i < root_nof; ++i) {
2537    PropertyDetails old_details = old_descriptors->GetDetails(i);
2538    if (old_details.type() == FIELD) current_offset++;
2539    Descriptor d(handle(old_descriptors->GetKey(i), isolate),
2540                 handle(old_descriptors->GetValue(i), isolate),
2541                 old_details);
2542    new_descriptors->Set(i, &d);
2543  }
2544
2545  // |root_nof| -> |target_nof|
2546  for (int i = root_nof; i < target_nof; ++i) {
2547    Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
2548    PropertyDetails old_details = old_descriptors->GetDetails(i);
2549    PropertyDetails target_details = target_descriptors->GetDetails(i);
2550    target_details = target_details.CopyWithRepresentation(
2551        old_details.representation().generalize(
2552            target_details.representation()));
2553    if (modify_index == i) {
2554      target_details = target_details.CopyWithRepresentation(
2555          new_representation.generalize(target_details.representation()));
2556    }
2557    DCHECK_EQ(old_details.attributes(), target_details.attributes());
2558    if (old_details.type() == FIELD ||
2559        target_details.type() == FIELD ||
2560        (modify_index == i && store_mode == FORCE_FIELD) ||
2561        (target_descriptors->GetValue(i) != old_descriptors->GetValue(i))) {
2562      Handle<HeapType> old_field_type = (old_details.type() == FIELD)
2563          ? handle(old_descriptors->GetFieldType(i), isolate)
2564          : old_descriptors->GetValue(i)->OptimalType(
2565              isolate, target_details.representation());
2566      Handle<HeapType> target_field_type = (target_details.type() == FIELD)
2567          ? handle(target_descriptors->GetFieldType(i), isolate)
2568          : target_descriptors->GetValue(i)->OptimalType(
2569              isolate, target_details.representation());
2570      target_field_type = GeneralizeFieldType(
2571          target_field_type, old_field_type, isolate);
2572      if (modify_index == i) {
2573        target_field_type = GeneralizeFieldType(
2574            target_field_type, new_field_type, isolate);
2575      }
2576      FieldDescriptor d(target_key,
2577                        current_offset++,
2578                        target_field_type,
2579                        target_details.attributes(),
2580                        target_details.representation());
2581      new_descriptors->Set(i, &d);
2582    } else {
2583      DCHECK_NE(FIELD, target_details.type());
2584      Descriptor d(target_key,
2585                   handle(target_descriptors->GetValue(i), isolate),
2586                   target_details);
2587      new_descriptors->Set(i, &d);
2588    }
2589  }
2590
2591  // |target_nof| -> |old_nof|
2592  for (int i = target_nof; i < old_nof; ++i) {
2593    PropertyDetails old_details = old_descriptors->GetDetails(i);
2594    Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
2595    if (modify_index == i) {
2596      old_details = old_details.CopyWithRepresentation(
2597          new_representation.generalize(old_details.representation()));
2598    }
2599    if (old_details.type() == FIELD) {
2600      Handle<HeapType> old_field_type(
2601          old_descriptors->GetFieldType(i), isolate);
2602      if (modify_index == i) {
2603        old_field_type = GeneralizeFieldType(
2604            old_field_type, new_field_type, isolate);
2605      }
2606      FieldDescriptor d(old_key,
2607                        current_offset++,
2608                        old_field_type,
2609                        old_details.attributes(),
2610                        old_details.representation());
2611      new_descriptors->Set(i, &d);
2612    } else {
2613      DCHECK(old_details.type() == CONSTANT || old_details.type() == CALLBACKS);
2614      if (modify_index == i && store_mode == FORCE_FIELD) {
2615        FieldDescriptor d(old_key,
2616                          current_offset++,
2617                          GeneralizeFieldType(
2618                              old_descriptors->GetValue(i)->OptimalType(
2619                                  isolate, old_details.representation()),
2620                              new_field_type, isolate),
2621                          old_details.attributes(),
2622                          old_details.representation());
2623        new_descriptors->Set(i, &d);
2624      } else {
2625        DCHECK_NE(FIELD, old_details.type());
2626        Descriptor d(old_key,
2627                     handle(old_descriptors->GetValue(i), isolate),
2628                     old_details);
2629        new_descriptors->Set(i, &d);
2630      }
2631    }
2632  }
2633
2634  new_descriptors->Sort();
2635
2636  DCHECK(store_mode != FORCE_FIELD ||
2637         new_descriptors->GetDetails(modify_index).type() == FIELD);
2638
2639  Handle<Map> split_map(root_map->FindLastMatchMap(
2640          root_nof, old_nof, *new_descriptors), isolate);
2641  int split_nof = split_map->NumberOfOwnDescriptors();
2642  DCHECK_NE(old_nof, split_nof);
2643
2644  split_map->DeprecateTarget(
2645      old_descriptors->GetKey(split_nof), *new_descriptors);
2646
2647  if (FLAG_trace_generalization) {
2648    PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
2649    PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
2650    Handle<HeapType> old_field_type = (old_details.type() == FIELD)
2651        ? handle(old_descriptors->GetFieldType(modify_index), isolate)
2652        : HeapType::Constant(handle(old_descriptors->GetValue(modify_index),
2653                                    isolate), isolate);
2654    Handle<HeapType> new_field_type = (new_details.type() == FIELD)
2655        ? handle(new_descriptors->GetFieldType(modify_index), isolate)
2656        : HeapType::Constant(handle(new_descriptors->GetValue(modify_index),
2657                                    isolate), isolate);
2658    old_map->PrintGeneralization(
2659        stdout, "", modify_index, split_nof, old_nof,
2660        old_details.type() == CONSTANT && store_mode == FORCE_FIELD,
2661        old_details.representation(), new_details.representation(),
2662        *old_field_type, *new_field_type);
2663  }
2664
2665  // Add missing transitions.
2666  Handle<Map> new_map = split_map;
2667  for (int i = split_nof; i < old_nof; ++i) {
2668    new_map = CopyInstallDescriptors(new_map, i, new_descriptors);
2669  }
2670  new_map->set_owns_descriptors(true);
2671  return new_map;
2672}
2673
2674
2675// Generalize the representation of all FIELD descriptors.
2676Handle<Map> Map::GeneralizeAllFieldRepresentations(
2677    Handle<Map> map) {
2678  Handle<DescriptorArray> descriptors(map->instance_descriptors());
2679  for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
2680    if (descriptors->GetDetails(i).type() == FIELD) {
2681      map = GeneralizeRepresentation(map, i, Representation::Tagged(),
2682                                     HeapType::Any(map->GetIsolate()),
2683                                     FORCE_FIELD);
2684    }
2685  }
2686  return map;
2687}
2688
2689
2690// static
2691MaybeHandle<Map> Map::TryUpdate(Handle<Map> map) {
2692  Handle<Map> proto_map(map);
2693  while (proto_map->prototype()->IsJSObject()) {
2694    Handle<JSObject> holder(JSObject::cast(proto_map->prototype()));
2695    proto_map = Handle<Map>(holder->map());
2696    if (proto_map->is_deprecated() && JSObject::TryMigrateInstance(holder)) {
2697      proto_map = Handle<Map>(holder->map());
2698    }
2699  }
2700  return TryUpdateInternal(map);
2701}
2702
2703
2704// static
2705Handle<Map> Map::Update(Handle<Map> map) {
2706  if (!map->is_deprecated()) return map;
2707  return GeneralizeRepresentation(map, 0, Representation::None(),
2708                                  HeapType::None(map->GetIsolate()),
2709                                  ALLOW_AS_CONSTANT);
2710}
2711
2712
2713// static
2714MaybeHandle<Map> Map::TryUpdateInternal(Handle<Map> old_map) {
2715  DisallowHeapAllocation no_allocation;
2716  DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
2717
2718  if (!old_map->is_deprecated()) return old_map;
2719
2720  // Check the state of the root map.
2721  Map* root_map = old_map->FindRootMap();
2722  if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
2723  int root_nof = root_map->NumberOfOwnDescriptors();
2724
2725  int old_nof = old_map->NumberOfOwnDescriptors();
2726  DescriptorArray* old_descriptors = old_map->instance_descriptors();
2727
2728  Map* new_map = root_map;
2729  for (int i = root_nof; i < old_nof; ++i) {
2730    int j = new_map->SearchTransition(old_descriptors->GetKey(i));
2731    if (j == TransitionArray::kNotFound) return MaybeHandle<Map>();
2732    new_map = new_map->GetTransition(j);
2733    DescriptorArray* new_descriptors = new_map->instance_descriptors();
2734
2735    PropertyDetails new_details = new_descriptors->GetDetails(i);
2736    PropertyDetails old_details = old_descriptors->GetDetails(i);
2737    if (old_details.attributes() != new_details.attributes() ||
2738        !old_details.representation().fits_into(new_details.representation())) {
2739      return MaybeHandle<Map>();
2740    }
2741    PropertyType new_type = new_details.type();
2742    PropertyType old_type = old_details.type();
2743    Object* new_value = new_descriptors->GetValue(i);
2744    Object* old_value = old_descriptors->GetValue(i);
2745    switch (new_type) {
2746      case FIELD:
2747        if ((old_type == FIELD &&
2748             !HeapType::cast(old_value)->NowIs(HeapType::cast(new_value))) ||
2749            (old_type == CONSTANT &&
2750             !HeapType::cast(new_value)->NowContains(old_value)) ||
2751            (old_type == CALLBACKS &&
2752             !HeapType::Any()->Is(HeapType::cast(new_value)))) {
2753          return MaybeHandle<Map>();
2754        }
2755        break;
2756
2757      case CONSTANT:
2758      case CALLBACKS:
2759        if (old_type != new_type || old_value != new_value) {
2760          return MaybeHandle<Map>();
2761        }
2762        break;
2763
2764      case NORMAL:
2765        UNREACHABLE();
2766    }
2767  }
2768  if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
2769  return handle(new_map);
2770}
2771
2772
2773MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
2774                                                         Handle<Object> value) {
2775  // TODO(rossberg): Support symbols in the API.
2776  if (it->name()->IsSymbol()) return value;
2777
2778  Handle<String> name_string = Handle<String>::cast(it->name());
2779  Handle<JSObject> holder = it->GetHolder<JSObject>();
2780  Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
2781  if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>();
2782
2783  LOG(it->isolate(),
2784      ApiNamedPropertyAccess("interceptor-named-set", *holder, *name_string));
2785  PropertyCallbackArguments args(it->isolate(), interceptor->data(), *holder,
2786                                 *holder);
2787  v8::NamedPropertySetterCallback setter =
2788      v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter());
2789  v8::Handle<v8::Value> result = args.Call(
2790      setter, v8::Utils::ToLocal(name_string), v8::Utils::ToLocal(value));
2791  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
2792  if (!result.IsEmpty()) return value;
2793
2794  return MaybeHandle<Object>();
2795}
2796
2797
2798MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
2799                                        Handle<Name> name, Handle<Object> value,
2800                                        StrictMode strict_mode,
2801                                        StoreFromKeyed store_mode) {
2802  LookupIterator it(object, name);
2803  return SetProperty(&it, value, strict_mode, store_mode);
2804}
2805
2806
2807MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
2808                                        Handle<Object> value,
2809                                        StrictMode strict_mode,
2810                                        StoreFromKeyed store_mode) {
2811  // Make sure that the top context does not change when doing callbacks or
2812  // interceptor calls.
2813  AssertNoContextChange ncc(it->isolate());
2814
2815  bool done = false;
2816  for (; it->IsFound(); it->Next()) {
2817    switch (it->state()) {
2818      case LookupIterator::NOT_FOUND:
2819        UNREACHABLE();
2820
2821      case LookupIterator::ACCESS_CHECK:
2822        // TODO(verwaest): Remove the distinction. This is mostly bogus since we
2823        // don't know whether we'll want to fetch attributes or call a setter
2824        // until we find the property.
2825        if (it->HasAccess(v8::ACCESS_SET)) break;
2826        return JSObject::SetPropertyWithFailedAccessCheck(it, value,
2827                                                          strict_mode);
2828
2829      case LookupIterator::JSPROXY:
2830        if (it->HolderIsReceiverOrHiddenPrototype()) {
2831          return JSProxy::SetPropertyWithHandler(it->GetHolder<JSProxy>(),
2832                                                 it->GetReceiver(), it->name(),
2833                                                 value, strict_mode);
2834        } else {
2835          // TODO(verwaest): Use the MaybeHandle to indicate result.
2836          bool has_result = false;
2837          MaybeHandle<Object> maybe_result =
2838              JSProxy::SetPropertyViaPrototypesWithHandler(
2839                  it->GetHolder<JSProxy>(), it->GetReceiver(), it->name(),
2840                  value, strict_mode, &has_result);
2841          if (has_result) return maybe_result;
2842          done = true;
2843        }
2844        break;
2845
2846      case LookupIterator::INTERCEPTOR:
2847        if (it->HolderIsReceiverOrHiddenPrototype()) {
2848          MaybeHandle<Object> maybe_result =
2849              JSObject::SetPropertyWithInterceptor(it, value);
2850          if (!maybe_result.is_null()) return maybe_result;
2851          if (it->isolate()->has_pending_exception()) return maybe_result;
2852        } else {
2853          Maybe<PropertyAttributes> maybe_attributes =
2854              JSObject::GetPropertyAttributesWithInterceptor(
2855                  it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
2856          if (!maybe_attributes.has_value) return MaybeHandle<Object>();
2857          done = maybe_attributes.value != ABSENT;
2858          if (done && (maybe_attributes.value & READ_ONLY) != 0) {
2859            return WriteToReadOnlyProperty(it, value, strict_mode);
2860          }
2861        }
2862        break;
2863
2864      case LookupIterator::ACCESSOR:
2865        if (it->property_details().IsReadOnly()) {
2866          return WriteToReadOnlyProperty(it, value, strict_mode);
2867        }
2868        if (it->HolderIsReceiverOrHiddenPrototype() ||
2869            !it->GetAccessors()->IsDeclaredAccessorInfo()) {
2870          return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
2871                                         it->GetHolder<JSObject>(),
2872                                         it->GetAccessors(), strict_mode);
2873        }
2874        done = true;
2875        break;
2876
2877      case LookupIterator::DATA:
2878        if (it->property_details().IsReadOnly()) {
2879          return WriteToReadOnlyProperty(it, value, strict_mode);
2880        }
2881        if (it->HolderIsReceiverOrHiddenPrototype()) {
2882          return SetDataProperty(it, value);
2883        }
2884        done = true;
2885        break;
2886
2887      case LookupIterator::TRANSITION:
2888        done = true;
2889        break;
2890    }
2891
2892    if (done) break;
2893  }
2894
2895  // If the receiver is the JSGlobalObject, the store was contextual. In case
2896  // the property did not exist yet on the global object itself, we have to
2897  // throw a reference error in strict mode.
2898  if (it->GetReceiver()->IsJSGlobalObject() && strict_mode == STRICT) {
2899    Handle<Object> args[1] = {it->name()};
2900    THROW_NEW_ERROR(it->isolate(),
2901                    NewReferenceError("not_defined", HandleVector(args, 1)),
2902                    Object);
2903  }
2904
2905  return AddDataProperty(it, value, NONE, strict_mode, store_mode);
2906}
2907
2908
2909MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it,
2910                                                    Handle<Object> value,
2911                                                    StrictMode strict_mode) {
2912  if (strict_mode != STRICT) return value;
2913
2914  Handle<Object> args[] = {it->name(), it->GetReceiver()};
2915  THROW_NEW_ERROR(it->isolate(),
2916                  NewTypeError("strict_read_only_property",
2917                               HandleVector(args, arraysize(args))),
2918                  Object);
2919}
2920
2921
2922Handle<Object> Object::SetDataProperty(LookupIterator* it,
2923                                       Handle<Object> value) {
2924  // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
2925  // have own properties.
2926  Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
2927
2928  // Store on the holder which may be hidden behind the receiver.
2929  DCHECK(it->HolderIsReceiverOrHiddenPrototype());
2930
2931  // Old value for the observation change record.
2932  // Fetch before transforming the object since the encoding may become
2933  // incompatible with what's cached in |it|.
2934  bool is_observed =
2935      receiver->map()->is_observed() &&
2936      !it->name().is_identical_to(it->factory()->hidden_string());
2937  MaybeHandle<Object> maybe_old;
2938  if (is_observed) maybe_old = it->GetDataValue();
2939
2940  // Possibly migrate to the most up-to-date map that will be able to store
2941  // |value| under it->name().
2942  it->PrepareForDataProperty(value);
2943
2944  // Write the property value.
2945  it->WriteDataValue(value);
2946
2947  // Send the change record if there are observers.
2948  if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
2949    JSObject::EnqueueChangeRecord(receiver, "update", it->name(),
2950                                  maybe_old.ToHandleChecked());
2951  }
2952
2953  return value;
2954}
2955
2956
2957MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
2958                                            Handle<Object> value,
2959                                            PropertyAttributes attributes,
2960                                            StrictMode strict_mode,
2961                                            StoreFromKeyed store_mode) {
2962  DCHECK(!it->GetReceiver()->IsJSProxy());
2963  if (!it->GetReceiver()->IsJSObject()) {
2964    // TODO(verwaest): Throw a TypeError with a more specific message.
2965    return WriteToReadOnlyProperty(it, value, strict_mode);
2966  }
2967
2968  Handle<JSObject> receiver = it->GetStoreTarget();
2969
2970  // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
2971  // instead. If the prototype is Null, the proxy is detached.
2972  if (receiver->IsJSGlobalProxy()) return value;
2973
2974  // Possibly migrate to the most up-to-date map that will be able to store
2975  // |value| under it->name() with |attributes|.
2976  it->PrepareTransitionToDataProperty(value, attributes, store_mode);
2977  if (it->state() != LookupIterator::TRANSITION) {
2978    if (strict_mode == SLOPPY) return value;
2979
2980    Handle<Object> args[1] = {it->name()};
2981    THROW_NEW_ERROR(it->isolate(),
2982                    NewTypeError("object_not_extensible",
2983                                 HandleVector(args, arraysize(args))),
2984                    Object);
2985  }
2986  it->ApplyTransitionToDataProperty();
2987
2988  // TODO(verwaest): Encapsulate dictionary handling better.
2989  if (receiver->map()->is_dictionary_map()) {
2990    // TODO(verwaest): Probably should ensure this is done beforehand.
2991    it->InternalizeName();
2992    JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
2993  } else {
2994    // Write the property value.
2995    it->WriteDataValue(value);
2996  }
2997
2998  // Send the change record if there are observers.
2999  if (receiver->map()->is_observed() &&
3000      !it->name().is_identical_to(it->factory()->hidden_string())) {
3001    JSObject::EnqueueChangeRecord(receiver, "add", it->name(),
3002                                  it->factory()->the_hole_value());
3003  }
3004
3005  return value;
3006}
3007
3008
3009MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3010    Handle<JSObject> object,
3011    uint32_t index,
3012    Handle<Object> value,
3013    bool* found,
3014    StrictMode strict_mode) {
3015  Isolate *isolate = object->GetIsolate();
3016  for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
3017       iter.Advance()) {
3018    if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
3019      return JSProxy::SetPropertyViaPrototypesWithHandler(
3020          Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object,
3021          isolate->factory()->Uint32ToString(index),  // name
3022          value, strict_mode, found);
3023    }
3024    Handle<JSObject> js_proto =
3025        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
3026    if (!js_proto->HasDictionaryElements()) {
3027      continue;
3028    }
3029    Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
3030    int entry = dictionary->FindEntry(index);
3031    if (entry != SeededNumberDictionary::kNotFound) {
3032      PropertyDetails details = dictionary->DetailsAt(entry);
3033      if (details.type() == CALLBACKS) {
3034        *found = true;
3035        Handle<Object> structure(dictionary->ValueAt(entry), isolate);
3036        return SetElementWithCallback(object, structure, index, value, js_proto,
3037                                      strict_mode);
3038      }
3039    }
3040  }
3041  *found = false;
3042  return isolate->factory()->the_hole_value();
3043}
3044
3045
3046void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3047  // Only supports adding slack to owned descriptors.
3048  DCHECK(map->owns_descriptors());
3049
3050  Handle<DescriptorArray> descriptors(map->instance_descriptors());
3051  int old_size = map->NumberOfOwnDescriptors();
3052  if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3053
3054  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3055      descriptors, old_size, slack);
3056
3057  if (old_size == 0) {
3058    map->set_instance_descriptors(*new_descriptors);
3059    return;
3060  }
3061
3062  // If the source descriptors had an enum cache we copy it. This ensures
3063  // that the maps to which we push the new descriptor array back can rely
3064  // on a cache always being available once it is set. If the map has more
3065  // enumerated descriptors than available in the original cache, the cache
3066  // will be lazily replaced by the extended cache when needed.
3067  if (descriptors->HasEnumCache()) {
3068    new_descriptors->CopyEnumCacheFrom(*descriptors);
3069  }
3070
3071  // Replace descriptors by new_descriptors in all maps that share it.
3072  map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
3073
3074  Map* walk_map;
3075  for (Object* current = map->GetBackPointer();
3076       !current->IsUndefined();
3077       current = walk_map->GetBackPointer()) {
3078    walk_map = Map::cast(current);
3079    if (walk_map->instance_descriptors() != *descriptors) break;
3080    walk_map->set_instance_descriptors(*new_descriptors);
3081  }
3082
3083  map->set_instance_descriptors(*new_descriptors);
3084}
3085
3086
3087template<class T>
3088static int AppendUniqueCallbacks(NeanderArray* callbacks,
3089                                 Handle<typename T::Array> array,
3090                                 int valid_descriptors) {
3091  int nof_callbacks = callbacks->length();
3092
3093  Isolate* isolate = array->GetIsolate();
3094  // Ensure the keys are unique names before writing them into the
3095  // instance descriptor. Since it may cause a GC, it has to be done before we
3096  // temporarily put the heap in an invalid state while appending descriptors.
3097  for (int i = 0; i < nof_callbacks; ++i) {
3098    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3099    if (entry->name()->IsUniqueName()) continue;
3100    Handle<String> key =
3101        isolate->factory()->InternalizeString(
3102            Handle<String>(String::cast(entry->name())));
3103    entry->set_name(*key);
3104  }
3105
3106  // Fill in new callback descriptors.  Process the callbacks from
3107  // back to front so that the last callback with a given name takes
3108  // precedence over previously added callbacks with that name.
3109  for (int i = nof_callbacks - 1; i >= 0; i--) {
3110    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3111    Handle<Name> key(Name::cast(entry->name()));
3112    // Check if a descriptor with this name already exists before writing.
3113    if (!T::Contains(key, entry, valid_descriptors, array)) {
3114      T::Insert(key, entry, valid_descriptors, array);
3115      valid_descriptors++;
3116    }
3117  }
3118
3119  return valid_descriptors;
3120}
3121
3122struct DescriptorArrayAppender {
3123  typedef DescriptorArray Array;
3124  static bool Contains(Handle<Name> key,
3125                       Handle<AccessorInfo> entry,
3126                       int valid_descriptors,
3127                       Handle<DescriptorArray> array) {
3128    DisallowHeapAllocation no_gc;
3129    return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
3130  }
3131  static void Insert(Handle<Name> key,
3132                     Handle<AccessorInfo> entry,
3133                     int valid_descriptors,
3134                     Handle<DescriptorArray> array) {
3135    DisallowHeapAllocation no_gc;
3136    CallbacksDescriptor desc(key, entry, entry->property_attributes());
3137    array->Append(&desc);
3138  }
3139};
3140
3141
3142struct FixedArrayAppender {
3143  typedef FixedArray Array;
3144  static bool Contains(Handle<Name> key,
3145                       Handle<AccessorInfo> entry,
3146                       int valid_descriptors,
3147                       Handle<FixedArray> array) {
3148    for (int i = 0; i < valid_descriptors; i++) {
3149      if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
3150    }
3151    return false;
3152  }
3153  static void Insert(Handle<Name> key,
3154                     Handle<AccessorInfo> entry,
3155                     int valid_descriptors,
3156                     Handle<FixedArray> array) {
3157    DisallowHeapAllocation no_gc;
3158    array->set(valid_descriptors, *entry);
3159  }
3160};
3161
3162
3163void Map::AppendCallbackDescriptors(Handle<Map> map,
3164                                    Handle<Object> descriptors) {
3165  int nof = map->NumberOfOwnDescriptors();
3166  Handle<DescriptorArray> array(map->instance_descriptors());
3167  NeanderArray callbacks(descriptors);
3168  DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
3169  nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3170  map->SetNumberOfOwnDescriptors(nof);
3171}
3172
3173
3174int AccessorInfo::AppendUnique(Handle<Object> descriptors,
3175                               Handle<FixedArray> array,
3176                               int valid_descriptors) {
3177  NeanderArray callbacks(descriptors);
3178  DCHECK(array->length() >= callbacks.length() + valid_descriptors);
3179  return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3180                                                   array,
3181                                                   valid_descriptors);
3182}
3183
3184
3185static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
3186  DCHECK(!map.is_null());
3187  for (int i = 0; i < maps->length(); ++i) {
3188    if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
3189  }
3190  return false;
3191}
3192
3193
3194template <class T>
3195static Handle<T> MaybeNull(T* p) {
3196  if (p == NULL) return Handle<T>::null();
3197  return Handle<T>(p);
3198}
3199
3200
3201Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
3202  ElementsKind kind = elements_kind();
3203  Handle<Map> transitioned_map = Handle<Map>::null();
3204  Handle<Map> current_map(this);
3205  bool packed = IsFastPackedElementsKind(kind);
3206  if (IsTransitionableFastElementsKind(kind)) {
3207    while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
3208      kind = GetNextMoreGeneralFastElementsKind(kind, false);
3209      Handle<Map> maybe_transitioned_map =
3210          MaybeNull(current_map->LookupElementsTransitionMap(kind));
3211      if (maybe_transitioned_map.is_null()) break;
3212      if (ContainsMap(candidates, maybe_transitioned_map) &&
3213          (packed || !IsFastPackedElementsKind(kind))) {
3214        transitioned_map = maybe_transitioned_map;
3215        if (!IsFastPackedElementsKind(kind)) packed = false;
3216      }
3217      current_map = maybe_transitioned_map;
3218    }
3219  }
3220  return transitioned_map;
3221}
3222
3223
3224static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
3225  Map* current_map = map;
3226  int target_kind =
3227      IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
3228      ? to_kind
3229      : TERMINAL_FAST_ELEMENTS_KIND;
3230
3231  // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
3232  // allows to change elements from arbitrary kind to any ExternalArray
3233  // elements kind. Satisfy its requirements, checking whether we already
3234  // have the cached transition.
3235  if (IsExternalArrayElementsKind(to_kind) &&
3236      !IsFixedTypedArrayElementsKind(map->elements_kind())) {
3237    if (map->HasElementsTransition()) {
3238        Map* next_map = map->elements_transition_map();
3239        if (next_map->elements_kind() == to_kind) return next_map;
3240    }
3241    return map;
3242  }
3243
3244  ElementsKind kind = map->elements_kind();
3245  while (kind != target_kind) {
3246    kind = GetNextTransitionElementsKind(kind);
3247    if (!current_map->HasElementsTransition()) return current_map;
3248    current_map = current_map->elements_transition_map();
3249  }
3250
3251  if (to_kind != kind && current_map->HasElementsTransition()) {
3252    DCHECK(to_kind == DICTIONARY_ELEMENTS);
3253    Map* next_map = current_map->elements_transition_map();
3254    if (next_map->elements_kind() == to_kind) return next_map;
3255  }
3256
3257  DCHECK(current_map->elements_kind() == target_kind);
3258  return current_map;
3259}
3260
3261
3262Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3263  Map* to_map = FindClosestElementsTransition(this, to_kind);
3264  if (to_map->elements_kind() == to_kind) return to_map;
3265  return NULL;
3266}
3267
3268
3269bool Map::IsMapInArrayPrototypeChain() {
3270  Isolate* isolate = GetIsolate();
3271  if (isolate->initial_array_prototype()->map() == this) {
3272    return true;
3273  }
3274
3275  if (isolate->initial_object_prototype()->map() == this) {
3276    return true;
3277  }
3278
3279  return false;
3280}
3281
3282
3283static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
3284                                                 ElementsKind to_kind) {
3285  DCHECK(IsTransitionElementsKind(map->elements_kind()));
3286
3287  Handle<Map> current_map = map;
3288
3289  ElementsKind kind = map->elements_kind();
3290  if (!map->is_prototype_map()) {
3291    while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3292      kind = GetNextTransitionElementsKind(kind);
3293      current_map =
3294          Map::CopyAsElementsKind(current_map, kind, INSERT_TRANSITION);
3295    }
3296  }
3297
3298  // In case we are exiting the fast elements kind system, just add the map in
3299  // the end.
3300  if (kind != to_kind) {
3301    current_map = Map::CopyAsElementsKind(
3302        current_map, to_kind, INSERT_TRANSITION);
3303  }
3304
3305  DCHECK(current_map->elements_kind() == to_kind);
3306  return current_map;
3307}
3308
3309
3310Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
3311                                      ElementsKind to_kind) {
3312  ElementsKind from_kind = map->elements_kind();
3313  if (from_kind == to_kind) return map;
3314
3315  Isolate* isolate = map->GetIsolate();
3316  Context* native_context = isolate->context()->native_context();
3317  Object* maybe_array_maps = native_context->js_array_maps();
3318  if (maybe_array_maps->IsFixedArray()) {
3319    DisallowHeapAllocation no_gc;
3320    FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
3321    if (array_maps->get(from_kind) == *map) {
3322      Object* maybe_transitioned_map = array_maps->get(to_kind);
3323      if (maybe_transitioned_map->IsMap()) {
3324        return handle(Map::cast(maybe_transitioned_map));
3325      }
3326    }
3327  }
3328
3329  return TransitionElementsToSlow(map, to_kind);
3330}
3331
3332
3333Handle<Map> Map::TransitionElementsToSlow(Handle<Map> map,
3334                                          ElementsKind to_kind) {
3335  ElementsKind from_kind = map->elements_kind();
3336
3337  if (from_kind == to_kind) {
3338    return map;
3339  }
3340
3341  bool allow_store_transition =
3342      // Only remember the map transition if there is not an already existing
3343      // non-matching element transition.
3344      !map->IsUndefined() && !map->is_dictionary_map() &&
3345      IsTransitionElementsKind(from_kind);
3346
3347  // Only store fast element maps in ascending generality.
3348  if (IsFastElementsKind(to_kind)) {
3349    allow_store_transition &=
3350        IsTransitionableFastElementsKind(from_kind) &&
3351        IsMoreGeneralElementsKindTransition(from_kind, to_kind);
3352  }
3353
3354  if (!allow_store_transition) {
3355    return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
3356  }
3357
3358  return Map::AsElementsKind(map, to_kind);
3359}
3360
3361
3362// static
3363Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
3364  Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
3365
3366  if (closest_map->elements_kind() == kind) {
3367    return closest_map;
3368  }
3369
3370  return AddMissingElementsTransitions(closest_map, kind);
3371}
3372
3373
3374Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
3375                                               ElementsKind to_kind) {
3376  Handle<Map> map(object->map());
3377  return Map::TransitionElementsTo(map, to_kind);
3378}
3379
3380
3381Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy,
3382                                            Handle<Name> name) {
3383  Isolate* isolate = proxy->GetIsolate();
3384
3385  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3386  if (name->IsSymbol()) return maybe(false);
3387
3388  Handle<Object> args[] = { name };
3389  Handle<Object> result;
3390  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3391      isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(),
3392                                arraysize(args), args),
3393      Maybe<bool>());
3394
3395  return maybe(result->BooleanValue());
3396}
3397
3398
3399MaybeHandle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy,
3400                                                    Handle<Object> receiver,
3401                                                    Handle<Name> name,
3402                                                    Handle<Object> value,
3403                                                    StrictMode strict_mode) {
3404  Isolate* isolate = proxy->GetIsolate();
3405
3406  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3407  if (name->IsSymbol()) return value;
3408
3409  Handle<Object> args[] = { receiver, name, value };
3410  RETURN_ON_EXCEPTION(
3411      isolate,
3412      CallTrap(proxy,
3413               "set",
3414               isolate->derived_set_trap(),
3415               arraysize(args),
3416               args),
3417      Object);
3418
3419  return value;
3420}
3421
3422
3423MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3424    Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3425    Handle<Object> value, StrictMode strict_mode, bool* done) {
3426  Isolate* isolate = proxy->GetIsolate();
3427  Handle<Object> handler(proxy->handler(), isolate);  // Trap might morph proxy.
3428
3429  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3430  if (name->IsSymbol()) {
3431    *done = false;
3432    return isolate->factory()->the_hole_value();
3433  }
3434
3435  *done = true;  // except where redefined...
3436  Handle<Object> args[] = { name };
3437  Handle<Object> result;
3438  ASSIGN_RETURN_ON_EXCEPTION(
3439      isolate, result,
3440      CallTrap(proxy,
3441               "getPropertyDescriptor",
3442               Handle<Object>(),
3443               arraysize(args),
3444               args),
3445      Object);
3446
3447  if (result->IsUndefined()) {
3448    *done = false;
3449    return isolate->factory()->the_hole_value();
3450  }
3451
3452  // Emulate [[GetProperty]] semantics for proxies.
3453  Handle<Object> argv[] = { result };
3454  Handle<Object> desc;
3455  ASSIGN_RETURN_ON_EXCEPTION(
3456      isolate, desc,
3457      Execution::Call(isolate,
3458                      isolate->to_complete_property_descriptor(),
3459                      result,
3460                      arraysize(argv),
3461                      argv),
3462      Object);
3463
3464  // [[GetProperty]] requires to check that all properties are configurable.
3465  Handle<String> configurable_name =
3466      isolate->factory()->InternalizeOneByteString(
3467          STATIC_CHAR_VECTOR("configurable_"));
3468  Handle<Object> configurable =
3469      Object::GetProperty(desc, configurable_name).ToHandleChecked();
3470  DCHECK(configurable->IsBoolean());
3471  if (configurable->IsFalse()) {
3472    Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3473        STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3474    Handle<Object> args[] = { handler, trap, name };
3475    THROW_NEW_ERROR(isolate, NewTypeError("proxy_prop_not_configurable",
3476                                          HandleVector(args, arraysize(args))),
3477                    Object);
3478  }
3479  DCHECK(configurable->IsTrue());
3480
3481  // Check for DataDescriptor.
3482  Handle<String> hasWritable_name =
3483      isolate->factory()->InternalizeOneByteString(
3484          STATIC_CHAR_VECTOR("hasWritable_"));
3485  Handle<Object> hasWritable =
3486      Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
3487  DCHECK(hasWritable->IsBoolean());
3488  if (hasWritable->IsTrue()) {
3489    Handle<String> writable_name = isolate->factory()->InternalizeOneByteString(
3490        STATIC_CHAR_VECTOR("writable_"));
3491    Handle<Object> writable =
3492        Object::GetProperty(desc, writable_name).ToHandleChecked();
3493    DCHECK(writable->IsBoolean());
3494    *done = writable->IsFalse();
3495    if (!*done) return isolate->factory()->the_hole_value();
3496    if (strict_mode == SLOPPY) return value;
3497    Handle<Object> args[] = { name, receiver };
3498    THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
3499                                          HandleVector(args, arraysize(args))),
3500                    Object);
3501  }
3502
3503  // We have an AccessorDescriptor.
3504  Handle<String> set_name =
3505      isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_"));
3506  Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
3507  if (!setter->IsUndefined()) {
3508    // TODO(rossberg): nicer would be to cast to some JSCallable here...
3509    return SetPropertyWithDefinedSetter(
3510        receiver, Handle<JSReceiver>::cast(setter), value);
3511  }
3512
3513  if (strict_mode == SLOPPY) return value;
3514  Handle<Object> args2[] = { name, proxy };
3515  THROW_NEW_ERROR(isolate, NewTypeError("no_setter_in_callback",
3516                                        HandleVector(args2, arraysize(args2))),
3517                  Object);
3518}
3519
3520
3521MaybeHandle<Object> JSProxy::DeletePropertyWithHandler(
3522    Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) {
3523  Isolate* isolate = proxy->GetIsolate();
3524
3525  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3526  if (name->IsSymbol()) return isolate->factory()->false_value();
3527
3528  Handle<Object> args[] = { name };
3529  Handle<Object> result;
3530  ASSIGN_RETURN_ON_EXCEPTION(
3531      isolate, result,
3532      CallTrap(proxy,
3533               "delete",
3534               Handle<Object>(),
3535               arraysize(args),
3536               args),
3537      Object);
3538
3539  bool result_bool = result->BooleanValue();
3540  if (mode == STRICT_DELETION && !result_bool) {
3541    Handle<Object> handler(proxy->handler(), isolate);
3542    Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
3543        STATIC_CHAR_VECTOR("delete"));
3544    Handle<Object> args[] = { handler, trap_name };
3545    THROW_NEW_ERROR(isolate, NewTypeError("handler_failed",
3546                                          HandleVector(args, arraysize(args))),
3547                    Object);
3548  }
3549  return isolate->factory()->ToBoolean(result_bool);
3550}
3551
3552
3553MaybeHandle<Object> JSProxy::DeleteElementWithHandler(
3554    Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) {
3555  Isolate* isolate = proxy->GetIsolate();
3556  Handle<String> name = isolate->factory()->Uint32ToString(index);
3557  return JSProxy::DeletePropertyWithHandler(proxy, name, mode);
3558}
3559
3560
3561Maybe<PropertyAttributes> JSProxy::GetPropertyAttributesWithHandler(
3562    Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
3563  Isolate* isolate = proxy->GetIsolate();
3564  HandleScope scope(isolate);
3565
3566  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3567  if (name->IsSymbol()) return maybe(ABSENT);
3568
3569  Handle<Object> args[] = { name };
3570  Handle<Object> result;
3571  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3572      isolate, result,
3573      proxy->CallTrap(proxy, "getPropertyDescriptor", Handle<Object>(),
3574                      arraysize(args), args),
3575      Maybe<PropertyAttributes>());
3576
3577  if (result->IsUndefined()) return maybe(ABSENT);
3578
3579  Handle<Object> argv[] = { result };
3580  Handle<Object> desc;
3581  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3582      isolate, desc,
3583      Execution::Call(isolate, isolate->to_complete_property_descriptor(),
3584                      result, arraysize(argv), argv),
3585      Maybe<PropertyAttributes>());
3586
3587  // Convert result to PropertyAttributes.
3588  Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3589      STATIC_CHAR_VECTOR("enumerable_"));
3590  Handle<Object> enumerable;
3591  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, enumerable,
3592                                   Object::GetProperty(desc, enum_n),
3593                                   Maybe<PropertyAttributes>());
3594  Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
3595      STATIC_CHAR_VECTOR("configurable_"));
3596  Handle<Object> configurable;
3597  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
3598                                   Object::GetProperty(desc, conf_n),
3599                                   Maybe<PropertyAttributes>());
3600  Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
3601      STATIC_CHAR_VECTOR("writable_"));
3602  Handle<Object> writable;
3603  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
3604                                   Object::GetProperty(desc, writ_n),
3605                                   Maybe<PropertyAttributes>());
3606  if (!writable->BooleanValue()) {
3607    Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
3608        STATIC_CHAR_VECTOR("set_"));
3609    Handle<Object> setter;
3610    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
3611                                     Object::GetProperty(desc, set_n),
3612                                     Maybe<PropertyAttributes>());
3613    writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
3614  }
3615
3616  if (configurable->IsFalse()) {
3617    Handle<Object> handler(proxy->handler(), isolate);
3618    Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3619        STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3620    Handle<Object> args[] = { handler, trap, name };
3621    Handle<Object> error;
3622    MaybeHandle<Object> maybe_error = isolate->factory()->NewTypeError(
3623        "proxy_prop_not_configurable", HandleVector(args, arraysize(args)));
3624    if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
3625    return maybe(NONE);
3626  }
3627
3628  int attributes = NONE;
3629  if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
3630  if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
3631  if (!writable->BooleanValue()) attributes |= READ_ONLY;
3632  return maybe(static_cast<PropertyAttributes>(attributes));
3633}
3634
3635
3636Maybe<PropertyAttributes> JSProxy::GetElementAttributeWithHandler(
3637    Handle<JSProxy> proxy, Handle<JSReceiver> receiver, uint32_t index) {
3638  Isolate* isolate = proxy->GetIsolate();
3639  Handle<String> name = isolate->factory()->Uint32ToString(index);
3640  return GetPropertyAttributesWithHandler(proxy, receiver, name);
3641}
3642
3643
3644void JSProxy::Fix(Handle<JSProxy> proxy) {
3645  Isolate* isolate = proxy->GetIsolate();
3646
3647  // Save identity hash.
3648  Handle<Object> hash(proxy->GetIdentityHash(), isolate);
3649
3650  if (proxy->IsJSFunctionProxy()) {
3651    isolate->factory()->BecomeJSFunction(proxy);
3652    // Code will be set on the JavaScript side.
3653  } else {
3654    isolate->factory()->BecomeJSObject(proxy);
3655  }
3656  DCHECK(proxy->IsJSObject());
3657
3658  // Inherit identity, if it was present.
3659  if (hash->IsSmi()) {
3660    JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
3661                              Handle<Smi>::cast(hash));
3662  }
3663}
3664
3665
3666MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
3667                                      const char* name,
3668                                      Handle<Object> derived,
3669                                      int argc,
3670                                      Handle<Object> argv[]) {
3671  Isolate* isolate = proxy->GetIsolate();
3672  Handle<Object> handler(proxy->handler(), isolate);
3673
3674  Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
3675  Handle<Object> trap;
3676  ASSIGN_RETURN_ON_EXCEPTION(
3677      isolate, trap,
3678      Object::GetPropertyOrElement(handler, trap_name),
3679      Object);
3680
3681  if (trap->IsUndefined()) {
3682    if (derived.is_null()) {
3683      Handle<Object> args[] = { handler, trap_name };
3684      THROW_NEW_ERROR(isolate,
3685                      NewTypeError("handler_trap_missing",
3686                                   HandleVector(args, arraysize(args))),
3687                      Object);
3688    }
3689    trap = Handle<Object>(derived);
3690  }
3691
3692  return Execution::Call(isolate, trap, handler, argc, argv);
3693}
3694
3695
3696void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
3697  DCHECK(object->map()->inobject_properties() == map->inobject_properties());
3698  ElementsKind obj_kind = object->map()->elements_kind();
3699  ElementsKind map_kind = map->elements_kind();
3700  if (map_kind != obj_kind) {
3701    ElementsKind to_kind = map_kind;
3702    if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
3703        IsDictionaryElementsKind(obj_kind)) {
3704      to_kind = obj_kind;
3705    }
3706    if (IsDictionaryElementsKind(to_kind)) {
3707      NormalizeElements(object);
3708    } else {
3709      TransitionElementsKind(object, to_kind);
3710    }
3711    map = Map::AsElementsKind(map, to_kind);
3712  }
3713  JSObject::MigrateToMap(object, map);
3714}
3715
3716
3717void JSObject::MigrateInstance(Handle<JSObject> object) {
3718  Handle<Map> original_map(object->map());
3719  Handle<Map> map = Map::Update(original_map);
3720  map->set_migration_target(true);
3721  MigrateToMap(object, map);
3722  if (FLAG_trace_migration) {
3723    object->PrintInstanceMigration(stdout, *original_map, *map);
3724  }
3725}
3726
3727
3728// static
3729bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
3730  Isolate* isolate = object->GetIsolate();
3731  DisallowDeoptimization no_deoptimization(isolate);
3732  Handle<Map> original_map(object->map(), isolate);
3733  Handle<Map> new_map;
3734  if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
3735    return false;
3736  }
3737  JSObject::MigrateToMap(object, new_map);
3738  if (FLAG_trace_migration) {
3739    object->PrintInstanceMigration(stdout, *original_map, object->map());
3740  }
3741  return true;
3742}
3743
3744
3745void JSObject::MigrateToNewProperty(Handle<JSObject> object,
3746                                    Handle<Map> map,
3747                                    Handle<Object> value) {
3748  JSObject::MigrateToMap(object, map);
3749  if (map->GetLastDescriptorDetails().type() != FIELD) return;
3750  object->WriteToField(map->LastAdded(), *value);
3751}
3752
3753
3754void JSObject::WriteToField(int descriptor, Object* value) {
3755  DisallowHeapAllocation no_gc;
3756
3757  DescriptorArray* desc = map()->instance_descriptors();
3758  PropertyDetails details = desc->GetDetails(descriptor);
3759
3760  DCHECK(details.type() == FIELD);
3761
3762  FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
3763  if (details.representation().IsDouble()) {
3764    // Nothing more to be done.
3765    if (value->IsUninitialized()) return;
3766    HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
3767    DCHECK(box->IsMutableHeapNumber());
3768    box->set_value(value->Number());
3769  } else {
3770    FastPropertyAtPut(index, value);
3771  }
3772}
3773
3774
3775void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
3776                           Handle<Object> value,
3777                           PropertyAttributes attributes) {
3778  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
3779  CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
3780#ifdef DEBUG
3781  uint32_t index;
3782  DCHECK(!object->IsJSProxy());
3783  DCHECK(!name->AsArrayIndex(&index));
3784  Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
3785  DCHECK(maybe.has_value);
3786  DCHECK(!it.IsFound());
3787  DCHECK(object->map()->is_extensible() ||
3788         name.is_identical_to(it.isolate()->factory()->hidden_string()));
3789#endif
3790  AddDataProperty(&it, value, attributes, STRICT,
3791                  CERTAINLY_NOT_STORE_FROM_KEYED).Check();
3792}
3793
3794
3795// Reconfigures a property to a data property with attributes, even if it is not
3796// reconfigurable.
3797MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
3798    Handle<JSObject> object,
3799    Handle<Name> name,
3800    Handle<Object> value,
3801    PropertyAttributes attributes,
3802    ExecutableAccessorInfoHandling handling) {
3803  DCHECK(!value->IsTheHole());
3804  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
3805  bool is_observed = object->map()->is_observed() &&
3806                     *name != it.isolate()->heap()->hidden_string();
3807  for (; it.IsFound(); it.Next()) {
3808    switch (it.state()) {
3809      case LookupIterator::INTERCEPTOR:
3810      case LookupIterator::JSPROXY:
3811      case LookupIterator::NOT_FOUND:
3812      case LookupIterator::TRANSITION:
3813        UNREACHABLE();
3814
3815      case LookupIterator::ACCESS_CHECK:
3816        if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) {
3817          return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
3818        }
3819        break;
3820
3821      case LookupIterator::ACCESSOR: {
3822        PropertyDetails details = it.property_details();
3823        Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
3824        // Ensure the context isn't changed after calling into accessors.
3825        AssertNoContextChange ncc(it.isolate());
3826
3827        Handle<Object> accessors = it.GetAccessors();
3828
3829        if (is_observed && accessors->IsAccessorInfo()) {
3830          ASSIGN_RETURN_ON_EXCEPTION(
3831              it.isolate(), old_value,
3832              GetPropertyWithAccessor(it.GetReceiver(), it.name(),
3833                                      it.GetHolder<JSObject>(), accessors),
3834              Object);
3835        }
3836
3837        // Special handling for ExecutableAccessorInfo, which behaves like a
3838        // data property.
3839        if (handling == DONT_FORCE_FIELD &&
3840            accessors->IsExecutableAccessorInfo()) {
3841          Handle<Object> result;
3842          ASSIGN_RETURN_ON_EXCEPTION(
3843              it.isolate(), result,
3844              JSObject::SetPropertyWithAccessor(it.GetReceiver(), it.name(),
3845                                                value, it.GetHolder<JSObject>(),
3846                                                accessors, STRICT),
3847              Object);
3848          DCHECK(result->SameValue(*value));
3849
3850          if (details.attributes() == attributes) {
3851            // Regular property update if the attributes match.
3852            if (is_observed && !old_value->SameValue(*value)) {
3853              // If we are setting the prototype of a function and are
3854              // observed, don't send change records because the prototype
3855              // handles that itself.
3856              if (!object->IsJSFunction() ||
3857                  !Name::Equals(it.isolate()->factory()->prototype_string(),
3858                                name) ||
3859                  !Handle<JSFunction>::cast(object)->should_have_prototype()) {
3860                EnqueueChangeRecord(object, "update", name, old_value);
3861              }
3862            }
3863            return value;
3864          }
3865
3866          // Reconfigure the accessor if attributes mismatch.
3867          Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor(
3868              it.isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
3869          new_data->set_property_attributes(attributes);
3870          // By clearing the setter we don't have to introduce a lookup to
3871          // the setter, simply make it unavailable to reflect the
3872          // attributes.
3873          if (attributes & READ_ONLY) new_data->clear_setter();
3874          SetPropertyCallback(object, name, new_data, attributes);
3875          if (is_observed) {
3876            if (old_value->SameValue(*value)) {
3877              old_value = it.isolate()->factory()->the_hole_value();
3878            }
3879            EnqueueChangeRecord(object, "reconfigure", name, old_value);
3880          }
3881          return value;
3882        }
3883
3884        it.ReconfigureDataProperty(value, attributes);
3885        it.PrepareForDataProperty(value);
3886        it.WriteDataValue(value);
3887
3888        if (is_observed) {
3889          if (old_value->SameValue(*value)) {
3890            old_value = it.isolate()->factory()->the_hole_value();
3891          }
3892          EnqueueChangeRecord(object, "reconfigure", name, old_value);
3893        }
3894
3895        return value;
3896      }
3897
3898      case LookupIterator::DATA: {
3899        PropertyDetails details = it.property_details();
3900        Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
3901        // Regular property update if the attributes match.
3902        if (details.attributes() == attributes) {
3903          return SetDataProperty(&it, value);
3904        }
3905        // Reconfigure the data property if the attributes mismatch.
3906        if (is_observed) old_value = it.GetDataValue();
3907
3908        it.ReconfigureDataProperty(value, attributes);
3909        it.PrepareForDataProperty(value);
3910        it.WriteDataValue(value);
3911
3912        if (is_observed) {
3913          if (old_value->SameValue(*value)) {
3914            old_value = it.isolate()->factory()->the_hole_value();
3915          }
3916          EnqueueChangeRecord(object, "reconfigure", name, old_value);
3917        }
3918
3919        return value;
3920      }
3921    }
3922  }
3923
3924  return AddDataProperty(&it, value, attributes, STRICT,
3925                         CERTAINLY_NOT_STORE_FROM_KEYED);
3926}
3927
3928
3929Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
3930    Handle<JSObject> holder,
3931    Handle<Object> receiver,
3932    Handle<Name> name) {
3933  // TODO(rossberg): Support symbols in the API.
3934  if (name->IsSymbol()) return maybe(ABSENT);
3935
3936  Isolate* isolate = holder->GetIsolate();
3937  HandleScope scope(isolate);
3938
3939  // Make sure that the top context does not change when doing
3940  // callbacks or interceptor calls.
3941  AssertNoContextChange ncc(isolate);
3942
3943  Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
3944  PropertyCallbackArguments args(
3945      isolate, interceptor->data(), *receiver, *holder);
3946  if (!interceptor->query()->IsUndefined()) {
3947    v8::NamedPropertyQueryCallback query =
3948        v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query());
3949    LOG(isolate,
3950        ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
3951    v8::Handle<v8::Integer> result =
3952        args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name)));
3953    if (!result.IsEmpty()) {
3954      DCHECK(result->IsInt32());
3955      return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
3956    }
3957  } else if (!interceptor->getter()->IsUndefined()) {
3958    v8::NamedPropertyGetterCallback getter =
3959        v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
3960    LOG(isolate,
3961        ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
3962    v8::Handle<v8::Value> result =
3963        args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name)));
3964    if (!result.IsEmpty()) return maybe(DONT_ENUM);
3965  }
3966
3967  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
3968  return maybe(ABSENT);
3969}
3970
3971
3972Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
3973    Handle<JSReceiver> object, Handle<Name> name) {
3974  // Check whether the name is an array index.
3975  uint32_t index = 0;
3976  if (object->IsJSObject() && name->AsArrayIndex(&index)) {
3977    return GetOwnElementAttribute(object, index);
3978  }
3979  LookupIterator it(object, name, LookupIterator::HIDDEN);
3980  return GetPropertyAttributes(&it);
3981}
3982
3983
3984Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
3985    LookupIterator* it) {
3986  for (; it->IsFound(); it->Next()) {
3987    switch (it->state()) {
3988      case LookupIterator::NOT_FOUND:
3989      case LookupIterator::TRANSITION:
3990        UNREACHABLE();
3991      case LookupIterator::JSPROXY:
3992        return JSProxy::GetPropertyAttributesWithHandler(
3993            it->GetHolder<JSProxy>(), it->GetReceiver(), it->name());
3994      case LookupIterator::INTERCEPTOR: {
3995        Maybe<PropertyAttributes> result =
3996            JSObject::GetPropertyAttributesWithInterceptor(
3997                it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
3998        if (!result.has_value) return result;
3999        if (result.value != ABSENT) return result;
4000        break;
4001      }
4002      case LookupIterator::ACCESS_CHECK:
4003        if (it->HasAccess(v8::ACCESS_HAS)) break;
4004        return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
4005      case LookupIterator::ACCESSOR:
4006      case LookupIterator::DATA:
4007        return maybe(it->property_details().attributes());
4008    }
4009  }
4010  return maybe(ABSENT);
4011}
4012
4013
4014Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver(
4015    Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4016    bool check_prototype) {
4017  Isolate* isolate = object->GetIsolate();
4018
4019  // Check access rights if needed.
4020  if (object->IsAccessCheckNeeded()) {
4021    if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
4022      isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
4023      RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
4024      return maybe(ABSENT);
4025    }
4026  }
4027
4028  if (object->IsJSGlobalProxy()) {
4029    PrototypeIterator iter(isolate, object);
4030    if (iter.IsAtEnd()) return maybe(ABSENT);
4031    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4032    return JSObject::GetElementAttributeWithReceiver(
4033        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4034        index, check_prototype);
4035  }
4036
4037  // Check for lookup interceptor except when bootstrapping.
4038  if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
4039    return JSObject::GetElementAttributeWithInterceptor(
4040        object, receiver, index, check_prototype);
4041  }
4042
4043  return GetElementAttributeWithoutInterceptor(
4044      object, receiver, index, check_prototype);
4045}
4046
4047
4048Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor(
4049    Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4050    bool check_prototype) {
4051  Isolate* isolate = object->GetIsolate();
4052  HandleScope scope(isolate);
4053
4054  // Make sure that the top context does not change when doing
4055  // callbacks or interceptor calls.
4056  AssertNoContextChange ncc(isolate);
4057
4058  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
4059  PropertyCallbackArguments args(
4060      isolate, interceptor->data(), *receiver, *object);
4061  if (!interceptor->query()->IsUndefined()) {
4062    v8::IndexedPropertyQueryCallback query =
4063        v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4064    LOG(isolate,
4065        ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index));
4066    v8::Handle<v8::Integer> result = args.Call(query, index);
4067    if (!result.IsEmpty())
4068      return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
4069  } else if (!interceptor->getter()->IsUndefined()) {
4070    v8::IndexedPropertyGetterCallback getter =
4071        v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4072    LOG(isolate,
4073        ApiIndexedPropertyAccess(
4074            "interceptor-indexed-get-has", *object, index));
4075    v8::Handle<v8::Value> result = args.Call(getter, index);
4076    if (!result.IsEmpty()) return maybe(NONE);
4077  }
4078
4079  return GetElementAttributeWithoutInterceptor(
4080       object, receiver, index, check_prototype);
4081}
4082
4083
4084Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor(
4085    Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4086    bool check_prototype) {
4087  PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes(
4088      receiver, object, index);
4089  if (attr != ABSENT) return maybe(attr);
4090
4091  // Handle [] on String objects.
4092  if (object->IsStringObjectWithCharacterAt(index)) {
4093    return maybe(static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE));
4094  }
4095
4096  if (!check_prototype) return maybe(ABSENT);
4097
4098  PrototypeIterator iter(object->GetIsolate(), object);
4099  if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
4100    // We need to follow the spec and simulate a call to [[GetOwnProperty]].
4101    return JSProxy::GetElementAttributeWithHandler(
4102        Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4103        index);
4104  }
4105  if (iter.IsAtEnd()) return maybe(ABSENT);
4106  return GetElementAttributeWithReceiver(
4107      Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
4108      index, true);
4109}
4110
4111
4112Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
4113  Handle<FixedArray> array(
4114      isolate->factory()->NewFixedArray(kEntries, TENURED));
4115  return Handle<NormalizedMapCache>::cast(array);
4116}
4117
4118
4119MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
4120                                         PropertyNormalizationMode mode) {
4121  DisallowHeapAllocation no_gc;
4122  Object* value = FixedArray::get(GetIndex(fast_map));
4123  if (!value->IsMap() ||
4124      !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4125    return MaybeHandle<Map>();
4126  }
4127  return handle(Map::cast(value));
4128}
4129
4130
4131void NormalizedMapCache::Set(Handle<Map> fast_map,
4132                             Handle<Map> normalized_map) {
4133  DisallowHeapAllocation no_gc;
4134  DCHECK(normalized_map->is_dictionary_map());
4135  FixedArray::set(GetIndex(fast_map), *normalized_map);
4136}
4137
4138
4139void NormalizedMapCache::Clear() {
4140  int entries = length();
4141  for (int i = 0; i != entries; i++) {
4142    set_undefined(i);
4143  }
4144}
4145
4146
4147void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
4148                                    Handle<Name> name,
4149                                    Handle<Code> code) {
4150  Handle<Map> map(object->map());
4151  Map::UpdateCodeCache(map, name, code);
4152}
4153
4154
4155void JSObject::NormalizeProperties(Handle<JSObject> object,
4156                                   PropertyNormalizationMode mode,
4157                                   int expected_additional_properties) {
4158  if (!object->HasFastProperties()) return;
4159
4160  Handle<Map> map(object->map());
4161  Handle<Map> new_map = Map::Normalize(map, mode);
4162
4163  MigrateFastToSlow(object, new_map, expected_additional_properties);
4164}
4165
4166
4167void JSObject::MigrateFastToSlow(Handle<JSObject> object,
4168                                 Handle<Map> new_map,
4169                                 int expected_additional_properties) {
4170  // The global object is always normalized.
4171  DCHECK(!object->IsGlobalObject());
4172  // JSGlobalProxy must never be normalized
4173  DCHECK(!object->IsJSGlobalProxy());
4174
4175  Isolate* isolate = object->GetIsolate();
4176  HandleScope scope(isolate);
4177  Handle<Map> map(object->map());
4178
4179  // Allocate new content.
4180  int real_size = map->NumberOfOwnDescriptors();
4181  int property_count = real_size;
4182  if (expected_additional_properties > 0) {
4183    property_count += expected_additional_properties;
4184  } else {
4185    property_count += 2;  // Make space for two more properties.
4186  }
4187  Handle<NameDictionary> dictionary =
4188      NameDictionary::New(isolate, property_count);
4189
4190  Handle<DescriptorArray> descs(map->instance_descriptors());
4191  for (int i = 0; i < real_size; i++) {
4192    PropertyDetails details = descs->GetDetails(i);
4193    switch (details.type()) {
4194      case CONSTANT: {
4195        Handle<Name> key(descs->GetKey(i));
4196        Handle<Object> value(descs->GetConstant(i), isolate);
4197        PropertyDetails d = PropertyDetails(
4198            details.attributes(), NORMAL, i + 1);
4199        dictionary = NameDictionary::Add(dictionary, key, value, d);
4200        break;
4201      }
4202      case FIELD: {
4203        Handle<Name> key(descs->GetKey(i));
4204        FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4205        Handle<Object> value(
4206            object->RawFastPropertyAt(index), isolate);
4207        if (details.representation().IsDouble()) {
4208          DCHECK(value->IsMutableHeapNumber());
4209          Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
4210          value = isolate->factory()->NewHeapNumber(old->value());
4211        }
4212        PropertyDetails d =
4213            PropertyDetails(details.attributes(), NORMAL, i + 1);
4214        dictionary = NameDictionary::Add(dictionary, key, value, d);
4215        break;
4216      }
4217      case CALLBACKS: {
4218        Handle<Name> key(descs->GetKey(i));
4219        Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4220        PropertyDetails d = PropertyDetails(
4221            details.attributes(), CALLBACKS, i + 1);
4222        dictionary = NameDictionary::Add(dictionary, key, value, d);
4223        break;
4224      }
4225      case NORMAL:
4226        UNREACHABLE();
4227        break;
4228    }
4229  }
4230
4231  // Copy the next enumeration index from instance descriptor.
4232  dictionary->SetNextEnumerationIndex(real_size + 1);
4233
4234  // From here on we cannot fail and we shouldn't GC anymore.
4235  DisallowHeapAllocation no_allocation;
4236
4237  // Resize the object in the heap if necessary.
4238  int new_instance_size = new_map->instance_size();
4239  int instance_size_delta = map->instance_size() - new_instance_size;
4240  DCHECK(instance_size_delta >= 0);
4241
4242  if (instance_size_delta > 0) {
4243    Heap* heap = isolate->heap();
4244    heap->CreateFillerObjectAt(object->address() + new_instance_size,
4245                               instance_size_delta);
4246    heap->AdjustLiveBytes(object->address(), -instance_size_delta,
4247                          Heap::FROM_MUTATOR);
4248  }
4249
4250  // We are storing the new map using release store after creating a filler for
4251  // the left-over space to avoid races with the sweeper thread.
4252  object->synchronized_set_map(*new_map);
4253
4254  object->set_properties(*dictionary);
4255
4256  isolate->counters()->props_to_dictionary()->Increment();
4257
4258#ifdef DEBUG
4259  if (FLAG_trace_normalization) {
4260    OFStream os(stdout);
4261    os << "Object properties have been normalized:\n";
4262    object->Print(os);
4263  }
4264#endif
4265}
4266
4267
4268void JSObject::MigrateSlowToFast(Handle<JSObject> object,
4269                                 int unused_property_fields) {
4270  if (object->HasFastProperties()) return;
4271  DCHECK(!object->IsGlobalObject());
4272  Isolate* isolate = object->GetIsolate();
4273  Factory* factory = isolate->factory();
4274  Handle<NameDictionary> dictionary(object->property_dictionary());
4275
4276  // Make sure we preserve dictionary representation if there are too many
4277  // descriptors.
4278  int number_of_elements = dictionary->NumberOfElements();
4279  if (number_of_elements > kMaxNumberOfDescriptors) return;
4280
4281  if (number_of_elements != dictionary->NextEnumerationIndex()) {
4282    NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
4283  }
4284
4285  int instance_descriptor_length = 0;
4286  int number_of_fields = 0;
4287
4288  // Compute the length of the instance descriptor.
4289  int capacity = dictionary->Capacity();
4290  for (int i = 0; i < capacity; i++) {
4291    Object* k = dictionary->KeyAt(i);
4292    if (dictionary->IsKey(k)) {
4293      Object* value = dictionary->ValueAt(i);
4294      PropertyType type = dictionary->DetailsAt(i).type();
4295      DCHECK(type != FIELD);
4296      instance_descriptor_length++;
4297      if (type == NORMAL && !value->IsJSFunction()) {
4298        number_of_fields += 1;
4299      }
4300    }
4301  }
4302
4303  int inobject_props = object->map()->inobject_properties();
4304
4305  // Allocate new map.
4306  Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
4307  new_map->set_dictionary_map(false);
4308
4309  if (instance_descriptor_length == 0) {
4310    DisallowHeapAllocation no_gc;
4311    DCHECK_LE(unused_property_fields, inobject_props);
4312    // Transform the object.
4313    new_map->set_unused_property_fields(inobject_props);
4314    object->synchronized_set_map(*new_map);
4315    object->set_properties(isolate->heap()->empty_fixed_array());
4316    // Check that it really works.
4317    DCHECK(object->HasFastProperties());
4318    return;
4319  }
4320
4321  // Allocate the instance descriptor.
4322  Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
4323      isolate, instance_descriptor_length);
4324
4325  int number_of_allocated_fields =
4326      number_of_fields + unused_property_fields - inobject_props;
4327  if (number_of_allocated_fields < 0) {
4328    // There is enough inobject space for all fields (including unused).
4329    number_of_allocated_fields = 0;
4330    unused_property_fields = inobject_props - number_of_fields;
4331  }
4332
4333  // Allocate the fixed array for the fields.
4334  Handle<FixedArray> fields = factory->NewFixedArray(
4335      number_of_allocated_fields);
4336
4337  // Fill in the instance descriptor and the fields.
4338  int current_offset = 0;
4339  for (int i = 0; i < capacity; i++) {
4340    Object* k = dictionary->KeyAt(i);
4341    if (dictionary->IsKey(k)) {
4342      Object* value = dictionary->ValueAt(i);
4343      Handle<Name> key;
4344      if (k->IsSymbol()) {
4345        key = handle(Symbol::cast(k));
4346      } else {
4347        // Ensure the key is a unique name before writing into the
4348        // instance descriptor.
4349        key = factory->InternalizeString(handle(String::cast(k)));
4350      }
4351
4352      PropertyDetails details = dictionary->DetailsAt(i);
4353      int enumeration_index = details.dictionary_index();
4354      PropertyType type = details.type();
4355
4356      if (value->IsJSFunction()) {
4357        ConstantDescriptor d(key,
4358                             handle(value, isolate),
4359                             details.attributes());
4360        descriptors->Set(enumeration_index - 1, &d);
4361      } else if (type == NORMAL) {
4362        if (current_offset < inobject_props) {
4363          object->InObjectPropertyAtPut(current_offset,
4364                                        value,
4365                                        UPDATE_WRITE_BARRIER);
4366        } else {
4367          int offset = current_offset - inobject_props;
4368          fields->set(offset, value);
4369        }
4370        FieldDescriptor d(key,
4371                          current_offset++,
4372                          details.attributes(),
4373                          // TODO(verwaest): value->OptimalRepresentation();
4374                          Representation::Tagged());
4375        descriptors->Set(enumeration_index - 1, &d);
4376      } else if (type == CALLBACKS) {
4377        CallbacksDescriptor d(key,
4378                              handle(value, isolate),
4379                              details.attributes());
4380        descriptors->Set(enumeration_index - 1, &d);
4381      } else {
4382        UNREACHABLE();
4383      }
4384    }
4385  }
4386  DCHECK(current_offset == number_of_fields);
4387
4388  descriptors->Sort();
4389
4390  DisallowHeapAllocation no_gc;
4391  new_map->InitializeDescriptors(*descriptors);
4392  new_map->set_unused_property_fields(unused_property_fields);
4393
4394  // Transform the object.
4395  object->synchronized_set_map(*new_map);
4396
4397  object->set_properties(*fields);
4398  DCHECK(object->IsJSObject());
4399
4400  // Check that it really works.
4401  DCHECK(object->HasFastProperties());
4402}
4403
4404
4405void JSObject::ResetElements(Handle<JSObject> object) {
4406  Isolate* isolate = object->GetIsolate();
4407  CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
4408  if (object->map()->has_dictionary_elements()) {
4409    Handle<SeededNumberDictionary> new_elements =
4410        SeededNumberDictionary::New(isolate, 0);
4411    object->set_elements(*new_elements);
4412  } else {
4413    object->set_elements(object->map()->GetInitialElements());
4414  }
4415}
4416
4417
4418static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
4419    Handle<FixedArrayBase> array,
4420    int length,
4421    Handle<SeededNumberDictionary> dictionary) {
4422  Isolate* isolate = array->GetIsolate();
4423  Factory* factory = isolate->factory();
4424  bool has_double_elements = array->IsFixedDoubleArray();
4425  for (int i = 0; i < length; i++) {
4426    Handle<Object> value;
4427    if (has_double_elements) {
4428      Handle<FixedDoubleArray> double_array =
4429          Handle<FixedDoubleArray>::cast(array);
4430      if (double_array->is_the_hole(i)) {
4431        value = factory->the_hole_value();
4432      } else {
4433        value = factory->NewHeapNumber(double_array->get_scalar(i));
4434      }
4435    } else {
4436      value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4437    }
4438    if (!value->IsTheHole()) {
4439      PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
4440      dictionary =
4441          SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4442    }
4443  }
4444  return dictionary;
4445}
4446
4447
4448Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4449    Handle<JSObject> object) {
4450  DCHECK(!object->HasExternalArrayElements() &&
4451         !object->HasFixedTypedArrayElements());
4452  Isolate* isolate = object->GetIsolate();
4453
4454  // Find the backing store.
4455  Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements()));
4456  bool is_arguments =
4457      (array->map() == isolate->heap()->sloppy_arguments_elements_map());
4458  if (is_arguments) {
4459    array = handle(FixedArrayBase::cast(
4460        Handle<FixedArray>::cast(array)->get(1)));
4461  }
4462  if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array);
4463
4464  DCHECK(object->HasFastSmiOrObjectElements() ||
4465         object->HasFastDoubleElements() ||
4466         object->HasFastArgumentsElements());
4467  // Compute the effective length and allocate a new backing store.
4468  int length = object->IsJSArray()
4469      ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4470      : array->length();
4471  int old_capacity = 0;
4472  int used_elements = 0;
4473  object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4474  Handle<SeededNumberDictionary> dictionary =
4475      SeededNumberDictionary::New(isolate, used_elements);
4476
4477  dictionary = CopyFastElementsToDictionary(array, length, dictionary);
4478
4479  // Switch to using the dictionary as the backing storage for elements.
4480  if (is_arguments) {
4481    FixedArray::cast(object->elements())->set(1, *dictionary);
4482  } else {
4483    // Set the new map first to satify the elements type assert in
4484    // set_elements().
4485    Handle<Map> new_map =
4486        JSObject::GetElementsTransitionMap(object, DICTIONARY_ELEMENTS);
4487
4488    JSObject::MigrateToMap(object, new_map);
4489    object->set_elements(*dictionary);
4490  }
4491
4492  isolate->counters()->elements_to_dictionary()->Increment();
4493
4494#ifdef DEBUG
4495  if (FLAG_trace_normalization) {
4496    OFStream os(stdout);
4497    os << "Object elements have been normalized:\n";
4498    object->Print(os);
4499  }
4500#endif
4501
4502  DCHECK(object->HasDictionaryElements() ||
4503         object->HasDictionaryArgumentsElements());
4504  return dictionary;
4505}
4506
4507
4508static Smi* GenerateIdentityHash(Isolate* isolate) {
4509  int hash_value;
4510  int attempts = 0;
4511  do {
4512    // Generate a random 32-bit hash value but limit range to fit
4513    // within a smi.
4514    hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4515    attempts++;
4516  } while (hash_value == 0 && attempts < 30);
4517  hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
4518
4519  return Smi::FromInt(hash_value);
4520}
4521
4522
4523void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4524  DCHECK(!object->IsJSGlobalProxy());
4525  Isolate* isolate = object->GetIsolate();
4526  SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4527}
4528
4529
4530template<typename ProxyType>
4531static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
4532  Isolate* isolate = proxy->GetIsolate();
4533
4534  Handle<Object> maybe_hash(proxy->hash(), isolate);
4535  if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4536
4537  Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4538  proxy->set_hash(*hash);
4539  return hash;
4540}
4541
4542
4543Object* JSObject::GetIdentityHash() {
4544  DisallowHeapAllocation no_gc;
4545  Isolate* isolate = GetIsolate();
4546  if (IsJSGlobalProxy()) {
4547    return JSGlobalProxy::cast(this)->hash();
4548  }
4549  Object* stored_value =
4550      GetHiddenProperty(isolate->factory()->identity_hash_string());
4551  return stored_value->IsSmi()
4552      ? stored_value
4553      : isolate->heap()->undefined_value();
4554}
4555
4556
4557Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
4558  if (object->IsJSGlobalProxy()) {
4559    return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
4560  }
4561
4562  Isolate* isolate = object->GetIsolate();
4563
4564  Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
4565  if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4566
4567  Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4568  SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4569  return hash;
4570}
4571
4572
4573Object* JSProxy::GetIdentityHash() {
4574  return this->hash();
4575}
4576
4577
4578Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
4579  return GetOrCreateIdentityHashHelper(proxy);
4580}
4581
4582
4583Object* JSObject::GetHiddenProperty(Handle<Name> key) {
4584  DisallowHeapAllocation no_gc;
4585  DCHECK(key->IsUniqueName());
4586  if (IsJSGlobalProxy()) {
4587    // JSGlobalProxies store their hash internally.
4588    DCHECK(*key != GetHeap()->identity_hash_string());
4589    // For a proxy, use the prototype as target object.
4590    PrototypeIterator iter(GetIsolate(), this);
4591    // If the proxy is detached, return undefined.
4592    if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
4593    DCHECK(iter.GetCurrent()->IsJSGlobalObject());
4594    return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key);
4595  }
4596  DCHECK(!IsJSGlobalProxy());
4597  Object* inline_value = GetHiddenPropertiesHashTable();
4598
4599  if (inline_value->IsSmi()) {
4600    // Handle inline-stored identity hash.
4601    if (*key == GetHeap()->identity_hash_string()) {
4602      return inline_value;
4603    } else {
4604      return GetHeap()->the_hole_value();
4605    }
4606  }
4607
4608  if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
4609
4610  ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
4611  Object* entry = hashtable->Lookup(key);
4612  return entry;
4613}
4614
4615
4616Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
4617                                           Handle<Name> key,
4618                                           Handle<Object> value) {
4619  Isolate* isolate = object->GetIsolate();
4620
4621  DCHECK(key->IsUniqueName());
4622  if (object->IsJSGlobalProxy()) {
4623    // JSGlobalProxies store their hash internally.
4624    DCHECK(*key != *isolate->factory()->identity_hash_string());
4625    // For a proxy, use the prototype as target object.
4626    PrototypeIterator iter(isolate, object);
4627    // If the proxy is detached, return undefined.
4628    if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
4629    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4630    return SetHiddenProperty(
4631        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key,
4632        value);
4633  }
4634  DCHECK(!object->IsJSGlobalProxy());
4635
4636  Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
4637
4638  // If there is no backing store yet, store the identity hash inline.
4639  if (value->IsSmi() &&
4640      *key == *isolate->factory()->identity_hash_string() &&
4641      (inline_value->IsUndefined() || inline_value->IsSmi())) {
4642    return JSObject::SetHiddenPropertiesHashTable(object, value);
4643  }
4644
4645  Handle<ObjectHashTable> hashtable =
4646      GetOrCreateHiddenPropertiesHashtable(object);
4647
4648  // If it was found, check if the key is already in the dictionary.
4649  Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
4650                                                           value);
4651  if (*new_table != *hashtable) {
4652    // If adding the key expanded the dictionary (i.e., Add returned a new
4653    // dictionary), store it back to the object.
4654    SetHiddenPropertiesHashTable(object, new_table);
4655  }
4656
4657  // Return this to mark success.
4658  return object;
4659}
4660
4661
4662void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
4663  Isolate* isolate = object->GetIsolate();
4664  DCHECK(key->IsUniqueName());
4665
4666  if (object->IsJSGlobalProxy()) {
4667    PrototypeIterator iter(isolate, object);
4668    if (iter.IsAtEnd()) return;
4669    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4670    return DeleteHiddenProperty(
4671        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key);
4672  }
4673
4674  Object* inline_value = object->GetHiddenPropertiesHashTable();
4675
4676  // We never delete (inline-stored) identity hashes.
4677  DCHECK(*key != *isolate->factory()->identity_hash_string());
4678  if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
4679
4680  Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
4681  bool was_present = false;
4682  ObjectHashTable::Remove(hashtable, key, &was_present);
4683}
4684
4685
4686bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
4687  Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
4688  LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR);
4689  Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
4690  // Cannot get an exception since the hidden_string isn't accessible to JS.
4691  DCHECK(maybe.has_value);
4692  return maybe.value != ABSENT;
4693}
4694
4695
4696Object* JSObject::GetHiddenPropertiesHashTable() {
4697  DCHECK(!IsJSGlobalProxy());
4698  if (HasFastProperties()) {
4699    // If the object has fast properties, check whether the first slot
4700    // in the descriptor array matches the hidden string. Since the
4701    // hidden strings hash code is zero (and no other name has hash
4702    // code zero) it will always occupy the first entry if present.
4703    DescriptorArray* descriptors = this->map()->instance_descriptors();
4704    if (descriptors->number_of_descriptors() > 0) {
4705      int sorted_index = descriptors->GetSortedKeyIndex(0);
4706      if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
4707          sorted_index < map()->NumberOfOwnDescriptors()) {
4708        DCHECK(descriptors->GetType(sorted_index) == FIELD);
4709        DCHECK(descriptors->GetDetails(sorted_index).representation().
4710               IsCompatibleForLoad(Representation::Tagged()));
4711        FieldIndex index = FieldIndex::ForDescriptor(this->map(),
4712                                                     sorted_index);
4713        return this->RawFastPropertyAt(index);
4714      } else {
4715        return GetHeap()->undefined_value();
4716      }
4717    } else {
4718      return GetHeap()->undefined_value();
4719    }
4720  } else {
4721    Isolate* isolate = GetIsolate();
4722    LookupIterator it(handle(this), isolate->factory()->hidden_string(),
4723                      LookupIterator::OWN_SKIP_INTERCEPTOR);
4724    // Access check is always skipped for the hidden string anyways.
4725    return *GetDataProperty(&it);
4726  }
4727}
4728
4729Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
4730    Handle<JSObject> object) {
4731  Isolate* isolate = object->GetIsolate();
4732
4733  static const int kInitialCapacity = 4;
4734  Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
4735  if (inline_value->IsHashTable()) {
4736    return Handle<ObjectHashTable>::cast(inline_value);
4737  }
4738
4739  Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
4740      isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
4741
4742  if (inline_value->IsSmi()) {
4743    // We were storing the identity hash inline and now allocated an actual
4744    // dictionary.  Put the identity hash into the new dictionary.
4745    hashtable = ObjectHashTable::Put(hashtable,
4746                                     isolate->factory()->identity_hash_string(),
4747                                     inline_value);
4748  }
4749
4750  SetHiddenPropertiesHashTable(object, hashtable);
4751  return hashtable;
4752}
4753
4754
4755Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
4756                                                      Handle<Object> value) {
4757  DCHECK(!object->IsJSGlobalProxy());
4758  Isolate* isolate = object->GetIsolate();
4759  Handle<Name> name = isolate->factory()->hidden_string();
4760  SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
4761  return object;
4762}
4763
4764
4765MaybeHandle<Object> JSObject::DeletePropertyWithInterceptor(
4766    Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name) {
4767  Isolate* isolate = holder->GetIsolate();
4768
4769  // TODO(rossberg): Support symbols in the API.
4770  if (name->IsSymbol()) return MaybeHandle<Object>();
4771
4772  Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
4773  if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>();
4774
4775  v8::NamedPropertyDeleterCallback deleter =
4776      v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter());
4777  LOG(isolate,
4778      ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name));
4779  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
4780                                 *holder);
4781  v8::Handle<v8::Boolean> result =
4782      args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name)));
4783  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
4784  if (result.IsEmpty()) return MaybeHandle<Object>();
4785
4786  DCHECK(result->IsBoolean());
4787  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
4788  result_internal->VerifyApiCallResultType();
4789  // Rebox CustomArguments::kReturnValueOffset before returning.
4790  return handle(*result_internal, isolate);
4791}
4792
4793
4794MaybeHandle<Object> JSObject::DeleteElementWithInterceptor(
4795    Handle<JSObject> object,
4796    uint32_t index) {
4797  Isolate* isolate = object->GetIsolate();
4798  Factory* factory = isolate->factory();
4799
4800  // Make sure that the top context does not change when doing
4801  // callbacks or interceptor calls.
4802  AssertNoContextChange ncc(isolate);
4803
4804  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
4805  if (interceptor->deleter()->IsUndefined()) return factory->false_value();
4806  v8::IndexedPropertyDeleterCallback deleter =
4807      v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
4808  LOG(isolate,
4809      ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index));
4810  PropertyCallbackArguments args(
4811      isolate, interceptor->data(), *object, *object);
4812  v8::Handle<v8::Boolean> result = args.Call(deleter, index);
4813  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
4814  if (!result.IsEmpty()) {
4815    DCHECK(result->IsBoolean());
4816    Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
4817    result_internal->VerifyApiCallResultType();
4818    // Rebox CustomArguments::kReturnValueOffset before returning.
4819    return handle(*result_internal, isolate);
4820  }
4821  MaybeHandle<Object> delete_result = object->GetElementsAccessor()->Delete(
4822      object, index, NORMAL_DELETION);
4823  return delete_result;
4824}
4825
4826
4827MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object,
4828                                            uint32_t index,
4829                                            DeleteMode mode) {
4830  Isolate* isolate = object->GetIsolate();
4831  Factory* factory = isolate->factory();
4832
4833  // Check access rights if needed.
4834  if (object->IsAccessCheckNeeded() &&
4835      !isolate->MayIndexedAccess(object, index, v8::ACCESS_DELETE)) {
4836    isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
4837    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
4838    return factory->false_value();
4839  }
4840
4841  if (object->IsStringObjectWithCharacterAt(index)) {
4842    if (mode == STRICT_DELETION) {
4843      // Deleting a non-configurable property in strict mode.
4844      Handle<Object> name = factory->NewNumberFromUint(index);
4845      Handle<Object> args[2] = { name, object };
4846      THROW_NEW_ERROR(isolate, NewTypeError("strict_delete_property",
4847                                            HandleVector(args, 2)),
4848                      Object);
4849    }
4850    return factory->false_value();
4851  }
4852
4853  if (object->IsJSGlobalProxy()) {
4854    PrototypeIterator iter(isolate, object);
4855    if (iter.IsAtEnd()) return factory->false_value();
4856    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4857    return DeleteElement(
4858        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
4859        mode);
4860  }
4861
4862  Handle<Object> old_value;
4863  bool should_enqueue_change_record = false;
4864  if (object->map()->is_observed()) {
4865    Maybe<bool> maybe = HasOwnElement(object, index);
4866    if (!maybe.has_value) return MaybeHandle<Object>();
4867    should_enqueue_change_record = maybe.value;
4868    if (should_enqueue_change_record) {
4869      if (!GetOwnElementAccessorPair(object, index).is_null()) {
4870        old_value = Handle<Object>::cast(factory->the_hole_value());
4871      } else {
4872        old_value = Object::GetElement(
4873            isolate, object, index).ToHandleChecked();
4874      }
4875    }
4876  }
4877
4878  // Skip interceptor if forcing deletion.
4879  MaybeHandle<Object> maybe_result;
4880  if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) {
4881    maybe_result = DeleteElementWithInterceptor(object, index);
4882  } else {
4883    maybe_result = object->GetElementsAccessor()->Delete(object, index, mode);
4884  }
4885  Handle<Object> result;
4886  ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
4887
4888  if (should_enqueue_change_record) {
4889    Maybe<bool> maybe = HasOwnElement(object, index);
4890    if (!maybe.has_value) return MaybeHandle<Object>();
4891    if (!maybe.value) {
4892      Handle<String> name = factory->Uint32ToString(index);
4893      EnqueueChangeRecord(object, "delete", name, old_value);
4894    }
4895  }
4896
4897  return result;
4898}
4899
4900
4901MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
4902                                             Handle<Name> name,
4903                                             DeleteMode delete_mode) {
4904  // ECMA-262, 3rd, 8.6.2.5
4905  DCHECK(name->IsName());
4906
4907  uint32_t index = 0;
4908  if (name->AsArrayIndex(&index)) {
4909    return DeleteElement(object, index, delete_mode);
4910  }
4911
4912  // Skip interceptors on FORCE_DELETION.
4913  LookupIterator::Configuration config =
4914      delete_mode == FORCE_DELETION ? LookupIterator::HIDDEN_SKIP_INTERCEPTOR
4915                                    : LookupIterator::HIDDEN;
4916
4917  LookupIterator it(object, name, config);
4918
4919  bool is_observed = object->map()->is_observed() &&
4920                     *name != it.isolate()->heap()->hidden_string();
4921  Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
4922
4923  for (; it.IsFound(); it.Next()) {
4924    switch (it.state()) {
4925      case LookupIterator::JSPROXY:
4926      case LookupIterator::NOT_FOUND:
4927      case LookupIterator::TRANSITION:
4928        UNREACHABLE();
4929      case LookupIterator::ACCESS_CHECK:
4930        if (it.HasAccess(v8::ACCESS_DELETE)) break;
4931        it.isolate()->ReportFailedAccessCheck(it.GetHolder<JSObject>(),
4932                                              v8::ACCESS_DELETE);
4933        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it.isolate(), Object);
4934        return it.isolate()->factory()->false_value();
4935      case LookupIterator::INTERCEPTOR: {
4936        MaybeHandle<Object> maybe_result =
4937            JSObject::DeletePropertyWithInterceptor(it.GetHolder<JSObject>(),
4938                                                    object, it.name());
4939        // Delete with interceptor succeeded. Return result.
4940        if (!maybe_result.is_null()) return maybe_result;
4941        // An exception was thrown in the interceptor. Propagate.
4942        if (it.isolate()->has_pending_exception()) return maybe_result;
4943        break;
4944      }
4945      case LookupIterator::DATA:
4946        if (is_observed) {
4947          old_value = it.GetDataValue();
4948        }
4949      // Fall through.
4950      case LookupIterator::ACCESSOR: {
4951        if (delete_mode != FORCE_DELETION && !it.IsConfigurable()) {
4952          // Fail if the property is not configurable.
4953          if (delete_mode == STRICT_DELETION) {
4954            Handle<Object> args[2] = {name, object};
4955            THROW_NEW_ERROR(it.isolate(),
4956                            NewTypeError("strict_delete_property",
4957                                         HandleVector(args, arraysize(args))),
4958                            Object);
4959          }
4960          return it.isolate()->factory()->false_value();
4961        }
4962
4963        PropertyNormalizationMode mode = object->map()->is_prototype_map()
4964                                             ? KEEP_INOBJECT_PROPERTIES
4965                                             : CLEAR_INOBJECT_PROPERTIES;
4966        Handle<JSObject> holder = it.GetHolder<JSObject>();
4967        // TODO(verwaest): Remove this temporary compatibility hack when blink
4968        // tests are updated.
4969        if (!holder.is_identical_to(object) &&
4970            !(object->IsJSGlobalProxy() && holder->IsJSGlobalObject())) {
4971          return it.isolate()->factory()->true_value();
4972        }
4973        NormalizeProperties(holder, mode, 0);
4974        Handle<Object> result =
4975            DeleteNormalizedProperty(holder, name, delete_mode);
4976        ReoptimizeIfPrototype(holder);
4977
4978        if (is_observed) {
4979          EnqueueChangeRecord(object, "delete", name, old_value);
4980        }
4981
4982        return result;
4983      }
4984    }
4985  }
4986
4987  return it.isolate()->factory()->true_value();
4988}
4989
4990
4991MaybeHandle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
4992                                              uint32_t index,
4993                                              DeleteMode mode) {
4994  if (object->IsJSProxy()) {
4995    return JSProxy::DeleteElementWithHandler(
4996        Handle<JSProxy>::cast(object), index, mode);
4997  }
4998  return JSObject::DeleteElement(Handle<JSObject>::cast(object), index, mode);
4999}
5000
5001
5002MaybeHandle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
5003                                               Handle<Name> name,
5004                                               DeleteMode mode) {
5005  if (object->IsJSProxy()) {
5006    return JSProxy::DeletePropertyWithHandler(
5007        Handle<JSProxy>::cast(object), name, mode);
5008  }
5009  return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, mode);
5010}
5011
5012
5013bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
5014                                            ElementsKind kind,
5015                                            Object* object) {
5016  DCHECK(IsFastObjectElementsKind(kind) ||
5017         kind == DICTIONARY_ELEMENTS);
5018  if (IsFastObjectElementsKind(kind)) {
5019    int length = IsJSArray()
5020        ? Smi::cast(JSArray::cast(this)->length())->value()
5021        : elements->length();
5022    for (int i = 0; i < length; ++i) {
5023      Object* element = elements->get(i);
5024      if (!element->IsTheHole() && element == object) return true;
5025    }
5026  } else {
5027    Object* key =
5028        SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5029    if (!key->IsUndefined()) return true;
5030  }
5031  return false;
5032}
5033
5034
5035// Check whether this object references another object.
5036bool JSObject::ReferencesObject(Object* obj) {
5037  Map* map_of_this = map();
5038  Heap* heap = GetHeap();
5039  DisallowHeapAllocation no_allocation;
5040
5041  // Is the object the constructor for this object?
5042  if (map_of_this->constructor() == obj) {
5043    return true;
5044  }
5045
5046  // Is the object the prototype for this object?
5047  if (map_of_this->prototype() == obj) {
5048    return true;
5049  }
5050
5051  // Check if the object is among the named properties.
5052  Object* key = SlowReverseLookup(obj);
5053  if (!key->IsUndefined()) {
5054    return true;
5055  }
5056
5057  // Check if the object is among the indexed properties.
5058  ElementsKind kind = GetElementsKind();
5059  switch (kind) {
5060    // Raw pixels and external arrays do not reference other
5061    // objects.
5062#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5063    case EXTERNAL_##TYPE##_ELEMENTS:                                           \
5064    case TYPE##_ELEMENTS:                                                      \
5065      break;
5066
5067    TYPED_ARRAYS(TYPED_ARRAY_CASE)
5068#undef TYPED_ARRAY_CASE
5069
5070    case FAST_DOUBLE_ELEMENTS:
5071    case FAST_HOLEY_DOUBLE_ELEMENTS:
5072      break;
5073    case FAST_SMI_ELEMENTS:
5074    case FAST_HOLEY_SMI_ELEMENTS:
5075      break;
5076    case FAST_ELEMENTS:
5077    case FAST_HOLEY_ELEMENTS:
5078    case DICTIONARY_ELEMENTS: {
5079      FixedArray* elements = FixedArray::cast(this->elements());
5080      if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5081      break;
5082    }
5083    case SLOPPY_ARGUMENTS_ELEMENTS: {
5084      FixedArray* parameter_map = FixedArray::cast(elements());
5085      // Check the mapped parameters.
5086      int length = parameter_map->length();
5087      for (int i = 2; i < length; ++i) {
5088        Object* value = parameter_map->get(i);
5089        if (!value->IsTheHole() && value == obj) return true;
5090      }
5091      // Check the arguments.
5092      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5093      kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5094          FAST_HOLEY_ELEMENTS;
5095      if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5096      break;
5097    }
5098  }
5099
5100  // For functions check the context.
5101  if (IsJSFunction()) {
5102    // Get the constructor function for arguments array.
5103    Map* arguments_map =
5104        heap->isolate()->context()->native_context()->sloppy_arguments_map();
5105    JSFunction* arguments_function =
5106        JSFunction::cast(arguments_map->constructor());
5107
5108    // Get the context and don't check if it is the native context.
5109    JSFunction* f = JSFunction::cast(this);
5110    Context* context = f->context();
5111    if (context->IsNativeContext()) {
5112      return false;
5113    }
5114
5115    // Check the non-special context slots.
5116    for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5117      // Only check JS objects.
5118      if (context->get(i)->IsJSObject()) {
5119        JSObject* ctxobj = JSObject::cast(context->get(i));
5120        // If it is an arguments array check the content.
5121        if (ctxobj->map()->constructor() == arguments_function) {
5122          if (ctxobj->ReferencesObject(obj)) {
5123            return true;
5124          }
5125        } else if (ctxobj == obj) {
5126          return true;
5127        }
5128      }
5129    }
5130
5131    // Check the context extension (if any) if it can have references.
5132    if (context->has_extension() && !context->IsCatchContext()) {
5133      // With harmony scoping, a JSFunction may have a global context.
5134      // TODO(mvstanton): walk into the ScopeInfo.
5135      if (FLAG_harmony_scoping && context->IsGlobalContext()) {
5136        return false;
5137      }
5138
5139      return JSObject::cast(context->extension())->ReferencesObject(obj);
5140    }
5141  }
5142
5143  // No references to object.
5144  return false;
5145}
5146
5147
5148MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5149  Isolate* isolate = object->GetIsolate();
5150
5151  if (!object->map()->is_extensible()) return object;
5152
5153  if (object->IsAccessCheckNeeded() &&
5154      !isolate->MayNamedAccess(
5155          object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5156    isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5157    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5158    return isolate->factory()->false_value();
5159  }
5160
5161  if (object->IsJSGlobalProxy()) {
5162    PrototypeIterator iter(isolate, object);
5163    if (iter.IsAtEnd()) return object;
5164    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5165    return PreventExtensions(
5166        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5167  }
5168
5169  // It's not possible to seal objects with external array elements
5170  if (object->HasExternalArrayElements() ||
5171      object->HasFixedTypedArrayElements()) {
5172    THROW_NEW_ERROR(isolate,
5173                    NewTypeError("cant_prevent_ext_external_array_elements",
5174                                 HandleVector(&object, 1)),
5175                    Object);
5176  }
5177
5178  // If there are fast elements we normalize.
5179  Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5180  DCHECK(object->HasDictionaryElements() ||
5181         object->HasDictionaryArgumentsElements());
5182
5183  // Make sure that we never go back to fast case.
5184  dictionary->set_requires_slow_elements();
5185
5186  // Do a map transition, other objects with this map may still
5187  // be extensible.
5188  // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5189  Handle<Map> new_map = Map::Copy(handle(object->map()));
5190
5191  new_map->set_is_extensible(false);
5192  JSObject::MigrateToMap(object, new_map);
5193  DCHECK(!object->map()->is_extensible());
5194
5195  if (object->map()->is_observed()) {
5196    EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5197                        isolate->factory()->the_hole_value());
5198  }
5199  return object;
5200}
5201
5202
5203template<typename Dictionary>
5204static void FreezeDictionary(Dictionary* dictionary) {
5205  int capacity = dictionary->Capacity();
5206  for (int i = 0; i < capacity; i++) {
5207    Object* k = dictionary->KeyAt(i);
5208    if (dictionary->IsKey(k) &&
5209        !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
5210      PropertyDetails details = dictionary->DetailsAt(i);
5211      int attrs = DONT_DELETE;
5212      // READ_ONLY is an invalid attribute for JS setters/getters.
5213      if (details.type() == CALLBACKS) {
5214        Object* v = dictionary->ValueAt(i);
5215        if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
5216        if (!v->IsAccessorPair()) attrs |= READ_ONLY;
5217      } else {
5218        attrs |= READ_ONLY;
5219      }
5220      details = details.CopyAddAttributes(
5221          static_cast<PropertyAttributes>(attrs));
5222      dictionary->DetailsAtPut(i, details);
5223    }
5224  }
5225}
5226
5227
5228MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) {
5229  // Freezing sloppy arguments should be handled elsewhere.
5230  DCHECK(!object->HasSloppyArgumentsElements());
5231  DCHECK(!object->map()->is_observed());
5232
5233  if (object->map()->is_frozen()) return object;
5234
5235  Isolate* isolate = object->GetIsolate();
5236  if (object->IsAccessCheckNeeded() &&
5237      !isolate->MayNamedAccess(
5238          object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5239    isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5240    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5241    return isolate->factory()->false_value();
5242  }
5243
5244  if (object->IsJSGlobalProxy()) {
5245    PrototypeIterator iter(isolate, object);
5246    if (iter.IsAtEnd()) return object;
5247    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5248    return Freeze(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
5249  }
5250
5251  // It's not possible to freeze objects with external array elements
5252  if (object->HasExternalArrayElements() ||
5253      object->HasFixedTypedArrayElements()) {
5254    THROW_NEW_ERROR(isolate,
5255                    NewTypeError("cant_prevent_ext_external_array_elements",
5256                                 HandleVector(&object, 1)),
5257                    Object);
5258  }
5259
5260  Handle<SeededNumberDictionary> new_element_dictionary;
5261  if (!object->elements()->IsDictionary()) {
5262    int length = object->IsJSArray()
5263        ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5264        : object->elements()->length();
5265    if (length > 0) {
5266      int capacity = 0;
5267      int used = 0;
5268      object->GetElementsCapacityAndUsage(&capacity, &used);
5269      new_element_dictionary = SeededNumberDictionary::New(isolate, used);
5270
5271      // Move elements to a dictionary; avoid calling NormalizeElements to avoid
5272      // unnecessary transitions.
5273      new_element_dictionary = CopyFastElementsToDictionary(
5274          handle(object->elements()), length, new_element_dictionary);
5275    } else {
5276      // No existing elements, use a pre-allocated empty backing store
5277      new_element_dictionary =
5278          isolate->factory()->empty_slow_element_dictionary();
5279    }
5280  }
5281
5282  Handle<Map> old_map(object->map(), isolate);
5283  int transition_index = old_map->SearchTransition(
5284      isolate->heap()->frozen_symbol());
5285  if (transition_index != TransitionArray::kNotFound) {
5286    Handle<Map> transition_map(old_map->GetTransition(transition_index));
5287    DCHECK(transition_map->has_dictionary_elements());
5288    DCHECK(transition_map->is_frozen());
5289    DCHECK(!transition_map->is_extensible());
5290    JSObject::MigrateToMap(object, transition_map);
5291  } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5292    // Create a new descriptor array with fully-frozen properties
5293    Handle<Map> new_map = Map::CopyForFreeze(old_map);
5294    JSObject::MigrateToMap(object, new_map);
5295  } else {
5296    DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5297    // Slow path: need to normalize properties for safety
5298    NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5299
5300    // Create a new map, since other objects with this map may be extensible.
5301    // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5302    Handle<Map> new_map = Map::Copy(handle(object->map()));
5303    new_map->freeze();
5304    new_map->set_is_extensible(false);
5305    new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5306    JSObject::MigrateToMap(object, new_map);
5307
5308    // Freeze dictionary-mode properties
5309    FreezeDictionary(object->property_dictionary());
5310  }
5311
5312  DCHECK(object->map()->has_dictionary_elements());
5313  if (!new_element_dictionary.is_null()) {
5314    object->set_elements(*new_element_dictionary);
5315  }
5316
5317  if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5318    SeededNumberDictionary* dictionary = object->element_dictionary();
5319    // Make sure we never go back to the fast case
5320    dictionary->set_requires_slow_elements();
5321    // Freeze all elements in the dictionary
5322    FreezeDictionary(dictionary);
5323  }
5324
5325  return object;
5326}
5327
5328
5329void JSObject::SetObserved(Handle<JSObject> object) {
5330  DCHECK(!object->IsJSGlobalProxy());
5331  DCHECK(!object->IsJSGlobalObject());
5332  Isolate* isolate = object->GetIsolate();
5333  Handle<Map> new_map;
5334  Handle<Map> old_map(object->map(), isolate);
5335  DCHECK(!old_map->is_observed());
5336  int transition_index = old_map->SearchTransition(
5337      isolate->heap()->observed_symbol());
5338  if (transition_index != TransitionArray::kNotFound) {
5339    new_map = handle(old_map->GetTransition(transition_index), isolate);
5340    DCHECK(new_map->is_observed());
5341  } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5342    new_map = Map::CopyForObserved(old_map);
5343  } else {
5344    new_map = Map::Copy(old_map);
5345    new_map->set_is_observed();
5346  }
5347  JSObject::MigrateToMap(object, new_map);
5348}
5349
5350
5351Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
5352                                        Representation representation,
5353                                        FieldIndex index) {
5354  Isolate* isolate = object->GetIsolate();
5355  Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
5356  return Object::WrapForRead(isolate, raw_value, representation);
5357}
5358
5359
5360template<class ContextObject>
5361class JSObjectWalkVisitor {
5362 public:
5363  JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5364                      JSObject::DeepCopyHints hints)
5365    : site_context_(site_context),
5366      copying_(copying),
5367      hints_(hints) {}
5368
5369  MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
5370
5371 protected:
5372  MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
5373      Handle<JSObject> object,
5374      Handle<JSObject> value) {
5375    Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5376    MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
5377    site_context()->ExitScope(current_site, value);
5378    return copy_of_value;
5379  }
5380
5381  inline ContextObject* site_context() { return site_context_; }
5382  inline Isolate* isolate() { return site_context()->isolate(); }
5383
5384  inline bool copying() const { return copying_; }
5385
5386 private:
5387  ContextObject* site_context_;
5388  const bool copying_;
5389  const JSObject::DeepCopyHints hints_;
5390};
5391
5392
5393template <class ContextObject>
5394MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
5395    Handle<JSObject> object) {
5396  Isolate* isolate = this->isolate();
5397  bool copying = this->copying();
5398  bool shallow = hints_ == JSObject::kObjectIsShallow;
5399
5400  if (!shallow) {
5401    StackLimitCheck check(isolate);
5402
5403    if (check.HasOverflowed()) {
5404      isolate->StackOverflow();
5405      return MaybeHandle<JSObject>();
5406    }
5407  }
5408
5409  if (object->map()->is_deprecated()) {
5410    JSObject::MigrateInstance(object);
5411  }
5412
5413  Handle<JSObject> copy;
5414  if (copying) {
5415    Handle<AllocationSite> site_to_pass;
5416    if (site_context()->ShouldCreateMemento(object)) {
5417      site_to_pass = site_context()->current();
5418    }
5419    copy = isolate->factory()->CopyJSObjectWithAllocationSite(
5420        object, site_to_pass);
5421  } else {
5422    copy = object;
5423  }
5424
5425  DCHECK(copying || copy.is_identical_to(object));
5426
5427  ElementsKind kind = copy->GetElementsKind();
5428  if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5429      FixedArray::cast(copy->elements())->map() ==
5430        isolate->heap()->fixed_cow_array_map()) {
5431    isolate->counters()->cow_arrays_created_runtime()->Increment();
5432  }
5433
5434  if (!shallow) {
5435    HandleScope scope(isolate);
5436
5437    // Deep copy own properties.
5438    if (copy->HasFastProperties()) {
5439      Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5440      int limit = copy->map()->NumberOfOwnDescriptors();
5441      for (int i = 0; i < limit; i++) {
5442        PropertyDetails details = descriptors->GetDetails(i);
5443        if (details.type() != FIELD) continue;
5444        FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
5445        Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5446        if (value->IsJSObject()) {
5447          ASSIGN_RETURN_ON_EXCEPTION(
5448              isolate, value,
5449              VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5450              JSObject);
5451        } else {
5452          Representation representation = details.representation();
5453          value = Object::NewStorageFor(isolate, value, representation);
5454        }
5455        if (copying) {
5456          copy->FastPropertyAtPut(index, *value);
5457        }
5458      }
5459    } else {
5460      Handle<FixedArray> names =
5461          isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
5462      copy->GetOwnPropertyNames(*names, 0);
5463      for (int i = 0; i < names->length(); i++) {
5464        DCHECK(names->get(i)->IsString());
5465        Handle<String> key_string(String::cast(names->get(i)));
5466        Maybe<PropertyAttributes> maybe =
5467            JSReceiver::GetOwnPropertyAttributes(copy, key_string);
5468        DCHECK(maybe.has_value);
5469        PropertyAttributes attributes = maybe.value;
5470        // Only deep copy fields from the object literal expression.
5471        // In particular, don't try to copy the length attribute of
5472        // an array.
5473        if (attributes != NONE) continue;
5474        Handle<Object> value =
5475            Object::GetProperty(copy, key_string).ToHandleChecked();
5476        if (value->IsJSObject()) {
5477          Handle<JSObject> result;
5478          ASSIGN_RETURN_ON_EXCEPTION(
5479              isolate, result,
5480              VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5481              JSObject);
5482          if (copying) {
5483            // Creating object copy for literals. No strict mode needed.
5484            JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert();
5485          }
5486        }
5487      }
5488    }
5489
5490    // Deep copy own elements.
5491    // Pixel elements cannot be created using an object literal.
5492    DCHECK(!copy->HasExternalArrayElements());
5493    switch (kind) {
5494      case FAST_SMI_ELEMENTS:
5495      case FAST_ELEMENTS:
5496      case FAST_HOLEY_SMI_ELEMENTS:
5497      case FAST_HOLEY_ELEMENTS: {
5498        Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5499        if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5500#ifdef DEBUG
5501          for (int i = 0; i < elements->length(); i++) {
5502            DCHECK(!elements->get(i)->IsJSObject());
5503          }
5504#endif
5505        } else {
5506          for (int i = 0; i < elements->length(); i++) {
5507            Handle<Object> value(elements->get(i), isolate);
5508            DCHECK(value->IsSmi() ||
5509                   value->IsTheHole() ||
5510                   (IsFastObjectElementsKind(copy->GetElementsKind())));
5511            if (value->IsJSObject()) {
5512              Handle<JSObject> result;
5513              ASSIGN_RETURN_ON_EXCEPTION(
5514                  isolate, result,
5515                  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5516                  JSObject);
5517              if (copying) {
5518                elements->set(i, *result);
5519              }
5520            }
5521          }
5522        }
5523        break;
5524      }
5525      case DICTIONARY_ELEMENTS: {
5526        Handle<SeededNumberDictionary> element_dictionary(
5527            copy->element_dictionary());
5528        int capacity = element_dictionary->Capacity();
5529        for (int i = 0; i < capacity; i++) {
5530          Object* k = element_dictionary->KeyAt(i);
5531          if (element_dictionary->IsKey(k)) {
5532            Handle<Object> value(element_dictionary->ValueAt(i), isolate);
5533            if (value->IsJSObject()) {
5534              Handle<JSObject> result;
5535              ASSIGN_RETURN_ON_EXCEPTION(
5536                  isolate, result,
5537                  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5538                  JSObject);
5539              if (copying) {
5540                element_dictionary->ValueAtPut(i, *result);
5541              }
5542            }
5543          }
5544        }
5545        break;
5546      }
5547      case SLOPPY_ARGUMENTS_ELEMENTS:
5548        UNIMPLEMENTED();
5549        break;
5550
5551
5552#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5553      case EXTERNAL_##TYPE##_ELEMENTS:                                         \
5554      case TYPE##_ELEMENTS:                                                    \
5555
5556      TYPED_ARRAYS(TYPED_ARRAY_CASE)
5557#undef TYPED_ARRAY_CASE
5558
5559      case FAST_DOUBLE_ELEMENTS:
5560      case FAST_HOLEY_DOUBLE_ELEMENTS:
5561        // No contained objects, nothing to do.
5562        break;
5563    }
5564  }
5565
5566  return copy;
5567}
5568
5569
5570MaybeHandle<JSObject> JSObject::DeepWalk(
5571    Handle<JSObject> object,
5572    AllocationSiteCreationContext* site_context) {
5573  JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
5574                                                       kNoHints);
5575  MaybeHandle<JSObject> result = v.StructureWalk(object);
5576  Handle<JSObject> for_assert;
5577  DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
5578  return result;
5579}
5580
5581
5582MaybeHandle<JSObject> JSObject::DeepCopy(
5583    Handle<JSObject> object,
5584    AllocationSiteUsageContext* site_context,
5585    DeepCopyHints hints) {
5586  JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
5587  MaybeHandle<JSObject> copy = v.StructureWalk(object);
5588  Handle<JSObject> for_assert;
5589  DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
5590  return copy;
5591}
5592
5593
5594// Tests for the fast common case for property enumeration:
5595// - This object and all prototypes has an enum cache (which means that
5596//   it is no proxy, has no interceptors and needs no access checks).
5597// - This object has no elements.
5598// - No prototype has enumerable properties/elements.
5599bool JSReceiver::IsSimpleEnum() {
5600  for (PrototypeIterator iter(GetIsolate(), this,
5601                              PrototypeIterator::START_AT_RECEIVER);
5602       !iter.IsAtEnd(); iter.Advance()) {
5603    if (!iter.GetCurrent()->IsJSObject()) return false;
5604    JSObject* curr = JSObject::cast(iter.GetCurrent());
5605    int enum_length = curr->map()->EnumLength();
5606    if (enum_length == kInvalidEnumCacheSentinel) return false;
5607    if (curr->IsAccessCheckNeeded()) return false;
5608    DCHECK(!curr->HasNamedInterceptor());
5609    DCHECK(!curr->HasIndexedInterceptor());
5610    if (curr->NumberOfEnumElements() > 0) return false;
5611    if (curr != this && enum_length != 0) return false;
5612  }
5613  return true;
5614}
5615
5616
5617static bool FilterKey(Object* key, PropertyAttributes filter) {
5618  if ((filter & SYMBOLIC) && key->IsSymbol()) {
5619    return true;
5620  }
5621
5622  if ((filter & PRIVATE_SYMBOL) &&
5623      key->IsSymbol() && Symbol::cast(key)->is_private()) {
5624    return true;
5625  }
5626
5627  if ((filter & STRING) && !key->IsSymbol()) {
5628    return true;
5629  }
5630
5631  return false;
5632}
5633
5634
5635int Map::NumberOfDescribedProperties(DescriptorFlag which,
5636                                     PropertyAttributes filter) {
5637  int result = 0;
5638  DescriptorArray* descs = instance_descriptors();
5639  int limit = which == ALL_DESCRIPTORS
5640      ? descs->number_of_descriptors()
5641      : NumberOfOwnDescriptors();
5642  for (int i = 0; i < limit; i++) {
5643    if ((descs->GetDetails(i).attributes() & filter) == 0 &&
5644        !FilterKey(descs->GetKey(i), filter)) {
5645      result++;
5646    }
5647  }
5648  return result;
5649}
5650
5651
5652int Map::NextFreePropertyIndex() {
5653  int max_index = -1;
5654  int number_of_own_descriptors = NumberOfOwnDescriptors();
5655  DescriptorArray* descs = instance_descriptors();
5656  for (int i = 0; i < number_of_own_descriptors; i++) {
5657    if (descs->GetType(i) == FIELD) {
5658      int current_index = descs->GetFieldIndex(i);
5659      if (current_index > max_index) max_index = current_index;
5660    }
5661  }
5662  return max_index + 1;
5663}
5664
5665
5666static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
5667  int len = array->length();
5668  for (int i = 0; i < len; i++) {
5669    Object* e = array->get(i);
5670    if (!(e->IsString() || e->IsNumber())) return false;
5671  }
5672  return true;
5673}
5674
5675
5676static Handle<FixedArray> ReduceFixedArrayTo(
5677    Handle<FixedArray> array, int length) {
5678  DCHECK(array->length() >= length);
5679  if (array->length() == length) return array;
5680
5681  Handle<FixedArray> new_array =
5682      array->GetIsolate()->factory()->NewFixedArray(length);
5683  for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
5684  return new_array;
5685}
5686
5687
5688static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
5689                                              bool cache_result) {
5690  Isolate* isolate = object->GetIsolate();
5691  if (object->HasFastProperties()) {
5692    int own_property_count = object->map()->EnumLength();
5693    // If the enum length of the given map is set to kInvalidEnumCache, this
5694    // means that the map itself has never used the present enum cache. The
5695    // first step to using the cache is to set the enum length of the map by
5696    // counting the number of own descriptors that are not DONT_ENUM or
5697    // SYMBOLIC.
5698    if (own_property_count == kInvalidEnumCacheSentinel) {
5699      own_property_count = object->map()->NumberOfDescribedProperties(
5700          OWN_DESCRIPTORS, DONT_SHOW);
5701    } else {
5702      DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
5703          OWN_DESCRIPTORS, DONT_SHOW));
5704    }
5705
5706    if (object->map()->instance_descriptors()->HasEnumCache()) {
5707      DescriptorArray* desc = object->map()->instance_descriptors();
5708      Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
5709
5710      // In case the number of properties required in the enum are actually
5711      // present, we can reuse the enum cache. Otherwise, this means that the
5712      // enum cache was generated for a previous (smaller) version of the
5713      // Descriptor Array. In that case we regenerate the enum cache.
5714      if (own_property_count <= keys->length()) {
5715        if (cache_result) object->map()->SetEnumLength(own_property_count);
5716        isolate->counters()->enum_cache_hits()->Increment();
5717        return ReduceFixedArrayTo(keys, own_property_count);
5718      }
5719    }
5720
5721    Handle<Map> map(object->map());
5722
5723    if (map->instance_descriptors()->IsEmpty()) {
5724      isolate->counters()->enum_cache_hits()->Increment();
5725      if (cache_result) map->SetEnumLength(0);
5726      return isolate->factory()->empty_fixed_array();
5727    }
5728
5729    isolate->counters()->enum_cache_misses()->Increment();
5730
5731    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
5732        own_property_count);
5733    Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
5734        own_property_count);
5735
5736    Handle<DescriptorArray> descs =
5737        Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
5738
5739    int size = map->NumberOfOwnDescriptors();
5740    int index = 0;
5741
5742    for (int i = 0; i < size; i++) {
5743      PropertyDetails details = descs->GetDetails(i);
5744      Object* key = descs->GetKey(i);
5745      if (!(details.IsDontEnum() || key->IsSymbol())) {
5746        storage->set(index, key);
5747        if (!indices.is_null()) {
5748          if (details.type() != FIELD) {
5749            indices = Handle<FixedArray>();
5750          } else {
5751            FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
5752            int load_by_field_index = field_index.GetLoadByFieldIndex();
5753            indices->set(index, Smi::FromInt(load_by_field_index));
5754          }
5755        }
5756        index++;
5757      }
5758    }
5759    DCHECK(index == storage->length());
5760
5761    Handle<FixedArray> bridge_storage =
5762        isolate->factory()->NewFixedArray(
5763            DescriptorArray::kEnumCacheBridgeLength);
5764    DescriptorArray* desc = object->map()->instance_descriptors();
5765    desc->SetEnumCache(*bridge_storage,
5766                       *storage,
5767                       indices.is_null() ? Object::cast(Smi::FromInt(0))
5768                                         : Object::cast(*indices));
5769    if (cache_result) {
5770      object->map()->SetEnumLength(own_property_count);
5771    }
5772    return storage;
5773  } else {
5774    Handle<NameDictionary> dictionary(object->property_dictionary());
5775    int length = dictionary->NumberOfEnumElements();
5776    if (length == 0) {
5777      return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
5778    }
5779    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
5780    dictionary->CopyEnumKeysTo(*storage);
5781    return storage;
5782  }
5783}
5784
5785
5786MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
5787                                            KeyCollectionType type) {
5788  USE(ContainsOnlyValidKeys);
5789  Isolate* isolate = object->GetIsolate();
5790  Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
5791  Handle<JSFunction> arguments_function(
5792      JSFunction::cast(isolate->sloppy_arguments_map()->constructor()));
5793
5794  // Only collect keys if access is permitted.
5795  for (PrototypeIterator iter(isolate, object,
5796                              PrototypeIterator::START_AT_RECEIVER);
5797       !iter.IsAtEnd(); iter.Advance()) {
5798    if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
5799      Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
5800                            isolate);
5801      Handle<Object> args[] = { proxy };
5802      Handle<Object> names;
5803      ASSIGN_RETURN_ON_EXCEPTION(
5804          isolate, names,
5805          Execution::Call(isolate,
5806                          isolate->proxy_enumerate(),
5807                          object,
5808                          arraysize(args),
5809                          args),
5810          FixedArray);
5811      ASSIGN_RETURN_ON_EXCEPTION(
5812          isolate, content,
5813          FixedArray::AddKeysFromArrayLike(
5814              content, Handle<JSObject>::cast(names)),
5815          FixedArray);
5816      break;
5817    }
5818
5819    Handle<JSObject> current =
5820        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
5821
5822    // Check access rights if required.
5823    if (current->IsAccessCheckNeeded() &&
5824        !isolate->MayNamedAccess(
5825            current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5826      isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS);
5827      RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
5828      break;
5829    }
5830
5831    // Compute the element keys.
5832    Handle<FixedArray> element_keys =
5833        isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
5834    current->GetEnumElementKeys(*element_keys);
5835    ASSIGN_RETURN_ON_EXCEPTION(
5836        isolate, content,
5837        FixedArray::UnionOfKeys(content, element_keys),
5838        FixedArray);
5839    DCHECK(ContainsOnlyValidKeys(content));
5840
5841    // Add the element keys from the interceptor.
5842    if (current->HasIndexedInterceptor()) {
5843      Handle<JSObject> result;
5844      if (JSObject::GetKeysForIndexedInterceptor(
5845              current, object).ToHandle(&result)) {
5846        ASSIGN_RETURN_ON_EXCEPTION(
5847            isolate, content,
5848            FixedArray::AddKeysFromArrayLike(content, result),
5849            FixedArray);
5850      }
5851      DCHECK(ContainsOnlyValidKeys(content));
5852    }
5853
5854    // We can cache the computed property keys if access checks are
5855    // not needed and no interceptors are involved.
5856    //
5857    // We do not use the cache if the object has elements and
5858    // therefore it does not make sense to cache the property names
5859    // for arguments objects.  Arguments objects will always have
5860    // elements.
5861    // Wrapped strings have elements, but don't have an elements
5862    // array or dictionary.  So the fast inline test for whether to
5863    // use the cache says yes, so we should not create a cache.
5864    bool cache_enum_keys =
5865        ((current->map()->constructor() != *arguments_function) &&
5866         !current->IsJSValue() &&
5867         !current->IsAccessCheckNeeded() &&
5868         !current->HasNamedInterceptor() &&
5869         !current->HasIndexedInterceptor());
5870    // Compute the property keys and cache them if possible.
5871    ASSIGN_RETURN_ON_EXCEPTION(
5872        isolate, content,
5873        FixedArray::UnionOfKeys(
5874            content, GetEnumPropertyKeys(current, cache_enum_keys)),
5875        FixedArray);
5876    DCHECK(ContainsOnlyValidKeys(content));
5877
5878    // Add the property keys from the interceptor.
5879    if (current->HasNamedInterceptor()) {
5880      Handle<JSObject> result;
5881      if (JSObject::GetKeysForNamedInterceptor(
5882              current, object).ToHandle(&result)) {
5883        ASSIGN_RETURN_ON_EXCEPTION(
5884            isolate, content,
5885            FixedArray::AddKeysFromArrayLike(content, result),
5886            FixedArray);
5887      }
5888      DCHECK(ContainsOnlyValidKeys(content));
5889    }
5890
5891    // If we only want own properties we bail out after the first
5892    // iteration.
5893    if (type == OWN_ONLY) break;
5894  }
5895  return content;
5896}
5897
5898
5899// Try to update an accessor in an elements dictionary. Return true if the
5900// update succeeded, and false otherwise.
5901static bool UpdateGetterSetterInDictionary(
5902    SeededNumberDictionary* dictionary,
5903    uint32_t index,
5904    Object* getter,
5905    Object* setter,
5906    PropertyAttributes attributes) {
5907  int entry = dictionary->FindEntry(index);
5908  if (entry != SeededNumberDictionary::kNotFound) {
5909    Object* result = dictionary->ValueAt(entry);
5910    PropertyDetails details = dictionary->DetailsAt(entry);
5911    if (details.type() == CALLBACKS && result->IsAccessorPair()) {
5912      DCHECK(details.IsConfigurable());
5913      if (details.attributes() != attributes) {
5914        dictionary->DetailsAtPut(
5915            entry,
5916            PropertyDetails(attributes, CALLBACKS, index));
5917      }
5918      AccessorPair::cast(result)->SetComponents(getter, setter);
5919      return true;
5920    }
5921  }
5922  return false;
5923}
5924
5925
5926void JSObject::DefineElementAccessor(Handle<JSObject> object,
5927                                     uint32_t index,
5928                                     Handle<Object> getter,
5929                                     Handle<Object> setter,
5930                                     PropertyAttributes attributes) {
5931  switch (object->GetElementsKind()) {
5932    case FAST_SMI_ELEMENTS:
5933    case FAST_ELEMENTS:
5934    case FAST_DOUBLE_ELEMENTS:
5935    case FAST_HOLEY_SMI_ELEMENTS:
5936    case FAST_HOLEY_ELEMENTS:
5937    case FAST_HOLEY_DOUBLE_ELEMENTS:
5938      break;
5939
5940#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
5941    case EXTERNAL_##TYPE##_ELEMENTS:                                           \
5942    case TYPE##_ELEMENTS:                                                      \
5943
5944    TYPED_ARRAYS(TYPED_ARRAY_CASE)
5945#undef TYPED_ARRAY_CASE
5946      // Ignore getters and setters on pixel and external array elements.
5947      return;
5948
5949    case DICTIONARY_ELEMENTS:
5950      if (UpdateGetterSetterInDictionary(object->element_dictionary(),
5951                                         index,
5952                                         *getter,
5953                                         *setter,
5954                                         attributes)) {
5955        return;
5956      }
5957      break;
5958    case SLOPPY_ARGUMENTS_ELEMENTS: {
5959      // Ascertain whether we have read-only properties or an existing
5960      // getter/setter pair in an arguments elements dictionary backing
5961      // store.
5962      FixedArray* parameter_map = FixedArray::cast(object->elements());
5963      uint32_t length = parameter_map->length();
5964      Object* probe =
5965          index < (length - 2) ? parameter_map->get(index + 2) : NULL;
5966      if (probe == NULL || probe->IsTheHole()) {
5967        FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5968        if (arguments->IsDictionary()) {
5969          SeededNumberDictionary* dictionary =
5970              SeededNumberDictionary::cast(arguments);
5971          if (UpdateGetterSetterInDictionary(dictionary,
5972                                             index,
5973                                             *getter,
5974                                             *setter,
5975                                             attributes)) {
5976            return;
5977          }
5978        }
5979      }
5980      break;
5981    }
5982  }
5983
5984  Isolate* isolate = object->GetIsolate();
5985  Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair();
5986  accessors->SetComponents(*getter, *setter);
5987
5988  SetElementCallback(object, index, accessors, attributes);
5989}
5990
5991
5992bool Map::DictionaryElementsInPrototypeChainOnly() {
5993  if (IsDictionaryElementsKind(elements_kind())) {
5994    return false;
5995  }
5996
5997  for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
5998    if (iter.GetCurrent()->IsJSProxy()) {
5999      // Be conservative, don't walk into proxies.
6000      return true;
6001    }
6002
6003    if (IsDictionaryElementsKind(
6004            JSObject::cast(iter.GetCurrent())->map()->elements_kind())) {
6005      return true;
6006    }
6007  }
6008
6009  return false;
6010}
6011
6012
6013void JSObject::SetElementCallback(Handle<JSObject> object,
6014                                  uint32_t index,
6015                                  Handle<Object> structure,
6016                                  PropertyAttributes attributes) {
6017  Heap* heap = object->GetHeap();
6018  PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6019
6020  // Normalize elements to make this operation simple.
6021  bool had_dictionary_elements = object->HasDictionaryElements();
6022  Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
6023  DCHECK(object->HasDictionaryElements() ||
6024         object->HasDictionaryArgumentsElements());
6025  // Update the dictionary with the new CALLBACKS property.
6026  dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
6027                                           details);
6028  dictionary->set_requires_slow_elements();
6029
6030  // Update the dictionary backing store on the object.
6031  if (object->elements()->map() == heap->sloppy_arguments_elements_map()) {
6032    // Also delete any parameter alias.
6033    //
6034    // TODO(kmillikin): when deleting the last parameter alias we could
6035    // switch to a direct backing store without the parameter map.  This
6036    // would allow GC of the context.
6037    FixedArray* parameter_map = FixedArray::cast(object->elements());
6038    if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
6039      parameter_map->set(index + 2, heap->the_hole_value());
6040    }
6041    parameter_map->set(1, *dictionary);
6042  } else {
6043    object->set_elements(*dictionary);
6044
6045    if (!had_dictionary_elements) {
6046      // KeyedStoreICs (at least the non-generic ones) need a reset.
6047      heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
6048    }
6049  }
6050}
6051
6052
6053void JSObject::SetPropertyCallback(Handle<JSObject> object,
6054                                   Handle<Name> name,
6055                                   Handle<Object> structure,
6056                                   PropertyAttributes attributes) {
6057  PropertyNormalizationMode mode = object->map()->is_prototype_map()
6058                                       ? KEEP_INOBJECT_PROPERTIES
6059                                       : CLEAR_INOBJECT_PROPERTIES;
6060  // Normalize object to make this operation simple.
6061  NormalizeProperties(object, mode, 0);
6062
6063  // For the global object allocate a new map to invalidate the global inline
6064  // caches which have a global property cell reference directly in the code.
6065  if (object->IsGlobalObject()) {
6066    Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
6067    DCHECK(new_map->is_dictionary_map());
6068    JSObject::MigrateToMap(object, new_map);
6069
6070    // When running crankshaft, changing the map is not enough. We
6071    // need to deoptimize all functions that rely on this global
6072    // object.
6073    Deoptimizer::DeoptimizeGlobalObject(*object);
6074  }
6075
6076  // Update the dictionary with the new CALLBACKS property.
6077  PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6078  SetNormalizedProperty(object, name, structure, details);
6079
6080  ReoptimizeIfPrototype(object);
6081}
6082
6083
6084MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
6085                                             Handle<Name> name,
6086                                             Handle<Object> getter,
6087                                             Handle<Object> setter,
6088                                             PropertyAttributes attributes) {
6089  Isolate* isolate = object->GetIsolate();
6090  // Check access rights if needed.
6091  if (object->IsAccessCheckNeeded() &&
6092      !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6093    isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6094    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6095    return isolate->factory()->undefined_value();
6096  }
6097
6098  if (object->IsJSGlobalProxy()) {
6099    PrototypeIterator iter(isolate, object);
6100    if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
6101    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6102    DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
6103                   name, getter, setter, attributes);
6104    return isolate->factory()->undefined_value();
6105  }
6106
6107  // Make sure that the top context does not change when doing callbacks or
6108  // interceptor calls.
6109  AssertNoContextChange ncc(isolate);
6110
6111  // Try to flatten before operating on the string.
6112  if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6113
6114  uint32_t index = 0;
6115  bool is_element = name->AsArrayIndex(&index);
6116
6117  Handle<Object> old_value = isolate->factory()->the_hole_value();
6118  bool is_observed = object->map()->is_observed() &&
6119                     *name != isolate->heap()->hidden_string();
6120  bool preexists = false;
6121  if (is_observed) {
6122    if (is_element) {
6123      Maybe<bool> maybe = HasOwnElement(object, index);
6124      // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used
6125      // uninitialized in this function".
6126      if (!maybe.has_value) {
6127        DCHECK(false);
6128        return isolate->factory()->undefined_value();
6129      }
6130      preexists = maybe.value;
6131      if (preexists && GetOwnElementAccessorPair(object, index).is_null()) {
6132        old_value =
6133            Object::GetElement(isolate, object, index).ToHandleChecked();
6134      }
6135    } else {
6136      LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6137      CHECK(GetPropertyAttributes(&it).has_value);
6138      preexists = it.IsFound();
6139      if (preexists && (it.state() == LookupIterator::DATA ||
6140                        it.GetAccessors()->IsAccessorInfo())) {
6141        old_value = GetProperty(&it).ToHandleChecked();
6142      }
6143    }
6144  }
6145
6146  if (is_element) {
6147    DefineElementAccessor(object, index, getter, setter, attributes);
6148  } else {
6149    DCHECK(getter->IsSpecFunction() || getter->IsUndefined() ||
6150           getter->IsNull());
6151    DCHECK(setter->IsSpecFunction() || setter->IsUndefined() ||
6152           setter->IsNull());
6153    // At least one of the accessors needs to be a new value.
6154    DCHECK(!getter->IsNull() || !setter->IsNull());
6155    LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
6156    if (it.state() == LookupIterator::ACCESS_CHECK) {
6157      // We already did an access check before. We do have access.
6158      it.Next();
6159    }
6160    if (!getter->IsNull()) {
6161      it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
6162    }
6163    if (!setter->IsNull()) {
6164      it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
6165    }
6166  }
6167
6168  if (is_observed) {
6169    const char* type = preexists ? "reconfigure" : "add";
6170    EnqueueChangeRecord(object, type, name, old_value);
6171  }
6172
6173  return isolate->factory()->undefined_value();
6174}
6175
6176
6177MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
6178                                          Handle<AccessorInfo> info) {
6179  Isolate* isolate = object->GetIsolate();
6180  Factory* factory = isolate->factory();
6181  Handle<Name> name(Name::cast(info->name()));
6182
6183  // Check access rights if needed.
6184  if (object->IsAccessCheckNeeded() &&
6185      !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6186    isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6187    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6188    return factory->undefined_value();
6189  }
6190
6191  if (object->IsJSGlobalProxy()) {
6192    PrototypeIterator iter(isolate, object);
6193    if (iter.IsAtEnd()) return object;
6194    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6195    return SetAccessor(
6196        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), info);
6197  }
6198
6199  // Make sure that the top context does not change when doing callbacks or
6200  // interceptor calls.
6201  AssertNoContextChange ncc(isolate);
6202
6203  // Try to flatten before operating on the string.
6204  if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6205
6206  uint32_t index = 0;
6207  bool is_element = name->AsArrayIndex(&index);
6208
6209  if (is_element) {
6210    if (object->IsJSArray()) return factory->undefined_value();
6211
6212    // Accessors overwrite previous callbacks (cf. with getters/setters).
6213    switch (object->GetElementsKind()) {
6214      case FAST_SMI_ELEMENTS:
6215      case FAST_ELEMENTS:
6216      case FAST_DOUBLE_ELEMENTS:
6217      case FAST_HOLEY_SMI_ELEMENTS:
6218      case FAST_HOLEY_ELEMENTS:
6219      case FAST_HOLEY_DOUBLE_ELEMENTS:
6220        break;
6221
6222#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
6223      case EXTERNAL_##TYPE##_ELEMENTS:                                         \
6224      case TYPE##_ELEMENTS:                                                    \
6225
6226      TYPED_ARRAYS(TYPED_ARRAY_CASE)
6227#undef TYPED_ARRAY_CASE
6228        // Ignore getters and setters on pixel and external array
6229        // elements.
6230        return factory->undefined_value();
6231
6232      case DICTIONARY_ELEMENTS:
6233        break;
6234      case SLOPPY_ARGUMENTS_ELEMENTS:
6235        UNIMPLEMENTED();
6236        break;
6237    }
6238
6239    SetElementCallback(object, index, info, info->property_attributes());
6240  } else {
6241    // Lookup the name.
6242    LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6243    CHECK(GetPropertyAttributes(&it).has_value);
6244    // ES5 forbids turning a property into an accessor if it's not
6245    // configurable. See 8.6.1 (Table 5).
6246    if (it.IsFound() && (it.IsReadOnly() || !it.IsConfigurable())) {
6247      return factory->undefined_value();
6248    }
6249
6250    SetPropertyCallback(object, name, info, info->property_attributes());
6251  }
6252
6253  return object;
6254}
6255
6256
6257MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
6258                                          Handle<Name> name,
6259                                          AccessorComponent component) {
6260  Isolate* isolate = object->GetIsolate();
6261
6262  // Make sure that the top context does not change when doing callbacks or
6263  // interceptor calls.
6264  AssertNoContextChange ncc(isolate);
6265
6266  // Make the lookup and include prototypes.
6267  uint32_t index = 0;
6268  if (name->AsArrayIndex(&index)) {
6269    for (PrototypeIterator iter(isolate, object,
6270                                PrototypeIterator::START_AT_RECEIVER);
6271         !iter.IsAtEnd(); iter.Advance()) {
6272      Handle<Object> current = PrototypeIterator::GetCurrent(iter);
6273      // Check access rights if needed.
6274      if (current->IsAccessCheckNeeded() &&
6275          !isolate->MayNamedAccess(Handle<JSObject>::cast(current), name,
6276                                   v8::ACCESS_HAS)) {
6277        isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(current),
6278                                         v8::ACCESS_HAS);
6279        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6280        return isolate->factory()->undefined_value();
6281      }
6282
6283      if (current->IsJSObject() &&
6284          Handle<JSObject>::cast(current)->HasDictionaryElements()) {
6285        JSObject* js_object = JSObject::cast(*current);
6286        SeededNumberDictionary* dictionary = js_object->element_dictionary();
6287        int entry = dictionary->FindEntry(index);
6288        if (entry != SeededNumberDictionary::kNotFound) {
6289          Object* element = dictionary->ValueAt(entry);
6290          if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
6291              element->IsAccessorPair()) {
6292            return handle(AccessorPair::cast(element)->GetComponent(component),
6293                          isolate);
6294          }
6295        }
6296      }
6297    }
6298  } else {
6299    LookupIterator it(object, name,
6300                      LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
6301    for (; it.IsFound(); it.Next()) {
6302      switch (it.state()) {
6303        case LookupIterator::INTERCEPTOR:
6304        case LookupIterator::NOT_FOUND:
6305        case LookupIterator::TRANSITION:
6306          UNREACHABLE();
6307
6308        case LookupIterator::ACCESS_CHECK:
6309          if (it.HasAccess(v8::ACCESS_HAS)) continue;
6310          isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>(),
6311                                           v8::ACCESS_HAS);
6312          RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
6313          return isolate->factory()->undefined_value();
6314
6315        case LookupIterator::JSPROXY:
6316          return isolate->factory()->undefined_value();
6317
6318        case LookupIterator::DATA:
6319          continue;
6320        case LookupIterator::ACCESSOR: {
6321          Handle<Object> maybe_pair = it.GetAccessors();
6322          if (maybe_pair->IsAccessorPair()) {
6323            return handle(
6324                AccessorPair::cast(*maybe_pair)->GetComponent(component),
6325                isolate);
6326          }
6327        }
6328      }
6329    }
6330  }
6331  return isolate->factory()->undefined_value();
6332}
6333
6334
6335Object* JSObject::SlowReverseLookup(Object* value) {
6336  if (HasFastProperties()) {
6337    int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
6338    DescriptorArray* descs = map()->instance_descriptors();
6339    for (int i = 0; i < number_of_own_descriptors; i++) {
6340      if (descs->GetType(i) == FIELD) {
6341        Object* property =
6342            RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i));
6343        if (descs->GetDetails(i).representation().IsDouble()) {
6344          DCHECK(property->IsMutableHeapNumber());
6345          if (value->IsNumber() && property->Number() == value->Number()) {
6346            return descs->GetKey(i);
6347          }
6348        } else if (property == value) {
6349          return descs->GetKey(i);
6350        }
6351      } else if (descs->GetType(i) == CONSTANT) {
6352        if (descs->GetConstant(i) == value) {
6353          return descs->GetKey(i);
6354        }
6355      }
6356    }
6357    return GetHeap()->undefined_value();
6358  } else {
6359    return property_dictionary()->SlowReverseLookup(value);
6360  }
6361}
6362
6363
6364Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
6365  Handle<Map> result = map->GetIsolate()->factory()->NewMap(
6366      map->instance_type(), instance_size);
6367  result->set_prototype(map->prototype());
6368  result->set_constructor(map->constructor());
6369  result->set_bit_field(map->bit_field());
6370  result->set_bit_field2(map->bit_field2());
6371  int new_bit_field3 = map->bit_field3();
6372  new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6373  new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6374  new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6375                                          kInvalidEnumCacheSentinel);
6376  new_bit_field3 = Deprecated::update(new_bit_field3, false);
6377  if (!map->is_dictionary_map()) {
6378    new_bit_field3 = IsUnstable::update(new_bit_field3, false);
6379  }
6380  new_bit_field3 = ConstructionCount::update(new_bit_field3,
6381                                             JSFunction::kNoSlackTracking);
6382  result->set_bit_field3(new_bit_field3);
6383  return result;
6384}
6385
6386
6387Handle<Map> Map::Normalize(Handle<Map> fast_map,
6388                           PropertyNormalizationMode mode) {
6389  DCHECK(!fast_map->is_dictionary_map());
6390
6391  Isolate* isolate = fast_map->GetIsolate();
6392  Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
6393                             isolate);
6394  bool use_cache = !maybe_cache->IsUndefined();
6395  Handle<NormalizedMapCache> cache;
6396  if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
6397
6398  Handle<Map> new_map;
6399  if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
6400#ifdef VERIFY_HEAP
6401    if (FLAG_verify_heap) new_map->DictionaryMapVerify();
6402#endif
6403#ifdef ENABLE_SLOW_DCHECKS
6404    if (FLAG_enable_slow_asserts) {
6405      // The cached map should match newly created normalized map bit-by-bit,
6406      // except for the code cache, which can contain some ics which can be
6407      // applied to the shared map.
6408      Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
6409
6410      DCHECK(memcmp(fresh->address(),
6411                    new_map->address(),
6412                    Map::kCodeCacheOffset) == 0);
6413      STATIC_ASSERT(Map::kDependentCodeOffset ==
6414                    Map::kCodeCacheOffset + kPointerSize);
6415      int offset = Map::kDependentCodeOffset + kPointerSize;
6416      DCHECK(memcmp(fresh->address() + offset,
6417                    new_map->address() + offset,
6418                    Map::kSize - offset) == 0);
6419    }
6420#endif
6421  } else {
6422    new_map = Map::CopyNormalized(fast_map, mode);
6423    if (use_cache) {
6424      cache->Set(fast_map, new_map);
6425      isolate->counters()->normalized_maps()->Increment();
6426    }
6427  }
6428  fast_map->NotifyLeafMapLayoutChange();
6429  return new_map;
6430}
6431
6432
6433Handle<Map> Map::CopyNormalized(Handle<Map> map,
6434                                PropertyNormalizationMode mode) {
6435  int new_instance_size = map->instance_size();
6436  if (mode == CLEAR_INOBJECT_PROPERTIES) {
6437    new_instance_size -= map->inobject_properties() * kPointerSize;
6438  }
6439
6440  Handle<Map> result = RawCopy(map, new_instance_size);
6441
6442  if (mode != CLEAR_INOBJECT_PROPERTIES) {
6443    result->set_inobject_properties(map->inobject_properties());
6444  }
6445
6446  result->set_dictionary_map(true);
6447  result->set_migration_target(false);
6448
6449#ifdef VERIFY_HEAP
6450  if (FLAG_verify_heap) result->DictionaryMapVerify();
6451#endif
6452
6453  return result;
6454}
6455
6456
6457Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
6458  Handle<Map> result = RawCopy(map, map->instance_size());
6459
6460  // Please note instance_type and instance_size are set when allocated.
6461  result->set_inobject_properties(map->inobject_properties());
6462  result->set_unused_property_fields(map->unused_property_fields());
6463
6464  result->set_pre_allocated_property_fields(
6465      map->pre_allocated_property_fields());
6466  result->ClearCodeCache(map->GetHeap());
6467  map->NotifyLeafMapLayoutChange();
6468  return result;
6469}
6470
6471
6472Handle<Map> Map::ShareDescriptor(Handle<Map> map,
6473                                 Handle<DescriptorArray> descriptors,
6474                                 Descriptor* descriptor) {
6475  // Sanity check. This path is only to be taken if the map owns its descriptor
6476  // array, implying that its NumberOfOwnDescriptors equals the number of
6477  // descriptors in the descriptor array.
6478  DCHECK(map->NumberOfOwnDescriptors() ==
6479         map->instance_descriptors()->number_of_descriptors());
6480
6481  Handle<Map> result = CopyDropDescriptors(map);
6482  Handle<Name> name = descriptor->GetKey();
6483
6484  // Ensure there's space for the new descriptor in the shared descriptor array.
6485  if (descriptors->NumberOfSlackDescriptors() == 0) {
6486    int old_size = descriptors->number_of_descriptors();
6487    if (old_size == 0) {
6488      descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
6489    } else {
6490      EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2);
6491      descriptors = handle(map->instance_descriptors());
6492    }
6493  }
6494
6495  {
6496    DisallowHeapAllocation no_gc;
6497    descriptors->Append(descriptor);
6498    result->InitializeDescriptors(*descriptors);
6499  }
6500
6501  DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
6502  ConnectTransition(map, result, name, SIMPLE_TRANSITION);
6503
6504  return result;
6505}
6506
6507
6508void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
6509                            Handle<Name> name, SimpleTransitionFlag flag) {
6510  parent->set_owns_descriptors(false);
6511  if (parent->is_prototype_map()) {
6512    DCHECK(child->is_prototype_map());
6513  } else {
6514    Handle<TransitionArray> transitions =
6515        TransitionArray::CopyInsert(parent, name, child, flag);
6516    parent->set_transitions(*transitions);
6517    child->SetBackPointer(*parent);
6518  }
6519}
6520
6521
6522Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
6523                                        Handle<DescriptorArray> descriptors,
6524                                        TransitionFlag flag,
6525                                        MaybeHandle<Name> maybe_name,
6526                                        SimpleTransitionFlag simple_flag) {
6527  DCHECK(descriptors->IsSortedNoDuplicates());
6528
6529  Handle<Map> result = CopyDropDescriptors(map);
6530  result->InitializeDescriptors(*descriptors);
6531
6532  if (!map->is_prototype_map()) {
6533    if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) {
6534      Handle<Name> name;
6535      CHECK(maybe_name.ToHandle(&name));
6536      ConnectTransition(map, result, name, simple_flag);
6537    } else {
6538      int length = descriptors->number_of_descriptors();
6539      for (int i = 0; i < length; i++) {
6540        descriptors->SetRepresentation(i, Representation::Tagged());
6541        if (descriptors->GetDetails(i).type() == FIELD) {
6542          descriptors->SetValue(i, HeapType::Any());
6543        }
6544      }
6545    }
6546  }
6547
6548  return result;
6549}
6550
6551
6552// Since this method is used to rewrite an existing transition tree, it can
6553// always insert transitions without checking.
6554Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map,
6555                                        int new_descriptor,
6556                                        Handle<DescriptorArray> descriptors) {
6557  DCHECK(descriptors->IsSortedNoDuplicates());
6558
6559  Handle<Map> result = CopyDropDescriptors(map);
6560
6561  result->InitializeDescriptors(*descriptors);
6562  result->SetNumberOfOwnDescriptors(new_descriptor + 1);
6563
6564  int unused_property_fields = map->unused_property_fields();
6565  if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
6566    unused_property_fields = map->unused_property_fields() - 1;
6567    if (unused_property_fields < 0) {
6568      unused_property_fields += JSObject::kFieldsAdded;
6569    }
6570  }
6571
6572  result->set_unused_property_fields(unused_property_fields);
6573
6574  Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
6575  ConnectTransition(map, result, name, SIMPLE_TRANSITION);
6576
6577  return result;
6578}
6579
6580
6581Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
6582                                    TransitionFlag flag) {
6583  if (flag == INSERT_TRANSITION) {
6584    DCHECK(!map->HasElementsTransition() ||
6585        ((map->elements_transition_map()->elements_kind() ==
6586          DICTIONARY_ELEMENTS ||
6587          IsExternalArrayElementsKind(
6588              map->elements_transition_map()->elements_kind())) &&
6589         (kind == DICTIONARY_ELEMENTS ||
6590          IsExternalArrayElementsKind(kind))));
6591    DCHECK(!IsFastElementsKind(kind) ||
6592           IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
6593    DCHECK(kind != map->elements_kind());
6594  }
6595
6596  bool insert_transition =
6597      flag == INSERT_TRANSITION && !map->HasElementsTransition();
6598
6599  if (insert_transition && map->owns_descriptors()) {
6600    // In case the map owned its own descriptors, share the descriptors and
6601    // transfer ownership to the new map.
6602    Handle<Map> new_map = CopyDropDescriptors(map);
6603
6604    ConnectElementsTransition(map, new_map);
6605
6606    new_map->set_elements_kind(kind);
6607    new_map->InitializeDescriptors(map->instance_descriptors());
6608    return new_map;
6609  }
6610
6611  // In case the map did not own its own descriptors, a split is forced by
6612  // copying the map; creating a new descriptor array cell.
6613  // Create a new free-floating map only if we are not allowed to store it.
6614  Handle<Map> new_map = Copy(map);
6615
6616  new_map->set_elements_kind(kind);
6617
6618  if (insert_transition) {
6619    ConnectElementsTransition(map, new_map);
6620  }
6621
6622  return new_map;
6623}
6624
6625
6626Handle<Map> Map::CopyForObserved(Handle<Map> map) {
6627  DCHECK(!map->is_observed());
6628
6629  Isolate* isolate = map->GetIsolate();
6630
6631  // In case the map owned its own descriptors, share the descriptors and
6632  // transfer ownership to the new map.
6633  Handle<Map> new_map;
6634  if (map->owns_descriptors()) {
6635    new_map = CopyDropDescriptors(map);
6636  } else {
6637    DCHECK(!map->is_prototype_map());
6638    new_map = Copy(map);
6639  }
6640
6641  new_map->set_is_observed();
6642  if (map->owns_descriptors()) {
6643    new_map->InitializeDescriptors(map->instance_descriptors());
6644  }
6645
6646  Handle<Name> name = isolate->factory()->observed_symbol();
6647  ConnectTransition(map, new_map, name, FULL_TRANSITION);
6648
6649  return new_map;
6650}
6651
6652
6653Handle<Map> Map::Copy(Handle<Map> map) {
6654  Handle<DescriptorArray> descriptors(map->instance_descriptors());
6655  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
6656  Handle<DescriptorArray> new_descriptors =
6657      DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
6658  return CopyReplaceDescriptors(
6659      map, new_descriptors, OMIT_TRANSITION, MaybeHandle<Name>());
6660}
6661
6662
6663Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
6664  Handle<Map> copy = Copy(handle(isolate->object_function()->initial_map()));
6665
6666  // Check that we do not overflow the instance size when adding the extra
6667  // inobject properties. If the instance size overflows, we allocate as many
6668  // properties as we can as inobject properties.
6669  int max_extra_properties =
6670      (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
6671
6672  if (inobject_properties > max_extra_properties) {
6673    inobject_properties = max_extra_properties;
6674  }
6675
6676  int new_instance_size =
6677      JSObject::kHeaderSize + kPointerSize * inobject_properties;
6678
6679  // Adjust the map with the extra inobject properties.
6680  copy->set_inobject_properties(inobject_properties);
6681  copy->set_unused_property_fields(inobject_properties);
6682  copy->set_instance_size(new_instance_size);
6683  copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
6684  return copy;
6685}
6686
6687
6688Handle<Map> Map::CopyForFreeze(Handle<Map> map) {
6689  int num_descriptors = map->NumberOfOwnDescriptors();
6690  Isolate* isolate = map->GetIsolate();
6691  Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
6692      handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN);
6693  Handle<Map> new_map = CopyReplaceDescriptors(
6694      map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol());
6695  new_map->freeze();
6696  new_map->set_is_extensible(false);
6697  new_map->set_elements_kind(DICTIONARY_ELEMENTS);
6698  return new_map;
6699}
6700
6701
6702bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
6703  PropertyDetails details = GetDetails(descriptor);
6704  switch (details.type()) {
6705    case FIELD:
6706      return value->FitsRepresentation(details.representation()) &&
6707             GetFieldType(descriptor)->NowContains(value);
6708
6709    case CONSTANT:
6710      DCHECK(GetConstant(descriptor) != value ||
6711             value->FitsRepresentation(details.representation()));
6712      return GetConstant(descriptor) == value;
6713
6714    case CALLBACKS:
6715      return false;
6716
6717    case NORMAL:
6718      UNREACHABLE();
6719      break;
6720  }
6721
6722  UNREACHABLE();
6723  return false;
6724}
6725
6726
6727Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
6728                                        Handle<Object> value) {
6729  // Dictionaries can store any property value.
6730  if (map->is_dictionary_map()) return map;
6731
6732  // Migrate to the newest map before storing the property.
6733  map = Update(map);
6734
6735  Handle<DescriptorArray> descriptors(map->instance_descriptors());
6736
6737  if (descriptors->CanHoldValue(descriptor, *value)) return map;
6738
6739  Isolate* isolate = map->GetIsolate();
6740  Representation representation = value->OptimalRepresentation();
6741  Handle<HeapType> type = value->OptimalType(isolate, representation);
6742
6743  return GeneralizeRepresentation(map, descriptor, representation, type,
6744                                  FORCE_FIELD);
6745}
6746
6747
6748Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
6749                                          Handle<Object> value,
6750                                          PropertyAttributes attributes,
6751                                          StoreFromKeyed store_mode) {
6752  // Dictionary maps can always have additional data properties.
6753  if (map->is_dictionary_map()) return map;
6754
6755  // Migrate to the newest map before storing the property.
6756  map = Update(map);
6757
6758  int index = map->SearchTransition(*name);
6759  if (index != TransitionArray::kNotFound) {
6760    Handle<Map> transition(map->GetTransition(index));
6761    int descriptor = transition->LastAdded();
6762
6763    // TODO(verwaest): Handle attributes better.
6764    DescriptorArray* descriptors = transition->instance_descriptors();
6765    if (descriptors->GetDetails(descriptor).attributes() != attributes) {
6766      return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES);
6767    }
6768
6769    return Map::PrepareForDataProperty(transition, descriptor, value);
6770  }
6771
6772  TransitionFlag flag = INSERT_TRANSITION;
6773  MaybeHandle<Map> maybe_map;
6774  if (value->IsJSFunction()) {
6775    maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
6776  } else if (!map->TooManyFastProperties(store_mode)) {
6777    Isolate* isolate = name->GetIsolate();
6778    Representation representation = value->OptimalRepresentation();
6779    Handle<HeapType> type = value->OptimalType(isolate, representation);
6780    maybe_map =
6781        Map::CopyWithField(map, name, type, attributes, representation, flag);
6782  }
6783
6784  Handle<Map> result;
6785  if (!maybe_map.ToHandle(&result)) {
6786    return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES);
6787  }
6788
6789  return result;
6790}
6791
6792
6793Handle<Map> Map::ReconfigureDataProperty(Handle<Map> map, int descriptor,
6794                                         PropertyAttributes attributes) {
6795  // Dictionaries have to be reconfigured in-place.
6796  DCHECK(!map->is_dictionary_map());
6797
6798  // For now, give up on transitioning and just create a unique map.
6799  // TODO(verwaest/ishell): Cache transitions with different attributes.
6800  return CopyGeneralizeAllRepresentations(map, descriptor, FORCE_FIELD,
6801                                          attributes, "attributes mismatch");
6802}
6803
6804
6805Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
6806                                              Handle<Name> name,
6807                                              AccessorComponent component,
6808                                              Handle<Object> accessor,
6809                                              PropertyAttributes attributes) {
6810  Isolate* isolate = name->GetIsolate();
6811
6812  // Dictionary maps can always have additional data properties.
6813  if (map->is_dictionary_map()) {
6814    // For global objects, property cells are inlined. We need to change the
6815    // map.
6816    if (map->IsGlobalObjectMap()) return Copy(map);
6817    return map;
6818  }
6819
6820  // Migrate to the newest map before transitioning to the new property.
6821  map = Update(map);
6822
6823  PropertyNormalizationMode mode = map->is_prototype_map()
6824                                       ? KEEP_INOBJECT_PROPERTIES
6825                                       : CLEAR_INOBJECT_PROPERTIES;
6826
6827  int index = map->SearchTransition(*name);
6828  if (index != TransitionArray::kNotFound) {
6829    Handle<Map> transition(map->GetTransition(index));
6830    DescriptorArray* descriptors = transition->instance_descriptors();
6831    // Fast path, assume that we're modifying the last added descriptor.
6832    int descriptor = transition->LastAdded();
6833    if (descriptors->GetKey(descriptor) != *name) {
6834      // If not, search for the descriptor.
6835      descriptor = descriptors->SearchWithCache(*name, *transition);
6836    }
6837
6838    if (descriptors->GetDetails(descriptor).type() != CALLBACKS) {
6839      return Map::Normalize(map, mode);
6840    }
6841
6842    // TODO(verwaest): Handle attributes better.
6843    if (descriptors->GetDetails(descriptor).attributes() != attributes) {
6844      return Map::Normalize(map, mode);
6845    }
6846
6847    Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
6848    if (!maybe_pair->IsAccessorPair()) {
6849      return Map::Normalize(map, mode);
6850    }
6851
6852    Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
6853    if (pair->get(component) != *accessor) {
6854      return Map::Normalize(map, mode);
6855    }
6856
6857    return transition;
6858  }
6859
6860  Handle<AccessorPair> pair;
6861  DescriptorArray* old_descriptors = map->instance_descriptors();
6862  int descriptor = old_descriptors->SearchWithCache(*name, *map);
6863  if (descriptor != DescriptorArray::kNotFound) {
6864    PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
6865    if (old_details.type() != CALLBACKS) {
6866      return Map::Normalize(map, mode);
6867    }
6868
6869    if (old_details.attributes() != attributes) {
6870      return Map::Normalize(map, mode);
6871    }
6872
6873    Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
6874    if (!maybe_pair->IsAccessorPair()) {
6875      return Map::Normalize(map, mode);
6876    }
6877
6878    Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component);
6879    if (current == *accessor) return map;
6880
6881    if (!current->IsTheHole()) {
6882      return Map::Normalize(map, mode);
6883    }
6884
6885    pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
6886  } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
6887             map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
6888    return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES);
6889  } else {
6890    pair = isolate->factory()->NewAccessorPair();
6891  }
6892
6893  pair->set(component, *accessor);
6894  TransitionFlag flag = INSERT_TRANSITION;
6895  CallbacksDescriptor new_desc(name, pair, attributes);
6896  return Map::CopyInsertDescriptor(map, &new_desc, flag);
6897}
6898
6899
6900Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
6901                                   Descriptor* descriptor,
6902                                   TransitionFlag flag) {
6903  Handle<DescriptorArray> descriptors(map->instance_descriptors());
6904
6905  // Ensure the key is unique.
6906  descriptor->KeyToUniqueName();
6907
6908  if (flag == INSERT_TRANSITION &&
6909      map->owns_descriptors() &&
6910      map->CanHaveMoreTransitions()) {
6911    return ShareDescriptor(map, descriptors, descriptor);
6912  }
6913
6914  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
6915      descriptors, map->NumberOfOwnDescriptors(), 1);
6916  new_descriptors->Append(descriptor);
6917
6918  return CopyReplaceDescriptors(
6919      map, new_descriptors, flag, descriptor->GetKey(), SIMPLE_TRANSITION);
6920}
6921
6922
6923Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
6924                                      Descriptor* descriptor,
6925                                      TransitionFlag flag) {
6926  Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
6927
6928  // Ensure the key is unique.
6929  descriptor->KeyToUniqueName();
6930
6931  // We replace the key if it is already present.
6932  int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
6933  if (index != DescriptorArray::kNotFound) {
6934    return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
6935  }
6936  return CopyAddDescriptor(map, descriptor, flag);
6937}
6938
6939
6940Handle<DescriptorArray> DescriptorArray::CopyUpTo(
6941    Handle<DescriptorArray> desc,
6942    int enumeration_index,
6943    int slack) {
6944  return DescriptorArray::CopyUpToAddAttributes(
6945      desc, enumeration_index, NONE, slack);
6946}
6947
6948
6949Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
6950    Handle<DescriptorArray> desc,
6951    int enumeration_index,
6952    PropertyAttributes attributes,
6953    int slack) {
6954  if (enumeration_index + slack == 0) {
6955    return desc->GetIsolate()->factory()->empty_descriptor_array();
6956  }
6957
6958  int size = enumeration_index;
6959
6960  Handle<DescriptorArray> descriptors =
6961      DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
6962  DescriptorArray::WhitenessWitness witness(*descriptors);
6963
6964  if (attributes != NONE) {
6965    for (int i = 0; i < size; ++i) {
6966      Object* value = desc->GetValue(i);
6967      Name* key = desc->GetKey(i);
6968      PropertyDetails details = desc->GetDetails(i);
6969      // Bulk attribute changes never affect private properties.
6970      if (!key->IsSymbol() || !Symbol::cast(key)->is_private()) {
6971        int mask = DONT_DELETE | DONT_ENUM;
6972        // READ_ONLY is an invalid attribute for JS setters/getters.
6973        if (details.type() != CALLBACKS || !value->IsAccessorPair()) {
6974          mask |= READ_ONLY;
6975        }
6976        details = details.CopyAddAttributes(
6977            static_cast<PropertyAttributes>(attributes & mask));
6978      }
6979      Descriptor inner_desc(
6980          handle(key), handle(value, desc->GetIsolate()), details);
6981      descriptors->Set(i, &inner_desc, witness);
6982    }
6983  } else {
6984    for (int i = 0; i < size; ++i) {
6985      descriptors->CopyFrom(i, *desc, witness);
6986    }
6987  }
6988
6989  if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
6990
6991  return descriptors;
6992}
6993
6994
6995Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
6996                                       Handle<DescriptorArray> descriptors,
6997                                       Descriptor* descriptor,
6998                                       int insertion_index,
6999                                       TransitionFlag flag) {
7000  // Ensure the key is unique.
7001  descriptor->KeyToUniqueName();
7002
7003  Handle<Name> key = descriptor->GetKey();
7004  DCHECK(*key == descriptors->GetKey(insertion_index));
7005
7006  Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
7007      descriptors, map->NumberOfOwnDescriptors());
7008
7009  new_descriptors->Replace(insertion_index, descriptor);
7010
7011  SimpleTransitionFlag simple_flag =
7012      (insertion_index == descriptors->number_of_descriptors() - 1)
7013      ? SIMPLE_TRANSITION
7014      : FULL_TRANSITION;
7015  return CopyReplaceDescriptors(map, new_descriptors, flag, key, simple_flag);
7016}
7017
7018
7019void Map::UpdateCodeCache(Handle<Map> map,
7020                          Handle<Name> name,
7021                          Handle<Code> code) {
7022  Isolate* isolate = map->GetIsolate();
7023  HandleScope scope(isolate);
7024  // Allocate the code cache if not present.
7025  if (map->code_cache()->IsFixedArray()) {
7026    Handle<Object> result = isolate->factory()->NewCodeCache();
7027    map->set_code_cache(*result);
7028  }
7029
7030  // Update the code cache.
7031  Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
7032  CodeCache::Update(code_cache, name, code);
7033}
7034
7035
7036Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
7037  // Do a lookup if a code cache exists.
7038  if (!code_cache()->IsFixedArray()) {
7039    return CodeCache::cast(code_cache())->Lookup(name, flags);
7040  } else {
7041    return GetHeap()->undefined_value();
7042  }
7043}
7044
7045
7046int Map::IndexInCodeCache(Object* name, Code* code) {
7047  // Get the internal index if a code cache exists.
7048  if (!code_cache()->IsFixedArray()) {
7049    return CodeCache::cast(code_cache())->GetIndex(name, code);
7050  }
7051  return -1;
7052}
7053
7054
7055void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7056  // No GC is supposed to happen between a call to IndexInCodeCache and
7057  // RemoveFromCodeCache so the code cache must be there.
7058  DCHECK(!code_cache()->IsFixedArray());
7059  CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7060}
7061
7062
7063// An iterator over all map transitions in an descriptor array, reusing the
7064// constructor field of the map while it is running. Negative values in
7065// the constructor field indicate an active map transition iteration. The
7066// original constructor is restored after iterating over all entries.
7067class IntrusiveMapTransitionIterator {
7068 public:
7069  IntrusiveMapTransitionIterator(
7070      Map* map, TransitionArray* transition_array, Object* constructor)
7071      : map_(map),
7072        transition_array_(transition_array),
7073        constructor_(constructor) { }
7074
7075  void StartIfNotStarted() {
7076    DCHECK(!(*IteratorField())->IsSmi() || IsIterating());
7077    if (!(*IteratorField())->IsSmi()) {
7078      DCHECK(*IteratorField() == constructor_);
7079      *IteratorField() = Smi::FromInt(-1);
7080    }
7081  }
7082
7083  bool IsIterating() {
7084    return (*IteratorField())->IsSmi() &&
7085           Smi::cast(*IteratorField())->value() < 0;
7086  }
7087
7088  Map* Next() {
7089    DCHECK(IsIterating());
7090    int value = Smi::cast(*IteratorField())->value();
7091    int index = -value - 1;
7092    int number_of_transitions = transition_array_->number_of_transitions();
7093    while (index < number_of_transitions) {
7094      *IteratorField() = Smi::FromInt(value - 1);
7095      return transition_array_->GetTarget(index);
7096    }
7097
7098    *IteratorField() = constructor_;
7099    return NULL;
7100  }
7101
7102 private:
7103  Object** IteratorField() {
7104    return HeapObject::RawField(map_, Map::kConstructorOffset);
7105  }
7106
7107  Map* map_;
7108  TransitionArray* transition_array_;
7109  Object* constructor_;
7110};
7111
7112
7113// An iterator over all prototype transitions, reusing the constructor field
7114// of the map while it is running.  Positive values in the constructor field
7115// indicate an active prototype transition iteration. The original constructor
7116// is restored after iterating over all entries.
7117class IntrusivePrototypeTransitionIterator {
7118 public:
7119  IntrusivePrototypeTransitionIterator(
7120      Map* map, HeapObject* proto_trans, Object* constructor)
7121      : map_(map), proto_trans_(proto_trans), constructor_(constructor) { }
7122
7123  void StartIfNotStarted() {
7124    if (!(*IteratorField())->IsSmi()) {
7125      DCHECK(*IteratorField() == constructor_);
7126      *IteratorField() = Smi::FromInt(0);
7127    }
7128  }
7129
7130  bool IsIterating() {
7131    return (*IteratorField())->IsSmi() &&
7132           Smi::cast(*IteratorField())->value() >= 0;
7133  }
7134
7135  Map* Next() {
7136    DCHECK(IsIterating());
7137    int transitionNumber = Smi::cast(*IteratorField())->value();
7138    if (transitionNumber < NumberOfTransitions()) {
7139      *IteratorField() = Smi::FromInt(transitionNumber + 1);
7140      return GetTransition(transitionNumber);
7141    }
7142    *IteratorField() = constructor_;
7143    return NULL;
7144  }
7145
7146 private:
7147  Object** IteratorField() {
7148    return HeapObject::RawField(map_, Map::kConstructorOffset);
7149  }
7150
7151  int NumberOfTransitions() {
7152    FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7153    Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
7154    return Smi::cast(num)->value();
7155  }
7156
7157  Map* GetTransition(int transitionNumber) {
7158    FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7159    return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
7160  }
7161
7162  int IndexFor(int transitionNumber) {
7163    return Map::kProtoTransitionHeaderSize +
7164        Map::kProtoTransitionMapOffset +
7165        transitionNumber * Map::kProtoTransitionElementsPerEntry;
7166  }
7167
7168  Map* map_;
7169  HeapObject* proto_trans_;
7170  Object* constructor_;
7171};
7172
7173
7174// To traverse the transition tree iteratively, we have to store two kinds of
7175// information in a map: The parent map in the traversal and which children of a
7176// node have already been visited. To do this without additional memory, we
7177// temporarily reuse two fields with known values:
7178//
7179//  (1) The map of the map temporarily holds the parent, and is restored to the
7180//      meta map afterwards.
7181//
7182//  (2) The info which children have already been visited depends on which part
7183//      of the map we currently iterate. We use the constructor field of the
7184//      map to store the current index. We can do that because the constructor
7185//      is the same for all involved maps.
7186//
7187//    (a) If we currently follow normal map transitions, we temporarily store
7188//        the current index in the constructor field, and restore it to the
7189//        original constructor afterwards. Note that a single descriptor can
7190//        have 0, 1, or 2 transitions.
7191//
7192//    (b) If we currently follow prototype transitions, we temporarily store
7193//        the current index in the constructor field, and restore it to the
7194//        original constructor afterwards.
7195//
7196// Note that the child iterator is just a concatenation of two iterators: One
7197// iterating over map transitions and one iterating over prototype transisitons.
7198class TraversableMap : public Map {
7199 public:
7200  // Record the parent in the traversal within this map. Note that this destroys
7201  // this map's map!
7202  void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
7203
7204  // Reset the current map's map, returning the parent previously stored in it.
7205  TraversableMap* GetAndResetParent() {
7206    TraversableMap* old_parent = static_cast<TraversableMap*>(map());
7207    set_map_no_write_barrier(GetHeap()->meta_map());
7208    return old_parent;
7209  }
7210
7211  // If we have an unvisited child map, return that one and advance. If we have
7212  // none, return NULL and restore the overwritten constructor field.
7213  TraversableMap* ChildIteratorNext(Object* constructor) {
7214    if (!HasTransitionArray()) return NULL;
7215
7216    TransitionArray* transition_array = transitions();
7217    if (transition_array->HasPrototypeTransitions()) {
7218      HeapObject* proto_transitions =
7219          transition_array->GetPrototypeTransitions();
7220      IntrusivePrototypeTransitionIterator proto_iterator(this,
7221                                                          proto_transitions,
7222                                                          constructor);
7223      proto_iterator.StartIfNotStarted();
7224      if (proto_iterator.IsIterating()) {
7225        Map* next = proto_iterator.Next();
7226        if (next != NULL) return static_cast<TraversableMap*>(next);
7227      }
7228    }
7229
7230    IntrusiveMapTransitionIterator transition_iterator(this,
7231                                                       transition_array,
7232                                                       constructor);
7233    transition_iterator.StartIfNotStarted();
7234    if (transition_iterator.IsIterating()) {
7235      Map* next = transition_iterator.Next();
7236      if (next != NULL) return static_cast<TraversableMap*>(next);
7237    }
7238
7239    return NULL;
7240  }
7241};
7242
7243
7244// Traverse the transition tree in postorder without using the C++ stack by
7245// doing pointer reversal.
7246void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
7247  // Make sure that we do not allocate in the callback.
7248  DisallowHeapAllocation no_allocation;
7249
7250  TraversableMap* current = static_cast<TraversableMap*>(this);
7251  // Get the root constructor here to restore it later when finished iterating
7252  // over maps.
7253  Object* root_constructor = constructor();
7254  while (true) {
7255    TraversableMap* child = current->ChildIteratorNext(root_constructor);
7256    if (child != NULL) {
7257      child->SetParent(current);
7258      current = child;
7259    } else {
7260      TraversableMap* parent = current->GetAndResetParent();
7261      callback(current, data);
7262      if (current == this) break;
7263      current = parent;
7264    }
7265  }
7266}
7267
7268
7269void CodeCache::Update(
7270    Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7271  // The number of monomorphic stubs for normal load/store/call IC's can grow to
7272  // a large number and therefore they need to go into a hash table. They are
7273  // used to load global properties from cells.
7274  if (code->type() == Code::NORMAL) {
7275    // Make sure that a hash table is allocated for the normal load code cache.
7276    if (code_cache->normal_type_cache()->IsUndefined()) {
7277      Handle<Object> result =
7278          CodeCacheHashTable::New(code_cache->GetIsolate(),
7279                                  CodeCacheHashTable::kInitialSize);
7280      code_cache->set_normal_type_cache(*result);
7281    }
7282    UpdateNormalTypeCache(code_cache, name, code);
7283  } else {
7284    DCHECK(code_cache->default_cache()->IsFixedArray());
7285    UpdateDefaultCache(code_cache, name, code);
7286  }
7287}
7288
7289
7290void CodeCache::UpdateDefaultCache(
7291    Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7292  // When updating the default code cache we disregard the type encoded in the
7293  // flags. This allows call constant stubs to overwrite call field
7294  // stubs, etc.
7295  Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7296
7297  // First check whether we can update existing code cache without
7298  // extending it.
7299  Handle<FixedArray> cache = handle(code_cache->default_cache());
7300  int length = cache->length();
7301  {
7302    DisallowHeapAllocation no_alloc;
7303    int deleted_index = -1;
7304    for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7305      Object* key = cache->get(i);
7306      if (key->IsNull()) {
7307        if (deleted_index < 0) deleted_index = i;
7308        continue;
7309      }
7310      if (key->IsUndefined()) {
7311        if (deleted_index >= 0) i = deleted_index;
7312        cache->set(i + kCodeCacheEntryNameOffset, *name);
7313        cache->set(i + kCodeCacheEntryCodeOffset, *code);
7314        return;
7315      }
7316      if (name->Equals(Name::cast(key))) {
7317        Code::Flags found =
7318            Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7319        if (Code::RemoveTypeFromFlags(found) == flags) {
7320          cache->set(i + kCodeCacheEntryCodeOffset, *code);
7321          return;
7322        }
7323      }
7324    }
7325
7326    // Reached the end of the code cache.  If there were deleted
7327    // elements, reuse the space for the first of them.
7328    if (deleted_index >= 0) {
7329      cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
7330      cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
7331      return;
7332    }
7333  }
7334
7335  // Extend the code cache with some new entries (at least one). Must be a
7336  // multiple of the entry size.
7337  int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7338  new_length = new_length - new_length % kCodeCacheEntrySize;
7339  DCHECK((new_length % kCodeCacheEntrySize) == 0);
7340  cache = FixedArray::CopySize(cache, new_length);
7341
7342  // Add the (name, code) pair to the new cache.
7343  cache->set(length + kCodeCacheEntryNameOffset, *name);
7344  cache->set(length + kCodeCacheEntryCodeOffset, *code);
7345  code_cache->set_default_cache(*cache);
7346}
7347
7348
7349void CodeCache::UpdateNormalTypeCache(
7350    Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7351  // Adding a new entry can cause a new cache to be allocated.
7352  Handle<CodeCacheHashTable> cache(
7353      CodeCacheHashTable::cast(code_cache->normal_type_cache()));
7354  Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
7355  code_cache->set_normal_type_cache(*new_cache);
7356}
7357
7358
7359Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
7360  Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7361  if (result->IsCode()) {
7362    if (Code::cast(result)->flags() == flags) return result;
7363    return GetHeap()->undefined_value();
7364  }
7365  return LookupNormalTypeCache(name, flags);
7366}
7367
7368
7369Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
7370  FixedArray* cache = default_cache();
7371  int length = cache->length();
7372  for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7373    Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7374    // Skip deleted elements.
7375    if (key->IsNull()) continue;
7376    if (key->IsUndefined()) return key;
7377    if (name->Equals(Name::cast(key))) {
7378      Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
7379      if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
7380        return code;
7381      }
7382    }
7383  }
7384  return GetHeap()->undefined_value();
7385}
7386
7387
7388Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
7389  if (!normal_type_cache()->IsUndefined()) {
7390    CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7391    return cache->Lookup(name, flags);
7392  } else {
7393    return GetHeap()->undefined_value();
7394  }
7395}
7396
7397
7398int CodeCache::GetIndex(Object* name, Code* code) {
7399  if (code->type() == Code::NORMAL) {
7400    if (normal_type_cache()->IsUndefined()) return -1;
7401    CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7402    return cache->GetIndex(Name::cast(name), code->flags());
7403  }
7404
7405  FixedArray* array = default_cache();
7406  int len = array->length();
7407  for (int i = 0; i < len; i += kCodeCacheEntrySize) {
7408    if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
7409  }
7410  return -1;
7411}
7412
7413
7414void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
7415  if (code->type() == Code::NORMAL) {
7416    DCHECK(!normal_type_cache()->IsUndefined());
7417    CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7418    DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
7419    cache->RemoveByIndex(index);
7420  } else {
7421    FixedArray* array = default_cache();
7422    DCHECK(array->length() >= index && array->get(index)->IsCode());
7423    // Use null instead of undefined for deleted elements to distinguish
7424    // deleted elements from unused elements.  This distinction is used
7425    // when looking up in the cache and when updating the cache.
7426    DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
7427    array->set_null(index - 1);  // Name.
7428    array->set_null(index);  // Code.
7429  }
7430}
7431
7432
7433// The key in the code cache hash table consists of the property name and the
7434// code object. The actual match is on the name and the code flags. If a key
7435// is created using the flags and not a code object it can only be used for
7436// lookup not to create a new entry.
7437class CodeCacheHashTableKey : public HashTableKey {
7438 public:
7439  CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
7440      : name_(name), flags_(flags), code_() { }
7441
7442  CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
7443      : name_(name), flags_(code->flags()), code_(code) { }
7444
7445  bool IsMatch(Object* other) OVERRIDE {
7446    if (!other->IsFixedArray()) return false;
7447    FixedArray* pair = FixedArray::cast(other);
7448    Name* name = Name::cast(pair->get(0));
7449    Code::Flags flags = Code::cast(pair->get(1))->flags();
7450    if (flags != flags_) {
7451      return false;
7452    }
7453    return name_->Equals(name);
7454  }
7455
7456  static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
7457    return name->Hash() ^ flags;
7458  }
7459
7460  uint32_t Hash() OVERRIDE { return NameFlagsHashHelper(*name_, flags_); }
7461
7462  uint32_t HashForObject(Object* obj) OVERRIDE {
7463    FixedArray* pair = FixedArray::cast(obj);
7464    Name* name = Name::cast(pair->get(0));
7465    Code* code = Code::cast(pair->get(1));
7466    return NameFlagsHashHelper(name, code->flags());
7467  }
7468
7469  MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
7470    Handle<Code> code = code_.ToHandleChecked();
7471    Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
7472    pair->set(0, *name_);
7473    pair->set(1, *code);
7474    return pair;
7475  }
7476
7477 private:
7478  Handle<Name> name_;
7479  Code::Flags flags_;
7480  // TODO(jkummerow): We should be able to get by without this.
7481  MaybeHandle<Code> code_;
7482};
7483
7484
7485Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
7486  DisallowHeapAllocation no_alloc;
7487  CodeCacheHashTableKey key(handle(name), flags);
7488  int entry = FindEntry(&key);
7489  if (entry == kNotFound) return GetHeap()->undefined_value();
7490  return get(EntryToIndex(entry) + 1);
7491}
7492
7493
7494Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
7495    Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
7496  CodeCacheHashTableKey key(name, code);
7497
7498  Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
7499
7500  int entry = new_cache->FindInsertionEntry(key.Hash());
7501  Handle<Object> k = key.AsHandle(cache->GetIsolate());
7502
7503  new_cache->set(EntryToIndex(entry), *k);
7504  new_cache->set(EntryToIndex(entry) + 1, *code);
7505  new_cache->ElementAdded();
7506  return new_cache;
7507}
7508
7509
7510int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
7511  DisallowHeapAllocation no_alloc;
7512  CodeCacheHashTableKey key(handle(name), flags);
7513  int entry = FindEntry(&key);
7514  return (entry == kNotFound) ? -1 : entry;
7515}
7516
7517
7518void CodeCacheHashTable::RemoveByIndex(int index) {
7519  DCHECK(index >= 0);
7520  Heap* heap = GetHeap();
7521  set(EntryToIndex(index), heap->the_hole_value());
7522  set(EntryToIndex(index) + 1, heap->the_hole_value());
7523  ElementRemoved();
7524}
7525
7526
7527void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
7528                                  MapHandleList* maps,
7529                                  Code::Flags flags,
7530                                  Handle<Code> code) {
7531  Isolate* isolate = code_cache->GetIsolate();
7532  if (code_cache->cache()->IsUndefined()) {
7533    Handle<PolymorphicCodeCacheHashTable> result =
7534        PolymorphicCodeCacheHashTable::New(
7535            isolate,
7536            PolymorphicCodeCacheHashTable::kInitialSize);
7537    code_cache->set_cache(*result);
7538  } else {
7539    // This entry shouldn't be contained in the cache yet.
7540    DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
7541               ->Lookup(maps, flags)->IsUndefined());
7542  }
7543  Handle<PolymorphicCodeCacheHashTable> hash_table =
7544      handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
7545  Handle<PolymorphicCodeCacheHashTable> new_cache =
7546      PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
7547  code_cache->set_cache(*new_cache);
7548}
7549
7550
7551Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
7552                                            Code::Flags flags) {
7553  if (!cache()->IsUndefined()) {
7554    PolymorphicCodeCacheHashTable* hash_table =
7555        PolymorphicCodeCacheHashTable::cast(cache());
7556    return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
7557  } else {
7558    return GetIsolate()->factory()->undefined_value();
7559  }
7560}
7561
7562
7563// Despite their name, object of this class are not stored in the actual
7564// hash table; instead they're temporarily used for lookups. It is therefore
7565// safe to have a weak (non-owning) pointer to a MapList as a member field.
7566class PolymorphicCodeCacheHashTableKey : public HashTableKey {
7567 public:
7568  // Callers must ensure that |maps| outlives the newly constructed object.
7569  PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
7570      : maps_(maps),
7571        code_flags_(code_flags) {}
7572
7573  bool IsMatch(Object* other) OVERRIDE {
7574    MapHandleList other_maps(kDefaultListAllocationSize);
7575    int other_flags;
7576    FromObject(other, &other_flags, &other_maps);
7577    if (code_flags_ != other_flags) return false;
7578    if (maps_->length() != other_maps.length()) return false;
7579    // Compare just the hashes first because it's faster.
7580    int this_hash = MapsHashHelper(maps_, code_flags_);
7581    int other_hash = MapsHashHelper(&other_maps, other_flags);
7582    if (this_hash != other_hash) return false;
7583
7584    // Full comparison: for each map in maps_, look for an equivalent map in
7585    // other_maps. This implementation is slow, but probably good enough for
7586    // now because the lists are short (<= 4 elements currently).
7587    for (int i = 0; i < maps_->length(); ++i) {
7588      bool match_found = false;
7589      for (int j = 0; j < other_maps.length(); ++j) {
7590        if (*(maps_->at(i)) == *(other_maps.at(j))) {
7591          match_found = true;
7592          break;
7593        }
7594      }
7595      if (!match_found) return false;
7596    }
7597    return true;
7598  }
7599
7600  static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
7601    uint32_t hash = code_flags;
7602    for (int i = 0; i < maps->length(); ++i) {
7603      hash ^= maps->at(i)->Hash();
7604    }
7605    return hash;
7606  }
7607
7608  uint32_t Hash() OVERRIDE {
7609    return MapsHashHelper(maps_, code_flags_);
7610  }
7611
7612  uint32_t HashForObject(Object* obj) OVERRIDE {
7613    MapHandleList other_maps(kDefaultListAllocationSize);
7614    int other_flags;
7615    FromObject(obj, &other_flags, &other_maps);
7616    return MapsHashHelper(&other_maps, other_flags);
7617  }
7618
7619  MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
7620    // The maps in |maps_| must be copied to a newly allocated FixedArray,
7621    // both because the referenced MapList is short-lived, and because C++
7622    // objects can't be stored in the heap anyway.
7623    Handle<FixedArray> list =
7624        isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
7625    list->set(0, Smi::FromInt(code_flags_));
7626    for (int i = 0; i < maps_->length(); ++i) {
7627      list->set(i + 1, *maps_->at(i));
7628    }
7629    return list;
7630  }
7631
7632 private:
7633  static MapHandleList* FromObject(Object* obj,
7634                                   int* code_flags,
7635                                   MapHandleList* maps) {
7636    FixedArray* list = FixedArray::cast(obj);
7637    maps->Rewind(0);
7638    *code_flags = Smi::cast(list->get(0))->value();
7639    for (int i = 1; i < list->length(); ++i) {
7640      maps->Add(Handle<Map>(Map::cast(list->get(i))));
7641    }
7642    return maps;
7643  }
7644
7645  MapHandleList* maps_;  // weak.
7646  int code_flags_;
7647  static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
7648};
7649
7650
7651Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
7652                                              int code_kind) {
7653  DisallowHeapAllocation no_alloc;
7654  PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7655  int entry = FindEntry(&key);
7656  if (entry == kNotFound) return GetHeap()->undefined_value();
7657  return get(EntryToIndex(entry) + 1);
7658}
7659
7660
7661Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
7662      Handle<PolymorphicCodeCacheHashTable> hash_table,
7663      MapHandleList* maps,
7664      int code_kind,
7665      Handle<Code> code) {
7666  PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7667  Handle<PolymorphicCodeCacheHashTable> cache =
7668      EnsureCapacity(hash_table, 1, &key);
7669  int entry = cache->FindInsertionEntry(key.Hash());
7670
7671  Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
7672  cache->set(EntryToIndex(entry), *obj);
7673  cache->set(EntryToIndex(entry) + 1, *code);
7674  cache->ElementAdded();
7675  return cache;
7676}
7677
7678
7679void FixedArray::Shrink(int new_length) {
7680  DCHECK(0 <= new_length && new_length <= length());
7681  if (new_length < length()) {
7682    GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>(
7683        this, length() - new_length);
7684  }
7685}
7686
7687
7688MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike(
7689    Handle<FixedArray> content,
7690    Handle<JSObject> array) {
7691  DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
7692  ElementsAccessor* accessor = array->GetElementsAccessor();
7693  Handle<FixedArray> result;
7694  ASSIGN_RETURN_ON_EXCEPTION(
7695      array->GetIsolate(), result,
7696      accessor->AddElementsToFixedArray(array, array, content),
7697      FixedArray);
7698
7699#ifdef ENABLE_SLOW_DCHECKS
7700  if (FLAG_enable_slow_asserts) {
7701    DisallowHeapAllocation no_allocation;
7702    for (int i = 0; i < result->length(); i++) {
7703      Object* current = result->get(i);
7704      DCHECK(current->IsNumber() || current->IsName());
7705    }
7706  }
7707#endif
7708  return result;
7709}
7710
7711
7712MaybeHandle<FixedArray> FixedArray::UnionOfKeys(Handle<FixedArray> first,
7713                                                Handle<FixedArray> second) {
7714  ElementsAccessor* accessor = ElementsAccessor::ForArray(second);
7715  Handle<FixedArray> result;
7716  ASSIGN_RETURN_ON_EXCEPTION(
7717      first->GetIsolate(), result,
7718      accessor->AddElementsToFixedArray(
7719          Handle<Object>::null(),     // receiver
7720          Handle<JSObject>::null(),   // holder
7721          first,
7722          Handle<FixedArrayBase>::cast(second)),
7723      FixedArray);
7724
7725#ifdef ENABLE_SLOW_DCHECKS
7726  if (FLAG_enable_slow_asserts) {
7727    DisallowHeapAllocation no_allocation;
7728    for (int i = 0; i < result->length(); i++) {
7729      Object* current = result->get(i);
7730      DCHECK(current->IsNumber() || current->IsName());
7731    }
7732  }
7733#endif
7734  return result;
7735}
7736
7737
7738Handle<FixedArray> FixedArray::CopySize(
7739    Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
7740  Isolate* isolate = array->GetIsolate();
7741  if (new_length == 0) return isolate->factory()->empty_fixed_array();
7742  Handle<FixedArray> result =
7743      isolate->factory()->NewFixedArray(new_length, pretenure);
7744  // Copy the content
7745  DisallowHeapAllocation no_gc;
7746  int len = array->length();
7747  if (new_length < len) len = new_length;
7748  // We are taking the map from the old fixed array so the map is sure to
7749  // be an immortal immutable object.
7750  result->set_map_no_write_barrier(array->map());
7751  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
7752  for (int i = 0; i < len; i++) {
7753    result->set(i, array->get(i), mode);
7754  }
7755  return result;
7756}
7757
7758
7759void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
7760  DisallowHeapAllocation no_gc;
7761  WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
7762  for (int index = 0; index < len; index++) {
7763    dest->set(dest_pos+index, get(pos+index), mode);
7764  }
7765}
7766
7767
7768#ifdef DEBUG
7769bool FixedArray::IsEqualTo(FixedArray* other) {
7770  if (length() != other->length()) return false;
7771  for (int i = 0 ; i < length(); ++i) {
7772    if (get(i) != other->get(i)) return false;
7773  }
7774  return true;
7775}
7776#endif
7777
7778
7779Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
7780                                                  int number_of_descriptors,
7781                                                  int slack) {
7782  DCHECK(0 <= number_of_descriptors);
7783  Factory* factory = isolate->factory();
7784  // Do not use DescriptorArray::cast on incomplete object.
7785  int size = number_of_descriptors + slack;
7786  if (size == 0) return factory->empty_descriptor_array();
7787  // Allocate the array of keys.
7788  Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
7789
7790  result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
7791  result->set(kEnumCacheIndex, Smi::FromInt(0));
7792  return Handle<DescriptorArray>::cast(result);
7793}
7794
7795
7796void DescriptorArray::ClearEnumCache() {
7797  set(kEnumCacheIndex, Smi::FromInt(0));
7798}
7799
7800
7801void DescriptorArray::Replace(int index, Descriptor* descriptor) {
7802  descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
7803  Set(index, descriptor);
7804}
7805
7806
7807void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
7808                                   FixedArray* new_cache,
7809                                   Object* new_index_cache) {
7810  DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
7811  DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
7812  DCHECK(!IsEmpty());
7813  DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
7814  FixedArray::cast(bridge_storage)->
7815    set(kEnumCacheBridgeCacheIndex, new_cache);
7816  FixedArray::cast(bridge_storage)->
7817    set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
7818  set(kEnumCacheIndex, bridge_storage);
7819}
7820
7821
7822void DescriptorArray::CopyFrom(int index,
7823                               DescriptorArray* src,
7824                               const WhitenessWitness& witness) {
7825  Object* value = src->GetValue(index);
7826  PropertyDetails details = src->GetDetails(index);
7827  Descriptor desc(handle(src->GetKey(index)),
7828                  handle(value, src->GetIsolate()),
7829                  details);
7830  Set(index, &desc, witness);
7831}
7832
7833
7834// We need the whiteness witness since sort will reshuffle the entries in the
7835// descriptor array. If the descriptor array were to be black, the shuffling
7836// would move a slot that was already recorded as pointing into an evacuation
7837// candidate. This would result in missing updates upon evacuation.
7838void DescriptorArray::Sort() {
7839  // In-place heap sort.
7840  int len = number_of_descriptors();
7841  // Reset sorting since the descriptor array might contain invalid pointers.
7842  for (int i = 0; i < len; ++i) SetSortedKey(i, i);
7843  // Bottom-up max-heap construction.
7844  // Index of the last node with children
7845  const int max_parent_index = (len / 2) - 1;
7846  for (int i = max_parent_index; i >= 0; --i) {
7847    int parent_index = i;
7848    const uint32_t parent_hash = GetSortedKey(i)->Hash();
7849    while (parent_index <= max_parent_index) {
7850      int child_index = 2 * parent_index + 1;
7851      uint32_t child_hash = GetSortedKey(child_index)->Hash();
7852      if (child_index + 1 < len) {
7853        uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
7854        if (right_child_hash > child_hash) {
7855          child_index++;
7856          child_hash = right_child_hash;
7857        }
7858      }
7859      if (child_hash <= parent_hash) break;
7860      SwapSortedKeys(parent_index, child_index);
7861      // Now element at child_index could be < its children.
7862      parent_index = child_index;  // parent_hash remains correct.
7863    }
7864  }
7865
7866  // Extract elements and create sorted array.
7867  for (int i = len - 1; i > 0; --i) {
7868    // Put max element at the back of the array.
7869    SwapSortedKeys(0, i);
7870    // Shift down the new top element.
7871    int parent_index = 0;
7872    const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
7873    const int max_parent_index = (i / 2) - 1;
7874    while (parent_index <= max_parent_index) {
7875      int child_index = parent_index * 2 + 1;
7876      uint32_t child_hash = GetSortedKey(child_index)->Hash();
7877      if (child_index + 1 < i) {
7878        uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
7879        if (right_child_hash > child_hash) {
7880          child_index++;
7881          child_hash = right_child_hash;
7882        }
7883      }
7884      if (child_hash <= parent_hash) break;
7885      SwapSortedKeys(parent_index, child_index);
7886      parent_index = child_index;
7887    }
7888  }
7889  DCHECK(IsSortedNoDuplicates());
7890}
7891
7892
7893Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
7894  Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
7895  copy->set_getter(pair->getter());
7896  copy->set_setter(pair->setter());
7897  return copy;
7898}
7899
7900
7901Object* AccessorPair::GetComponent(AccessorComponent component) {
7902  Object* accessor = get(component);
7903  return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
7904}
7905
7906
7907Handle<DeoptimizationInputData> DeoptimizationInputData::New(
7908    Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
7909  DCHECK(deopt_entry_count > 0);
7910  return Handle<DeoptimizationInputData>::cast(
7911      isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
7912                                        pretenure));
7913}
7914
7915
7916Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
7917    Isolate* isolate,
7918    int number_of_deopt_points,
7919    PretenureFlag pretenure) {
7920  Handle<FixedArray> result;
7921  if (number_of_deopt_points == 0) {
7922    result = isolate->factory()->empty_fixed_array();
7923  } else {
7924    result = isolate->factory()->NewFixedArray(
7925        LengthOfFixedArray(number_of_deopt_points), pretenure);
7926  }
7927  return Handle<DeoptimizationOutputData>::cast(result);
7928}
7929
7930
7931#ifdef DEBUG
7932bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
7933  if (IsEmpty()) return other->IsEmpty();
7934  if (other->IsEmpty()) return false;
7935  if (length() != other->length()) return false;
7936  for (int i = 0; i < length(); ++i) {
7937    if (get(i) != other->get(i)) return false;
7938  }
7939  return true;
7940}
7941#endif
7942
7943
7944bool String::LooksValid() {
7945  if (!GetIsolate()->heap()->Contains(this)) return false;
7946  return true;
7947}
7948
7949
7950String::FlatContent String::GetFlatContent() {
7951  DCHECK(!AllowHeapAllocation::IsAllowed());
7952  int length = this->length();
7953  StringShape shape(this);
7954  String* string = this;
7955  int offset = 0;
7956  if (shape.representation_tag() == kConsStringTag) {
7957    ConsString* cons = ConsString::cast(string);
7958    if (cons->second()->length() != 0) {
7959      return FlatContent();
7960    }
7961    string = cons->first();
7962    shape = StringShape(string);
7963  }
7964  if (shape.representation_tag() == kSlicedStringTag) {
7965    SlicedString* slice = SlicedString::cast(string);
7966    offset = slice->offset();
7967    string = slice->parent();
7968    shape = StringShape(string);
7969    DCHECK(shape.representation_tag() != kConsStringTag &&
7970           shape.representation_tag() != kSlicedStringTag);
7971  }
7972  if (shape.encoding_tag() == kOneByteStringTag) {
7973    const uint8_t* start;
7974    if (shape.representation_tag() == kSeqStringTag) {
7975      start = SeqOneByteString::cast(string)->GetChars();
7976    } else {
7977      start = ExternalOneByteString::cast(string)->GetChars();
7978    }
7979    return FlatContent(start + offset, length);
7980  } else {
7981    DCHECK(shape.encoding_tag() == kTwoByteStringTag);
7982    const uc16* start;
7983    if (shape.representation_tag() == kSeqStringTag) {
7984      start = SeqTwoByteString::cast(string)->GetChars();
7985    } else {
7986      start = ExternalTwoByteString::cast(string)->GetChars();
7987    }
7988    return FlatContent(start + offset, length);
7989  }
7990}
7991
7992
7993SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
7994                                          RobustnessFlag robust_flag,
7995                                          int offset,
7996                                          int length,
7997                                          int* length_return) {
7998  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
7999    return SmartArrayPointer<char>(NULL);
8000  }
8001  Heap* heap = GetHeap();
8002
8003  // Negative length means the to the end of the string.
8004  if (length < 0) length = kMaxInt - offset;
8005
8006  // Compute the size of the UTF-8 string. Start at the specified offset.
8007  Access<ConsStringIteratorOp> op(
8008      heap->isolate()->objects_string_iterator());
8009  StringCharacterStream stream(this, op.value(), offset);
8010  int character_position = offset;
8011  int utf8_bytes = 0;
8012  int last = unibrow::Utf16::kNoPreviousCharacter;
8013  while (stream.HasMore() && character_position++ < offset + length) {
8014    uint16_t character = stream.GetNext();
8015    utf8_bytes += unibrow::Utf8::Length(character, last);
8016    last = character;
8017  }
8018
8019  if (length_return) {
8020    *length_return = utf8_bytes;
8021  }
8022
8023  char* result = NewArray<char>(utf8_bytes + 1);
8024
8025  // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8026  stream.Reset(this, offset);
8027  character_position = offset;
8028  int utf8_byte_position = 0;
8029  last = unibrow::Utf16::kNoPreviousCharacter;
8030  while (stream.HasMore() && character_position++ < offset + length) {
8031    uint16_t character = stream.GetNext();
8032    if (allow_nulls == DISALLOW_NULLS && character == 0) {
8033      character = ' ';
8034    }
8035    utf8_byte_position +=
8036        unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8037    last = character;
8038  }
8039  result[utf8_byte_position] = 0;
8040  return SmartArrayPointer<char>(result);
8041}
8042
8043
8044SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8045                                          RobustnessFlag robust_flag,
8046                                          int* length_return) {
8047  return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8048}
8049
8050
8051const uc16* String::GetTwoByteData(unsigned start) {
8052  DCHECK(!IsOneByteRepresentationUnderneath());
8053  switch (StringShape(this).representation_tag()) {
8054    case kSeqStringTag:
8055      return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8056    case kExternalStringTag:
8057      return ExternalTwoByteString::cast(this)->
8058        ExternalTwoByteStringGetData(start);
8059    case kSlicedStringTag: {
8060      SlicedString* slice = SlicedString::cast(this);
8061      return slice->parent()->GetTwoByteData(start + slice->offset());
8062    }
8063    case kConsStringTag:
8064      UNREACHABLE();
8065      return NULL;
8066  }
8067  UNREACHABLE();
8068  return NULL;
8069}
8070
8071
8072SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
8073  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8074    return SmartArrayPointer<uc16>();
8075  }
8076  Heap* heap = GetHeap();
8077
8078  Access<ConsStringIteratorOp> op(
8079      heap->isolate()->objects_string_iterator());
8080  StringCharacterStream stream(this, op.value());
8081
8082  uc16* result = NewArray<uc16>(length() + 1);
8083
8084  int i = 0;
8085  while (stream.HasMore()) {
8086    uint16_t character = stream.GetNext();
8087    result[i++] = character;
8088  }
8089  result[i] = 0;
8090  return SmartArrayPointer<uc16>(result);
8091}
8092
8093
8094const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
8095  return reinterpret_cast<uc16*>(
8096      reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8097}
8098
8099
8100void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8101  Relocatable* current = isolate->relocatable_top();
8102  while (current != NULL) {
8103    current->PostGarbageCollection();
8104    current = current->prev_;
8105  }
8106}
8107
8108
8109// Reserve space for statics needing saving and restoring.
8110int Relocatable::ArchiveSpacePerThread() {
8111  return sizeof(Relocatable*);  // NOLINT
8112}
8113
8114
8115// Archive statics that are thread-local.
8116char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8117  *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8118  isolate->set_relocatable_top(NULL);
8119  return to + ArchiveSpacePerThread();
8120}
8121
8122
8123// Restore statics that are thread-local.
8124char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8125  isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8126  return from + ArchiveSpacePerThread();
8127}
8128
8129
8130char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8131  Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8132  Iterate(v, top);
8133  return thread_storage + ArchiveSpacePerThread();
8134}
8135
8136
8137void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8138  Iterate(v, isolate->relocatable_top());
8139}
8140
8141
8142void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8143  Relocatable* current = top;
8144  while (current != NULL) {
8145    current->IterateInstance(v);
8146    current = current->prev_;
8147  }
8148}
8149
8150
8151FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
8152    : Relocatable(isolate),
8153      str_(str.location()),
8154      length_(str->length()) {
8155  PostGarbageCollection();
8156}
8157
8158
8159FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
8160    : Relocatable(isolate),
8161      str_(0),
8162      is_one_byte_(true),
8163      length_(input.length()),
8164      start_(input.start()) {}
8165
8166
8167void FlatStringReader::PostGarbageCollection() {
8168  if (str_ == NULL) return;
8169  Handle<String> str(str_);
8170  DCHECK(str->IsFlat());
8171  DisallowHeapAllocation no_gc;
8172  // This does not actually prevent the vector from being relocated later.
8173  String::FlatContent content = str->GetFlatContent();
8174  DCHECK(content.IsFlat());
8175  is_one_byte_ = content.IsOneByte();
8176  if (is_one_byte_) {
8177    start_ = content.ToOneByteVector().start();
8178  } else {
8179    start_ = content.ToUC16Vector().start();
8180  }
8181}
8182
8183
8184void ConsStringIteratorOp::Initialize(ConsString* cons_string, int offset) {
8185  DCHECK(cons_string != NULL);
8186  root_ = cons_string;
8187  consumed_ = offset;
8188  // Force stack blown condition to trigger restart.
8189  depth_ = 1;
8190  maximum_depth_ = kStackSize + depth_;
8191  DCHECK(StackBlown());
8192}
8193
8194
8195String* ConsStringIteratorOp::Continue(int* offset_out) {
8196  DCHECK(depth_ != 0);
8197  DCHECK_EQ(0, *offset_out);
8198  bool blew_stack = StackBlown();
8199  String* string = NULL;
8200  // Get the next leaf if there is one.
8201  if (!blew_stack) string = NextLeaf(&blew_stack);
8202  // Restart search from root.
8203  if (blew_stack) {
8204    DCHECK(string == NULL);
8205    string = Search(offset_out);
8206  }
8207  // Ensure future calls return null immediately.
8208  if (string == NULL) Reset(NULL);
8209  return string;
8210}
8211
8212
8213String* ConsStringIteratorOp::Search(int* offset_out) {
8214  ConsString* cons_string = root_;
8215  // Reset the stack, pushing the root string.
8216  depth_ = 1;
8217  maximum_depth_ = 1;
8218  frames_[0] = cons_string;
8219  const int consumed = consumed_;
8220  int offset = 0;
8221  while (true) {
8222    // Loop until the string is found which contains the target offset.
8223    String* string = cons_string->first();
8224    int length = string->length();
8225    int32_t type;
8226    if (consumed < offset + length) {
8227      // Target offset is in the left branch.
8228      // Keep going if we're still in a ConString.
8229      type = string->map()->instance_type();
8230      if ((type & kStringRepresentationMask) == kConsStringTag) {
8231        cons_string = ConsString::cast(string);
8232        PushLeft(cons_string);
8233        continue;
8234      }
8235      // Tell the stack we're done descending.
8236      AdjustMaximumDepth();
8237    } else {
8238      // Descend right.
8239      // Update progress through the string.
8240      offset += length;
8241      // Keep going if we're still in a ConString.
8242      string = cons_string->second();
8243      type = string->map()->instance_type();
8244      if ((type & kStringRepresentationMask) == kConsStringTag) {
8245        cons_string = ConsString::cast(string);
8246        PushRight(cons_string);
8247        continue;
8248      }
8249      // Need this to be updated for the current string.
8250      length = string->length();
8251      // Account for the possibility of an empty right leaf.
8252      // This happens only if we have asked for an offset outside the string.
8253      if (length == 0) {
8254        // Reset so future operations will return null immediately.
8255        Reset(NULL);
8256        return NULL;
8257      }
8258      // Tell the stack we're done descending.
8259      AdjustMaximumDepth();
8260      // Pop stack so next iteration is in correct place.
8261      Pop();
8262    }
8263    DCHECK(length != 0);
8264    // Adjust return values and exit.
8265    consumed_ = offset + length;
8266    *offset_out = consumed - offset;
8267    return string;
8268  }
8269  UNREACHABLE();
8270  return NULL;
8271}
8272
8273
8274String* ConsStringIteratorOp::NextLeaf(bool* blew_stack) {
8275  while (true) {
8276    // Tree traversal complete.
8277    if (depth_ == 0) {
8278      *blew_stack = false;
8279      return NULL;
8280    }
8281    // We've lost track of higher nodes.
8282    if (StackBlown()) {
8283      *blew_stack = true;
8284      return NULL;
8285    }
8286    // Go right.
8287    ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
8288    String* string = cons_string->second();
8289    int32_t type = string->map()->instance_type();
8290    if ((type & kStringRepresentationMask) != kConsStringTag) {
8291      // Pop stack so next iteration is in correct place.
8292      Pop();
8293      int length = string->length();
8294      // Could be a flattened ConsString.
8295      if (length == 0) continue;
8296      consumed_ += length;
8297      return string;
8298    }
8299    cons_string = ConsString::cast(string);
8300    PushRight(cons_string);
8301    // Need to traverse all the way left.
8302    while (true) {
8303      // Continue left.
8304      string = cons_string->first();
8305      type = string->map()->instance_type();
8306      if ((type & kStringRepresentationMask) != kConsStringTag) {
8307        AdjustMaximumDepth();
8308        int length = string->length();
8309        DCHECK(length != 0);
8310        consumed_ += length;
8311        return string;
8312      }
8313      cons_string = ConsString::cast(string);
8314      PushLeft(cons_string);
8315    }
8316  }
8317  UNREACHABLE();
8318  return NULL;
8319}
8320
8321
8322uint16_t ConsString::ConsStringGet(int index) {
8323  DCHECK(index >= 0 && index < this->length());
8324
8325  // Check for a flattened cons string
8326  if (second()->length() == 0) {
8327    String* left = first();
8328    return left->Get(index);
8329  }
8330
8331  String* string = String::cast(this);
8332
8333  while (true) {
8334    if (StringShape(string).IsCons()) {
8335      ConsString* cons_string = ConsString::cast(string);
8336      String* left = cons_string->first();
8337      if (left->length() > index) {
8338        string = left;
8339      } else {
8340        index -= left->length();
8341        string = cons_string->second();
8342      }
8343    } else {
8344      return string->Get(index);
8345    }
8346  }
8347
8348  UNREACHABLE();
8349  return 0;
8350}
8351
8352
8353uint16_t SlicedString::SlicedStringGet(int index) {
8354  return parent()->Get(offset() + index);
8355}
8356
8357
8358template <typename sinkchar>
8359void String::WriteToFlat(String* src,
8360                         sinkchar* sink,
8361                         int f,
8362                         int t) {
8363  String* source = src;
8364  int from = f;
8365  int to = t;
8366  while (true) {
8367    DCHECK(0 <= from && from <= to && to <= source->length());
8368    switch (StringShape(source).full_representation_tag()) {
8369      case kOneByteStringTag | kExternalStringTag: {
8370        CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
8371                  to - from);
8372        return;
8373      }
8374      case kTwoByteStringTag | kExternalStringTag: {
8375        const uc16* data =
8376            ExternalTwoByteString::cast(source)->GetChars();
8377        CopyChars(sink,
8378                  data + from,
8379                  to - from);
8380        return;
8381      }
8382      case kOneByteStringTag | kSeqStringTag: {
8383        CopyChars(sink,
8384                  SeqOneByteString::cast(source)->GetChars() + from,
8385                  to - from);
8386        return;
8387      }
8388      case kTwoByteStringTag | kSeqStringTag: {
8389        CopyChars(sink,
8390                  SeqTwoByteString::cast(source)->GetChars() + from,
8391                  to - from);
8392        return;
8393      }
8394      case kOneByteStringTag | kConsStringTag:
8395      case kTwoByteStringTag | kConsStringTag: {
8396        ConsString* cons_string = ConsString::cast(source);
8397        String* first = cons_string->first();
8398        int boundary = first->length();
8399        if (to - boundary >= boundary - from) {
8400          // Right hand side is longer.  Recurse over left.
8401          if (from < boundary) {
8402            WriteToFlat(first, sink, from, boundary);
8403            sink += boundary - from;
8404            from = 0;
8405          } else {
8406            from -= boundary;
8407          }
8408          to -= boundary;
8409          source = cons_string->second();
8410        } else {
8411          // Left hand side is longer.  Recurse over right.
8412          if (to > boundary) {
8413            String* second = cons_string->second();
8414            // When repeatedly appending to a string, we get a cons string that
8415            // is unbalanced to the left, a list, essentially.  We inline the
8416            // common case of sequential one-byte right child.
8417            if (to - boundary == 1) {
8418              sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
8419            } else if (second->IsSeqOneByteString()) {
8420              CopyChars(sink + boundary - from,
8421                        SeqOneByteString::cast(second)->GetChars(),
8422                        to - boundary);
8423            } else {
8424              WriteToFlat(second,
8425                          sink + boundary - from,
8426                          0,
8427                          to - boundary);
8428            }
8429            to = boundary;
8430          }
8431          source = first;
8432        }
8433        break;
8434      }
8435      case kOneByteStringTag | kSlicedStringTag:
8436      case kTwoByteStringTag | kSlicedStringTag: {
8437        SlicedString* slice = SlicedString::cast(source);
8438        unsigned offset = slice->offset();
8439        WriteToFlat(slice->parent(), sink, from + offset, to + offset);
8440        return;
8441      }
8442    }
8443  }
8444}
8445
8446
8447
8448template <typename SourceChar>
8449static void CalculateLineEndsImpl(Isolate* isolate,
8450                                  List<int>* line_ends,
8451                                  Vector<const SourceChar> src,
8452                                  bool include_ending_line) {
8453  const int src_len = src.length();
8454  StringSearch<uint8_t, SourceChar> search(isolate, STATIC_CHAR_VECTOR("\n"));
8455
8456  // Find and record line ends.
8457  int position = 0;
8458  while (position != -1 && position < src_len) {
8459    position = search.Search(src, position);
8460    if (position != -1) {
8461      line_ends->Add(position);
8462      position++;
8463    } else if (include_ending_line) {
8464      // Even if the last line misses a line end, it is counted.
8465      line_ends->Add(src_len);
8466      return;
8467    }
8468  }
8469}
8470
8471
8472Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
8473                                             bool include_ending_line) {
8474  src = Flatten(src);
8475  // Rough estimate of line count based on a roughly estimated average
8476  // length of (unpacked) code.
8477  int line_count_estimate = src->length() >> 4;
8478  List<int> line_ends(line_count_estimate);
8479  Isolate* isolate = src->GetIsolate();
8480  { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
8481    // Dispatch on type of strings.
8482    String::FlatContent content = src->GetFlatContent();
8483    DCHECK(content.IsFlat());
8484    if (content.IsOneByte()) {
8485      CalculateLineEndsImpl(isolate,
8486                            &line_ends,
8487                            content.ToOneByteVector(),
8488                            include_ending_line);
8489    } else {
8490      CalculateLineEndsImpl(isolate,
8491                            &line_ends,
8492                            content.ToUC16Vector(),
8493                            include_ending_line);
8494    }
8495  }
8496  int line_count = line_ends.length();
8497  Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
8498  for (int i = 0; i < line_count; i++) {
8499    array->set(i, Smi::FromInt(line_ends[i]));
8500  }
8501  return array;
8502}
8503
8504
8505// Compares the contents of two strings by reading and comparing
8506// int-sized blocks of characters.
8507template <typename Char>
8508static inline bool CompareRawStringContents(const Char* const a,
8509                                            const Char* const b,
8510                                            int length) {
8511  return CompareChars(a, b, length) == 0;
8512}
8513
8514
8515template<typename Chars1, typename Chars2>
8516class RawStringComparator : public AllStatic {
8517 public:
8518  static inline bool compare(const Chars1* a, const Chars2* b, int len) {
8519    DCHECK(sizeof(Chars1) != sizeof(Chars2));
8520    for (int i = 0; i < len; i++) {
8521      if (a[i] != b[i]) {
8522        return false;
8523      }
8524    }
8525    return true;
8526  }
8527};
8528
8529
8530template<>
8531class RawStringComparator<uint16_t, uint16_t> {
8532 public:
8533  static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
8534    return CompareRawStringContents(a, b, len);
8535  }
8536};
8537
8538
8539template<>
8540class RawStringComparator<uint8_t, uint8_t> {
8541 public:
8542  static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
8543    return CompareRawStringContents(a, b, len);
8544  }
8545};
8546
8547
8548class StringComparator {
8549  class State {
8550   public:
8551    explicit inline State(ConsStringIteratorOp* op)
8552      : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {}
8553
8554    inline void Init(String* string) {
8555      ConsString* cons_string = String::VisitFlat(this, string);
8556      op_->Reset(cons_string);
8557      if (cons_string != NULL) {
8558        int offset;
8559        string = op_->Next(&offset);
8560        String::VisitFlat(this, string, offset);
8561      }
8562    }
8563
8564    inline void VisitOneByteString(const uint8_t* chars, int length) {
8565      is_one_byte_ = true;
8566      buffer8_ = chars;
8567      length_ = length;
8568    }
8569
8570    inline void VisitTwoByteString(const uint16_t* chars, int length) {
8571      is_one_byte_ = false;
8572      buffer16_ = chars;
8573      length_ = length;
8574    }
8575
8576    void Advance(int consumed) {
8577      DCHECK(consumed <= length_);
8578      // Still in buffer.
8579      if (length_ != consumed) {
8580        if (is_one_byte_) {
8581          buffer8_ += consumed;
8582        } else {
8583          buffer16_ += consumed;
8584        }
8585        length_ -= consumed;
8586        return;
8587      }
8588      // Advance state.
8589      int offset;
8590      String* next = op_->Next(&offset);
8591      DCHECK_EQ(0, offset);
8592      DCHECK(next != NULL);
8593      String::VisitFlat(this, next);
8594    }
8595
8596    ConsStringIteratorOp* const op_;
8597    bool is_one_byte_;
8598    int length_;
8599    union {
8600      const uint8_t* buffer8_;
8601      const uint16_t* buffer16_;
8602    };
8603
8604   private:
8605    DISALLOW_IMPLICIT_CONSTRUCTORS(State);
8606  };
8607
8608 public:
8609  inline StringComparator(ConsStringIteratorOp* op_1,
8610                          ConsStringIteratorOp* op_2)
8611    : state_1_(op_1),
8612      state_2_(op_2) {
8613  }
8614
8615  template<typename Chars1, typename Chars2>
8616  static inline bool Equals(State* state_1, State* state_2, int to_check) {
8617    const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
8618    const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
8619    return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
8620  }
8621
8622  bool Equals(String* string_1, String* string_2) {
8623    int length = string_1->length();
8624    state_1_.Init(string_1);
8625    state_2_.Init(string_2);
8626    while (true) {
8627      int to_check = Min(state_1_.length_, state_2_.length_);
8628      DCHECK(to_check > 0 && to_check <= length);
8629      bool is_equal;
8630      if (state_1_.is_one_byte_) {
8631        if (state_2_.is_one_byte_) {
8632          is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
8633        } else {
8634          is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
8635        }
8636      } else {
8637        if (state_2_.is_one_byte_) {
8638          is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
8639        } else {
8640          is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
8641        }
8642      }
8643      // Looping done.
8644      if (!is_equal) return false;
8645      length -= to_check;
8646      // Exit condition. Strings are equal.
8647      if (length == 0) return true;
8648      state_1_.Advance(to_check);
8649      state_2_.Advance(to_check);
8650    }
8651  }
8652
8653 private:
8654  State state_1_;
8655  State state_2_;
8656  DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator);
8657};
8658
8659
8660bool String::SlowEquals(String* other) {
8661  DisallowHeapAllocation no_gc;
8662  // Fast check: negative check with lengths.
8663  int len = length();
8664  if (len != other->length()) return false;
8665  if (len == 0) return true;
8666
8667  // Fast check: if hash code is computed for both strings
8668  // a fast negative check can be performed.
8669  if (HasHashCode() && other->HasHashCode()) {
8670#ifdef ENABLE_SLOW_DCHECKS
8671    if (FLAG_enable_slow_asserts) {
8672      if (Hash() != other->Hash()) {
8673        bool found_difference = false;
8674        for (int i = 0; i < len; i++) {
8675          if (Get(i) != other->Get(i)) {
8676            found_difference = true;
8677            break;
8678          }
8679        }
8680        DCHECK(found_difference);
8681      }
8682    }
8683#endif
8684    if (Hash() != other->Hash()) return false;
8685  }
8686
8687  // We know the strings are both non-empty. Compare the first chars
8688  // before we try to flatten the strings.
8689  if (this->Get(0) != other->Get(0)) return false;
8690
8691  if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
8692    const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
8693    const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
8694    return CompareRawStringContents(str1, str2, len);
8695  }
8696
8697  Isolate* isolate = GetIsolate();
8698  StringComparator comparator(isolate->objects_string_compare_iterator_a(),
8699                              isolate->objects_string_compare_iterator_b());
8700
8701  return comparator.Equals(this, other);
8702}
8703
8704
8705bool String::SlowEquals(Handle<String> one, Handle<String> two) {
8706  // Fast check: negative check with lengths.
8707  int one_length = one->length();
8708  if (one_length != two->length()) return false;
8709  if (one_length == 0) return true;
8710
8711  // Fast check: if hash code is computed for both strings
8712  // a fast negative check can be performed.
8713  if (one->HasHashCode() && two->HasHashCode()) {
8714#ifdef ENABLE_SLOW_DCHECKS
8715    if (FLAG_enable_slow_asserts) {
8716      if (one->Hash() != two->Hash()) {
8717        bool found_difference = false;
8718        for (int i = 0; i < one_length; i++) {
8719          if (one->Get(i) != two->Get(i)) {
8720            found_difference = true;
8721            break;
8722          }
8723        }
8724        DCHECK(found_difference);
8725      }
8726    }
8727#endif
8728    if (one->Hash() != two->Hash()) return false;
8729  }
8730
8731  // We know the strings are both non-empty. Compare the first chars
8732  // before we try to flatten the strings.
8733  if (one->Get(0) != two->Get(0)) return false;
8734
8735  one = String::Flatten(one);
8736  two = String::Flatten(two);
8737
8738  DisallowHeapAllocation no_gc;
8739  String::FlatContent flat1 = one->GetFlatContent();
8740  String::FlatContent flat2 = two->GetFlatContent();
8741
8742  if (flat1.IsOneByte() && flat2.IsOneByte()) {
8743      return CompareRawStringContents(flat1.ToOneByteVector().start(),
8744                                      flat2.ToOneByteVector().start(),
8745                                      one_length);
8746  } else {
8747    for (int i = 0; i < one_length; i++) {
8748      if (flat1.Get(i) != flat2.Get(i)) return false;
8749    }
8750    return true;
8751  }
8752}
8753
8754
8755bool String::MarkAsUndetectable() {
8756  if (StringShape(this).IsInternalized()) return false;
8757
8758  Map* map = this->map();
8759  Heap* heap = GetHeap();
8760  if (map == heap->string_map()) {
8761    this->set_map(heap->undetectable_string_map());
8762    return true;
8763  } else if (map == heap->one_byte_string_map()) {
8764    this->set_map(heap->undetectable_one_byte_string_map());
8765    return true;
8766  }
8767  // Rest cannot be marked as undetectable
8768  return false;
8769}
8770
8771
8772bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
8773  int slen = length();
8774  // Can't check exact length equality, but we can check bounds.
8775  int str_len = str.length();
8776  if (!allow_prefix_match &&
8777      (str_len < slen ||
8778          str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
8779    return false;
8780  }
8781  int i;
8782  unsigned remaining_in_str = static_cast<unsigned>(str_len);
8783  const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
8784  for (i = 0; i < slen && remaining_in_str > 0; i++) {
8785    unsigned cursor = 0;
8786    uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
8787    DCHECK(cursor > 0 && cursor <= remaining_in_str);
8788    if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
8789      if (i > slen - 1) return false;
8790      if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
8791      if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
8792    } else {
8793      if (Get(i) != r) return false;
8794    }
8795    utf8_data += cursor;
8796    remaining_in_str -= cursor;
8797  }
8798  return (allow_prefix_match || i == slen) && remaining_in_str == 0;
8799}
8800
8801
8802bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
8803  int slen = length();
8804  if (str.length() != slen) return false;
8805  DisallowHeapAllocation no_gc;
8806  FlatContent content = GetFlatContent();
8807  if (content.IsOneByte()) {
8808    return CompareChars(content.ToOneByteVector().start(),
8809                        str.start(), slen) == 0;
8810  }
8811  for (int i = 0; i < slen; i++) {
8812    if (Get(i) != static_cast<uint16_t>(str[i])) return false;
8813  }
8814  return true;
8815}
8816
8817
8818bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
8819  int slen = length();
8820  if (str.length() != slen) return false;
8821  DisallowHeapAllocation no_gc;
8822  FlatContent content = GetFlatContent();
8823  if (content.IsTwoByte()) {
8824    return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
8825  }
8826  for (int i = 0; i < slen; i++) {
8827    if (Get(i) != str[i]) return false;
8828  }
8829  return true;
8830}
8831
8832
8833uint32_t String::ComputeAndSetHash() {
8834  // Should only be called if hash code has not yet been computed.
8835  DCHECK(!HasHashCode());
8836
8837  // Store the hash code in the object.
8838  uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
8839  set_hash_field(field);
8840
8841  // Check the hash code is there.
8842  DCHECK(HasHashCode());
8843  uint32_t result = field >> kHashShift;
8844  DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
8845  return result;
8846}
8847
8848
8849bool String::ComputeArrayIndex(uint32_t* index) {
8850  int length = this->length();
8851  if (length == 0 || length > kMaxArrayIndexSize) return false;
8852  ConsStringIteratorOp op;
8853  StringCharacterStream stream(this, &op);
8854  return StringToArrayIndex(&stream, index);
8855}
8856
8857
8858bool String::SlowAsArrayIndex(uint32_t* index) {
8859  if (length() <= kMaxCachedArrayIndexLength) {
8860    Hash();  // force computation of hash code
8861    uint32_t field = hash_field();
8862    if ((field & kIsNotArrayIndexMask) != 0) return false;
8863    // Isolate the array index form the full hash field.
8864    *index = ArrayIndexValueBits::decode(field);
8865    return true;
8866  } else {
8867    return ComputeArrayIndex(index);
8868  }
8869}
8870
8871
8872Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
8873  int new_size, old_size;
8874  int old_length = string->length();
8875  if (old_length <= new_length) return string;
8876
8877  if (string->IsSeqOneByteString()) {
8878    old_size = SeqOneByteString::SizeFor(old_length);
8879    new_size = SeqOneByteString::SizeFor(new_length);
8880  } else {
8881    DCHECK(string->IsSeqTwoByteString());
8882    old_size = SeqTwoByteString::SizeFor(old_length);
8883    new_size = SeqTwoByteString::SizeFor(new_length);
8884  }
8885
8886  int delta = old_size - new_size;
8887
8888  Address start_of_string = string->address();
8889  DCHECK_OBJECT_ALIGNED(start_of_string);
8890  DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
8891
8892  Heap* heap = string->GetHeap();
8893  NewSpace* newspace = heap->new_space();
8894  if (newspace->Contains(start_of_string) &&
8895      newspace->top() == start_of_string + old_size) {
8896    // Last allocated object in new space.  Simply lower allocation top.
8897    newspace->set_top(start_of_string + new_size);
8898  } else {
8899    // Sizes are pointer size aligned, so that we can use filler objects
8900    // that are a multiple of pointer size.
8901    heap->CreateFillerObjectAt(start_of_string + new_size, delta);
8902  }
8903  heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR);
8904
8905  // We are storing the new length using release store after creating a filler
8906  // for the left-over space to avoid races with the sweeper thread.
8907  string->synchronized_set_length(new_length);
8908
8909  if (new_length == 0) return heap->isolate()->factory()->empty_string();
8910  return string;
8911}
8912
8913
8914uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
8915  // For array indexes mix the length into the hash as an array index could
8916  // be zero.
8917  DCHECK(length > 0);
8918  DCHECK(length <= String::kMaxArrayIndexSize);
8919  DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
8920         (1 << String::kArrayIndexValueBits));
8921
8922  value <<= String::ArrayIndexValueBits::kShift;
8923  value |= length << String::ArrayIndexLengthBits::kShift;
8924
8925  DCHECK((value & String::kIsNotArrayIndexMask) == 0);
8926  DCHECK((length > String::kMaxCachedArrayIndexLength) ||
8927         (value & String::kContainsCachedArrayIndexMask) == 0);
8928  return value;
8929}
8930
8931
8932uint32_t StringHasher::GetHashField() {
8933  if (length_ <= String::kMaxHashCalcLength) {
8934    if (is_array_index_) {
8935      return MakeArrayIndexHash(array_index_, length_);
8936    }
8937    return (GetHashCore(raw_running_hash_) << String::kHashShift) |
8938           String::kIsNotArrayIndexMask;
8939  } else {
8940    return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
8941  }
8942}
8943
8944
8945uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
8946                                       uint32_t seed,
8947                                       int* utf16_length_out) {
8948  int vector_length = chars.length();
8949  // Handle some edge cases
8950  if (vector_length <= 1) {
8951    DCHECK(vector_length == 0 ||
8952           static_cast<uint8_t>(chars.start()[0]) <=
8953               unibrow::Utf8::kMaxOneByteChar);
8954    *utf16_length_out = vector_length;
8955    return HashSequentialString(chars.start(), vector_length, seed);
8956  }
8957  // Start with a fake length which won't affect computation.
8958  // It will be updated later.
8959  StringHasher hasher(String::kMaxArrayIndexSize, seed);
8960  unsigned remaining = static_cast<unsigned>(vector_length);
8961  const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
8962  int utf16_length = 0;
8963  bool is_index = true;
8964  DCHECK(hasher.is_array_index_);
8965  while (remaining > 0) {
8966    unsigned consumed = 0;
8967    uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
8968    DCHECK(consumed > 0 && consumed <= remaining);
8969    stream += consumed;
8970    remaining -= consumed;
8971    bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
8972    utf16_length += is_two_characters ? 2 : 1;
8973    // No need to keep hashing. But we do need to calculate utf16_length.
8974    if (utf16_length > String::kMaxHashCalcLength) continue;
8975    if (is_two_characters) {
8976      uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
8977      uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
8978      hasher.AddCharacter(c1);
8979      hasher.AddCharacter(c2);
8980      if (is_index) is_index = hasher.UpdateIndex(c1);
8981      if (is_index) is_index = hasher.UpdateIndex(c2);
8982    } else {
8983      hasher.AddCharacter(c);
8984      if (is_index) is_index = hasher.UpdateIndex(c);
8985    }
8986  }
8987  *utf16_length_out = static_cast<int>(utf16_length);
8988  // Must set length here so that hash computation is correct.
8989  hasher.length_ = utf16_length;
8990  return hasher.GetHashField();
8991}
8992
8993
8994void String::PrintOn(FILE* file) {
8995  int length = this->length();
8996  for (int i = 0; i < length; i++) {
8997    PrintF(file, "%c", Get(i));
8998  }
8999}
9000
9001
9002int Map::Hash() {
9003  // For performance reasons we only hash the 3 most variable fields of a map:
9004  // constructor, prototype and bit_field2.
9005
9006  // Shift away the tag.
9007  int hash = (static_cast<uint32_t>(
9008        reinterpret_cast<uintptr_t>(constructor())) >> 2);
9009
9010  // XOR-ing the prototype and constructor directly yields too many zero bits
9011  // when the two pointers are close (which is fairly common).
9012  // To avoid this we shift the prototype 4 bits relatively to the constructor.
9013  hash ^= (static_cast<uint32_t>(
9014        reinterpret_cast<uintptr_t>(prototype())) << 2);
9015
9016  return hash ^ (hash >> 16) ^ bit_field2();
9017}
9018
9019
9020static bool CheckEquivalent(Map* first, Map* second) {
9021  return
9022    first->constructor() == second->constructor() &&
9023    first->prototype() == second->prototype() &&
9024    first->instance_type() == second->instance_type() &&
9025    first->bit_field() == second->bit_field() &&
9026    first->bit_field2() == second->bit_field2() &&
9027    first->is_frozen() == second->is_frozen() &&
9028    first->has_instance_call_handler() == second->has_instance_call_handler();
9029}
9030
9031
9032bool Map::EquivalentToForTransition(Map* other) {
9033  return CheckEquivalent(this, other);
9034}
9035
9036
9037bool Map::EquivalentToForNormalization(Map* other,
9038                                       PropertyNormalizationMode mode) {
9039  int properties = mode == CLEAR_INOBJECT_PROPERTIES
9040      ? 0 : other->inobject_properties();
9041  return CheckEquivalent(this, other) && inobject_properties() == properties;
9042}
9043
9044
9045void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) {
9046  // Unfortunately the serializer relies on pointers within an object being
9047  // visited in-order, so we have to iterate both the code and heap pointers in
9048  // the small section before doing so in the extended section.
9049  for (int s = 0; s <= final_section(); ++s) {
9050    LayoutSection section = static_cast<LayoutSection>(s);
9051    ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR,
9052                                          section);
9053    while (!code_iter.is_finished()) {
9054      v->VisitCodeEntry(reinterpret_cast<Address>(
9055          RawFieldOfElementAt(code_iter.next_index())));
9056    }
9057
9058    ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR,
9059                                          section);
9060    while (!heap_iter.is_finished()) {
9061      v->VisitPointer(RawFieldOfElementAt(heap_iter.next_index()));
9062    }
9063  }
9064}
9065
9066
9067void ConstantPoolArray::ClearPtrEntries(Isolate* isolate) {
9068  Type type[] = { CODE_PTR, HEAP_PTR };
9069  Address default_value[] = {
9070        isolate->builtins()->builtin(Builtins::kIllegal)->entry(),
9071        reinterpret_cast<Address>(isolate->heap()->undefined_value()) };
9072
9073  for (int i = 0; i < 2; ++i) {
9074    for (int s = 0; s <= final_section(); ++s) {
9075      LayoutSection section = static_cast<LayoutSection>(s);
9076      if (number_of_entries(type[i], section) > 0) {
9077        int offset = OffsetOfElementAt(first_index(type[i], section));
9078        MemsetPointer(
9079          reinterpret_cast<Address*>(HeapObject::RawField(this, offset)),
9080          default_value[i],
9081          number_of_entries(type[i], section));
9082      }
9083    }
9084  }
9085}
9086
9087
9088void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
9089  // Iterate over all fields in the body but take care in dealing with
9090  // the code entry.
9091  IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
9092  v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9093  IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9094}
9095
9096
9097void JSFunction::MarkForOptimization() {
9098  DCHECK(!IsOptimized());
9099  DCHECK(shared()->allows_lazy_compilation() ||
9100         code()->optimizable());
9101  DCHECK(!shared()->is_generator());
9102  set_code_no_write_barrier(
9103      GetIsolate()->builtins()->builtin(Builtins::kCompileOptimized));
9104  // No write barrier required, since the builtin is part of the root set.
9105}
9106
9107
9108void JSFunction::MarkForConcurrentOptimization() {
9109  DCHECK(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
9110  DCHECK(!IsOptimized());
9111  DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9112  DCHECK(!shared()->is_generator());
9113  DCHECK(GetIsolate()->concurrent_recompilation_enabled());
9114  if (FLAG_trace_concurrent_recompilation) {
9115    PrintF("  ** Marking ");
9116    ShortPrint();
9117    PrintF(" for concurrent recompilation.\n");
9118  }
9119  set_code_no_write_barrier(
9120      GetIsolate()->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9121  // No write barrier required, since the builtin is part of the root set.
9122}
9123
9124
9125void JSFunction::MarkInOptimizationQueue() {
9126  // We can only arrive here via the concurrent-recompilation builtin.  If
9127  // break points were set, the code would point to the lazy-compile builtin.
9128  DCHECK(!GetIsolate()->DebuggerHasBreakPoints());
9129  DCHECK(IsMarkedForConcurrentOptimization() && !IsOptimized());
9130  DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9131  DCHECK(GetIsolate()->concurrent_recompilation_enabled());
9132  if (FLAG_trace_concurrent_recompilation) {
9133    PrintF("  ** Queueing ");
9134    ShortPrint();
9135    PrintF(" for concurrent recompilation.\n");
9136  }
9137  set_code_no_write_barrier(
9138      GetIsolate()->builtins()->builtin(Builtins::kInOptimizationQueue));
9139  // No write barrier required, since the builtin is part of the root set.
9140}
9141
9142
9143Handle<JSFunction> JSFunction::CloneClosure(Handle<JSFunction> function) {
9144  Isolate* isolate = function->GetIsolate();
9145  Handle<Map> map(function->map());
9146  Handle<SharedFunctionInfo> shared(function->shared());
9147  Handle<Context> context(function->context());
9148  Handle<JSFunction> clone =
9149      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
9150
9151  if (shared->bound()) {
9152    clone->set_function_bindings(function->function_bindings());
9153  }
9154
9155  // In typical case, __proto__ of ``function`` is the default Function
9156  // prototype, which means that SetPrototype below is a no-op.
9157  // In rare cases when that is not true, we mutate the clone's __proto__.
9158  Handle<Object> original_prototype(map->prototype(), isolate);
9159  if (*original_prototype != clone->map()->prototype()) {
9160    JSObject::SetPrototype(clone, original_prototype, false).Assert();
9161  }
9162
9163  return clone;
9164}
9165
9166
9167void SharedFunctionInfo::AddToOptimizedCodeMap(
9168    Handle<SharedFunctionInfo> shared,
9169    Handle<Context> native_context,
9170    Handle<Code> code,
9171    Handle<FixedArray> literals,
9172    BailoutId osr_ast_id) {
9173  Isolate* isolate = shared->GetIsolate();
9174  DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9175  DCHECK(native_context->IsNativeContext());
9176  STATIC_ASSERT(kEntryLength == 4);
9177  Handle<FixedArray> new_code_map;
9178  Handle<Object> value(shared->optimized_code_map(), isolate);
9179  int old_length;
9180  if (value->IsSmi()) {
9181    // No optimized code map.
9182    DCHECK_EQ(0, Smi::cast(*value)->value());
9183    // Create 3 entries per context {context, code, literals}.
9184    new_code_map = isolate->factory()->NewFixedArray(kInitialLength);
9185    old_length = kEntriesStart;
9186  } else {
9187    // Copy old map and append one new entry.
9188    Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value);
9189    DCHECK_EQ(-1, shared->SearchOptimizedCodeMap(*native_context, osr_ast_id));
9190    old_length = old_code_map->length();
9191    new_code_map = FixedArray::CopySize(
9192        old_code_map, old_length + kEntryLength);
9193    // Zap the old map for the sake of the heap verifier.
9194    if (Heap::ShouldZapGarbage()) {
9195      Object** data = old_code_map->data_start();
9196      MemsetPointer(data, isolate->heap()->the_hole_value(), old_length);
9197    }
9198  }
9199  new_code_map->set(old_length + kContextOffset, *native_context);
9200  new_code_map->set(old_length + kCachedCodeOffset, *code);
9201  new_code_map->set(old_length + kLiteralsOffset, *literals);
9202  new_code_map->set(old_length + kOsrAstIdOffset,
9203                    Smi::FromInt(osr_ast_id.ToInt()));
9204
9205#ifdef DEBUG
9206  for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9207    DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext());
9208    DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9209    DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9210           Code::OPTIMIZED_FUNCTION);
9211    DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9212    DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9213  }
9214#endif
9215  shared->set_optimized_code_map(*new_code_map);
9216}
9217
9218
9219FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) {
9220  DCHECK(index > kEntriesStart);
9221  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9222  if (!bound()) {
9223    FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
9224    DCHECK_NE(NULL, cached_literals);
9225    return cached_literals;
9226  }
9227  return NULL;
9228}
9229
9230
9231Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) {
9232  DCHECK(index > kEntriesStart);
9233  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9234  Code* code = Code::cast(code_map->get(index));
9235  DCHECK_NE(NULL, code);
9236  return code;
9237}
9238
9239
9240void SharedFunctionInfo::ClearOptimizedCodeMap() {
9241  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9242
9243  // If the next map link slot is already used then the function was
9244  // enqueued with code flushing and we remove it now.
9245  if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9246    CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
9247    flusher->EvictOptimizedCodeMap(this);
9248  }
9249
9250  DCHECK(code_map->get(kNextMapIndex)->IsUndefined());
9251  set_optimized_code_map(Smi::FromInt(0));
9252}
9253
9254
9255void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
9256                                                   const char* reason) {
9257  DisallowHeapAllocation no_gc;
9258  if (optimized_code_map()->IsSmi()) return;
9259
9260  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9261  int dst = kEntriesStart;
9262  int length = code_map->length();
9263  for (int src = kEntriesStart; src < length; src += kEntryLength) {
9264    DCHECK(code_map->get(src)->IsNativeContext());
9265    if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9266      // Evict the src entry by not copying it to the dst entry.
9267      if (FLAG_trace_opt) {
9268        PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9269        ShortPrint();
9270        BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9271        if (osr.IsNone()) {
9272          PrintF("]\n");
9273        } else {
9274          PrintF(" (osr ast id %d)]\n", osr.ToInt());
9275        }
9276      }
9277    } else {
9278      // Keep the src entry by copying it to the dst entry.
9279      if (dst != src) {
9280        code_map->set(dst + kContextOffset,
9281                      code_map->get(src + kContextOffset));
9282        code_map->set(dst + kCachedCodeOffset,
9283                      code_map->get(src + kCachedCodeOffset));
9284        code_map->set(dst + kLiteralsOffset,
9285                      code_map->get(src + kLiteralsOffset));
9286        code_map->set(dst + kOsrAstIdOffset,
9287                      code_map->get(src + kOsrAstIdOffset));
9288      }
9289      dst += kEntryLength;
9290    }
9291  }
9292  if (dst != length) {
9293    // Always trim even when array is cleared because of heap verifier.
9294    GetHeap()->RightTrimFixedArray<Heap::FROM_MUTATOR>(code_map, length - dst);
9295    if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap();
9296  }
9297}
9298
9299
9300void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
9301  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9302  DCHECK(shrink_by % kEntryLength == 0);
9303  DCHECK(shrink_by <= code_map->length() - kEntriesStart);
9304  // Always trim even when array is cleared because of heap verifier.
9305  GetHeap()->RightTrimFixedArray<Heap::FROM_GC>(code_map, shrink_by);
9306  if (code_map->length() == kEntriesStart) {
9307    ClearOptimizedCodeMap();
9308  }
9309}
9310
9311
9312void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
9313                                   PrototypeOptimizationMode mode) {
9314  if (object->IsGlobalObject()) return;
9315  if (object->IsJSGlobalProxy()) return;
9316  if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) {
9317    // First normalize to ensure all JSFunctions are CONSTANT.
9318    JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0);
9319  }
9320  if (!object->HasFastProperties()) {
9321    JSObject::MigrateSlowToFast(object, 0);
9322  }
9323  if (mode == FAST_PROTOTYPE && object->HasFastProperties() &&
9324      !object->map()->is_prototype_map()) {
9325    Handle<Map> new_map = Map::Copy(handle(object->map()));
9326    JSObject::MigrateToMap(object, new_map);
9327    object->map()->set_is_prototype_map(true);
9328  }
9329}
9330
9331
9332void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9333  if (!object->map()->is_prototype_map()) return;
9334  OptimizeAsPrototype(object, FAST_PROTOTYPE);
9335}
9336
9337
9338Handle<Object> CacheInitialJSArrayMaps(
9339    Handle<Context> native_context, Handle<Map> initial_map) {
9340  // Replace all of the cached initial array maps in the native context with
9341  // the appropriate transitioned elements kind maps.
9342  Factory* factory = native_context->GetIsolate()->factory();
9343  Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9344      kElementsKindCount, TENURED);
9345
9346  Handle<Map> current_map = initial_map;
9347  ElementsKind kind = current_map->elements_kind();
9348  DCHECK(kind == GetInitialFastElementsKind());
9349  maps->set(kind, *current_map);
9350  for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
9351       i < kFastElementsKindCount; ++i) {
9352    Handle<Map> new_map;
9353    ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
9354    if (current_map->HasElementsTransition()) {
9355      new_map = handle(current_map->elements_transition_map());
9356      DCHECK(new_map->elements_kind() == next_kind);
9357    } else {
9358      new_map = Map::CopyAsElementsKind(
9359          current_map, next_kind, INSERT_TRANSITION);
9360    }
9361    maps->set(next_kind, *new_map);
9362    current_map = new_map;
9363  }
9364  native_context->set_js_array_maps(*maps);
9365  return initial_map;
9366}
9367
9368
9369void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
9370                                      Handle<Object> value) {
9371  Isolate* isolate = function->GetIsolate();
9372
9373  DCHECK(value->IsJSReceiver());
9374
9375  // Now some logic for the maps of the objects that are created by using this
9376  // function as a constructor.
9377  if (function->has_initial_map()) {
9378    // If the function has allocated the initial map replace it with a
9379    // copy containing the new prototype.  Also complete any in-object
9380    // slack tracking that is in progress at this point because it is
9381    // still tracking the old copy.
9382    if (function->IsInobjectSlackTrackingInProgress()) {
9383      function->CompleteInobjectSlackTracking();
9384    }
9385
9386    Handle<Map> initial_map(function->initial_map(), isolate);
9387
9388    if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
9389        initial_map->instance_type() == JS_OBJECT_TYPE) {
9390      // Put the value in the initial map field until an initial map is needed.
9391      // At that point, a new initial map is created and the prototype is put
9392      // into the initial map where it belongs.
9393      function->set_prototype_or_initial_map(*value);
9394    } else {
9395      Handle<Map> new_map = Map::Copy(initial_map);
9396      JSFunction::SetInitialMap(function, new_map, value);
9397
9398      // If the function is used as the global Array function, cache the
9399      // initial map (and transitioned versions) in the native context.
9400      Context* native_context = function->context()->native_context();
9401      Object* array_function =
9402          native_context->get(Context::ARRAY_FUNCTION_INDEX);
9403      if (array_function->IsJSFunction() &&
9404          *function == JSFunction::cast(array_function)) {
9405        CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
9406      }
9407    }
9408
9409    // Deoptimize all code that embeds the previous initial map.
9410    initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
9411        isolate, DependentCode::kInitialMapChangedGroup);
9412  } else {
9413    // Put the value in the initial map field until an initial map is
9414    // needed.  At that point, a new initial map is created and the
9415    // prototype is put into the initial map where it belongs.
9416    function->set_prototype_or_initial_map(*value);
9417  }
9418  isolate->heap()->ClearInstanceofCache();
9419}
9420
9421
9422void JSFunction::SetPrototype(Handle<JSFunction> function,
9423                              Handle<Object> value) {
9424  DCHECK(function->should_have_prototype());
9425  Handle<Object> construct_prototype = value;
9426
9427  // If the value is not a JSReceiver, store the value in the map's
9428  // constructor field so it can be accessed.  Also, set the prototype
9429  // used for constructing objects to the original object prototype.
9430  // See ECMA-262 13.2.2.
9431  if (!value->IsJSReceiver()) {
9432    // Copy the map so this does not affect unrelated functions.
9433    // Remove map transitions because they point to maps with a
9434    // different prototype.
9435    Handle<Map> new_map = Map::Copy(handle(function->map()));
9436
9437    JSObject::MigrateToMap(function, new_map);
9438    new_map->set_constructor(*value);
9439    new_map->set_non_instance_prototype(true);
9440    Isolate* isolate = new_map->GetIsolate();
9441    construct_prototype = handle(
9442        isolate->context()->native_context()->initial_object_prototype(),
9443        isolate);
9444  } else {
9445    function->map()->set_non_instance_prototype(false);
9446  }
9447
9448  return SetInstancePrototype(function, construct_prototype);
9449}
9450
9451
9452bool JSFunction::RemovePrototype() {
9453  Context* native_context = context()->native_context();
9454  Map* no_prototype_map = shared()->strict_mode() == SLOPPY
9455      ? native_context->sloppy_function_without_prototype_map()
9456      : native_context->strict_function_without_prototype_map();
9457
9458  if (map() == no_prototype_map) return true;
9459
9460#ifdef DEBUG
9461  if (map() != (shared()->strict_mode() == SLOPPY
9462                   ? native_context->sloppy_function_map()
9463                   : native_context->strict_function_map())) {
9464    return false;
9465  }
9466#endif
9467
9468  set_map(no_prototype_map);
9469  set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9470  return true;
9471}
9472
9473
9474void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
9475                               Handle<Object> prototype) {
9476  if (prototype->IsJSObject()) {
9477    Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype);
9478    JSObject::OptimizeAsPrototype(js_proto, FAST_PROTOTYPE);
9479  }
9480  map->set_prototype(*prototype);
9481  function->set_prototype_or_initial_map(*map);
9482  map->set_constructor(*function);
9483}
9484
9485
9486void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
9487  if (function->has_initial_map()) return;
9488  Isolate* isolate = function->GetIsolate();
9489
9490  // First create a new map with the size and number of in-object properties
9491  // suggested by the function.
9492  InstanceType instance_type;
9493  int instance_size;
9494  int in_object_properties;
9495  if (function->shared()->is_generator()) {
9496    instance_type = JS_GENERATOR_OBJECT_TYPE;
9497    instance_size = JSGeneratorObject::kSize;
9498    in_object_properties = 0;
9499  } else {
9500    instance_type = JS_OBJECT_TYPE;
9501    instance_size = function->shared()->CalculateInstanceSize();
9502    in_object_properties = function->shared()->CalculateInObjectProperties();
9503  }
9504  Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
9505
9506  // Fetch or allocate prototype.
9507  Handle<Object> prototype;
9508  if (function->has_instance_prototype()) {
9509    prototype = handle(function->instance_prototype(), isolate);
9510  } else {
9511    prototype = isolate->factory()->NewFunctionPrototype(function);
9512  }
9513  map->set_inobject_properties(in_object_properties);
9514  map->set_unused_property_fields(in_object_properties);
9515  DCHECK(map->has_fast_object_elements());
9516
9517  // Finally link initial map and constructor function.
9518  JSFunction::SetInitialMap(function, map, Handle<JSReceiver>::cast(prototype));
9519
9520  if (!function->shared()->is_generator()) {
9521    function->StartInobjectSlackTracking();
9522  }
9523}
9524
9525
9526void JSFunction::SetInstanceClassName(String* name) {
9527  shared()->set_instance_class_name(name);
9528}
9529
9530
9531void JSFunction::PrintName(FILE* out) {
9532  SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
9533  PrintF(out, "%s", name.get());
9534}
9535
9536
9537Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) {
9538  return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex));
9539}
9540
9541
9542// The filter is a pattern that matches function names in this way:
9543//   "*"      all; the default
9544//   "-"      all but the top-level function
9545//   "-name"  all but the function "name"
9546//   ""       only the top-level function
9547//   "name"   only the function "name"
9548//   "name*"  only functions starting with "name"
9549//   "~"      none; the tilde is not an identifier
9550bool JSFunction::PassesFilter(const char* raw_filter) {
9551  if (*raw_filter == '*') return true;
9552  String* name = shared()->DebugName();
9553  Vector<const char> filter = CStrVector(raw_filter);
9554  if (filter.length() == 0) return name->length() == 0;
9555  if (filter[0] == '-') {
9556    // Negative filter.
9557    if (filter.length() == 1) {
9558      return (name->length() != 0);
9559    } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
9560      return false;
9561    }
9562    if (filter[filter.length() - 1] == '*' &&
9563        name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
9564      return false;
9565    }
9566    return true;
9567
9568  } else if (name->IsUtf8EqualTo(filter)) {
9569    return true;
9570  }
9571  if (filter[filter.length() - 1] == '*' &&
9572      name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
9573    return true;
9574  }
9575  return false;
9576}
9577
9578
9579void Oddball::Initialize(Isolate* isolate,
9580                         Handle<Oddball> oddball,
9581                         const char* to_string,
9582                         Handle<Object> to_number,
9583                         byte kind) {
9584  Handle<String> internalized_to_string =
9585      isolate->factory()->InternalizeUtf8String(to_string);
9586  oddball->set_to_string(*internalized_to_string);
9587  oddball->set_to_number(*to_number);
9588  oddball->set_kind(kind);
9589}
9590
9591
9592void Script::InitLineEnds(Handle<Script> script) {
9593  if (!script->line_ends()->IsUndefined()) return;
9594
9595  Isolate* isolate = script->GetIsolate();
9596
9597  if (!script->source()->IsString()) {
9598    DCHECK(script->source()->IsUndefined());
9599    Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
9600    script->set_line_ends(*empty);
9601    DCHECK(script->line_ends()->IsFixedArray());
9602    return;
9603  }
9604
9605  Handle<String> src(String::cast(script->source()), isolate);
9606
9607  Handle<FixedArray> array = String::CalculateLineEnds(src, true);
9608
9609  if (*array != isolate->heap()->empty_fixed_array()) {
9610    array->set_map(isolate->heap()->fixed_cow_array_map());
9611  }
9612
9613  script->set_line_ends(*array);
9614  DCHECK(script->line_ends()->IsFixedArray());
9615}
9616
9617
9618int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
9619  int line_number = GetLineNumber(script, code_pos);
9620  if (line_number == -1) return -1;
9621
9622  DisallowHeapAllocation no_allocation;
9623  FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
9624  line_number = line_number - script->line_offset()->value();
9625  if (line_number == 0) return code_pos + script->column_offset()->value();
9626  int prev_line_end_pos =
9627      Smi::cast(line_ends_array->get(line_number - 1))->value();
9628  return code_pos - (prev_line_end_pos + 1);
9629}
9630
9631
9632int Script::GetLineNumberWithArray(int code_pos) {
9633  DisallowHeapAllocation no_allocation;
9634  DCHECK(line_ends()->IsFixedArray());
9635  FixedArray* line_ends_array = FixedArray::cast(line_ends());
9636  int line_ends_len = line_ends_array->length();
9637  if (line_ends_len == 0) return -1;
9638
9639  if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
9640    return line_offset()->value();
9641  }
9642
9643  int left = 0;
9644  int right = line_ends_len;
9645  while (int half = (right - left) / 2) {
9646    if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
9647      right -= half;
9648    } else {
9649      left += half;
9650    }
9651  }
9652  return right + line_offset()->value();
9653}
9654
9655
9656int Script::GetLineNumber(Handle<Script> script, int code_pos) {
9657  InitLineEnds(script);
9658  return script->GetLineNumberWithArray(code_pos);
9659}
9660
9661
9662int Script::GetLineNumber(int code_pos) {
9663  DisallowHeapAllocation no_allocation;
9664  if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
9665
9666  // Slow mode: we do not have line_ends. We have to iterate through source.
9667  if (!source()->IsString()) return -1;
9668
9669  String* source_string = String::cast(source());
9670  int line = 0;
9671  int len = source_string->length();
9672  for (int pos = 0; pos < len; pos++) {
9673    if (pos == code_pos) break;
9674    if (source_string->Get(pos) == '\n') line++;
9675  }
9676  return line;
9677}
9678
9679
9680Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
9681  Isolate* isolate = script->GetIsolate();
9682  Handle<String> name_or_source_url_key =
9683      isolate->factory()->InternalizeOneByteString(
9684          STATIC_CHAR_VECTOR("nameOrSourceURL"));
9685  Handle<JSObject> script_wrapper = Script::GetWrapper(script);
9686  Handle<Object> property = Object::GetProperty(
9687      script_wrapper, name_or_source_url_key).ToHandleChecked();
9688  DCHECK(property->IsJSFunction());
9689  Handle<JSFunction> method = Handle<JSFunction>::cast(property);
9690  Handle<Object> result;
9691  // Do not check against pending exception, since this function may be called
9692  // when an exception has already been pending.
9693  if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
9694    return isolate->factory()->undefined_value();
9695  }
9696  return result;
9697}
9698
9699
9700// Wrappers for scripts are kept alive and cached in weak global
9701// handles referred from foreign objects held by the scripts as long as
9702// they are used. When they are not used anymore, the garbage
9703// collector will call the weak callback on the global handle
9704// associated with the wrapper and get rid of both the wrapper and the
9705// handle.
9706static void ClearWrapperCacheWeakCallback(
9707    const v8::WeakCallbackData<v8::Value, void>& data) {
9708  Object** location = reinterpret_cast<Object**>(data.GetParameter());
9709  JSValue* wrapper = JSValue::cast(*location);
9710  Script::cast(wrapper->value())->ClearWrapperCache();
9711}
9712
9713
9714void Script::ClearWrapperCache() {
9715  Foreign* foreign = wrapper();
9716  Object** location = reinterpret_cast<Object**>(foreign->foreign_address());
9717  DCHECK_EQ(foreign->foreign_address(), reinterpret_cast<Address>(location));
9718  foreign->set_foreign_address(0);
9719  GlobalHandles::Destroy(location);
9720  GetIsolate()->counters()->script_wrappers()->Decrement();
9721}
9722
9723
9724Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
9725  if (script->wrapper()->foreign_address() != NULL) {
9726    // Return a handle for the existing script wrapper from the cache.
9727    return Handle<JSValue>(
9728        *reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
9729  }
9730  Isolate* isolate = script->GetIsolate();
9731  // Construct a new script wrapper.
9732  isolate->counters()->script_wrappers()->Increment();
9733  Handle<JSFunction> constructor = isolate->script_function();
9734  Handle<JSValue> result =
9735      Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
9736
9737  result->set_value(*script);
9738
9739  // Create a new weak global handle and use it to cache the wrapper
9740  // for future use. The cache will automatically be cleared by the
9741  // garbage collector when it is not used anymore.
9742  Handle<Object> handle = isolate->global_handles()->Create(*result);
9743  GlobalHandles::MakeWeak(handle.location(),
9744                          reinterpret_cast<void*>(handle.location()),
9745                          &ClearWrapperCacheWeakCallback);
9746  script->wrapper()->set_foreign_address(
9747      reinterpret_cast<Address>(handle.location()));
9748  return result;
9749}
9750
9751
9752String* SharedFunctionInfo::DebugName() {
9753  Object* n = name();
9754  if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
9755  return String::cast(n);
9756}
9757
9758
9759bool SharedFunctionInfo::HasSourceCode() const {
9760  return !script()->IsUndefined() &&
9761         !reinterpret_cast<Script*>(script())->source()->IsUndefined();
9762}
9763
9764
9765Handle<Object> SharedFunctionInfo::GetSourceCode() {
9766  if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
9767  Handle<String> source(String::cast(Script::cast(script())->source()));
9768  return GetIsolate()->factory()->NewSubString(
9769      source, start_position(), end_position());
9770}
9771
9772
9773bool SharedFunctionInfo::IsInlineable() {
9774  // Check that the function has a script associated with it.
9775  if (!script()->IsScript()) return false;
9776  if (optimization_disabled()) return false;
9777  // If we never ran this (unlikely) then lets try to optimize it.
9778  if (code()->kind() != Code::FUNCTION) return true;
9779  return code()->optimizable();
9780}
9781
9782
9783int SharedFunctionInfo::SourceSize() {
9784  return end_position() - start_position();
9785}
9786
9787
9788int SharedFunctionInfo::CalculateInstanceSize() {
9789  int instance_size =
9790      JSObject::kHeaderSize +
9791      expected_nof_properties() * kPointerSize;
9792  if (instance_size > JSObject::kMaxInstanceSize) {
9793    instance_size = JSObject::kMaxInstanceSize;
9794  }
9795  return instance_size;
9796}
9797
9798
9799int SharedFunctionInfo::CalculateInObjectProperties() {
9800  return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
9801}
9802
9803
9804// Output the source code without any allocation in the heap.
9805OStream& operator<<(OStream& os, const SourceCodeOf& v) {
9806  const SharedFunctionInfo* s = v.value;
9807  // For some native functions there is no source.
9808  if (!s->HasSourceCode()) return os << "<No Source>";
9809
9810  // Get the source for the script which this function came from.
9811  // Don't use String::cast because we don't want more assertion errors while
9812  // we are already creating a stack dump.
9813  String* script_source =
9814      reinterpret_cast<String*>(Script::cast(s->script())->source());
9815
9816  if (!script_source->LooksValid()) return os << "<Invalid Source>";
9817
9818  if (!s->is_toplevel()) {
9819    os << "function ";
9820    Object* name = s->name();
9821    if (name->IsString() && String::cast(name)->length() > 0) {
9822      String::cast(name)->PrintUC16(os);
9823    }
9824  }
9825
9826  int len = s->end_position() - s->start_position();
9827  if (len <= v.max_length || v.max_length < 0) {
9828    script_source->PrintUC16(os, s->start_position(), s->end_position());
9829    return os;
9830  } else {
9831    script_source->PrintUC16(os, s->start_position(),
9832                             s->start_position() + v.max_length);
9833    return os << "...\n";
9834  }
9835}
9836
9837
9838static bool IsCodeEquivalent(Code* code, Code* recompiled) {
9839  if (code->instruction_size() != recompiled->instruction_size()) return false;
9840  ByteArray* code_relocation = code->relocation_info();
9841  ByteArray* recompiled_relocation = recompiled->relocation_info();
9842  int length = code_relocation->length();
9843  if (length != recompiled_relocation->length()) return false;
9844  int compare = memcmp(code_relocation->GetDataStartAddress(),
9845                       recompiled_relocation->GetDataStartAddress(),
9846                       length);
9847  return compare == 0;
9848}
9849
9850
9851void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
9852  DCHECK(!has_deoptimization_support());
9853  DisallowHeapAllocation no_allocation;
9854  Code* code = this->code();
9855  if (IsCodeEquivalent(code, recompiled)) {
9856    // Copy the deoptimization data from the recompiled code.
9857    code->set_deoptimization_data(recompiled->deoptimization_data());
9858    code->set_has_deoptimization_support(true);
9859  } else {
9860    // TODO(3025757): In case the recompiled isn't equivalent to the
9861    // old code, we have to replace it. We should try to avoid this
9862    // altogether because it flushes valuable type feedback by
9863    // effectively resetting all IC state.
9864    ReplaceCode(recompiled);
9865  }
9866  DCHECK(has_deoptimization_support());
9867}
9868
9869
9870void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
9871  // Disable optimization for the shared function info and mark the
9872  // code as non-optimizable. The marker on the shared function info
9873  // is there because we flush non-optimized code thereby loosing the
9874  // non-optimizable information for the code. When the code is
9875  // regenerated and set on the shared function info it is marked as
9876  // non-optimizable if optimization is disabled for the shared
9877  // function info.
9878  set_optimization_disabled(true);
9879  set_bailout_reason(reason);
9880  // Code should be the lazy compilation stub or else unoptimized.  If the
9881  // latter, disable optimization for the code too.
9882  DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
9883  if (code()->kind() == Code::FUNCTION) {
9884    code()->set_optimizable(false);
9885  }
9886  PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
9887  if (FLAG_trace_opt) {
9888    PrintF("[disabled optimization for ");
9889    ShortPrint();
9890    PrintF(", reason: %s]\n", GetBailoutReason(reason));
9891  }
9892}
9893
9894
9895bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
9896  DCHECK(!id.IsNone());
9897  Code* unoptimized = code();
9898  DeoptimizationOutputData* data =
9899      DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
9900  unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
9901  USE(ignore);
9902  return true;  // Return true if there was no DCHECK.
9903}
9904
9905
9906void JSFunction::StartInobjectSlackTracking() {
9907  DCHECK(has_initial_map() && !IsInobjectSlackTrackingInProgress());
9908
9909  if (!FLAG_clever_optimizations) return;
9910  Map* map = initial_map();
9911
9912  // Only initiate the tracking the first time.
9913  if (map->done_inobject_slack_tracking()) return;
9914  map->set_done_inobject_slack_tracking(true);
9915
9916  // No tracking during the snapshot construction phase.
9917  Isolate* isolate = GetIsolate();
9918  if (isolate->serializer_enabled()) return;
9919
9920  if (map->unused_property_fields() == 0) return;
9921
9922  map->set_construction_count(kGenerousAllocationCount);
9923}
9924
9925
9926void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
9927  code()->ClearInlineCaches();
9928  // If we clear ICs, we need to clear the type feedback vector too, since
9929  // CallICs are synced with a feedback vector slot.
9930  ClearTypeFeedbackInfo();
9931  set_ic_age(new_ic_age);
9932  if (code()->kind() == Code::FUNCTION) {
9933    code()->set_profiler_ticks(0);
9934    if (optimization_disabled() &&
9935        opt_count() >= FLAG_max_opt_count) {
9936      // Re-enable optimizations if they were disabled due to opt_count limit.
9937      set_optimization_disabled(false);
9938      code()->set_optimizable(true);
9939    }
9940    set_opt_count(0);
9941    set_deopt_count(0);
9942  }
9943}
9944
9945
9946static void GetMinInobjectSlack(Map* map, void* data) {
9947  int slack = map->unused_property_fields();
9948  if (*reinterpret_cast<int*>(data) > slack) {
9949    *reinterpret_cast<int*>(data) = slack;
9950  }
9951}
9952
9953
9954static void ShrinkInstanceSize(Map* map, void* data) {
9955  int slack = *reinterpret_cast<int*>(data);
9956  map->set_inobject_properties(map->inobject_properties() - slack);
9957  map->set_unused_property_fields(map->unused_property_fields() - slack);
9958  map->set_instance_size(map->instance_size() - slack * kPointerSize);
9959
9960  // Visitor id might depend on the instance size, recalculate it.
9961  map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
9962}
9963
9964
9965void JSFunction::CompleteInobjectSlackTracking() {
9966  DCHECK(has_initial_map());
9967  Map* map = initial_map();
9968
9969  DCHECK(map->done_inobject_slack_tracking());
9970  map->set_construction_count(kNoSlackTracking);
9971
9972  int slack = map->unused_property_fields();
9973  map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
9974  if (slack != 0) {
9975    // Resize the initial map and all maps in its transition tree.
9976    map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
9977  }
9978}
9979
9980
9981int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
9982                                               BailoutId osr_ast_id) {
9983  DisallowHeapAllocation no_gc;
9984  DCHECK(native_context->IsNativeContext());
9985  if (!FLAG_cache_optimized_code) return -1;
9986  Object* value = optimized_code_map();
9987  if (!value->IsSmi()) {
9988    FixedArray* optimized_code_map = FixedArray::cast(value);
9989    int length = optimized_code_map->length();
9990    Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
9991    for (int i = kEntriesStart; i < length; i += kEntryLength) {
9992      if (optimized_code_map->get(i + kContextOffset) == native_context &&
9993          optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
9994        return i + kCachedCodeOffset;
9995      }
9996    }
9997    if (FLAG_trace_opt) {
9998      PrintF("[didn't find optimized code in optimized code map for ");
9999      ShortPrint();
10000      PrintF("]\n");
10001    }
10002  }
10003  return -1;
10004}
10005
10006
10007#define DECLARE_TAG(ignore1, name, ignore2) name,
10008const char* const VisitorSynchronization::kTags[
10009    VisitorSynchronization::kNumberOfSyncTags] = {
10010  VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10011};
10012#undef DECLARE_TAG
10013
10014
10015#define DECLARE_TAG(ignore1, ignore2, name) name,
10016const char* const VisitorSynchronization::kTagNames[
10017    VisitorSynchronization::kNumberOfSyncTags] = {
10018  VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
10019};
10020#undef DECLARE_TAG
10021
10022
10023void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10024  DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
10025  Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10026  Object* old_target = target;
10027  VisitPointer(&target);
10028  CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10029}
10030
10031
10032void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10033  DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10034  Object* stub = rinfo->code_age_stub();
10035  if (stub) {
10036    VisitPointer(&stub);
10037  }
10038}
10039
10040
10041void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10042  Object* code = Code::GetObjectFromEntryAddress(entry_address);
10043  Object* old_code = code;
10044  VisitPointer(&code);
10045  if (code != old_code) {
10046    Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10047  }
10048}
10049
10050
10051void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10052  DCHECK(rinfo->rmode() == RelocInfo::CELL);
10053  Object* cell = rinfo->target_cell();
10054  Object* old_cell = cell;
10055  VisitPointer(&cell);
10056  if (cell != old_cell) {
10057    rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10058  }
10059}
10060
10061
10062void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10063  DCHECK((RelocInfo::IsJSReturn(rinfo->rmode()) &&
10064          rinfo->IsPatchedReturnSequence()) ||
10065         (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10066          rinfo->IsPatchedDebugBreakSlotSequence()));
10067  Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
10068  Object* old_target = target;
10069  VisitPointer(&target);
10070  CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
10071}
10072
10073
10074void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10075  DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10076  Object* p = rinfo->target_object();
10077  VisitPointer(&p);
10078}
10079
10080
10081void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10082  Address p = rinfo->target_reference();
10083  VisitExternalReference(&p);
10084}
10085
10086
10087void Code::InvalidateRelocation() {
10088  InvalidateEmbeddedObjects();
10089  set_relocation_info(GetHeap()->empty_byte_array());
10090}
10091
10092
10093void Code::InvalidateEmbeddedObjects() {
10094  Object* undefined = GetHeap()->undefined_value();
10095  Cell* undefined_cell = GetHeap()->undefined_cell();
10096  int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10097                  RelocInfo::ModeMask(RelocInfo::CELL);
10098  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10099    RelocInfo::Mode mode = it.rinfo()->rmode();
10100    if (mode == RelocInfo::EMBEDDED_OBJECT) {
10101      it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10102    } else if (mode == RelocInfo::CELL) {
10103      it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10104    }
10105  }
10106}
10107
10108
10109void Code::Relocate(intptr_t delta) {
10110  for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10111    it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10112  }
10113  CpuFeatures::FlushICache(instruction_start(), instruction_size());
10114}
10115
10116
10117void Code::CopyFrom(const CodeDesc& desc) {
10118  DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT);
10119
10120  // copy code
10121  CopyBytes(instruction_start(), desc.buffer,
10122            static_cast<size_t>(desc.instr_size));
10123
10124  // copy reloc info
10125  CopyBytes(relocation_start(),
10126            desc.buffer + desc.buffer_size - desc.reloc_size,
10127            static_cast<size_t>(desc.reloc_size));
10128
10129  // unbox handles and relocate
10130  intptr_t delta = instruction_start() - desc.buffer;
10131  int mode_mask = RelocInfo::kCodeTargetMask |
10132                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
10133                  RelocInfo::ModeMask(RelocInfo::CELL) |
10134                  RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
10135                  RelocInfo::kApplyMask;
10136  // Needed to find target_object and runtime_entry on X64
10137  Assembler* origin = desc.origin;
10138  AllowDeferredHandleDereference embedding_raw_address;
10139  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10140    RelocInfo::Mode mode = it.rinfo()->rmode();
10141    if (mode == RelocInfo::EMBEDDED_OBJECT) {
10142      Handle<Object> p = it.rinfo()->target_object_handle(origin);
10143      it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10144    } else if (mode == RelocInfo::CELL) {
10145      Handle<Cell> cell  = it.rinfo()->target_cell_handle();
10146      it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10147    } else if (RelocInfo::IsCodeTarget(mode)) {
10148      // rewrite code handles in inline cache targets to direct
10149      // pointers to the first instruction in the code object
10150      Handle<Object> p = it.rinfo()->target_object_handle(origin);
10151      Code* code = Code::cast(*p);
10152      it.rinfo()->set_target_address(code->instruction_start(),
10153                                     SKIP_WRITE_BARRIER,
10154                                     SKIP_ICACHE_FLUSH);
10155    } else if (RelocInfo::IsRuntimeEntry(mode)) {
10156      Address p = it.rinfo()->target_runtime_entry(origin);
10157      it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
10158                                           SKIP_ICACHE_FLUSH);
10159    } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10160      Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10161      Code* code = Code::cast(*p);
10162      it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
10163    } else {
10164      it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10165    }
10166  }
10167  CpuFeatures::FlushICache(instruction_start(), instruction_size());
10168}
10169
10170
10171// Locate the source position which is closest to the address in the code. This
10172// is using the source position information embedded in the relocation info.
10173// The position returned is relative to the beginning of the script where the
10174// source for this function is found.
10175int Code::SourcePosition(Address pc) {
10176  int distance = kMaxInt;
10177  int position = RelocInfo::kNoPosition;  // Initially no position found.
10178  // Run through all the relocation info to find the best matching source
10179  // position. All the code needs to be considered as the sequence of the
10180  // instructions in the code does not necessarily follow the same order as the
10181  // source.
10182  RelocIterator it(this, RelocInfo::kPositionMask);
10183  while (!it.done()) {
10184    // Only look at positions after the current pc.
10185    if (it.rinfo()->pc() < pc) {
10186      // Get position and distance.
10187
10188      int dist = static_cast<int>(pc - it.rinfo()->pc());
10189      int pos = static_cast<int>(it.rinfo()->data());
10190      // If this position is closer than the current candidate or if it has the
10191      // same distance as the current candidate and the position is higher then
10192      // this position is the new candidate.
10193      if ((dist < distance) ||
10194          (dist == distance && pos > position)) {
10195        position = pos;
10196        distance = dist;
10197      }
10198    }
10199    it.next();
10200  }
10201  return position;
10202}
10203
10204
10205// Same as Code::SourcePosition above except it only looks for statement
10206// positions.
10207int Code::SourceStatementPosition(Address pc) {
10208  // First find the position as close as possible using all position
10209  // information.
10210  int position = SourcePosition(pc);
10211  // Now find the closest statement position before the position.
10212  int statement_position = 0;
10213  RelocIterator it(this, RelocInfo::kPositionMask);
10214  while (!it.done()) {
10215    if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
10216      int p = static_cast<int>(it.rinfo()->data());
10217      if (statement_position < p && p <= position) {
10218        statement_position = p;
10219      }
10220    }
10221    it.next();
10222  }
10223  return statement_position;
10224}
10225
10226
10227SafepointEntry Code::GetSafepointEntry(Address pc) {
10228  SafepointTable table(this);
10229  return table.FindEntry(pc);
10230}
10231
10232
10233Object* Code::FindNthObject(int n, Map* match_map) {
10234  DCHECK(is_inline_cache_stub());
10235  DisallowHeapAllocation no_allocation;
10236  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10237  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10238    RelocInfo* info = it.rinfo();
10239    Object* object = info->target_object();
10240    if (object->IsHeapObject()) {
10241      if (HeapObject::cast(object)->map() == match_map) {
10242        if (--n == 0) return object;
10243      }
10244    }
10245  }
10246  return NULL;
10247}
10248
10249
10250AllocationSite* Code::FindFirstAllocationSite() {
10251  Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
10252  return (result != NULL) ? AllocationSite::cast(result) : NULL;
10253}
10254
10255
10256Map* Code::FindFirstMap() {
10257  Object* result = FindNthObject(1, GetHeap()->meta_map());
10258  return (result != NULL) ? Map::cast(result) : NULL;
10259}
10260
10261
10262void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
10263  DCHECK(is_inline_cache_stub() || is_handler());
10264  DisallowHeapAllocation no_allocation;
10265  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10266  STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
10267  int current_pattern = 0;
10268  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10269    RelocInfo* info = it.rinfo();
10270    Object* object = info->target_object();
10271    if (object->IsHeapObject()) {
10272      Map* map = HeapObject::cast(object)->map();
10273      if (map == *pattern.find_[current_pattern]) {
10274        info->set_target_object(*pattern.replace_[current_pattern]);
10275        if (++current_pattern == pattern.count_) return;
10276      }
10277    }
10278  }
10279  UNREACHABLE();
10280}
10281
10282
10283void Code::FindAllMaps(MapHandleList* maps) {
10284  DCHECK(is_inline_cache_stub());
10285  DisallowHeapAllocation no_allocation;
10286  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10287  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10288    RelocInfo* info = it.rinfo();
10289    Object* object = info->target_object();
10290    if (object->IsMap()) maps->Add(handle(Map::cast(object)));
10291  }
10292}
10293
10294
10295Code* Code::FindFirstHandler() {
10296  DCHECK(is_inline_cache_stub());
10297  DisallowHeapAllocation no_allocation;
10298  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
10299  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10300    RelocInfo* info = it.rinfo();
10301    Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10302    if (code->kind() == Code::HANDLER) return code;
10303  }
10304  return NULL;
10305}
10306
10307
10308bool Code::FindHandlers(CodeHandleList* code_list, int length) {
10309  DCHECK(is_inline_cache_stub());
10310  DisallowHeapAllocation no_allocation;
10311  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
10312  int i = 0;
10313  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10314    if (i == length) return true;
10315    RelocInfo* info = it.rinfo();
10316    Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10317    // IC stubs with handlers never contain non-handler code objects before
10318    // handler targets.
10319    if (code->kind() != Code::HANDLER) break;
10320    code_list->Add(Handle<Code>(code));
10321    i++;
10322  }
10323  return i == length;
10324}
10325
10326
10327MaybeHandle<Code> Code::FindHandlerForMap(Map* map) {
10328  DCHECK(is_inline_cache_stub());
10329  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10330             RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10331  bool return_next = false;
10332  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10333    RelocInfo* info = it.rinfo();
10334    if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10335      Object* object = info->target_object();
10336      if (object == map) return_next = true;
10337    } else if (return_next) {
10338      Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10339      DCHECK(code->kind() == Code::HANDLER);
10340      return handle(code);
10341    }
10342  }
10343  return MaybeHandle<Code>();
10344}
10345
10346
10347Name* Code::FindFirstName() {
10348  DCHECK(is_inline_cache_stub());
10349  DisallowHeapAllocation no_allocation;
10350  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
10351  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10352    RelocInfo* info = it.rinfo();
10353    Object* object = info->target_object();
10354    if (object->IsName()) return Name::cast(object);
10355  }
10356  return NULL;
10357}
10358
10359
10360void Code::ClearInlineCaches() {
10361  ClearInlineCaches(NULL);
10362}
10363
10364
10365void Code::ClearInlineCaches(Code::Kind kind) {
10366  ClearInlineCaches(&kind);
10367}
10368
10369
10370void Code::ClearInlineCaches(Code::Kind* kind) {
10371  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10372             RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
10373             RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
10374  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10375    RelocInfo* info = it.rinfo();
10376    Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10377    if (target->is_inline_cache_stub()) {
10378      if (kind == NULL || *kind == target->kind()) {
10379        IC::Clear(this->GetIsolate(), info->pc(),
10380                  info->host()->constant_pool());
10381      }
10382    }
10383  }
10384}
10385
10386
10387void SharedFunctionInfo::ClearTypeFeedbackInfo() {
10388  TypeFeedbackVector* vector = feedback_vector();
10389  Heap* heap = GetHeap();
10390  int length = vector->length();
10391
10392  for (int i = 0; i < length; i++) {
10393    Object* obj = vector->get(i);
10394    if (obj->IsHeapObject()) {
10395      InstanceType instance_type =
10396          HeapObject::cast(obj)->map()->instance_type();
10397      switch (instance_type) {
10398        case ALLOCATION_SITE_TYPE:
10399          // AllocationSites are not cleared because they do not store
10400          // information that leaks.
10401          break;
10402          // Fall through...
10403        default:
10404          vector->set(i, TypeFeedbackVector::RawUninitializedSentinel(heap),
10405                      SKIP_WRITE_BARRIER);
10406      }
10407    }
10408  }
10409}
10410
10411
10412BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
10413  DisallowHeapAllocation no_gc;
10414  DCHECK(kind() == FUNCTION);
10415  BackEdgeTable back_edges(this, &no_gc);
10416  for (uint32_t i = 0; i < back_edges.length(); i++) {
10417    if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
10418  }
10419  return BailoutId::None();
10420}
10421
10422
10423uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
10424  DisallowHeapAllocation no_gc;
10425  DCHECK(kind() == FUNCTION);
10426  BackEdgeTable back_edges(this, &no_gc);
10427  for (uint32_t i = 0; i < back_edges.length(); i++) {
10428    if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
10429  }
10430  UNREACHABLE();  // We expect to find the back edge.
10431  return 0;
10432}
10433
10434
10435void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
10436  PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
10437}
10438
10439
10440void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
10441  PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
10442      NO_MARKING_PARITY);
10443}
10444
10445
10446static Code::Age EffectiveAge(Code::Age age) {
10447  if (age == Code::kNotExecutedCodeAge) {
10448    // Treat that's never been executed as old immediately.
10449    age = Code::kIsOldCodeAge;
10450  } else if (age == Code::kExecutedOnceCodeAge) {
10451    // Pre-age code that has only been executed once.
10452    age = Code::kPreAgedCodeAge;
10453  }
10454  return age;
10455}
10456
10457
10458void Code::MakeOlder(MarkingParity current_parity) {
10459  byte* sequence = FindCodeAgeSequence();
10460  if (sequence != NULL) {
10461    Age age;
10462    MarkingParity code_parity;
10463    Isolate* isolate = GetIsolate();
10464    GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
10465    age = EffectiveAge(age);
10466    if (age != kLastCodeAge && code_parity != current_parity) {
10467      PatchPlatformCodeAge(isolate,
10468                           sequence,
10469                           static_cast<Age>(age + 1),
10470                           current_parity);
10471    }
10472  }
10473}
10474
10475
10476bool Code::IsOld() {
10477  return GetAge() >= kIsOldCodeAge;
10478}
10479
10480
10481byte* Code::FindCodeAgeSequence() {
10482  return FLAG_age_code &&
10483      prologue_offset() != Code::kPrologueOffsetNotSet &&
10484      (kind() == OPTIMIZED_FUNCTION ||
10485       (kind() == FUNCTION && !has_debug_break_slots()))
10486      ? instruction_start() + prologue_offset()
10487      : NULL;
10488}
10489
10490
10491Code::Age Code::GetAge() {
10492  return EffectiveAge(GetRawAge());
10493}
10494
10495
10496Code::Age Code::GetRawAge() {
10497  byte* sequence = FindCodeAgeSequence();
10498  if (sequence == NULL) {
10499    return kNoAgeCodeAge;
10500  }
10501  Age age;
10502  MarkingParity parity;
10503  GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
10504  return age;
10505}
10506
10507
10508void Code::GetCodeAgeAndParity(Code* code, Age* age,
10509                               MarkingParity* parity) {
10510  Isolate* isolate = code->GetIsolate();
10511  Builtins* builtins = isolate->builtins();
10512  Code* stub = NULL;
10513#define HANDLE_CODE_AGE(AGE)                                            \
10514  stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
10515  if (code == stub) {                                                   \
10516    *age = k##AGE##CodeAge;                                             \
10517    *parity = EVEN_MARKING_PARITY;                                      \
10518    return;                                                             \
10519  }                                                                     \
10520  stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
10521  if (code == stub) {                                                   \
10522    *age = k##AGE##CodeAge;                                             \
10523    *parity = ODD_MARKING_PARITY;                                       \
10524    return;                                                             \
10525  }
10526  CODE_AGE_LIST(HANDLE_CODE_AGE)
10527#undef HANDLE_CODE_AGE
10528  stub = *builtins->MarkCodeAsExecutedOnce();
10529  if (code == stub) {
10530    *age = kNotExecutedCodeAge;
10531    *parity = NO_MARKING_PARITY;
10532    return;
10533  }
10534  stub = *builtins->MarkCodeAsExecutedTwice();
10535  if (code == stub) {
10536    *age = kExecutedOnceCodeAge;
10537    *parity = NO_MARKING_PARITY;
10538    return;
10539  }
10540  UNREACHABLE();
10541}
10542
10543
10544Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
10545  Builtins* builtins = isolate->builtins();
10546  switch (age) {
10547#define HANDLE_CODE_AGE(AGE)                                            \
10548    case k##AGE##CodeAge: {                                             \
10549      Code* stub = parity == EVEN_MARKING_PARITY                        \
10550          ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
10551          : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
10552      return stub;                                                      \
10553    }
10554    CODE_AGE_LIST(HANDLE_CODE_AGE)
10555#undef HANDLE_CODE_AGE
10556    case kNotExecutedCodeAge: {
10557      DCHECK(parity == NO_MARKING_PARITY);
10558      return *builtins->MarkCodeAsExecutedOnce();
10559    }
10560    case kExecutedOnceCodeAge: {
10561      DCHECK(parity == NO_MARKING_PARITY);
10562      return *builtins->MarkCodeAsExecutedTwice();
10563    }
10564    default:
10565      UNREACHABLE();
10566      break;
10567  }
10568  return NULL;
10569}
10570
10571
10572void Code::PrintDeoptLocation(FILE* out, int bailout_id) {
10573  const char* last_comment = NULL;
10574  int mask = RelocInfo::ModeMask(RelocInfo::COMMENT)
10575      | RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
10576  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10577    RelocInfo* info = it.rinfo();
10578    if (info->rmode() == RelocInfo::COMMENT) {
10579      last_comment = reinterpret_cast<const char*>(info->data());
10580    } else if (last_comment != NULL) {
10581      if ((bailout_id == Deoptimizer::GetDeoptimizationId(
10582              GetIsolate(), info->target_address(), Deoptimizer::EAGER)) ||
10583          (bailout_id == Deoptimizer::GetDeoptimizationId(
10584              GetIsolate(), info->target_address(), Deoptimizer::SOFT)) ||
10585          (bailout_id == Deoptimizer::GetDeoptimizationId(
10586              GetIsolate(), info->target_address(), Deoptimizer::LAZY))) {
10587        CHECK(RelocInfo::IsRuntimeEntry(info->rmode()));
10588        PrintF(out, "            %s\n", last_comment);
10589        return;
10590      }
10591    }
10592  }
10593}
10594
10595
10596bool Code::CanDeoptAt(Address pc) {
10597  DeoptimizationInputData* deopt_data =
10598      DeoptimizationInputData::cast(deoptimization_data());
10599  Address code_start_address = instruction_start();
10600  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
10601    if (deopt_data->Pc(i)->value() == -1) continue;
10602    Address address = code_start_address + deopt_data->Pc(i)->value();
10603    if (address == pc) return true;
10604  }
10605  return false;
10606}
10607
10608
10609// Identify kind of code.
10610const char* Code::Kind2String(Kind kind) {
10611  switch (kind) {
10612#define CASE(name) case name: return #name;
10613    CODE_KIND_LIST(CASE)
10614#undef CASE
10615    case NUMBER_OF_KINDS: break;
10616  }
10617  UNREACHABLE();
10618  return NULL;
10619}
10620
10621
10622#ifdef ENABLE_DISASSEMBLER
10623
10624void DeoptimizationInputData::DeoptimizationInputDataPrint(
10625    OStream& os) {  // NOLINT
10626  disasm::NameConverter converter;
10627  int deopt_count = DeoptCount();
10628  os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
10629  if (0 != deopt_count) {
10630    os << " index  ast id    argc     pc";
10631    if (FLAG_print_code_verbose) os << "  commands";
10632    os << "\n";
10633  }
10634  for (int i = 0; i < deopt_count; i++) {
10635    // TODO(svenpanne) Add some basic formatting to our streams.
10636    Vector<char> buf1 = Vector<char>::New(128);
10637    SNPrintF(buf1, "%6d  %6d  %6d %6d", i, AstId(i).ToInt(),
10638             ArgumentsStackHeight(i)->value(), Pc(i)->value());
10639    os << buf1.start();
10640
10641    if (!FLAG_print_code_verbose) {
10642      os << "\n";
10643      continue;
10644    }
10645    // Print details of the frame translation.
10646    int translation_index = TranslationIndex(i)->value();
10647    TranslationIterator iterator(TranslationByteArray(), translation_index);
10648    Translation::Opcode opcode =
10649        static_cast<Translation::Opcode>(iterator.Next());
10650    DCHECK(Translation::BEGIN == opcode);
10651    int frame_count = iterator.Next();
10652    int jsframe_count = iterator.Next();
10653    os << "  " << Translation::StringFor(opcode)
10654       << " {frame count=" << frame_count
10655       << ", js frame count=" << jsframe_count << "}\n";
10656
10657    while (iterator.HasNext() &&
10658           Translation::BEGIN !=
10659           (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
10660      Vector<char> buf2 = Vector<char>::New(128);
10661      SNPrintF(buf2, "%27s    %s ", "", Translation::StringFor(opcode));
10662      os << buf2.start();
10663
10664      switch (opcode) {
10665        case Translation::BEGIN:
10666          UNREACHABLE();
10667          break;
10668
10669        case Translation::JS_FRAME: {
10670          int ast_id = iterator.Next();
10671          int function_id = iterator.Next();
10672          unsigned height = iterator.Next();
10673          os << "{ast_id=" << ast_id << ", function=";
10674          if (function_id != Translation::kSelfLiteralId) {
10675            Object* function = LiteralArray()->get(function_id);
10676            os << Brief(JSFunction::cast(function)->shared()->DebugName());
10677          } else {
10678            os << "<self>";
10679          }
10680          os << ", height=" << height << "}";
10681          break;
10682        }
10683
10684        case Translation::COMPILED_STUB_FRAME: {
10685          Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
10686          os << "{kind=" << stub_kind << "}";
10687          break;
10688        }
10689
10690        case Translation::ARGUMENTS_ADAPTOR_FRAME:
10691        case Translation::CONSTRUCT_STUB_FRAME: {
10692          int function_id = iterator.Next();
10693          JSFunction* function =
10694              JSFunction::cast(LiteralArray()->get(function_id));
10695          unsigned height = iterator.Next();
10696          os << "{function=" << Brief(function->shared()->DebugName())
10697             << ", height=" << height << "}";
10698          break;
10699        }
10700
10701        case Translation::GETTER_STUB_FRAME:
10702        case Translation::SETTER_STUB_FRAME: {
10703          int function_id = iterator.Next();
10704          JSFunction* function =
10705              JSFunction::cast(LiteralArray()->get(function_id));
10706          os << "{function=" << Brief(function->shared()->DebugName()) << "}";
10707          break;
10708        }
10709
10710        case Translation::REGISTER: {
10711          int reg_code = iterator.Next();
10712          os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
10713          break;
10714        }
10715
10716        case Translation::INT32_REGISTER: {
10717          int reg_code = iterator.Next();
10718          os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
10719          break;
10720        }
10721
10722        case Translation::UINT32_REGISTER: {
10723          int reg_code = iterator.Next();
10724          os << "{input=" << converter.NameOfCPURegister(reg_code)
10725             << " (unsigned)}";
10726          break;
10727        }
10728
10729        case Translation::DOUBLE_REGISTER: {
10730          int reg_code = iterator.Next();
10731          os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
10732             << "}";
10733          break;
10734        }
10735
10736        case Translation::STACK_SLOT: {
10737          int input_slot_index = iterator.Next();
10738          os << "{input=" << input_slot_index << "}";
10739          break;
10740        }
10741
10742        case Translation::INT32_STACK_SLOT: {
10743          int input_slot_index = iterator.Next();
10744          os << "{input=" << input_slot_index << "}";
10745          break;
10746        }
10747
10748        case Translation::UINT32_STACK_SLOT: {
10749          int input_slot_index = iterator.Next();
10750          os << "{input=" << input_slot_index << " (unsigned)}";
10751          break;
10752        }
10753
10754        case Translation::DOUBLE_STACK_SLOT: {
10755          int input_slot_index = iterator.Next();
10756          os << "{input=" << input_slot_index << "}";
10757          break;
10758        }
10759
10760        case Translation::LITERAL: {
10761          unsigned literal_index = iterator.Next();
10762          os << "{literal_id=" << literal_index << "}";
10763          break;
10764        }
10765
10766        case Translation::DUPLICATED_OBJECT: {
10767          int object_index = iterator.Next();
10768          os << "{object_index=" << object_index << "}";
10769          break;
10770        }
10771
10772        case Translation::ARGUMENTS_OBJECT:
10773        case Translation::CAPTURED_OBJECT: {
10774          int args_length = iterator.Next();
10775          os << "{length=" << args_length << "}";
10776          break;
10777        }
10778      }
10779      os << "\n";
10780    }
10781  }
10782}
10783
10784
10785void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
10786    OStream& os) {  // NOLINT
10787  os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
10788     << ")\n";
10789  if (this->DeoptPoints() == 0) return;
10790
10791  os << "ast id        pc  state\n";
10792  for (int i = 0; i < this->DeoptPoints(); i++) {
10793    int pc_and_state = this->PcAndState(i)->value();
10794    // TODO(svenpanne) Add some basic formatting to our streams.
10795    Vector<char> buf = Vector<char>::New(100);
10796    SNPrintF(buf, "%6d  %8d  %s\n", this->AstId(i).ToInt(),
10797             FullCodeGenerator::PcField::decode(pc_and_state),
10798             FullCodeGenerator::State2String(
10799                 FullCodeGenerator::StateField::decode(pc_and_state)));
10800    os << buf.start();
10801  }
10802}
10803
10804
10805const char* Code::ICState2String(InlineCacheState state) {
10806  switch (state) {
10807    case UNINITIALIZED: return "UNINITIALIZED";
10808    case PREMONOMORPHIC: return "PREMONOMORPHIC";
10809    case MONOMORPHIC: return "MONOMORPHIC";
10810    case PROTOTYPE_FAILURE:
10811      return "PROTOTYPE_FAILURE";
10812    case POLYMORPHIC: return "POLYMORPHIC";
10813    case MEGAMORPHIC: return "MEGAMORPHIC";
10814    case GENERIC: return "GENERIC";
10815    case DEBUG_STUB: return "DEBUG_STUB";
10816    case DEFAULT:
10817      return "DEFAULT";
10818  }
10819  UNREACHABLE();
10820  return NULL;
10821}
10822
10823
10824const char* Code::StubType2String(StubType type) {
10825  switch (type) {
10826    case NORMAL: return "NORMAL";
10827    case FAST: return "FAST";
10828  }
10829  UNREACHABLE();  // keep the compiler happy
10830  return NULL;
10831}
10832
10833
10834void Code::PrintExtraICState(OStream& os,  // NOLINT
10835                             Kind kind, ExtraICState extra) {
10836  os << "extra_ic_state = ";
10837  if ((kind == STORE_IC || kind == KEYED_STORE_IC) && (extra == STRICT)) {
10838    os << "STRICT\n";
10839  } else {
10840    os << extra << "\n";
10841  }
10842}
10843
10844
10845void Code::Disassemble(const char* name, OStream& os) {  // NOLINT
10846  os << "kind = " << Kind2String(kind()) << "\n";
10847  if (IsCodeStubOrIC()) {
10848    const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true);
10849    os << "major_key = " << (n == NULL ? "null" : n) << "\n";
10850  }
10851  if (is_inline_cache_stub()) {
10852    os << "ic_state = " << ICState2String(ic_state()) << "\n";
10853    PrintExtraICState(os, kind(), extra_ic_state());
10854    if (ic_state() == MONOMORPHIC) {
10855      os << "type = " << StubType2String(type()) << "\n";
10856    }
10857    if (is_compare_ic_stub()) {
10858      DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
10859      CompareICStub stub(stub_key(), GetIsolate());
10860      os << "compare_state = " << CompareICState::GetStateName(stub.left())
10861         << "*" << CompareICState::GetStateName(stub.right()) << " -> "
10862         << CompareICState::GetStateName(stub.state()) << "\n";
10863      os << "compare_operation = " << Token::Name(stub.op()) << "\n";
10864    }
10865  }
10866  if ((name != NULL) && (name[0] != '\0')) {
10867    os << "name = " << name << "\n";
10868  }
10869  if (kind() == OPTIMIZED_FUNCTION) {
10870    os << "stack_slots = " << stack_slots() << "\n";
10871  }
10872
10873  os << "Instructions (size = " << instruction_size() << ")\n";
10874  // TODO(svenpanne) The Disassembler should use streams, too!
10875  {
10876    CodeTracer::Scope trace_scope(GetIsolate()->GetCodeTracer());
10877    Disassembler::Decode(trace_scope.file(), this);
10878  }
10879  os << "\n";
10880
10881  if (kind() == FUNCTION) {
10882    DeoptimizationOutputData* data =
10883        DeoptimizationOutputData::cast(this->deoptimization_data());
10884    data->DeoptimizationOutputDataPrint(os);
10885  } else if (kind() == OPTIMIZED_FUNCTION) {
10886    DeoptimizationInputData* data =
10887        DeoptimizationInputData::cast(this->deoptimization_data());
10888    data->DeoptimizationInputDataPrint(os);
10889  }
10890  os << "\n";
10891
10892  if (is_crankshafted()) {
10893    SafepointTable table(this);
10894    os << "Safepoints (size = " << table.size() << ")\n";
10895    for (unsigned i = 0; i < table.length(); i++) {
10896      unsigned pc_offset = table.GetPcOffset(i);
10897      os << (instruction_start() + pc_offset) << "  ";
10898      // TODO(svenpanne) Add some basic formatting to our streams.
10899      Vector<char> buf1 = Vector<char>::New(30);
10900      SNPrintF(buf1, "%4d", pc_offset);
10901      os << buf1.start() << "  ";
10902      table.PrintEntry(i, os);
10903      os << " (sp -> fp)  ";
10904      SafepointEntry entry = table.GetEntry(i);
10905      if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
10906        Vector<char> buf2 = Vector<char>::New(30);
10907        SNPrintF(buf2, "%6d", entry.deoptimization_index());
10908        os << buf2.start();
10909      } else {
10910        os << "<none>";
10911      }
10912      if (entry.argument_count() > 0) {
10913        os << " argc: " << entry.argument_count();
10914      }
10915      os << "\n";
10916    }
10917    os << "\n";
10918  } else if (kind() == FUNCTION) {
10919    unsigned offset = back_edge_table_offset();
10920    // If there is no back edge table, the "table start" will be at or after
10921    // (due to alignment) the end of the instruction stream.
10922    if (static_cast<int>(offset) < instruction_size()) {
10923      DisallowHeapAllocation no_gc;
10924      BackEdgeTable back_edges(this, &no_gc);
10925
10926      os << "Back edges (size = " << back_edges.length() << ")\n";
10927      os << "ast_id  pc_offset  loop_depth\n";
10928
10929      for (uint32_t i = 0; i < back_edges.length(); i++) {
10930        Vector<char> buf = Vector<char>::New(100);
10931        SNPrintF(buf, "%6d  %9u  %10u\n", back_edges.ast_id(i).ToInt(),
10932                 back_edges.pc_offset(i), back_edges.loop_depth(i));
10933        os << buf.start();
10934      }
10935
10936      os << "\n";
10937    }
10938#ifdef OBJECT_PRINT
10939    if (!type_feedback_info()->IsUndefined()) {
10940      OFStream os(stdout);
10941      TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
10942      os << "\n";
10943    }
10944#endif
10945  }
10946
10947  os << "RelocInfo (size = " << relocation_size() << ")\n";
10948  for (RelocIterator it(this); !it.done(); it.next()) {
10949    it.rinfo()->Print(GetIsolate(), os);
10950  }
10951  os << "\n";
10952}
10953#endif  // ENABLE_DISASSEMBLER
10954
10955
10956Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
10957    Handle<JSObject> object,
10958    int capacity,
10959    int length,
10960    SetFastElementsCapacitySmiMode smi_mode) {
10961  // We should never end in here with a pixel or external array.
10962  DCHECK(!object->HasExternalArrayElements());
10963
10964  // Allocate a new fast elements backing store.
10965  Handle<FixedArray> new_elements =
10966      object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
10967
10968  ElementsKind elements_kind = object->GetElementsKind();
10969  ElementsKind new_elements_kind;
10970  // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
10971  // or if it's allowed and the old elements array contained only SMIs.
10972  bool has_fast_smi_elements =
10973      (smi_mode == kForceSmiElements) ||
10974      ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements());
10975  if (has_fast_smi_elements) {
10976    if (IsHoleyElementsKind(elements_kind)) {
10977      new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
10978    } else {
10979      new_elements_kind = FAST_SMI_ELEMENTS;
10980    }
10981  } else {
10982    if (IsHoleyElementsKind(elements_kind)) {
10983      new_elements_kind = FAST_HOLEY_ELEMENTS;
10984    } else {
10985      new_elements_kind = FAST_ELEMENTS;
10986    }
10987  }
10988  Handle<FixedArrayBase> old_elements(object->elements());
10989  ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
10990  accessor->CopyElements(object, new_elements, elements_kind);
10991
10992  if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
10993    Handle<Map> new_map = (new_elements_kind != elements_kind)
10994        ? GetElementsTransitionMap(object, new_elements_kind)
10995        : handle(object->map());
10996    JSObject::ValidateElements(object);
10997    JSObject::SetMapAndElements(object, new_map, new_elements);
10998
10999    // Transition through the allocation site as well if present.
11000    JSObject::UpdateAllocationSite(object, new_elements_kind);
11001  } else {
11002    Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11003    parameter_map->set(1, *new_elements);
11004  }
11005
11006  if (FLAG_trace_elements_transitions) {
11007    PrintElementsTransition(stdout, object, elements_kind, old_elements,
11008                            object->GetElementsKind(), new_elements);
11009  }
11010
11011  if (object->IsJSArray()) {
11012    Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11013  }
11014  return new_elements;
11015}
11016
11017
11018void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object,
11019                                                      int capacity,
11020                                                      int length) {
11021  // We should never end in here with a pixel or external array.
11022  DCHECK(!object->HasExternalArrayElements());
11023
11024  Handle<FixedArrayBase> elems =
11025      object->GetIsolate()->factory()->NewFixedDoubleArray(capacity);
11026
11027  ElementsKind elements_kind = object->GetElementsKind();
11028  CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS);
11029  ElementsKind new_elements_kind = elements_kind;
11030  if (IsHoleyElementsKind(elements_kind)) {
11031    new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
11032  } else {
11033    new_elements_kind = FAST_DOUBLE_ELEMENTS;
11034  }
11035
11036  Handle<Map> new_map = GetElementsTransitionMap(object, new_elements_kind);
11037
11038  Handle<FixedArrayBase> old_elements(object->elements());
11039  ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
11040  accessor->CopyElements(object, elems, elements_kind);
11041
11042  JSObject::ValidateElements(object);
11043  JSObject::SetMapAndElements(object, new_map, elems);
11044
11045  if (FLAG_trace_elements_transitions) {
11046    PrintElementsTransition(stdout, object, elements_kind, old_elements,
11047                            object->GetElementsKind(), elems);
11048  }
11049
11050  if (object->IsJSArray()) {
11051    Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11052  }
11053}
11054
11055
11056// static
11057void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11058  DCHECK(capacity >= 0);
11059  array->GetIsolate()->factory()->NewJSArrayStorage(
11060      array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11061}
11062
11063
11064void JSArray::Expand(Handle<JSArray> array, int required_size) {
11065  ElementsAccessor* accessor = array->GetElementsAccessor();
11066  accessor->SetCapacityAndLength(array, required_size, required_size);
11067}
11068
11069
11070// Returns false if the passed-in index is marked non-configurable,
11071// which will cause the ES5 truncation operation to halt, and thus
11072// no further old values need be collected.
11073static bool GetOldValue(Isolate* isolate,
11074                        Handle<JSObject> object,
11075                        uint32_t index,
11076                        List<Handle<Object> >* old_values,
11077                        List<uint32_t>* indices) {
11078  Maybe<PropertyAttributes> maybe =
11079      JSReceiver::GetOwnElementAttribute(object, index);
11080  DCHECK(maybe.has_value);
11081  DCHECK(maybe.value != ABSENT);
11082  if (maybe.value == DONT_DELETE) return false;
11083  Handle<Object> value;
11084  if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
11085    value = Handle<Object>::cast(isolate->factory()->the_hole_value());
11086  } else {
11087    value = Object::GetElement(isolate, object, index).ToHandleChecked();
11088  }
11089  old_values->Add(value);
11090  indices->Add(index);
11091  return true;
11092}
11093
11094static void EnqueueSpliceRecord(Handle<JSArray> object,
11095                                uint32_t index,
11096                                Handle<JSArray> deleted,
11097                                uint32_t add_count) {
11098  Isolate* isolate = object->GetIsolate();
11099  HandleScope scope(isolate);
11100  Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
11101  Handle<Object> add_count_object =
11102      isolate->factory()->NewNumberFromUint(add_count);
11103
11104  Handle<Object> args[] =
11105      { object, index_object, deleted, add_count_object };
11106
11107  Execution::Call(isolate,
11108                  Handle<JSFunction>(isolate->observers_enqueue_splice()),
11109                  isolate->factory()->undefined_value(),
11110                  arraysize(args),
11111                  args).Assert();
11112}
11113
11114
11115static void BeginPerformSplice(Handle<JSArray> object) {
11116  Isolate* isolate = object->GetIsolate();
11117  HandleScope scope(isolate);
11118  Handle<Object> args[] = { object };
11119
11120  Execution::Call(isolate,
11121                  Handle<JSFunction>(isolate->observers_begin_perform_splice()),
11122                  isolate->factory()->undefined_value(),
11123                  arraysize(args),
11124                  args).Assert();
11125}
11126
11127
11128static void EndPerformSplice(Handle<JSArray> object) {
11129  Isolate* isolate = object->GetIsolate();
11130  HandleScope scope(isolate);
11131  Handle<Object> args[] = { object };
11132
11133  Execution::Call(isolate,
11134                  Handle<JSFunction>(isolate->observers_end_perform_splice()),
11135                  isolate->factory()->undefined_value(),
11136                  arraysize(args),
11137                  args).Assert();
11138}
11139
11140
11141MaybeHandle<Object> JSArray::SetElementsLength(
11142    Handle<JSArray> array,
11143    Handle<Object> new_length_handle) {
11144  if (array->HasFastElements()) {
11145    // If the new array won't fit in a some non-trivial fraction of the max old
11146    // space size, then force it to go dictionary mode.
11147    int max_fast_array_size = static_cast<int>(
11148        (array->GetHeap()->MaxOldGenerationSize() / kDoubleSize) / 4);
11149    if (new_length_handle->IsNumber() &&
11150        NumberToInt32(*new_length_handle) >= max_fast_array_size) {
11151      NormalizeElements(array);
11152    }
11153  }
11154
11155  // We should never end in here with a pixel or external array.
11156  DCHECK(array->AllowsSetElementsLength());
11157  if (!array->map()->is_observed()) {
11158    return array->GetElementsAccessor()->SetLength(array, new_length_handle);
11159  }
11160
11161  Isolate* isolate = array->GetIsolate();
11162  List<uint32_t> indices;
11163  List<Handle<Object> > old_values;
11164  Handle<Object> old_length_handle(array->length(), isolate);
11165  uint32_t old_length = 0;
11166  CHECK(old_length_handle->ToArrayIndex(&old_length));
11167  uint32_t new_length = 0;
11168  CHECK(new_length_handle->ToArrayIndex(&new_length));
11169
11170  static const PropertyAttributes kNoAttrFilter = NONE;
11171  int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
11172  if (num_elements > 0) {
11173    if (old_length == static_cast<uint32_t>(num_elements)) {
11174      // Simple case for arrays without holes.
11175      for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
11176        if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
11177      }
11178    } else {
11179      // For sparse arrays, only iterate over existing elements.
11180      // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
11181      // the to-be-removed indices twice.
11182      Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
11183      array->GetOwnElementKeys(*keys, kNoAttrFilter);
11184      while (num_elements-- > 0) {
11185        uint32_t index = NumberToUint32(keys->get(num_elements));
11186        if (index < new_length) break;
11187        if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
11188      }
11189    }
11190  }
11191
11192  Handle<Object> hresult;
11193  ASSIGN_RETURN_ON_EXCEPTION(
11194      isolate, hresult,
11195      array->GetElementsAccessor()->SetLength(array, new_length_handle),
11196      Object);
11197
11198  CHECK(array->length()->ToArrayIndex(&new_length));
11199  if (old_length == new_length) return hresult;
11200
11201  BeginPerformSplice(array);
11202
11203  for (int i = 0; i < indices.length(); ++i) {
11204    // For deletions where the property was an accessor, old_values[i]
11205    // will be the hole, which instructs EnqueueChangeRecord to elide
11206    // the "oldValue" property.
11207    JSObject::EnqueueChangeRecord(
11208        array, "delete", isolate->factory()->Uint32ToString(indices[i]),
11209        old_values[i]);
11210  }
11211  JSObject::EnqueueChangeRecord(
11212      array, "update", isolate->factory()->length_string(),
11213      old_length_handle);
11214
11215  EndPerformSplice(array);
11216
11217  uint32_t index = Min(old_length, new_length);
11218  uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11219  uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11220  Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11221  if (delete_count > 0) {
11222    for (int i = indices.length() - 1; i >= 0; i--) {
11223      // Skip deletions where the property was an accessor, leaving holes
11224      // in the array of old values.
11225      if (old_values[i]->IsTheHole()) continue;
11226      JSObject::SetElement(
11227          deleted, indices[i] - index, old_values[i], NONE, SLOPPY).Assert();
11228    }
11229
11230    SetProperty(deleted, isolate->factory()->length_string(),
11231                isolate->factory()->NewNumberFromUint(delete_count),
11232                STRICT).Assert();
11233  }
11234
11235  EnqueueSpliceRecord(array, index, deleted, add_count);
11236
11237  return hresult;
11238}
11239
11240
11241Handle<Map> Map::GetPrototypeTransition(Handle<Map> map,
11242                                        Handle<Object> prototype) {
11243  FixedArray* cache = map->GetPrototypeTransitions();
11244  int number_of_transitions = map->NumberOfProtoTransitions();
11245  const int proto_offset =
11246      kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
11247  const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
11248  const int step = kProtoTransitionElementsPerEntry;
11249  for (int i = 0; i < number_of_transitions; i++) {
11250    if (cache->get(proto_offset + i * step) == *prototype) {
11251      Object* result = cache->get(map_offset + i * step);
11252      return Handle<Map>(Map::cast(result));
11253    }
11254  }
11255  return Handle<Map>();
11256}
11257
11258
11259Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
11260                                        Handle<Object> prototype,
11261                                        Handle<Map> target_map) {
11262  DCHECK(target_map->IsMap());
11263  DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
11264  // Don't cache prototype transition if this map is either shared, or a map of
11265  // a prototype.
11266  if (map->is_prototype_map()) return map;
11267  if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;
11268
11269  const int step = kProtoTransitionElementsPerEntry;
11270  const int header = kProtoTransitionHeaderSize;
11271
11272  Handle<FixedArray> cache(map->GetPrototypeTransitions());
11273  int capacity = (cache->length() - header) / step;
11274  int transitions = map->NumberOfProtoTransitions() + 1;
11275
11276  if (transitions > capacity) {
11277    if (capacity > kMaxCachedPrototypeTransitions) return map;
11278
11279    // Grow array by factor 2 over and above what we need.
11280    cache = FixedArray::CopySize(cache, transitions * 2 * step + header);
11281
11282    SetPrototypeTransitions(map, cache);
11283  }
11284
11285  // Reload number of transitions as GC might shrink them.
11286  int last = map->NumberOfProtoTransitions();
11287  int entry = header + last * step;
11288
11289  cache->set(entry + kProtoTransitionPrototypeOffset, *prototype);
11290  cache->set(entry + kProtoTransitionMapOffset, *target_map);
11291  map->SetNumberOfProtoTransitions(last + 1);
11292
11293  return map;
11294}
11295
11296
11297void Map::ZapTransitions() {
11298  TransitionArray* transition_array = transitions();
11299  // TODO(mstarzinger): Temporarily use a slower version instead of the faster
11300  // MemsetPointer to investigate a crasher. Switch back to MemsetPointer.
11301  Object** data = transition_array->data_start();
11302  Object* the_hole = GetHeap()->the_hole_value();
11303  int length = transition_array->length();
11304  for (int i = 0; i < length; i++) {
11305    data[i] = the_hole;
11306  }
11307}
11308
11309
11310void Map::ZapPrototypeTransitions() {
11311  FixedArray* proto_transitions = GetPrototypeTransitions();
11312  MemsetPointer(proto_transitions->data_start(),
11313                GetHeap()->the_hole_value(),
11314                proto_transitions->length());
11315}
11316
11317
11318// static
11319void Map::AddDependentCompilationInfo(Handle<Map> map,
11320                                      DependentCode::DependencyGroup group,
11321                                      CompilationInfo* info) {
11322  Handle<DependentCode> codes =
11323      DependentCode::Insert(handle(map->dependent_code(), info->isolate()),
11324                            group, info->object_wrapper());
11325  if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11326  info->dependencies(group)->Add(map, info->zone());
11327}
11328
11329
11330// static
11331void Map::AddDependentCode(Handle<Map> map,
11332                           DependentCode::DependencyGroup group,
11333                           Handle<Code> code) {
11334  Handle<DependentCode> codes = DependentCode::Insert(
11335      Handle<DependentCode>(map->dependent_code()), group, code);
11336  if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11337}
11338
11339
11340// static
11341void Map::AddDependentIC(Handle<Map> map,
11342                         Handle<Code> stub) {
11343  DCHECK(stub->next_code_link()->IsUndefined());
11344  int n = map->dependent_code()->number_of_entries(DependentCode::kWeakICGroup);
11345  if (n == 0) {
11346    // Slow path: insert the head of the list with possible heap allocation.
11347    Map::AddDependentCode(map, DependentCode::kWeakICGroup, stub);
11348  } else {
11349    // Fast path: link the stub to the existing head of the list without any
11350    // heap allocation.
11351    DCHECK(n == 1);
11352    map->dependent_code()->AddToDependentICList(stub);
11353  }
11354}
11355
11356
11357DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
11358  Recompute(entries);
11359}
11360
11361
11362void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
11363  start_indexes_[0] = 0;
11364  for (int g = 1; g <= kGroupCount; g++) {
11365    int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
11366    start_indexes_[g] = start_indexes_[g - 1] + count;
11367  }
11368}
11369
11370
11371DependentCode* DependentCode::ForObject(Handle<HeapObject> object,
11372                                        DependencyGroup group) {
11373  AllowDeferredHandleDereference dependencies_are_safe;
11374  if (group == DependentCode::kPropertyCellChangedGroup) {
11375    return Handle<PropertyCell>::cast(object)->dependent_code();
11376  } else if (group == DependentCode::kAllocationSiteTenuringChangedGroup ||
11377      group == DependentCode::kAllocationSiteTransitionChangedGroup) {
11378    return Handle<AllocationSite>::cast(object)->dependent_code();
11379  }
11380  return Handle<Map>::cast(object)->dependent_code();
11381}
11382
11383
11384Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
11385                                            DependencyGroup group,
11386                                            Handle<Object> object) {
11387  GroupStartIndexes starts(*entries);
11388  int start = starts.at(group);
11389  int end = starts.at(group + 1);
11390  int number_of_entries = starts.number_of_entries();
11391  // Check for existing entry to avoid duplicates.
11392  for (int i = start; i < end; i++) {
11393    if (entries->object_at(i) == *object) return entries;
11394  }
11395  if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
11396    int capacity = kCodesStartIndex + number_of_entries + 1;
11397    if (capacity > 5) capacity = capacity * 5 / 4;
11398    Handle<DependentCode> new_entries = Handle<DependentCode>::cast(
11399        FixedArray::CopySize(entries, capacity, TENURED));
11400    // The number of codes can change after GC.
11401    starts.Recompute(*entries);
11402    start = starts.at(group);
11403    end = starts.at(group + 1);
11404    number_of_entries = starts.number_of_entries();
11405    for (int i = 0; i < number_of_entries; i++) {
11406      entries->clear_at(i);
11407    }
11408    // If the old fixed array was empty, we need to reset counters of the
11409    // new array.
11410    if (number_of_entries == 0) {
11411      for (int g = 0; g < kGroupCount; g++) {
11412        new_entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
11413      }
11414    }
11415    entries = new_entries;
11416  }
11417  entries->ExtendGroup(group);
11418  entries->set_object_at(end, *object);
11419  entries->set_number_of_entries(group, end + 1 - start);
11420  return entries;
11421}
11422
11423
11424void DependentCode::UpdateToFinishedCode(DependencyGroup group,
11425                                         CompilationInfo* info,
11426                                         Code* code) {
11427  DisallowHeapAllocation no_gc;
11428  AllowDeferredHandleDereference get_object_wrapper;
11429  Foreign* info_wrapper = *info->object_wrapper();
11430  GroupStartIndexes starts(this);
11431  int start = starts.at(group);
11432  int end = starts.at(group + 1);
11433  for (int i = start; i < end; i++) {
11434    if (object_at(i) == info_wrapper) {
11435      set_object_at(i, code);
11436      break;
11437    }
11438  }
11439
11440#ifdef DEBUG
11441  for (int i = start; i < end; i++) {
11442    DCHECK(is_code_at(i) || compilation_info_at(i) != info);
11443  }
11444#endif
11445}
11446
11447
11448void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
11449                                          CompilationInfo* info) {
11450  DisallowHeapAllocation no_allocation;
11451  AllowDeferredHandleDereference get_object_wrapper;
11452  Foreign* info_wrapper = *info->object_wrapper();
11453  GroupStartIndexes starts(this);
11454  int start = starts.at(group);
11455  int end = starts.at(group + 1);
11456  // Find compilation info wrapper.
11457  int info_pos = -1;
11458  for (int i = start; i < end; i++) {
11459    if (object_at(i) == info_wrapper) {
11460      info_pos = i;
11461      break;
11462    }
11463  }
11464  if (info_pos == -1) return;  // Not found.
11465  int gap = info_pos;
11466  // Use the last of each group to fill the gap in the previous group.
11467  for (int i = group; i < kGroupCount; i++) {
11468    int last_of_group = starts.at(i + 1) - 1;
11469    DCHECK(last_of_group >= gap);
11470    if (last_of_group == gap) continue;
11471    copy(last_of_group, gap);
11472    gap = last_of_group;
11473  }
11474  DCHECK(gap == starts.number_of_entries() - 1);
11475  clear_at(gap);  // Clear last gap.
11476  set_number_of_entries(group, end - start - 1);
11477
11478#ifdef DEBUG
11479  for (int i = start; i < end - 1; i++) {
11480    DCHECK(is_code_at(i) || compilation_info_at(i) != info);
11481  }
11482#endif
11483}
11484
11485
11486static bool CodeListContains(Object* head, Code* code) {
11487  while (!head->IsUndefined()) {
11488    if (head == code) return true;
11489    head = Code::cast(head)->next_code_link();
11490  }
11491  return false;
11492}
11493
11494
11495bool DependentCode::Contains(DependencyGroup group, Code* code) {
11496  GroupStartIndexes starts(this);
11497  int start = starts.at(group);
11498  int end = starts.at(group + 1);
11499  if (group == kWeakICGroup) {
11500    return CodeListContains(object_at(start), code);
11501  }
11502  for (int i = start; i < end; i++) {
11503    if (object_at(i) == code) return true;
11504  }
11505  return false;
11506}
11507
11508
11509bool DependentCode::MarkCodeForDeoptimization(
11510    Isolate* isolate,
11511    DependentCode::DependencyGroup group) {
11512  DisallowHeapAllocation no_allocation_scope;
11513  DependentCode::GroupStartIndexes starts(this);
11514  int start = starts.at(group);
11515  int end = starts.at(group + 1);
11516  int code_entries = starts.number_of_entries();
11517  if (start == end) return false;
11518
11519  // Mark all the code that needs to be deoptimized.
11520  bool marked = false;
11521  for (int i = start; i < end; i++) {
11522    if (is_code_at(i)) {
11523      Code* code = code_at(i);
11524      if (!code->marked_for_deoptimization()) {
11525        SetMarkedForDeoptimization(code, group);
11526        marked = true;
11527      }
11528    } else {
11529      CompilationInfo* info = compilation_info_at(i);
11530      info->AbortDueToDependencyChange();
11531    }
11532  }
11533  // Compact the array by moving all subsequent groups to fill in the new holes.
11534  for (int src = end, dst = start; src < code_entries; src++, dst++) {
11535    copy(src, dst);
11536  }
11537  // Now the holes are at the end of the array, zap them for heap-verifier.
11538  int removed = end - start;
11539  for (int i = code_entries - removed; i < code_entries; i++) {
11540    clear_at(i);
11541  }
11542  set_number_of_entries(group, 0);
11543  return marked;
11544}
11545
11546
11547void DependentCode::DeoptimizeDependentCodeGroup(
11548    Isolate* isolate,
11549    DependentCode::DependencyGroup group) {
11550  DCHECK(AllowCodeDependencyChange::IsAllowed());
11551  DisallowHeapAllocation no_allocation_scope;
11552  bool marked = MarkCodeForDeoptimization(isolate, group);
11553
11554  if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
11555}
11556
11557
11558void DependentCode::AddToDependentICList(Handle<Code> stub) {
11559  DisallowHeapAllocation no_heap_allocation;
11560  GroupStartIndexes starts(this);
11561  int i = starts.at(kWeakICGroup);
11562  Object* head = object_at(i);
11563  // Try to insert the stub after the head of the list to minimize number of
11564  // writes to the DependentCode array, since a write to the array can make it
11565  // strong if it was alread marked by incremental marker.
11566  if (head->IsCode()) {
11567    stub->set_next_code_link(Code::cast(head)->next_code_link());
11568    Code::cast(head)->set_next_code_link(*stub);
11569  } else {
11570    stub->set_next_code_link(head);
11571    set_object_at(i, *stub);
11572  }
11573}
11574
11575
11576void DependentCode::SetMarkedForDeoptimization(Code* code,
11577                                               DependencyGroup group) {
11578  code->set_marked_for_deoptimization(true);
11579  if (FLAG_trace_deopt &&
11580      (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
11581    DeoptimizationInputData* deopt_data =
11582        DeoptimizationInputData::cast(code->deoptimization_data());
11583    CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
11584    PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
11585                         " (opt #%d) for deoptimization, reason: %s]\n",
11586           reinterpret_cast<intptr_t>(code),
11587           deopt_data->OptimizationId()->value(), DependencyGroupName(group));
11588  }
11589}
11590
11591
11592const char* DependentCode::DependencyGroupName(DependencyGroup group) {
11593  switch (group) {
11594    case kWeakICGroup:
11595      return "weak-ic";
11596    case kWeakCodeGroup:
11597      return "weak-code";
11598    case kTransitionGroup:
11599      return "transition";
11600    case kPrototypeCheckGroup:
11601      return "prototype-check";
11602    case kElementsCantBeAddedGroup:
11603      return "elements-cant-be-added";
11604    case kPropertyCellChangedGroup:
11605      return "property-cell-changed";
11606    case kFieldTypeGroup:
11607      return "field-type";
11608    case kInitialMapChangedGroup:
11609      return "initial-map-changed";
11610    case kAllocationSiteTenuringChangedGroup:
11611      return "allocation-site-tenuring-changed";
11612    case kAllocationSiteTransitionChangedGroup:
11613      return "allocation-site-transition-changed";
11614  }
11615  UNREACHABLE();
11616  return "?";
11617}
11618
11619
11620Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
11621                                       Handle<Object> prototype) {
11622  Handle<Map> new_map = GetPrototypeTransition(map, prototype);
11623  if (new_map.is_null()) {
11624    new_map = Copy(map);
11625    PutPrototypeTransition(map, prototype, new_map);
11626    new_map->set_prototype(*prototype);
11627  }
11628  return new_map;
11629}
11630
11631
11632MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
11633                                           Handle<Object> value,
11634                                           bool from_javascript) {
11635#ifdef DEBUG
11636  int size = object->Size();
11637#endif
11638
11639  Isolate* isolate = object->GetIsolate();
11640  Heap* heap = isolate->heap();
11641  // Silently ignore the change if value is not a JSObject or null.
11642  // SpiderMonkey behaves this way.
11643  if (!value->IsJSReceiver() && !value->IsNull()) return value;
11644
11645  // From 8.6.2 Object Internal Methods
11646  // ...
11647  // In addition, if [[Extensible]] is false the value of the [[Class]] and
11648  // [[Prototype]] internal properties of the object may not be modified.
11649  // ...
11650  // Implementation specific extensions that modify [[Class]], [[Prototype]]
11651  // or [[Extensible]] must not violate the invariants defined in the preceding
11652  // paragraph.
11653  if (!object->map()->is_extensible()) {
11654    Handle<Object> args[] = { object };
11655    THROW_NEW_ERROR(isolate, NewTypeError("non_extensible_proto",
11656                                          HandleVector(args, arraysize(args))),
11657                    Object);
11658  }
11659
11660  // Before we can set the prototype we need to be sure
11661  // prototype cycles are prevented.
11662  // It is sufficient to validate that the receiver is not in the new prototype
11663  // chain.
11664  for (PrototypeIterator iter(isolate, *value,
11665                              PrototypeIterator::START_AT_RECEIVER);
11666       !iter.IsAtEnd(); iter.Advance()) {
11667    if (JSReceiver::cast(iter.GetCurrent()) == *object) {
11668      // Cycle detected.
11669      THROW_NEW_ERROR(isolate,
11670                      NewError("cyclic_proto", HandleVector<Object>(NULL, 0)),
11671                      Object);
11672    }
11673  }
11674
11675  bool dictionary_elements_in_chain =
11676      object->map()->DictionaryElementsInPrototypeChainOnly();
11677  Handle<JSObject> real_receiver = object;
11678
11679  if (from_javascript) {
11680    // Find the first object in the chain whose prototype object is not
11681    // hidden and set the new prototype on that object.
11682    PrototypeIterator iter(isolate, real_receiver);
11683    while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
11684      real_receiver =
11685          Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
11686      iter.Advance();
11687    }
11688  }
11689
11690  // Set the new prototype of the object.
11691  Handle<Map> map(real_receiver->map());
11692
11693  // Nothing to do if prototype is already set.
11694  if (map->prototype() == *value) return value;
11695
11696  if (value->IsJSObject()) {
11697    PrototypeOptimizationMode mode =
11698        from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
11699    JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value), mode);
11700  }
11701
11702  Handle<Map> new_map = Map::TransitionToPrototype(map, value);
11703  DCHECK(new_map->prototype() == *value);
11704  JSObject::MigrateToMap(real_receiver, new_map);
11705
11706  if (!dictionary_elements_in_chain &&
11707      new_map->DictionaryElementsInPrototypeChainOnly()) {
11708    // If the prototype chain didn't previously have element callbacks, then
11709    // KeyedStoreICs need to be cleared to ensure any that involve this
11710    // map go generic.
11711    object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
11712  }
11713
11714  heap->ClearInstanceofCache();
11715  DCHECK(size == object->Size());
11716  return value;
11717}
11718
11719
11720void JSObject::EnsureCanContainElements(Handle<JSObject> object,
11721                                        Arguments* args,
11722                                        uint32_t first_arg,
11723                                        uint32_t arg_count,
11724                                        EnsureElementsMode mode) {
11725  // Elements in |Arguments| are ordered backwards (because they're on the
11726  // stack), but the method that's called here iterates over them in forward
11727  // direction.
11728  return EnsureCanContainElements(
11729      object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
11730}
11731
11732
11733MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair(
11734    Handle<JSObject> object,
11735    uint32_t index) {
11736  if (object->IsJSGlobalProxy()) {
11737    PrototypeIterator iter(object->GetIsolate(), object);
11738    if (iter.IsAtEnd()) return MaybeHandle<AccessorPair>();
11739    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
11740    return GetOwnElementAccessorPair(
11741        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
11742  }
11743
11744  // Check for lookup interceptor.
11745  if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>();
11746
11747  return object->GetElementsAccessor()->GetAccessorPair(object, object, index);
11748}
11749
11750
11751MaybeHandle<Object> JSObject::SetElementWithInterceptor(
11752    Handle<JSObject> object,
11753    uint32_t index,
11754    Handle<Object> value,
11755    PropertyAttributes attributes,
11756    StrictMode strict_mode,
11757    bool check_prototype,
11758    SetPropertyMode set_mode) {
11759  Isolate* isolate = object->GetIsolate();
11760
11761  // Make sure that the top context does not change when doing
11762  // callbacks or interceptor calls.
11763  AssertNoContextChange ncc(isolate);
11764
11765  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
11766  if (!interceptor->setter()->IsUndefined()) {
11767    v8::IndexedPropertySetterCallback setter =
11768        v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
11769    LOG(isolate,
11770        ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
11771    PropertyCallbackArguments args(isolate, interceptor->data(), *object,
11772                                   *object);
11773    v8::Handle<v8::Value> result =
11774        args.Call(setter, index, v8::Utils::ToLocal(value));
11775    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
11776    if (!result.IsEmpty()) return value;
11777  }
11778
11779  return SetElementWithoutInterceptor(object, index, value, attributes,
11780                                      strict_mode,
11781                                      check_prototype,
11782                                      set_mode);
11783}
11784
11785
11786MaybeHandle<Object> JSObject::GetElementWithCallback(
11787    Handle<JSObject> object,
11788    Handle<Object> receiver,
11789    Handle<Object> structure,
11790    uint32_t index,
11791    Handle<Object> holder) {
11792  Isolate* isolate = object->GetIsolate();
11793  DCHECK(!structure->IsForeign());
11794  // api style callbacks.
11795  if (structure->IsExecutableAccessorInfo()) {
11796    Handle<ExecutableAccessorInfo> data =
11797        Handle<ExecutableAccessorInfo>::cast(structure);
11798    Object* fun_obj = data->getter();
11799    v8::AccessorNameGetterCallback call_fun =
11800        v8::ToCData<v8::AccessorNameGetterCallback>(fun_obj);
11801    if (call_fun == NULL) return isolate->factory()->undefined_value();
11802    Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder);
11803    Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
11804    Handle<String> key = isolate->factory()->NumberToString(number);
11805    LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key));
11806    PropertyCallbackArguments
11807        args(isolate, data->data(), *receiver, *holder_handle);
11808    v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
11809    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
11810    if (result.IsEmpty()) return isolate->factory()->undefined_value();
11811    Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
11812    result_internal->VerifyApiCallResultType();
11813    // Rebox handle before return.
11814    return handle(*result_internal, isolate);
11815  }
11816
11817  // __defineGetter__ callback
11818  if (structure->IsAccessorPair()) {
11819    Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
11820                          isolate);
11821    if (getter->IsSpecFunction()) {
11822      // TODO(rossberg): nicer would be to cast to some JSCallable here...
11823      return GetPropertyWithDefinedGetter(
11824          receiver, Handle<JSReceiver>::cast(getter));
11825    }
11826    // Getter is not a function.
11827    return isolate->factory()->undefined_value();
11828  }
11829
11830  if (structure->IsDeclaredAccessorInfo()) {
11831    return GetDeclaredAccessorProperty(
11832        receiver, Handle<DeclaredAccessorInfo>::cast(structure), isolate);
11833  }
11834
11835  UNREACHABLE();
11836  return MaybeHandle<Object>();
11837}
11838
11839
11840MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
11841                                                     Handle<Object> structure,
11842                                                     uint32_t index,
11843                                                     Handle<Object> value,
11844                                                     Handle<JSObject> holder,
11845                                                     StrictMode strict_mode) {
11846  Isolate* isolate = object->GetIsolate();
11847
11848  // We should never get here to initialize a const with the hole
11849  // value since a const declaration would conflict with the setter.
11850  DCHECK(!value->IsTheHole());
11851  DCHECK(!structure->IsForeign());
11852  if (structure->IsExecutableAccessorInfo()) {
11853    // api style callbacks
11854    Handle<ExecutableAccessorInfo> data =
11855        Handle<ExecutableAccessorInfo>::cast(structure);
11856    Object* call_obj = data->setter();
11857    v8::AccessorNameSetterCallback call_fun =
11858        v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
11859    if (call_fun == NULL) return value;
11860    Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
11861    Handle<String> key(isolate->factory()->NumberToString(number));
11862    LOG(isolate, ApiNamedPropertyAccess("store", *object, *key));
11863    PropertyCallbackArguments
11864        args(isolate, data->data(), *object, *holder);
11865    args.Call(call_fun,
11866              v8::Utils::ToLocal(key),
11867              v8::Utils::ToLocal(value));
11868    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
11869    return value;
11870  }
11871
11872  if (structure->IsAccessorPair()) {
11873    Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
11874    if (setter->IsSpecFunction()) {
11875      // TODO(rossberg): nicer would be to cast to some JSCallable here...
11876      return SetPropertyWithDefinedSetter(
11877          object, Handle<JSReceiver>::cast(setter), value);
11878    } else {
11879      if (strict_mode == SLOPPY) return value;
11880      Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
11881      Handle<Object> args[2] = { key, holder };
11882      THROW_NEW_ERROR(
11883          isolate, NewTypeError("no_setter_in_callback", HandleVector(args, 2)),
11884          Object);
11885    }
11886  }
11887
11888  // TODO(dcarney): Handle correctly.
11889  if (structure->IsDeclaredAccessorInfo()) return value;
11890
11891  UNREACHABLE();
11892  return MaybeHandle<Object>();
11893}
11894
11895
11896bool JSObject::HasFastArgumentsElements() {
11897  Heap* heap = GetHeap();
11898  if (!elements()->IsFixedArray()) return false;
11899  FixedArray* elements = FixedArray::cast(this->elements());
11900  if (elements->map() != heap->sloppy_arguments_elements_map()) {
11901    return false;
11902  }
11903  FixedArray* arguments = FixedArray::cast(elements->get(1));
11904  return !arguments->IsDictionary();
11905}
11906
11907
11908bool JSObject::HasDictionaryArgumentsElements() {
11909  Heap* heap = GetHeap();
11910  if (!elements()->IsFixedArray()) return false;
11911  FixedArray* elements = FixedArray::cast(this->elements());
11912  if (elements->map() != heap->sloppy_arguments_elements_map()) {
11913    return false;
11914  }
11915  FixedArray* arguments = FixedArray::cast(elements->get(1));
11916  return arguments->IsDictionary();
11917}
11918
11919
11920// Adding n elements in fast case is O(n*n).
11921// Note: revisit design to have dual undefined values to capture absent
11922// elements.
11923MaybeHandle<Object> JSObject::SetFastElement(Handle<JSObject> object,
11924                                             uint32_t index,
11925                                             Handle<Object> value,
11926                                             StrictMode strict_mode,
11927                                             bool check_prototype) {
11928  DCHECK(object->HasFastSmiOrObjectElements() ||
11929         object->HasFastArgumentsElements());
11930
11931  Isolate* isolate = object->GetIsolate();
11932
11933  // Array optimizations rely on the prototype lookups of Array objects always
11934  // returning undefined. If there is a store to the initial prototype object,
11935  // make sure all of these optimizations are invalidated.
11936  if (isolate->is_initial_object_prototype(*object) ||
11937      isolate->is_initial_array_prototype(*object)) {
11938    object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate,
11939        DependentCode::kElementsCantBeAddedGroup);
11940  }
11941
11942  Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
11943  if (backing_store->map() ==
11944      isolate->heap()->sloppy_arguments_elements_map()) {
11945    backing_store = handle(FixedArray::cast(backing_store->get(1)));
11946  } else {
11947    backing_store = EnsureWritableFastElements(object);
11948  }
11949  uint32_t capacity = static_cast<uint32_t>(backing_store->length());
11950
11951  if (check_prototype &&
11952      (index >= capacity || backing_store->get(index)->IsTheHole())) {
11953    bool found;
11954    MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
11955        object, index, value, &found, strict_mode);
11956    if (found) return result;
11957  }
11958
11959  uint32_t new_capacity = capacity;
11960  // Check if the length property of this object needs to be updated.
11961  uint32_t array_length = 0;
11962  bool must_update_array_length = false;
11963  bool introduces_holes = true;
11964  if (object->IsJSArray()) {
11965    CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
11966    introduces_holes = index > array_length;
11967    if (index >= array_length) {
11968      must_update_array_length = true;
11969      array_length = index + 1;
11970    }
11971  } else {
11972    introduces_holes = index >= capacity;
11973  }
11974
11975  // If the array is growing, and it's not growth by a single element at the
11976  // end, make sure that the ElementsKind is HOLEY.
11977  ElementsKind elements_kind = object->GetElementsKind();
11978  if (introduces_holes &&
11979      IsFastElementsKind(elements_kind) &&
11980      !IsFastHoleyElementsKind(elements_kind)) {
11981    ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
11982    TransitionElementsKind(object, transitioned_kind);
11983  }
11984
11985  // Check if the capacity of the backing store needs to be increased, or if
11986  // a transition to slow elements is necessary.
11987  if (index >= capacity) {
11988    bool convert_to_slow = true;
11989    if ((index - capacity) < kMaxGap) {
11990      new_capacity = NewElementsCapacity(index + 1);
11991      DCHECK(new_capacity > index);
11992      if (!object->ShouldConvertToSlowElements(new_capacity)) {
11993        convert_to_slow = false;
11994      }
11995    }
11996    if (convert_to_slow) {
11997      NormalizeElements(object);
11998      return SetDictionaryElement(object, index, value, NONE, strict_mode,
11999                                  check_prototype);
12000    }
12001  }
12002  // Convert to fast double elements if appropriate.
12003  if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12004    // Consider fixing the boilerplate as well if we have one.
12005    ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
12006        ? FAST_HOLEY_DOUBLE_ELEMENTS
12007        : FAST_DOUBLE_ELEMENTS;
12008
12009    UpdateAllocationSite(object, to_kind);
12010
12011    SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12012    FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12013    JSObject::ValidateElements(object);
12014    return value;
12015  }
12016  // Change elements kind from Smi-only to generic FAST if necessary.
12017  if (object->HasFastSmiElements() && !value->IsSmi()) {
12018    ElementsKind kind = object->HasFastHoleyElements()
12019        ? FAST_HOLEY_ELEMENTS
12020        : FAST_ELEMENTS;
12021
12022    UpdateAllocationSite(object, kind);
12023    Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12024    JSObject::MigrateToMap(object, new_map);
12025    DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12026  }
12027  // Increase backing store capacity if that's been decided previously.
12028  if (new_capacity != capacity) {
12029    SetFastElementsCapacitySmiMode smi_mode =
12030        value->IsSmi() && object->HasFastSmiElements()
12031            ? kAllowSmiElements
12032            : kDontAllowSmiElements;
12033    Handle<FixedArray> new_elements =
12034        SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12035                                         smi_mode);
12036    new_elements->set(index, *value);
12037    JSObject::ValidateElements(object);
12038    return value;
12039  }
12040
12041  // Finally, set the new element and length.
12042  DCHECK(object->elements()->IsFixedArray());
12043  backing_store->set(index, *value);
12044  if (must_update_array_length) {
12045    Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12046  }
12047  return value;
12048}
12049
12050
12051MaybeHandle<Object> JSObject::SetDictionaryElement(
12052    Handle<JSObject> object,
12053    uint32_t index,
12054    Handle<Object> value,
12055    PropertyAttributes attributes,
12056    StrictMode strict_mode,
12057    bool check_prototype,
12058    SetPropertyMode set_mode) {
12059  DCHECK(object->HasDictionaryElements() ||
12060         object->HasDictionaryArgumentsElements());
12061  Isolate* isolate = object->GetIsolate();
12062
12063  // Insert element in the dictionary.
12064  Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12065  bool is_arguments =
12066      (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12067  Handle<SeededNumberDictionary> dictionary(is_arguments
12068    ? SeededNumberDictionary::cast(elements->get(1))
12069    : SeededNumberDictionary::cast(*elements));
12070
12071  int entry = dictionary->FindEntry(index);
12072  if (entry != SeededNumberDictionary::kNotFound) {
12073    Handle<Object> element(dictionary->ValueAt(entry), isolate);
12074    PropertyDetails details = dictionary->DetailsAt(entry);
12075    if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
12076      return SetElementWithCallback(object, element, index, value, object,
12077                                    strict_mode);
12078    } else {
12079      dictionary->UpdateMaxNumberKey(index);
12080      // If a value has not been initialized we allow writing to it even if it
12081      // is read-only (a declared const that has not been initialized).  If a
12082      // value is being defined we skip attribute checks completely.
12083      if (set_mode == DEFINE_PROPERTY) {
12084        details = PropertyDetails(
12085            attributes, NORMAL, details.dictionary_index());
12086        dictionary->DetailsAtPut(entry, details);
12087      } else if (details.IsReadOnly() && !element->IsTheHole()) {
12088        if (strict_mode == SLOPPY) {
12089          return isolate->factory()->undefined_value();
12090        } else {
12091          Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12092          Handle<Object> args[2] = { number, object };
12093          THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
12094                                                HandleVector(args, 2)),
12095                          Object);
12096        }
12097      }
12098      // Elements of the arguments object in slow mode might be slow aliases.
12099      if (is_arguments && element->IsAliasedArgumentsEntry()) {
12100        Handle<AliasedArgumentsEntry> entry =
12101            Handle<AliasedArgumentsEntry>::cast(element);
12102        Handle<Context> context(Context::cast(elements->get(0)));
12103        int context_index = entry->aliased_context_slot();
12104        DCHECK(!context->get(context_index)->IsTheHole());
12105        context->set(context_index, *value);
12106        // For elements that are still writable we keep slow aliasing.
12107        if (!details.IsReadOnly()) value = element;
12108      }
12109      dictionary->ValueAtPut(entry, *value);
12110    }
12111  } else {
12112    // Index not already used. Look for an accessor in the prototype chain.
12113    // Can cause GC!
12114    if (check_prototype) {
12115      bool found;
12116      MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12117          object, index, value, &found, strict_mode);
12118      if (found) return result;
12119    }
12120
12121    // When we set the is_extensible flag to false we always force the
12122    // element into dictionary mode (and force them to stay there).
12123    if (!object->map()->is_extensible()) {
12124      if (strict_mode == SLOPPY) {
12125        return isolate->factory()->undefined_value();
12126      } else {
12127        Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12128        Handle<String> name = isolate->factory()->NumberToString(number);
12129        Handle<Object> args[1] = { name };
12130        THROW_NEW_ERROR(isolate, NewTypeError("object_not_extensible",
12131                                              HandleVector(args, 1)),
12132                        Object);
12133      }
12134    }
12135
12136    PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
12137    Handle<SeededNumberDictionary> new_dictionary =
12138        SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
12139                                               details);
12140    if (*dictionary != *new_dictionary) {
12141      if (is_arguments) {
12142        elements->set(1, *new_dictionary);
12143      } else {
12144        object->set_elements(*new_dictionary);
12145      }
12146      dictionary = new_dictionary;
12147    }
12148  }
12149
12150  // Update the array length if this JSObject is an array.
12151  if (object->IsJSArray()) {
12152    JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index,
12153                                          value);
12154  }
12155
12156  // Attempt to put this object back in fast case.
12157  if (object->ShouldConvertToFastElements()) {
12158    uint32_t new_length = 0;
12159    if (object->IsJSArray()) {
12160      CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length));
12161    } else {
12162      new_length = dictionary->max_number_key() + 1;
12163    }
12164    bool has_smi_only_elements = false;
12165    bool should_convert_to_fast_double_elements =
12166        object->ShouldConvertToFastDoubleElements(&has_smi_only_elements);
12167    SetFastElementsCapacitySmiMode smi_mode =
12168        has_smi_only_elements ? kForceSmiElements : kAllowSmiElements;
12169
12170    if (should_convert_to_fast_double_elements) {
12171      SetFastDoubleElementsCapacityAndLength(object, new_length, new_length);
12172    } else {
12173      SetFastElementsCapacityAndLength(object, new_length, new_length,
12174                                       smi_mode);
12175    }
12176    JSObject::ValidateElements(object);
12177#ifdef DEBUG
12178    if (FLAG_trace_normalization) {
12179      OFStream os(stdout);
12180      os << "Object elements are fast case again:\n";
12181      object->Print(os);
12182    }
12183#endif
12184  }
12185  return value;
12186}
12187
12188MaybeHandle<Object> JSObject::SetFastDoubleElement(
12189    Handle<JSObject> object,
12190    uint32_t index,
12191    Handle<Object> value,
12192    StrictMode strict_mode,
12193    bool check_prototype) {
12194  DCHECK(object->HasFastDoubleElements());
12195
12196  Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12197  uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
12198
12199  // If storing to an element that isn't in the array, pass the store request
12200  // up the prototype chain before storing in the receiver's elements.
12201  if (check_prototype &&
12202      (index >= elms_length ||
12203       Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
12204    bool found;
12205    MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12206        object, index, value, &found, strict_mode);
12207    if (found) return result;
12208  }
12209
12210  // If the value object is not a heap number, switch to fast elements and try
12211  // again.
12212  bool value_is_smi = value->IsSmi();
12213  bool introduces_holes = true;
12214  uint32_t length = elms_length;
12215  if (object->IsJSArray()) {
12216    CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length));
12217    introduces_holes = index > length;
12218  } else {
12219    introduces_holes = index >= elms_length;
12220  }
12221
12222  if (!value->IsNumber()) {
12223    SetFastElementsCapacityAndLength(object, elms_length, length,
12224                                     kDontAllowSmiElements);
12225    Handle<Object> result;
12226    ASSIGN_RETURN_ON_EXCEPTION(
12227        object->GetIsolate(), result,
12228        SetFastElement(object, index, value, strict_mode, check_prototype),
12229        Object);
12230    JSObject::ValidateElements(object);
12231    return result;
12232  }
12233
12234  double double_value = value_is_smi
12235      ? static_cast<double>(Handle<Smi>::cast(value)->value())
12236      : Handle<HeapNumber>::cast(value)->value();
12237
12238  // If the array is growing, and it's not growth by a single element at the
12239  // end, make sure that the ElementsKind is HOLEY.
12240  ElementsKind elements_kind = object->GetElementsKind();
12241  if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
12242    ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12243    TransitionElementsKind(object, transitioned_kind);
12244  }
12245
12246  // Check whether there is extra space in the fixed array.
12247  if (index < elms_length) {
12248    Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
12249    elms->set(index, double_value);
12250    if (object->IsJSArray()) {
12251      // Update the length of the array if needed.
12252      uint32_t array_length = 0;
12253      CHECK(
12254          Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12255      if (index >= array_length) {
12256        Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12257      }
12258    }
12259    return value;
12260  }
12261
12262  // Allow gap in fast case.
12263  if ((index - elms_length) < kMaxGap) {
12264    // Try allocating extra space.
12265    int new_capacity = NewElementsCapacity(index+1);
12266    if (!object->ShouldConvertToSlowElements(new_capacity)) {
12267      DCHECK(static_cast<uint32_t>(new_capacity) > index);
12268      SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
12269      FixedDoubleArray::cast(object->elements())->set(index, double_value);
12270      JSObject::ValidateElements(object);
12271      return value;
12272    }
12273  }
12274
12275  // Otherwise default to slow case.
12276  DCHECK(object->HasFastDoubleElements());
12277  DCHECK(object->map()->has_fast_double_elements());
12278  DCHECK(object->elements()->IsFixedDoubleArray() ||
12279         object->elements()->length() == 0);
12280
12281  NormalizeElements(object);
12282  DCHECK(object->HasDictionaryElements());
12283  return SetElement(object, index, value, NONE, strict_mode, check_prototype);
12284}
12285
12286
12287MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12288                                           uint32_t index,
12289                                           Handle<Object> value,
12290                                           PropertyAttributes attributes,
12291                                           StrictMode strict_mode) {
12292  if (object->IsJSProxy()) {
12293    return JSProxy::SetElementWithHandler(
12294        Handle<JSProxy>::cast(object), object, index, value, strict_mode);
12295  }
12296  return JSObject::SetElement(
12297      Handle<JSObject>::cast(object), index, value, attributes, strict_mode);
12298}
12299
12300
12301MaybeHandle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
12302                                            uint32_t index,
12303                                            Handle<Object> value,
12304                                            StrictMode strict_mode) {
12305  DCHECK(!object->HasExternalArrayElements());
12306  return JSObject::SetElement(object, index, value, NONE, strict_mode, false);
12307}
12308
12309
12310MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object,
12311                                         uint32_t index,
12312                                         Handle<Object> value,
12313                                         PropertyAttributes attributes,
12314                                         StrictMode strict_mode,
12315                                         bool check_prototype,
12316                                         SetPropertyMode set_mode) {
12317  Isolate* isolate = object->GetIsolate();
12318
12319  if (object->HasExternalArrayElements() ||
12320      object->HasFixedTypedArrayElements()) {
12321    if (!value->IsNumber() && !value->IsUndefined()) {
12322      ASSIGN_RETURN_ON_EXCEPTION(
12323          isolate, value,
12324          Execution::ToNumber(isolate, value), Object);
12325    }
12326  }
12327
12328  // Check access rights if needed.
12329  if (object->IsAccessCheckNeeded()) {
12330    if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_SET)) {
12331      isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
12332      RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12333      return value;
12334    }
12335  }
12336
12337  if (object->IsJSGlobalProxy()) {
12338    PrototypeIterator iter(isolate, object);
12339    if (iter.IsAtEnd()) return value;
12340    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
12341    return SetElement(
12342        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index,
12343        value, attributes, strict_mode, check_prototype, set_mode);
12344  }
12345
12346  // Don't allow element properties to be redefined for external arrays.
12347  if ((object->HasExternalArrayElements() ||
12348          object->HasFixedTypedArrayElements()) &&
12349      set_mode == DEFINE_PROPERTY) {
12350    Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12351    Handle<Object> args[] = { object, number };
12352    THROW_NEW_ERROR(isolate, NewTypeError("redef_external_array_element",
12353                                          HandleVector(args, arraysize(args))),
12354                    Object);
12355  }
12356
12357  // Normalize the elements to enable attributes on the property.
12358  if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
12359    Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
12360    // Make sure that we never go back to fast case.
12361    dictionary->set_requires_slow_elements();
12362  }
12363
12364  if (!object->map()->is_observed()) {
12365    return object->HasIndexedInterceptor()
12366      ? SetElementWithInterceptor(object, index, value, attributes,
12367                                  strict_mode, check_prototype, set_mode)
12368      : SetElementWithoutInterceptor(object, index, value, attributes,
12369                                     strict_mode, check_prototype, set_mode);
12370  }
12371
12372  Maybe<PropertyAttributes> maybe =
12373      JSReceiver::GetOwnElementAttribute(object, index);
12374  if (!maybe.has_value) return MaybeHandle<Object>();
12375  PropertyAttributes old_attributes = maybe.value;
12376
12377  Handle<Object> old_value = isolate->factory()->the_hole_value();
12378  Handle<Object> old_length_handle;
12379  Handle<Object> new_length_handle;
12380
12381  if (old_attributes != ABSENT) {
12382    if (GetOwnElementAccessorPair(object, index).is_null()) {
12383      old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
12384    }
12385  } else if (object->IsJSArray()) {
12386    // Store old array length in case adding an element grows the array.
12387    old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
12388                               isolate);
12389  }
12390
12391  // Check for lookup interceptor
12392  Handle<Object> result;
12393  ASSIGN_RETURN_ON_EXCEPTION(
12394      isolate, result,
12395      object->HasIndexedInterceptor()
12396          ? SetElementWithInterceptor(
12397              object, index, value, attributes,
12398              strict_mode, check_prototype, set_mode)
12399          : SetElementWithoutInterceptor(
12400              object, index, value, attributes,
12401              strict_mode, check_prototype, set_mode),
12402      Object);
12403
12404  Handle<String> name = isolate->factory()->Uint32ToString(index);
12405  maybe = GetOwnElementAttribute(object, index);
12406  if (!maybe.has_value) return MaybeHandle<Object>();
12407  PropertyAttributes new_attributes = maybe.value;
12408
12409  if (old_attributes == ABSENT) {
12410    if (object->IsJSArray() &&
12411        !old_length_handle->SameValue(
12412            Handle<JSArray>::cast(object)->length())) {
12413      new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
12414                                 isolate);
12415      uint32_t old_length = 0;
12416      uint32_t new_length = 0;
12417      CHECK(old_length_handle->ToArrayIndex(&old_length));
12418      CHECK(new_length_handle->ToArrayIndex(&new_length));
12419
12420      BeginPerformSplice(Handle<JSArray>::cast(object));
12421      EnqueueChangeRecord(object, "add", name, old_value);
12422      EnqueueChangeRecord(object, "update", isolate->factory()->length_string(),
12423                          old_length_handle);
12424      EndPerformSplice(Handle<JSArray>::cast(object));
12425      Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12426      EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length, deleted,
12427                          new_length - old_length);
12428    } else {
12429      EnqueueChangeRecord(object, "add", name, old_value);
12430    }
12431  } else if (old_value->IsTheHole()) {
12432    EnqueueChangeRecord(object, "reconfigure", name, old_value);
12433  } else {
12434    Handle<Object> new_value =
12435        Object::GetElement(isolate, object, index).ToHandleChecked();
12436    bool value_changed = !old_value->SameValue(*new_value);
12437    if (old_attributes != new_attributes) {
12438      if (!value_changed) old_value = isolate->factory()->the_hole_value();
12439      EnqueueChangeRecord(object, "reconfigure", name, old_value);
12440    } else if (value_changed) {
12441      EnqueueChangeRecord(object, "update", name, old_value);
12442    }
12443  }
12444
12445  return result;
12446}
12447
12448
12449MaybeHandle<Object> JSObject::SetElementWithoutInterceptor(
12450    Handle<JSObject> object,
12451    uint32_t index,
12452    Handle<Object> value,
12453    PropertyAttributes attributes,
12454    StrictMode strict_mode,
12455    bool check_prototype,
12456    SetPropertyMode set_mode) {
12457  DCHECK(object->HasDictionaryElements() ||
12458         object->HasDictionaryArgumentsElements() ||
12459         (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
12460  Isolate* isolate = object->GetIsolate();
12461  if (FLAG_trace_external_array_abuse &&
12462      IsExternalArrayElementsKind(object->GetElementsKind())) {
12463    CheckArrayAbuse(object, "external elements write", index);
12464  }
12465  if (FLAG_trace_js_array_abuse &&
12466      !IsExternalArrayElementsKind(object->GetElementsKind())) {
12467    if (object->IsJSArray()) {
12468      CheckArrayAbuse(object, "elements write", index, true);
12469    }
12470  }
12471  if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
12472      Handle<JSArray>::cast(object), index)) {
12473    if (strict_mode == SLOPPY) {
12474      return value;
12475    } else {
12476      return JSArray::ReadOnlyLengthError(Handle<JSArray>::cast(object));
12477    }
12478  }
12479  switch (object->GetElementsKind()) {
12480    case FAST_SMI_ELEMENTS:
12481    case FAST_ELEMENTS:
12482    case FAST_HOLEY_SMI_ELEMENTS:
12483    case FAST_HOLEY_ELEMENTS:
12484      return SetFastElement(object, index, value, strict_mode, check_prototype);
12485    case FAST_DOUBLE_ELEMENTS:
12486    case FAST_HOLEY_DOUBLE_ELEMENTS:
12487      return SetFastDoubleElement(object, index, value, strict_mode,
12488                                  check_prototype);
12489
12490#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
12491    case EXTERNAL_##TYPE##_ELEMENTS: {                                        \
12492      Handle<External##Type##Array> array(                                    \
12493          External##Type##Array::cast(object->elements()));                   \
12494      return External##Type##Array::SetValue(array, index, value);            \
12495    }                                                                         \
12496    case TYPE##_ELEMENTS: {                                                   \
12497      Handle<Fixed##Type##Array> array(                                       \
12498          Fixed##Type##Array::cast(object->elements()));                      \
12499      return Fixed##Type##Array::SetValue(array, index, value);               \
12500    }
12501
12502    TYPED_ARRAYS(TYPED_ARRAY_CASE)
12503
12504#undef TYPED_ARRAY_CASE
12505
12506    case DICTIONARY_ELEMENTS:
12507      return SetDictionaryElement(object, index, value, attributes, strict_mode,
12508                                  check_prototype,
12509                                  set_mode);
12510    case SLOPPY_ARGUMENTS_ELEMENTS: {
12511      Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
12512      uint32_t length = parameter_map->length();
12513      Handle<Object> probe = index < length - 2 ?
12514          Handle<Object>(parameter_map->get(index + 2), isolate) :
12515          Handle<Object>();
12516      if (!probe.is_null() && !probe->IsTheHole()) {
12517        Handle<Context> context(Context::cast(parameter_map->get(0)));
12518        int context_index = Handle<Smi>::cast(probe)->value();
12519        DCHECK(!context->get(context_index)->IsTheHole());
12520        context->set(context_index, *value);
12521        // Redefining attributes of an aliased element destroys fast aliasing.
12522        if (set_mode == SET_PROPERTY || attributes == NONE) return value;
12523        parameter_map->set_the_hole(index + 2);
12524        // For elements that are still writable we re-establish slow aliasing.
12525        if ((attributes & READ_ONLY) == 0) {
12526          value = Handle<Object>::cast(
12527              isolate->factory()->NewAliasedArgumentsEntry(context_index));
12528        }
12529      }
12530      Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
12531      if (arguments->IsDictionary()) {
12532        return SetDictionaryElement(object, index, value, attributes,
12533                                    strict_mode,
12534                                    check_prototype,
12535                                    set_mode);
12536      } else {
12537        return SetFastElement(object, index, value, strict_mode,
12538                              check_prototype);
12539      }
12540    }
12541  }
12542  // All possible cases have been handled above. Add a return to avoid the
12543  // complaints from the compiler.
12544  UNREACHABLE();
12545  return isolate->factory()->null_value();
12546}
12547
12548
12549const double AllocationSite::kPretenureRatio = 0.85;
12550
12551
12552void AllocationSite::ResetPretenureDecision() {
12553  set_pretenure_decision(kUndecided);
12554  set_memento_found_count(0);
12555  set_memento_create_count(0);
12556}
12557
12558
12559PretenureFlag AllocationSite::GetPretenureMode() {
12560  PretenureDecision mode = pretenure_decision();
12561  // Zombie objects "decide" to be untenured.
12562  return mode == kTenure ? TENURED : NOT_TENURED;
12563}
12564
12565
12566bool AllocationSite::IsNestedSite() {
12567  DCHECK(FLAG_trace_track_allocation_sites);
12568  Object* current = GetHeap()->allocation_sites_list();
12569  while (current->IsAllocationSite()) {
12570    AllocationSite* current_site = AllocationSite::cast(current);
12571    if (current_site->nested_site() == this) {
12572      return true;
12573    }
12574    current = current_site->weak_next();
12575  }
12576  return false;
12577}
12578
12579
12580void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
12581                                              ElementsKind to_kind) {
12582  Isolate* isolate = site->GetIsolate();
12583
12584  if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
12585    Handle<JSArray> transition_info =
12586        handle(JSArray::cast(site->transition_info()));
12587    ElementsKind kind = transition_info->GetElementsKind();
12588    // if kind is holey ensure that to_kind is as well.
12589    if (IsHoleyElementsKind(kind)) {
12590      to_kind = GetHoleyElementsKind(to_kind);
12591    }
12592    if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12593      // If the array is huge, it's not likely to be defined in a local
12594      // function, so we shouldn't make new instances of it very often.
12595      uint32_t length = 0;
12596      CHECK(transition_info->length()->ToArrayIndex(&length));
12597      if (length <= kMaximumArrayBytesToPretransition) {
12598        if (FLAG_trace_track_allocation_sites) {
12599          bool is_nested = site->IsNestedSite();
12600          PrintF(
12601              "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
12602              reinterpret_cast<void*>(*site),
12603              is_nested ? "(nested)" : "",
12604              ElementsKindToString(kind),
12605              ElementsKindToString(to_kind));
12606        }
12607        JSObject::TransitionElementsKind(transition_info, to_kind);
12608        site->dependent_code()->DeoptimizeDependentCodeGroup(
12609            isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12610      }
12611    }
12612  } else {
12613    ElementsKind kind = site->GetElementsKind();
12614    // if kind is holey ensure that to_kind is as well.
12615    if (IsHoleyElementsKind(kind)) {
12616      to_kind = GetHoleyElementsKind(to_kind);
12617    }
12618    if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12619      if (FLAG_trace_track_allocation_sites) {
12620        PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
12621               reinterpret_cast<void*>(*site),
12622               ElementsKindToString(kind),
12623               ElementsKindToString(to_kind));
12624      }
12625      site->SetElementsKind(to_kind);
12626      site->dependent_code()->DeoptimizeDependentCodeGroup(
12627          isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
12628    }
12629  }
12630}
12631
12632
12633// static
12634void AllocationSite::AddDependentCompilationInfo(Handle<AllocationSite> site,
12635                                                 Reason reason,
12636                                                 CompilationInfo* info) {
12637  DependentCode::DependencyGroup group = site->ToDependencyGroup(reason);
12638  Handle<DependentCode> dep(site->dependent_code());
12639  Handle<DependentCode> codes =
12640      DependentCode::Insert(dep, group, info->object_wrapper());
12641  if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
12642  info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
12643}
12644
12645
12646const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
12647  switch (decision) {
12648    case kUndecided: return "undecided";
12649    case kDontTenure: return "don't tenure";
12650    case kMaybeTenure: return "maybe tenure";
12651    case kTenure: return "tenure";
12652    case kZombie: return "zombie";
12653    default: UNREACHABLE();
12654  }
12655  return NULL;
12656}
12657
12658
12659void JSObject::UpdateAllocationSite(Handle<JSObject> object,
12660                                    ElementsKind to_kind) {
12661  if (!object->IsJSArray()) return;
12662
12663  Heap* heap = object->GetHeap();
12664  if (!heap->InNewSpace(*object)) return;
12665
12666  Handle<AllocationSite> site;
12667  {
12668    DisallowHeapAllocation no_allocation;
12669
12670    AllocationMemento* memento = heap->FindAllocationMemento(*object);
12671    if (memento == NULL) return;
12672
12673    // Walk through to the Allocation Site
12674    site = handle(memento->GetAllocationSite());
12675  }
12676  AllocationSite::DigestTransitionFeedback(site, to_kind);
12677}
12678
12679
12680void JSObject::TransitionElementsKind(Handle<JSObject> object,
12681                                      ElementsKind to_kind) {
12682  ElementsKind from_kind = object->map()->elements_kind();
12683
12684  if (IsFastHoleyElementsKind(from_kind)) {
12685    to_kind = GetHoleyElementsKind(to_kind);
12686  }
12687
12688  if (from_kind == to_kind) return;
12689  // Don't update the site if to_kind isn't fast
12690  if (IsFastElementsKind(to_kind)) {
12691    UpdateAllocationSite(object, to_kind);
12692  }
12693
12694  Isolate* isolate = object->GetIsolate();
12695  if (object->elements() == isolate->heap()->empty_fixed_array() ||
12696      (IsFastSmiOrObjectElementsKind(from_kind) &&
12697       IsFastSmiOrObjectElementsKind(to_kind)) ||
12698      (from_kind == FAST_DOUBLE_ELEMENTS &&
12699       to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
12700    DCHECK(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
12701    // No change is needed to the elements() buffer, the transition
12702    // only requires a map change.
12703    Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
12704    MigrateToMap(object, new_map);
12705    if (FLAG_trace_elements_transitions) {
12706      Handle<FixedArrayBase> elms(object->elements());
12707      PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
12708    }
12709    return;
12710  }
12711
12712  Handle<FixedArrayBase> elms(object->elements());
12713  uint32_t capacity = static_cast<uint32_t>(elms->length());
12714  uint32_t length = capacity;
12715
12716  if (object->IsJSArray()) {
12717    Object* raw_length = Handle<JSArray>::cast(object)->length();
12718    if (raw_length->IsUndefined()) {
12719      // If length is undefined, then JSArray is being initialized and has no
12720      // elements, assume a length of zero.
12721      length = 0;
12722    } else {
12723      CHECK(raw_length->ToArrayIndex(&length));
12724    }
12725  }
12726
12727  if (IsFastSmiElementsKind(from_kind) &&
12728      IsFastDoubleElementsKind(to_kind)) {
12729    SetFastDoubleElementsCapacityAndLength(object, capacity, length);
12730    JSObject::ValidateElements(object);
12731    return;
12732  }
12733
12734  if (IsFastDoubleElementsKind(from_kind) &&
12735      IsFastObjectElementsKind(to_kind)) {
12736    SetFastElementsCapacityAndLength(object, capacity, length,
12737                                     kDontAllowSmiElements);
12738    JSObject::ValidateElements(object);
12739    return;
12740  }
12741
12742  // This method should never be called for any other case than the ones
12743  // handled above.
12744  UNREACHABLE();
12745}
12746
12747
12748// static
12749bool Map::IsValidElementsTransition(ElementsKind from_kind,
12750                                    ElementsKind to_kind) {
12751  // Transitions can't go backwards.
12752  if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
12753    return false;
12754  }
12755
12756  // Transitions from HOLEY -> PACKED are not allowed.
12757  return !IsFastHoleyElementsKind(from_kind) ||
12758      IsFastHoleyElementsKind(to_kind);
12759}
12760
12761
12762void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array,
12763                                           uint32_t index,
12764                                           Handle<Object> value) {
12765  uint32_t old_len = 0;
12766  CHECK(array->length()->ToArrayIndex(&old_len));
12767  // Check to see if we need to update the length. For now, we make
12768  // sure that the length stays within 32-bits (unsigned).
12769  if (index >= old_len && index != 0xffffffff) {
12770    Handle<Object> len = array->GetIsolate()->factory()->NewNumber(
12771        static_cast<double>(index) + 1);
12772    array->set_length(*len);
12773  }
12774}
12775
12776
12777bool JSArray::IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map) {
12778  Isolate* isolate = jsarray_map->GetIsolate();
12779  DCHECK(!jsarray_map->is_dictionary_map());
12780  LookupResult lookup(isolate);
12781  Handle<Name> length_string = isolate->factory()->length_string();
12782  jsarray_map->LookupDescriptor(NULL, *length_string, &lookup);
12783  return lookup.IsReadOnly();
12784}
12785
12786
12787bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
12788                                        uint32_t index) {
12789  uint32_t length = 0;
12790  CHECK(array->length()->ToArrayIndex(&length));
12791  if (length <= index) {
12792    LookupIterator it(array, array->GetIsolate()->factory()->length_string(),
12793                      LookupIterator::OWN_SKIP_INTERCEPTOR);
12794    CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
12795    CHECK(it.IsFound());
12796    CHECK_EQ(LookupIterator::ACCESSOR, it.state());
12797    return it.IsReadOnly();
12798  }
12799  return false;
12800}
12801
12802
12803MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
12804  Isolate* isolate = array->GetIsolate();
12805  Handle<Name> length = isolate->factory()->length_string();
12806  Handle<Object> args[2] = { length, array };
12807  THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
12808                                        HandleVector(args, arraysize(args))),
12809                  Object);
12810}
12811
12812
12813MaybeHandle<Object> JSObject::GetElementWithInterceptor(
12814    Handle<JSObject> object,
12815    Handle<Object> receiver,
12816    uint32_t index) {
12817  Isolate* isolate = object->GetIsolate();
12818
12819  // Make sure that the top context does not change when doing
12820  // callbacks or interceptor calls.
12821  AssertNoContextChange ncc(isolate);
12822
12823  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate);
12824  if (!interceptor->getter()->IsUndefined()) {
12825    v8::IndexedPropertyGetterCallback getter =
12826        v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
12827    LOG(isolate,
12828        ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
12829    PropertyCallbackArguments
12830        args(isolate, interceptor->data(), *receiver, *object);
12831    v8::Handle<v8::Value> result = args.Call(getter, index);
12832    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
12833    if (!result.IsEmpty()) {
12834      Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12835      result_internal->VerifyApiCallResultType();
12836      // Rebox handle before return.
12837      return handle(*result_internal, isolate);
12838    }
12839  }
12840
12841  ElementsAccessor* handler = object->GetElementsAccessor();
12842  Handle<Object> result;
12843  ASSIGN_RETURN_ON_EXCEPTION(
12844      isolate, result, handler->Get(receiver,  object, index),
12845      Object);
12846  if (!result->IsTheHole()) return result;
12847
12848  PrototypeIterator iter(isolate, object);
12849  if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
12850  return Object::GetElementWithReceiver(
12851      isolate, PrototypeIterator::GetCurrent(iter), receiver, index);
12852}
12853
12854
12855bool JSObject::HasDenseElements() {
12856  int capacity = 0;
12857  int used = 0;
12858  GetElementsCapacityAndUsage(&capacity, &used);
12859  return (capacity == 0) || (used > (capacity / 2));
12860}
12861
12862
12863void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
12864  *capacity = 0;
12865  *used = 0;
12866
12867  FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
12868  FixedArray* backing_store = NULL;
12869  switch (GetElementsKind()) {
12870    case SLOPPY_ARGUMENTS_ELEMENTS:
12871      backing_store_base =
12872          FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
12873      backing_store = FixedArray::cast(backing_store_base);
12874      if (backing_store->IsDictionary()) {
12875        SeededNumberDictionary* dictionary =
12876            SeededNumberDictionary::cast(backing_store);
12877        *capacity = dictionary->Capacity();
12878        *used = dictionary->NumberOfElements();
12879        break;
12880      }
12881      // Fall through.
12882    case FAST_SMI_ELEMENTS:
12883    case FAST_ELEMENTS:
12884      if (IsJSArray()) {
12885        *capacity = backing_store_base->length();
12886        *used = Smi::cast(JSArray::cast(this)->length())->value();
12887        break;
12888      }
12889      // Fall through if packing is not guaranteed.
12890    case FAST_HOLEY_SMI_ELEMENTS:
12891    case FAST_HOLEY_ELEMENTS:
12892      backing_store = FixedArray::cast(backing_store_base);
12893      *capacity = backing_store->length();
12894      for (int i = 0; i < *capacity; ++i) {
12895        if (!backing_store->get(i)->IsTheHole()) ++(*used);
12896      }
12897      break;
12898    case DICTIONARY_ELEMENTS: {
12899      SeededNumberDictionary* dictionary = element_dictionary();
12900      *capacity = dictionary->Capacity();
12901      *used = dictionary->NumberOfElements();
12902      break;
12903    }
12904    case FAST_DOUBLE_ELEMENTS:
12905      if (IsJSArray()) {
12906        *capacity = backing_store_base->length();
12907        *used = Smi::cast(JSArray::cast(this)->length())->value();
12908        break;
12909      }
12910      // Fall through if packing is not guaranteed.
12911    case FAST_HOLEY_DOUBLE_ELEMENTS: {
12912      *capacity = elements()->length();
12913      if (*capacity == 0) break;
12914      FixedDoubleArray * elms = FixedDoubleArray::cast(elements());
12915      for (int i = 0; i < *capacity; i++) {
12916        if (!elms->is_the_hole(i)) ++(*used);
12917      }
12918      break;
12919    }
12920
12921#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
12922    case EXTERNAL_##TYPE##_ELEMENTS:                                         \
12923    case TYPE##_ELEMENTS:                                                    \
12924
12925    TYPED_ARRAYS(TYPED_ARRAY_CASE)
12926#undef TYPED_ARRAY_CASE
12927    {
12928      // External arrays are considered 100% used.
12929      FixedArrayBase* external_array = FixedArrayBase::cast(elements());
12930      *capacity = external_array->length();
12931      *used = external_array->length();
12932      break;
12933    }
12934  }
12935}
12936
12937
12938bool JSObject::WouldConvertToSlowElements(Handle<Object> key) {
12939  uint32_t index;
12940  if (HasFastElements() && key->ToArrayIndex(&index)) {
12941    Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
12942    uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12943    if (index >= capacity) {
12944      if ((index - capacity) >= kMaxGap) return true;
12945      uint32_t new_capacity = NewElementsCapacity(index + 1);
12946      return ShouldConvertToSlowElements(new_capacity);
12947    }
12948  }
12949  return false;
12950}
12951
12952
12953bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
12954  STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
12955                kMaxUncheckedFastElementsLength);
12956  if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
12957      (new_capacity <= kMaxUncheckedFastElementsLength &&
12958       GetHeap()->InNewSpace(this))) {
12959    return false;
12960  }
12961  // If the fast-case backing storage takes up roughly three times as
12962  // much space (in machine words) as a dictionary backing storage
12963  // would, the object should have slow elements.
12964  int old_capacity = 0;
12965  int used_elements = 0;
12966  GetElementsCapacityAndUsage(&old_capacity, &used_elements);
12967  int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
12968      SeededNumberDictionary::kEntrySize;
12969  return 3 * dictionary_size <= new_capacity;
12970}
12971
12972
12973bool JSObject::ShouldConvertToFastElements() {
12974  DCHECK(HasDictionaryElements() || HasDictionaryArgumentsElements());
12975  // If the elements are sparse, we should not go back to fast case.
12976  if (!HasDenseElements()) return false;
12977  // An object requiring access checks is never allowed to have fast
12978  // elements.  If it had fast elements we would skip security checks.
12979  if (IsAccessCheckNeeded()) return false;
12980  // Observed objects may not go to fast mode because they rely on map checks,
12981  // and for fast element accesses we sometimes check element kinds only.
12982  if (map()->is_observed()) return false;
12983
12984  FixedArray* elements = FixedArray::cast(this->elements());
12985  SeededNumberDictionary* dictionary = NULL;
12986  if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) {
12987    dictionary = SeededNumberDictionary::cast(elements->get(1));
12988  } else {
12989    dictionary = SeededNumberDictionary::cast(elements);
12990  }
12991  // If an element has been added at a very high index in the elements
12992  // dictionary, we cannot go back to fast case.
12993  if (dictionary->requires_slow_elements()) return false;
12994  // If the dictionary backing storage takes up roughly half as much
12995  // space (in machine words) as a fast-case backing storage would,
12996  // the object should have fast elements.
12997  uint32_t array_size = 0;
12998  if (IsJSArray()) {
12999    CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
13000  } else {
13001    array_size = dictionary->max_number_key();
13002  }
13003  uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
13004      SeededNumberDictionary::kEntrySize;
13005  return 2 * dictionary_size >= array_size;
13006}
13007
13008
13009bool JSObject::ShouldConvertToFastDoubleElements(
13010    bool* has_smi_only_elements) {
13011  *has_smi_only_elements = false;
13012  if (HasSloppyArgumentsElements()) return false;
13013  if (FLAG_unbox_double_arrays) {
13014    DCHECK(HasDictionaryElements());
13015    SeededNumberDictionary* dictionary = element_dictionary();
13016    bool found_double = false;
13017    for (int i = 0; i < dictionary->Capacity(); i++) {
13018      Object* key = dictionary->KeyAt(i);
13019      if (key->IsNumber()) {
13020        Object* value = dictionary->ValueAt(i);
13021        if (!value->IsNumber()) return false;
13022        if (!value->IsSmi()) {
13023          found_double = true;
13024        }
13025      }
13026    }
13027    *has_smi_only_elements = !found_double;
13028    return found_double;
13029  } else {
13030    return false;
13031  }
13032}
13033
13034
13035// Certain compilers request function template instantiation when they
13036// see the definition of the other template functions in the
13037// class. This requires us to have the template functions put
13038// together, so even though this function belongs in objects-debug.cc,
13039// we keep it here instead to satisfy certain compilers.
13040#ifdef OBJECT_PRINT
13041template <typename Derived, typename Shape, typename Key>
13042void Dictionary<Derived, Shape, Key>::Print(OStream& os) {  // NOLINT
13043  int capacity = DerivedHashTable::Capacity();
13044  for (int i = 0; i < capacity; i++) {
13045    Object* k = DerivedHashTable::KeyAt(i);
13046    if (DerivedHashTable::IsKey(k)) {
13047      os << " ";
13048      if (k->IsString()) {
13049        String::cast(k)->StringPrint(os);
13050      } else {
13051        os << Brief(k);
13052      }
13053      os << ": " << Brief(ValueAt(i)) << "\n";
13054    }
13055  }
13056}
13057#endif
13058
13059
13060template<typename Derived, typename Shape, typename Key>
13061void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
13062  int pos = 0;
13063  int capacity = DerivedHashTable::Capacity();
13064  DisallowHeapAllocation no_gc;
13065  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
13066  for (int i = 0; i < capacity; i++) {
13067    Object* k =  Dictionary::KeyAt(i);
13068    if (Dictionary::IsKey(k)) {
13069      elements->set(pos++, ValueAt(i), mode);
13070    }
13071  }
13072  DCHECK(pos == elements->length());
13073}
13074
13075
13076InterceptorInfo* JSObject::GetNamedInterceptor() {
13077  DCHECK(map()->has_named_interceptor());
13078  JSFunction* constructor = JSFunction::cast(map()->constructor());
13079  DCHECK(constructor->shared()->IsApiFunction());
13080  Object* result =
13081      constructor->shared()->get_api_func_data()->named_property_handler();
13082  return InterceptorInfo::cast(result);
13083}
13084
13085
13086InterceptorInfo* JSObject::GetIndexedInterceptor() {
13087  DCHECK(map()->has_indexed_interceptor());
13088  JSFunction* constructor = JSFunction::cast(map()->constructor());
13089  DCHECK(constructor->shared()->IsApiFunction());
13090  Object* result =
13091      constructor->shared()->get_api_func_data()->indexed_property_handler();
13092  return InterceptorInfo::cast(result);
13093}
13094
13095
13096MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(
13097    Handle<JSObject> holder,
13098    Handle<Object> receiver,
13099    Handle<Name> name) {
13100  Isolate* isolate = holder->GetIsolate();
13101
13102  // TODO(rossberg): Support symbols in the API.
13103  if (name->IsSymbol()) return isolate->factory()->undefined_value();
13104
13105  Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor(), isolate);
13106  Handle<String> name_string = Handle<String>::cast(name);
13107
13108  if (interceptor->getter()->IsUndefined()) return MaybeHandle<Object>();
13109
13110  v8::NamedPropertyGetterCallback getter =
13111      v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
13112  LOG(isolate,
13113      ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
13114  PropertyCallbackArguments
13115      args(isolate, interceptor->data(), *receiver, *holder);
13116  v8::Handle<v8::Value> result =
13117      args.Call(getter, v8::Utils::ToLocal(name_string));
13118  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
13119  if (result.IsEmpty()) return MaybeHandle<Object>();
13120
13121  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13122  result_internal->VerifyApiCallResultType();
13123  // Rebox handle before return
13124  return handle(*result_internal, isolate);
13125}
13126
13127
13128// Compute the property keys from the interceptor.
13129// TODO(rossberg): support symbols in API, and filter here if needed.
13130MaybeHandle<JSObject> JSObject::GetKeysForNamedInterceptor(
13131    Handle<JSObject> object, Handle<JSReceiver> receiver) {
13132  Isolate* isolate = receiver->GetIsolate();
13133  Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
13134  PropertyCallbackArguments
13135      args(isolate, interceptor->data(), *receiver, *object);
13136  v8::Handle<v8::Object> result;
13137  if (!interceptor->enumerator()->IsUndefined()) {
13138    v8::NamedPropertyEnumeratorCallback enum_fun =
13139        v8::ToCData<v8::NamedPropertyEnumeratorCallback>(
13140            interceptor->enumerator());
13141    LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
13142    result = args.Call(enum_fun);
13143  }
13144  if (result.IsEmpty()) return MaybeHandle<JSObject>();
13145#if ENABLE_EXTRA_CHECKS
13146  CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13147        v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13148#endif
13149  // Rebox before returning.
13150  return handle(*v8::Utils::OpenHandle(*result), isolate);
13151}
13152
13153
13154// Compute the element keys from the interceptor.
13155MaybeHandle<JSObject> JSObject::GetKeysForIndexedInterceptor(
13156    Handle<JSObject> object, Handle<JSReceiver> receiver) {
13157  Isolate* isolate = receiver->GetIsolate();
13158  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
13159  PropertyCallbackArguments
13160      args(isolate, interceptor->data(), *receiver, *object);
13161  v8::Handle<v8::Object> result;
13162  if (!interceptor->enumerator()->IsUndefined()) {
13163    v8::IndexedPropertyEnumeratorCallback enum_fun =
13164        v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
13165            interceptor->enumerator());
13166    LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
13167    result = args.Call(enum_fun);
13168  }
13169  if (result.IsEmpty()) return MaybeHandle<JSObject>();
13170#if ENABLE_EXTRA_CHECKS
13171  CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13172        v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13173#endif
13174  // Rebox before returning.
13175  return handle(*v8::Utils::OpenHandle(*result), isolate);
13176}
13177
13178
13179Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
13180                                           Handle<Name> key) {
13181  LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
13182  Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
13183  if (!maybe_result.has_value) return Maybe<bool>();
13184  return maybe(it.IsFound());
13185}
13186
13187
13188Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
13189                                             uint32_t index) {
13190  Isolate* isolate = object->GetIsolate();
13191  HandleScope scope(isolate);
13192  // Check access rights if needed.
13193  if (object->IsAccessCheckNeeded()) {
13194    if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
13195      isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
13196      RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<bool>());
13197      return maybe(false);
13198    }
13199  }
13200
13201  if (object->IsJSGlobalProxy()) {
13202    HandleScope scope(isolate);
13203    PrototypeIterator iter(isolate, object);
13204    if (iter.IsAtEnd()) return maybe(false);
13205    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
13206    return HasRealElementProperty(
13207        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index);
13208  }
13209
13210  Maybe<PropertyAttributes> result =
13211      GetElementAttributeWithoutInterceptor(object, object, index, false);
13212  if (!result.has_value) return Maybe<bool>();
13213  return maybe(result.value != ABSENT);
13214}
13215
13216
13217Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
13218                                                   Handle<Name> key) {
13219  LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
13220  Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
13221  if (!maybe_result.has_value) return Maybe<bool>();
13222  return maybe(it.state() == LookupIterator::ACCESSOR);
13223}
13224
13225
13226int JSObject::NumberOfOwnProperties(PropertyAttributes filter) {
13227  if (HasFastProperties()) {
13228    Map* map = this->map();
13229    if (filter == NONE) return map->NumberOfOwnDescriptors();
13230    if (filter & DONT_ENUM) {
13231      int result = map->EnumLength();
13232      if (result != kInvalidEnumCacheSentinel) return result;
13233    }
13234    return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
13235  }
13236  return property_dictionary()->NumberOfElementsFilterAttributes(filter);
13237}
13238
13239
13240void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
13241  Object* temp = get(i);
13242  set(i, get(j));
13243  set(j, temp);
13244  if (this != numbers) {
13245    temp = numbers->get(i);
13246    numbers->set(i, Smi::cast(numbers->get(j)));
13247    numbers->set(j, Smi::cast(temp));
13248  }
13249}
13250
13251
13252static void InsertionSortPairs(FixedArray* content,
13253                               FixedArray* numbers,
13254                               int len) {
13255  for (int i = 1; i < len; i++) {
13256    int j = i;
13257    while (j > 0 &&
13258           (NumberToUint32(numbers->get(j - 1)) >
13259            NumberToUint32(numbers->get(j)))) {
13260      content->SwapPairs(numbers, j - 1, j);
13261      j--;
13262    }
13263  }
13264}
13265
13266
13267void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
13268  // In-place heap sort.
13269  DCHECK(content->length() == numbers->length());
13270
13271  // Bottom-up max-heap construction.
13272  for (int i = 1; i < len; ++i) {
13273    int child_index = i;
13274    while (child_index > 0) {
13275      int parent_index = ((child_index + 1) >> 1) - 1;
13276      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13277      uint32_t child_value = NumberToUint32(numbers->get(child_index));
13278      if (parent_value < child_value) {
13279        content->SwapPairs(numbers, parent_index, child_index);
13280      } else {
13281        break;
13282      }
13283      child_index = parent_index;
13284    }
13285  }
13286
13287  // Extract elements and create sorted array.
13288  for (int i = len - 1; i > 0; --i) {
13289    // Put max element at the back of the array.
13290    content->SwapPairs(numbers, 0, i);
13291    // Sift down the new top element.
13292    int parent_index = 0;
13293    while (true) {
13294      int child_index = ((parent_index + 1) << 1) - 1;
13295      if (child_index >= i) break;
13296      uint32_t child1_value = NumberToUint32(numbers->get(child_index));
13297      uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
13298      uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13299      if (child_index + 1 >= i || child1_value > child2_value) {
13300        if (parent_value > child1_value) break;
13301        content->SwapPairs(numbers, parent_index, child_index);
13302        parent_index = child_index;
13303      } else {
13304        if (parent_value > child2_value) break;
13305        content->SwapPairs(numbers, parent_index, child_index + 1);
13306        parent_index = child_index + 1;
13307      }
13308    }
13309  }
13310}
13311
13312
13313// Sort this array and the numbers as pairs wrt. the (distinct) numbers.
13314void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
13315  DCHECK(this->length() == numbers->length());
13316  // For small arrays, simply use insertion sort.
13317  if (len <= 10) {
13318    InsertionSortPairs(this, numbers, len);
13319    return;
13320  }
13321  // Check the range of indices.
13322  uint32_t min_index = NumberToUint32(numbers->get(0));
13323  uint32_t max_index = min_index;
13324  uint32_t i;
13325  for (i = 1; i < len; i++) {
13326    if (NumberToUint32(numbers->get(i)) < min_index) {
13327      min_index = NumberToUint32(numbers->get(i));
13328    } else if (NumberToUint32(numbers->get(i)) > max_index) {
13329      max_index = NumberToUint32(numbers->get(i));
13330    }
13331  }
13332  if (max_index - min_index + 1 == len) {
13333    // Indices form a contiguous range, unless there are duplicates.
13334    // Do an in-place linear time sort assuming distinct numbers, but
13335    // avoid hanging in case they are not.
13336    for (i = 0; i < len; i++) {
13337      uint32_t p;
13338      uint32_t j = 0;
13339      // While the current element at i is not at its correct position p,
13340      // swap the elements at these two positions.
13341      while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
13342             j++ < len) {
13343        SwapPairs(numbers, i, p);
13344      }
13345    }
13346  } else {
13347    HeapSortPairs(this, numbers, len);
13348    return;
13349  }
13350}
13351
13352
13353// Fill in the names of own properties into the supplied storage. The main
13354// purpose of this function is to provide reflection information for the object
13355// mirrors.
13356void JSObject::GetOwnPropertyNames(
13357    FixedArray* storage, int index, PropertyAttributes filter) {
13358  DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index));
13359  if (HasFastProperties()) {
13360    int real_size = map()->NumberOfOwnDescriptors();
13361    DescriptorArray* descs = map()->instance_descriptors();
13362    for (int i = 0; i < real_size; i++) {
13363      if ((descs->GetDetails(i).attributes() & filter) == 0 &&
13364          !FilterKey(descs->GetKey(i), filter)) {
13365        storage->set(index++, descs->GetKey(i));
13366      }
13367    }
13368  } else {
13369    property_dictionary()->CopyKeysTo(storage,
13370                                      index,
13371                                      filter,
13372                                      NameDictionary::UNSORTED);
13373  }
13374}
13375
13376
13377int JSObject::NumberOfOwnElements(PropertyAttributes filter) {
13378  return GetOwnElementKeys(NULL, filter);
13379}
13380
13381
13382int JSObject::NumberOfEnumElements() {
13383  // Fast case for objects with no elements.
13384  if (!IsJSValue() && HasFastObjectElements()) {
13385    uint32_t length = IsJSArray() ?
13386        static_cast<uint32_t>(
13387            Smi::cast(JSArray::cast(this)->length())->value()) :
13388        static_cast<uint32_t>(FixedArray::cast(elements())->length());
13389    if (length == 0) return 0;
13390  }
13391  // Compute the number of enumerable elements.
13392  return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
13393}
13394
13395
13396int JSObject::GetOwnElementKeys(FixedArray* storage,
13397                                PropertyAttributes filter) {
13398  int counter = 0;
13399  switch (GetElementsKind()) {
13400    case FAST_SMI_ELEMENTS:
13401    case FAST_ELEMENTS:
13402    case FAST_HOLEY_SMI_ELEMENTS:
13403    case FAST_HOLEY_ELEMENTS: {
13404      int length = IsJSArray() ?
13405          Smi::cast(JSArray::cast(this)->length())->value() :
13406          FixedArray::cast(elements())->length();
13407      for (int i = 0; i < length; i++) {
13408        if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
13409          if (storage != NULL) {
13410            storage->set(counter, Smi::FromInt(i));
13411          }
13412          counter++;
13413        }
13414      }
13415      DCHECK(!storage || storage->length() >= counter);
13416      break;
13417    }
13418    case FAST_DOUBLE_ELEMENTS:
13419    case FAST_HOLEY_DOUBLE_ELEMENTS: {
13420      int length = IsJSArray() ?
13421          Smi::cast(JSArray::cast(this)->length())->value() :
13422          FixedArrayBase::cast(elements())->length();
13423      for (int i = 0; i < length; i++) {
13424        if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
13425          if (storage != NULL) {
13426            storage->set(counter, Smi::FromInt(i));
13427          }
13428          counter++;
13429        }
13430      }
13431      DCHECK(!storage || storage->length() >= counter);
13432      break;
13433    }
13434
13435#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
13436    case EXTERNAL_##TYPE##_ELEMENTS:                                         \
13437    case TYPE##_ELEMENTS:                                                    \
13438
13439    TYPED_ARRAYS(TYPED_ARRAY_CASE)
13440#undef TYPED_ARRAY_CASE
13441    {
13442      int length = FixedArrayBase::cast(elements())->length();
13443      while (counter < length) {
13444        if (storage != NULL) {
13445          storage->set(counter, Smi::FromInt(counter));
13446        }
13447        counter++;
13448      }
13449      DCHECK(!storage || storage->length() >= counter);
13450      break;
13451    }
13452
13453    case DICTIONARY_ELEMENTS: {
13454      if (storage != NULL) {
13455        element_dictionary()->CopyKeysTo(storage,
13456                                         filter,
13457                                         SeededNumberDictionary::SORTED);
13458      }
13459      counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
13460      break;
13461    }
13462    case SLOPPY_ARGUMENTS_ELEMENTS: {
13463      FixedArray* parameter_map = FixedArray::cast(elements());
13464      int mapped_length = parameter_map->length() - 2;
13465      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
13466      if (arguments->IsDictionary()) {
13467        // Copy the keys from arguments first, because Dictionary::CopyKeysTo
13468        // will insert in storage starting at index 0.
13469        SeededNumberDictionary* dictionary =
13470            SeededNumberDictionary::cast(arguments);
13471        if (storage != NULL) {
13472          dictionary->CopyKeysTo(
13473              storage, filter, SeededNumberDictionary::UNSORTED);
13474        }
13475        counter += dictionary->NumberOfElementsFilterAttributes(filter);
13476        for (int i = 0; i < mapped_length; ++i) {
13477          if (!parameter_map->get(i + 2)->IsTheHole()) {
13478            if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13479            ++counter;
13480          }
13481        }
13482        if (storage != NULL) storage->SortPairs(storage, counter);
13483
13484      } else {
13485        int backing_length = arguments->length();
13486        int i = 0;
13487        for (; i < mapped_length; ++i) {
13488          if (!parameter_map->get(i + 2)->IsTheHole()) {
13489            if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13490            ++counter;
13491          } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
13492            if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13493            ++counter;
13494          }
13495        }
13496        for (; i < backing_length; ++i) {
13497          if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13498          ++counter;
13499        }
13500      }
13501      break;
13502    }
13503  }
13504
13505  if (this->IsJSValue()) {
13506    Object* val = JSValue::cast(this)->value();
13507    if (val->IsString()) {
13508      String* str = String::cast(val);
13509      if (storage) {
13510        for (int i = 0; i < str->length(); i++) {
13511          storage->set(counter + i, Smi::FromInt(i));
13512        }
13513      }
13514      counter += str->length();
13515    }
13516  }
13517  DCHECK(!storage || storage->length() == counter);
13518  return counter;
13519}
13520
13521
13522int JSObject::GetEnumElementKeys(FixedArray* storage) {
13523  return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
13524}
13525
13526
13527// StringSharedKeys are used as keys in the eval cache.
13528class StringSharedKey : public HashTableKey {
13529 public:
13530  StringSharedKey(Handle<String> source,
13531                  Handle<SharedFunctionInfo> shared,
13532                  StrictMode strict_mode,
13533                  int scope_position)
13534      : source_(source),
13535        shared_(shared),
13536        strict_mode_(strict_mode),
13537        scope_position_(scope_position) { }
13538
13539  bool IsMatch(Object* other) OVERRIDE {
13540    DisallowHeapAllocation no_allocation;
13541    if (!other->IsFixedArray()) return false;
13542    FixedArray* other_array = FixedArray::cast(other);
13543    SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13544    if (shared != *shared_) return false;
13545    int strict_unchecked = Smi::cast(other_array->get(2))->value();
13546    DCHECK(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
13547    StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
13548    if (strict_mode != strict_mode_) return false;
13549    int scope_position = Smi::cast(other_array->get(3))->value();
13550    if (scope_position != scope_position_) return false;
13551    String* source = String::cast(other_array->get(1));
13552    return source->Equals(*source_);
13553  }
13554
13555  static uint32_t StringSharedHashHelper(String* source,
13556                                         SharedFunctionInfo* shared,
13557                                         StrictMode strict_mode,
13558                                         int scope_position) {
13559    uint32_t hash = source->Hash();
13560    if (shared->HasSourceCode()) {
13561      // Instead of using the SharedFunctionInfo pointer in the hash
13562      // code computation, we use a combination of the hash of the
13563      // script source code and the start position of the calling scope.
13564      // We do this to ensure that the cache entries can survive garbage
13565      // collection.
13566      Script* script(Script::cast(shared->script()));
13567      hash ^= String::cast(script->source())->Hash();
13568      if (strict_mode == STRICT) hash ^= 0x8000;
13569      hash += scope_position;
13570    }
13571    return hash;
13572  }
13573
13574  uint32_t Hash() OVERRIDE {
13575    return StringSharedHashHelper(*source_, *shared_, strict_mode_,
13576                                  scope_position_);
13577  }
13578
13579  uint32_t HashForObject(Object* obj) OVERRIDE {
13580    DisallowHeapAllocation no_allocation;
13581    FixedArray* other_array = FixedArray::cast(obj);
13582    SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13583    String* source = String::cast(other_array->get(1));
13584    int strict_unchecked = Smi::cast(other_array->get(2))->value();
13585    DCHECK(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
13586    StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
13587    int scope_position = Smi::cast(other_array->get(3))->value();
13588    return StringSharedHashHelper(
13589        source, shared, strict_mode, scope_position);
13590  }
13591
13592
13593  Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
13594    Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
13595    array->set(0, *shared_);
13596    array->set(1, *source_);
13597    array->set(2, Smi::FromInt(strict_mode_));
13598    array->set(3, Smi::FromInt(scope_position_));
13599    return array;
13600  }
13601
13602 private:
13603  Handle<String> source_;
13604  Handle<SharedFunctionInfo> shared_;
13605  StrictMode strict_mode_;
13606  int scope_position_;
13607};
13608
13609
13610// RegExpKey carries the source and flags of a regular expression as key.
13611class RegExpKey : public HashTableKey {
13612 public:
13613  RegExpKey(Handle<String> string, JSRegExp::Flags flags)
13614      : string_(string),
13615        flags_(Smi::FromInt(flags.value())) { }
13616
13617  // Rather than storing the key in the hash table, a pointer to the
13618  // stored value is stored where the key should be.  IsMatch then
13619  // compares the search key to the found object, rather than comparing
13620  // a key to a key.
13621  bool IsMatch(Object* obj) OVERRIDE {
13622    FixedArray* val = FixedArray::cast(obj);
13623    return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
13624        && (flags_ == val->get(JSRegExp::kFlagsIndex));
13625  }
13626
13627  uint32_t Hash() OVERRIDE { return RegExpHash(*string_, flags_); }
13628
13629  Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
13630    // Plain hash maps, which is where regexp keys are used, don't
13631    // use this function.
13632    UNREACHABLE();
13633    return MaybeHandle<Object>().ToHandleChecked();
13634  }
13635
13636  uint32_t HashForObject(Object* obj) OVERRIDE {
13637    FixedArray* val = FixedArray::cast(obj);
13638    return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
13639                      Smi::cast(val->get(JSRegExp::kFlagsIndex)));
13640  }
13641
13642  static uint32_t RegExpHash(String* string, Smi* flags) {
13643    return string->Hash() + flags->value();
13644  }
13645
13646  Handle<String> string_;
13647  Smi* flags_;
13648};
13649
13650
13651Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
13652  if (hash_field_ == 0) Hash();
13653  return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
13654}
13655
13656
13657Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
13658  if (hash_field_ == 0) Hash();
13659  return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
13660}
13661
13662
13663Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
13664  if (hash_field_ == 0) Hash();
13665  return isolate->factory()->NewOneByteInternalizedSubString(
13666      string_, from_, length_, hash_field_);
13667}
13668
13669
13670bool SeqOneByteSubStringKey::IsMatch(Object* string) {
13671  Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
13672  return String::cast(string)->IsOneByteEqualTo(chars);
13673}
13674
13675
13676// InternalizedStringKey carries a string/internalized-string object as key.
13677class InternalizedStringKey : public HashTableKey {
13678 public:
13679  explicit InternalizedStringKey(Handle<String> string)
13680      : string_(string) { }
13681
13682  virtual bool IsMatch(Object* string) OVERRIDE {
13683    return String::cast(string)->Equals(*string_);
13684  }
13685
13686  virtual uint32_t Hash() OVERRIDE { return string_->Hash(); }
13687
13688  virtual uint32_t HashForObject(Object* other) OVERRIDE {
13689    return String::cast(other)->Hash();
13690  }
13691
13692  virtual Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
13693    // Internalize the string if possible.
13694    MaybeHandle<Map> maybe_map =
13695        isolate->factory()->InternalizedStringMapForString(string_);
13696    Handle<Map> map;
13697    if (maybe_map.ToHandle(&map)) {
13698      string_->set_map_no_write_barrier(*map);
13699      DCHECK(string_->IsInternalizedString());
13700      return string_;
13701    }
13702    // Otherwise allocate a new internalized string.
13703    return isolate->factory()->NewInternalizedStringImpl(
13704        string_, string_->length(), string_->hash_field());
13705  }
13706
13707  static uint32_t StringHash(Object* obj) {
13708    return String::cast(obj)->Hash();
13709  }
13710
13711  Handle<String> string_;
13712};
13713
13714
13715template<typename Derived, typename Shape, typename Key>
13716void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
13717  IteratePointers(v, 0, kElementsStartOffset);
13718}
13719
13720
13721template<typename Derived, typename Shape, typename Key>
13722void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
13723  IteratePointers(v,
13724                  kElementsStartOffset,
13725                  kHeaderSize + length() * kPointerSize);
13726}
13727
13728
13729template<typename Derived, typename Shape, typename Key>
13730Handle<Derived> HashTable<Derived, Shape, Key>::New(
13731    Isolate* isolate,
13732    int at_least_space_for,
13733    MinimumCapacity capacity_option,
13734    PretenureFlag pretenure) {
13735  DCHECK(0 <= at_least_space_for);
13736  DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
13737  int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
13738                     ? at_least_space_for
13739                     : ComputeCapacity(at_least_space_for);
13740  if (capacity > HashTable::kMaxCapacity) {
13741    v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
13742  }
13743
13744  Factory* factory = isolate->factory();
13745  int length = EntryToIndex(capacity);
13746  Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
13747  array->set_map_no_write_barrier(*factory->hash_table_map());
13748  Handle<Derived> table = Handle<Derived>::cast(array);
13749
13750  table->SetNumberOfElements(0);
13751  table->SetNumberOfDeletedElements(0);
13752  table->SetCapacity(capacity);
13753  return table;
13754}
13755
13756
13757// Find entry for key otherwise return kNotFound.
13758int NameDictionary::FindEntry(Handle<Name> key) {
13759  if (!key->IsUniqueName()) {
13760    return DerivedHashTable::FindEntry(key);
13761  }
13762
13763  // Optimized for unique names. Knowledge of the key type allows:
13764  // 1. Move the check if the key is unique out of the loop.
13765  // 2. Avoid comparing hash codes in unique-to-unique comparison.
13766  // 3. Detect a case when a dictionary key is not unique but the key is.
13767  //    In case of positive result the dictionary key may be replaced by the
13768  //    internalized string with minimal performance penalty. It gives a chance
13769  //    to perform further lookups in code stubs (and significant performance
13770  //    boost a certain style of code).
13771
13772  // EnsureCapacity will guarantee the hash table is never full.
13773  uint32_t capacity = Capacity();
13774  uint32_t entry = FirstProbe(key->Hash(), capacity);
13775  uint32_t count = 1;
13776
13777  while (true) {
13778    int index = EntryToIndex(entry);
13779    Object* element = get(index);
13780    if (element->IsUndefined()) break;  // Empty entry.
13781    if (*key == element) return entry;
13782    if (!element->IsUniqueName() &&
13783        !element->IsTheHole() &&
13784        Name::cast(element)->Equals(*key)) {
13785      // Replace a key that is a non-internalized string by the equivalent
13786      // internalized string for faster further lookups.
13787      set(index, *key);
13788      return entry;
13789    }
13790    DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
13791    entry = NextProbe(entry, count++, capacity);
13792  }
13793  return kNotFound;
13794}
13795
13796
13797template<typename Derived, typename Shape, typename Key>
13798void HashTable<Derived, Shape, Key>::Rehash(
13799    Handle<Derived> new_table,
13800    Key key) {
13801  DCHECK(NumberOfElements() < new_table->Capacity());
13802
13803  DisallowHeapAllocation no_gc;
13804  WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
13805
13806  // Copy prefix to new array.
13807  for (int i = kPrefixStartIndex;
13808       i < kPrefixStartIndex + Shape::kPrefixSize;
13809       i++) {
13810    new_table->set(i, get(i), mode);
13811  }
13812
13813  // Rehash the elements.
13814  int capacity = Capacity();
13815  for (int i = 0; i < capacity; i++) {
13816    uint32_t from_index = EntryToIndex(i);
13817    Object* k = get(from_index);
13818    if (IsKey(k)) {
13819      uint32_t hash = HashTable::HashForObject(key, k);
13820      uint32_t insertion_index =
13821          EntryToIndex(new_table->FindInsertionEntry(hash));
13822      for (int j = 0; j < Shape::kEntrySize; j++) {
13823        new_table->set(insertion_index + j, get(from_index + j), mode);
13824      }
13825    }
13826  }
13827  new_table->SetNumberOfElements(NumberOfElements());
13828  new_table->SetNumberOfDeletedElements(0);
13829}
13830
13831
13832template<typename Derived, typename Shape, typename Key>
13833uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
13834    Key key,
13835    Object* k,
13836    int probe,
13837    uint32_t expected) {
13838  uint32_t hash = HashTable::HashForObject(key, k);
13839  uint32_t capacity = Capacity();
13840  uint32_t entry = FirstProbe(hash, capacity);
13841  for (int i = 1; i < probe; i++) {
13842    if (entry == expected) return expected;
13843    entry = NextProbe(entry, i, capacity);
13844  }
13845  return entry;
13846}
13847
13848
13849template<typename Derived, typename Shape, typename Key>
13850void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
13851                                          uint32_t entry2,
13852                                          WriteBarrierMode mode) {
13853  int index1 = EntryToIndex(entry1);
13854  int index2 = EntryToIndex(entry2);
13855  Object* temp[Shape::kEntrySize];
13856  for (int j = 0; j < Shape::kEntrySize; j++) {
13857    temp[j] = get(index1 + j);
13858  }
13859  for (int j = 0; j < Shape::kEntrySize; j++) {
13860    set(index1 + j, get(index2 + j), mode);
13861  }
13862  for (int j = 0; j < Shape::kEntrySize; j++) {
13863    set(index2 + j, temp[j], mode);
13864  }
13865}
13866
13867
13868template<typename Derived, typename Shape, typename Key>
13869void HashTable<Derived, Shape, Key>::Rehash(Key key) {
13870  DisallowHeapAllocation no_gc;
13871  WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
13872  uint32_t capacity = Capacity();
13873  bool done = false;
13874  for (int probe = 1; !done; probe++) {
13875    // All elements at entries given by one of the first _probe_ probes
13876    // are placed correctly. Other elements might need to be moved.
13877    done = true;
13878    for (uint32_t current = 0; current < capacity; current++) {
13879      Object* current_key = get(EntryToIndex(current));
13880      if (IsKey(current_key)) {
13881        uint32_t target = EntryForProbe(key, current_key, probe, current);
13882        if (current == target) continue;
13883        Object* target_key = get(EntryToIndex(target));
13884        if (!IsKey(target_key) ||
13885            EntryForProbe(key, target_key, probe, target) != target) {
13886          // Put the current element into the correct position.
13887          Swap(current, target, mode);
13888          // The other element will be processed on the next iteration.
13889          current--;
13890        } else {
13891          // The place for the current element is occupied. Leave the element
13892          // for the next probe.
13893          done = false;
13894        }
13895      }
13896    }
13897  }
13898}
13899
13900
13901template<typename Derived, typename Shape, typename Key>
13902Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
13903    Handle<Derived> table,
13904    int n,
13905    Key key,
13906    PretenureFlag pretenure) {
13907  Isolate* isolate = table->GetIsolate();
13908  int capacity = table->Capacity();
13909  int nof = table->NumberOfElements() + n;
13910  int nod = table->NumberOfDeletedElements();
13911  // Return if:
13912  //   50% is still free after adding n elements and
13913  //   at most 50% of the free elements are deleted elements.
13914  if (nod <= (capacity - nof) >> 1) {
13915    int needed_free = nof >> 1;
13916    if (nof + needed_free <= capacity) return table;
13917  }
13918
13919  const int kMinCapacityForPretenure = 256;
13920  bool should_pretenure = pretenure == TENURED ||
13921      ((capacity > kMinCapacityForPretenure) &&
13922          !isolate->heap()->InNewSpace(*table));
13923  Handle<Derived> new_table = HashTable::New(
13924      isolate,
13925      nof * 2,
13926      USE_DEFAULT_MINIMUM_CAPACITY,
13927      should_pretenure ? TENURED : NOT_TENURED);
13928
13929  table->Rehash(new_table, key);
13930  return new_table;
13931}
13932
13933
13934template<typename Derived, typename Shape, typename Key>
13935Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
13936                                                       Key key) {
13937  int capacity = table->Capacity();
13938  int nof = table->NumberOfElements();
13939
13940  // Shrink to fit the number of elements if only a quarter of the
13941  // capacity is filled with elements.
13942  if (nof > (capacity >> 2)) return table;
13943  // Allocate a new dictionary with room for at least the current
13944  // number of elements. The allocation method will make sure that
13945  // there is extra room in the dictionary for additions. Don't go
13946  // lower than room for 16 elements.
13947  int at_least_room_for = nof;
13948  if (at_least_room_for < 16) return table;
13949
13950  Isolate* isolate = table->GetIsolate();
13951  const int kMinCapacityForPretenure = 256;
13952  bool pretenure =
13953      (at_least_room_for > kMinCapacityForPretenure) &&
13954      !isolate->heap()->InNewSpace(*table);
13955  Handle<Derived> new_table = HashTable::New(
13956      isolate,
13957      at_least_room_for,
13958      USE_DEFAULT_MINIMUM_CAPACITY,
13959      pretenure ? TENURED : NOT_TENURED);
13960
13961  table->Rehash(new_table, key);
13962  return new_table;
13963}
13964
13965
13966template<typename Derived, typename Shape, typename Key>
13967uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
13968  uint32_t capacity = Capacity();
13969  uint32_t entry = FirstProbe(hash, capacity);
13970  uint32_t count = 1;
13971  // EnsureCapacity will guarantee the hash table is never full.
13972  while (true) {
13973    Object* element = KeyAt(entry);
13974    if (element->IsUndefined() || element->IsTheHole()) break;
13975    entry = NextProbe(entry, count++, capacity);
13976  }
13977  return entry;
13978}
13979
13980
13981// Force instantiation of template instances class.
13982// Please note this list is compiler dependent.
13983
13984template class HashTable<StringTable, StringTableShape, HashTableKey*>;
13985
13986template class HashTable<CompilationCacheTable,
13987                         CompilationCacheShape,
13988                         HashTableKey*>;
13989
13990template class HashTable<MapCache, MapCacheShape, HashTableKey*>;
13991
13992template class HashTable<ObjectHashTable,
13993                         ObjectHashTableShape,
13994                         Handle<Object> >;
13995
13996template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
13997
13998template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
13999
14000template class Dictionary<SeededNumberDictionary,
14001                          SeededNumberDictionaryShape,
14002                          uint32_t>;
14003
14004template class Dictionary<UnseededNumberDictionary,
14005                          UnseededNumberDictionaryShape,
14006                          uint32_t>;
14007
14008template Handle<SeededNumberDictionary>
14009Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14010    New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14011
14012template Handle<UnseededNumberDictionary>
14013Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14014    New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14015
14016template Handle<NameDictionary>
14017Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14018    New(Isolate*, int n, PretenureFlag pretenure);
14019
14020template Handle<SeededNumberDictionary>
14021Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14022    AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
14023
14024template Handle<UnseededNumberDictionary>
14025Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14026    AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
14027
14028template Object*
14029Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14030    SlowReverseLookup(Object* value);
14031
14032template Object*
14033Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14034    SlowReverseLookup(Object* value);
14035
14036template void
14037Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14038    CopyKeysTo(
14039        FixedArray*,
14040        PropertyAttributes,
14041        Dictionary<SeededNumberDictionary,
14042                   SeededNumberDictionaryShape,
14043                   uint32_t>::SortMode);
14044
14045template Handle<Object>
14046Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
14047    Handle<NameDictionary>, int, JSObject::DeleteMode);
14048
14049template Handle<Object>
14050Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14051    DeleteProperty(Handle<SeededNumberDictionary>, int, JSObject::DeleteMode);
14052
14053template Handle<NameDictionary>
14054HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14055    New(Isolate*, int, MinimumCapacity, PretenureFlag);
14056
14057template Handle<NameDictionary>
14058HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
14059    Shrink(Handle<NameDictionary>, Handle<Name>);
14060
14061template Handle<SeededNumberDictionary>
14062HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14063    Shrink(Handle<SeededNumberDictionary>, uint32_t);
14064
14065template void Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14066    CopyKeysTo(
14067        FixedArray*,
14068        int,
14069        PropertyAttributes,
14070        Dictionary<
14071            NameDictionary, NameDictionaryShape, Handle<Name> >::SortMode);
14072
14073template int
14074Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14075    NumberOfElementsFilterAttributes(PropertyAttributes);
14076
14077template Handle<NameDictionary>
14078Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
14079    Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
14080
14081template void
14082Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14083    GenerateNewEnumerationIndices(Handle<NameDictionary>);
14084
14085template int
14086Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14087    NumberOfElementsFilterAttributes(PropertyAttributes);
14088
14089template Handle<SeededNumberDictionary>
14090Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14091    Add(Handle<SeededNumberDictionary>,
14092        uint32_t,
14093        Handle<Object>,
14094        PropertyDetails);
14095
14096template Handle<UnseededNumberDictionary>
14097Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14098    Add(Handle<UnseededNumberDictionary>,
14099        uint32_t,
14100        Handle<Object>,
14101        PropertyDetails);
14102
14103template Handle<SeededNumberDictionary>
14104Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14105    EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
14106
14107template Handle<UnseededNumberDictionary>
14108Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
14109    EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
14110
14111template Handle<NameDictionary>
14112Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14113    EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
14114
14115template
14116int Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14117    NumberOfEnumElements();
14118
14119template
14120int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
14121    NumberOfEnumElements();
14122
14123template
14124int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
14125    FindEntry(uint32_t);
14126
14127
14128Handle<Object> JSObject::PrepareSlowElementsForSort(
14129    Handle<JSObject> object, uint32_t limit) {
14130  DCHECK(object->HasDictionaryElements());
14131  Isolate* isolate = object->GetIsolate();
14132  // Must stay in dictionary mode, either because of requires_slow_elements,
14133  // or because we are not going to sort (and therefore compact) all of the
14134  // elements.
14135  Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
14136  Handle<SeededNumberDictionary> new_dict =
14137      SeededNumberDictionary::New(isolate, dict->NumberOfElements());
14138
14139  uint32_t pos = 0;
14140  uint32_t undefs = 0;
14141  int capacity = dict->Capacity();
14142  Handle<Smi> bailout(Smi::FromInt(-1), isolate);
14143  // Entry to the new dictionary does not cause it to grow, as we have
14144  // allocated one that is large enough for all entries.
14145  DisallowHeapAllocation no_gc;
14146  for (int i = 0; i < capacity; i++) {
14147    Object* k = dict->KeyAt(i);
14148    if (!dict->IsKey(k)) continue;
14149
14150    DCHECK(k->IsNumber());
14151    DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
14152    DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
14153    DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
14154
14155    HandleScope scope(isolate);
14156    Handle<Object> value(dict->ValueAt(i), isolate);
14157    PropertyDetails details = dict->DetailsAt(i);
14158    if (details.type() == CALLBACKS || details.IsReadOnly()) {
14159      // Bail out and do the sorting of undefineds and array holes in JS.
14160      // Also bail out if the element is not supposed to be moved.
14161      return bailout;
14162    }
14163
14164    uint32_t key = NumberToUint32(k);
14165    if (key < limit) {
14166      if (value->IsUndefined()) {
14167        undefs++;
14168      } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14169        // Adding an entry with the key beyond smi-range requires
14170        // allocation. Bailout.
14171        return bailout;
14172      } else {
14173        Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14174            new_dict, pos, value, details);
14175        DCHECK(result.is_identical_to(new_dict));
14176        USE(result);
14177        pos++;
14178      }
14179    } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
14180      // Adding an entry with the key beyond smi-range requires
14181      // allocation. Bailout.
14182      return bailout;
14183    } else {
14184      Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14185          new_dict, key, value, details);
14186      DCHECK(result.is_identical_to(new_dict));
14187      USE(result);
14188    }
14189  }
14190
14191  uint32_t result = pos;
14192  PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0);
14193  while (undefs > 0) {
14194    if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14195      // Adding an entry with the key beyond smi-range requires
14196      // allocation. Bailout.
14197      return bailout;
14198    }
14199    HandleScope scope(isolate);
14200    Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
14201        new_dict, pos, isolate->factory()->undefined_value(), no_details);
14202    DCHECK(result.is_identical_to(new_dict));
14203    USE(result);
14204    pos++;
14205    undefs--;
14206  }
14207
14208  object->set_elements(*new_dict);
14209
14210  AllowHeapAllocation allocate_return_value;
14211  return isolate->factory()->NewNumberFromUint(result);
14212}
14213
14214
14215// Collects all defined (non-hole) and non-undefined (array) elements at
14216// the start of the elements array.
14217// If the object is in dictionary mode, it is converted to fast elements
14218// mode.
14219Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
14220                                                uint32_t limit) {
14221  Isolate* isolate = object->GetIsolate();
14222  if (object->HasSloppyArgumentsElements() ||
14223      object->map()->is_observed()) {
14224    return handle(Smi::FromInt(-1), isolate);
14225  }
14226
14227  if (object->HasDictionaryElements()) {
14228    // Convert to fast elements containing only the existing properties.
14229    // Ordering is irrelevant, since we are going to sort anyway.
14230    Handle<SeededNumberDictionary> dict(object->element_dictionary());
14231    if (object->IsJSArray() || dict->requires_slow_elements() ||
14232        dict->max_number_key() >= limit) {
14233      return JSObject::PrepareSlowElementsForSort(object, limit);
14234    }
14235    // Convert to fast elements.
14236
14237    Handle<Map> new_map =
14238        JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
14239
14240    PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
14241        NOT_TENURED: TENURED;
14242    Handle<FixedArray> fast_elements =
14243        isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
14244    dict->CopyValuesTo(*fast_elements);
14245    JSObject::ValidateElements(object);
14246
14247    JSObject::SetMapAndElements(object, new_map, fast_elements);
14248  } else if (object->HasExternalArrayElements() ||
14249             object->HasFixedTypedArrayElements()) {
14250    // Typed arrays cannot have holes or undefined elements.
14251    return handle(Smi::FromInt(
14252        FixedArrayBase::cast(object->elements())->length()), isolate);
14253  } else if (!object->HasFastDoubleElements()) {
14254    EnsureWritableFastElements(object);
14255  }
14256  DCHECK(object->HasFastSmiOrObjectElements() ||
14257         object->HasFastDoubleElements());
14258
14259  // Collect holes at the end, undefined before that and the rest at the
14260  // start, and return the number of non-hole, non-undefined values.
14261
14262  Handle<FixedArrayBase> elements_base(object->elements());
14263  uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
14264  if (limit > elements_length) {
14265    limit = elements_length ;
14266  }
14267  if (limit == 0) {
14268    return handle(Smi::FromInt(0), isolate);
14269  }
14270
14271  uint32_t result = 0;
14272  if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
14273    FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
14274    // Split elements into defined and the_hole, in that order.
14275    unsigned int holes = limit;
14276    // Assume most arrays contain no holes and undefined values, so minimize the
14277    // number of stores of non-undefined, non-the-hole values.
14278    for (unsigned int i = 0; i < holes; i++) {
14279      if (elements->is_the_hole(i)) {
14280        holes--;
14281      } else {
14282        continue;
14283      }
14284      // Position i needs to be filled.
14285      while (holes > i) {
14286        if (elements->is_the_hole(holes)) {
14287          holes--;
14288        } else {
14289          elements->set(i, elements->get_scalar(holes));
14290          break;
14291        }
14292      }
14293    }
14294    result = holes;
14295    while (holes < limit) {
14296      elements->set_the_hole(holes);
14297      holes++;
14298    }
14299  } else {
14300    FixedArray* elements = FixedArray::cast(*elements_base);
14301    DisallowHeapAllocation no_gc;
14302
14303    // Split elements into defined, undefined and the_hole, in that order.  Only
14304    // count locations for undefined and the hole, and fill them afterwards.
14305    WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
14306    unsigned int undefs = limit;
14307    unsigned int holes = limit;
14308    // Assume most arrays contain no holes and undefined values, so minimize the
14309    // number of stores of non-undefined, non-the-hole values.
14310    for (unsigned int i = 0; i < undefs; i++) {
14311      Object* current = elements->get(i);
14312      if (current->IsTheHole()) {
14313        holes--;
14314        undefs--;
14315      } else if (current->IsUndefined()) {
14316        undefs--;
14317      } else {
14318        continue;
14319      }
14320      // Position i needs to be filled.
14321      while (undefs > i) {
14322        current = elements->get(undefs);
14323        if (current->IsTheHole()) {
14324          holes--;
14325          undefs--;
14326        } else if (current->IsUndefined()) {
14327          undefs--;
14328        } else {
14329          elements->set(i, current, write_barrier);
14330          break;
14331        }
14332      }
14333    }
14334    result = undefs;
14335    while (undefs < holes) {
14336      elements->set_undefined(undefs);
14337      undefs++;
14338    }
14339    while (holes < limit) {
14340      elements->set_the_hole(holes);
14341      holes++;
14342    }
14343  }
14344
14345  return isolate->factory()->NewNumberFromUint(result);
14346}
14347
14348
14349ExternalArrayType JSTypedArray::type() {
14350  switch (elements()->map()->instance_type()) {
14351#define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
14352    case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
14353    case FIXED_##TYPE##_ARRAY_TYPE:                                           \
14354      return kExternal##Type##Array;
14355
14356    TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
14357#undef INSTANCE_TYPE_TO_ARRAY_TYPE
14358
14359    default:
14360      UNREACHABLE();
14361      return static_cast<ExternalArrayType>(-1);
14362  }
14363}
14364
14365
14366size_t JSTypedArray::element_size() {
14367  switch (elements()->map()->instance_type()) {
14368#define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)          \
14369    case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
14370      return size;
14371
14372    TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
14373#undef INSTANCE_TYPE_TO_ELEMENT_SIZE
14374
14375    default:
14376      UNREACHABLE();
14377      return 0;
14378  }
14379}
14380
14381
14382Handle<Object> ExternalUint8ClampedArray::SetValue(
14383    Handle<ExternalUint8ClampedArray> array,
14384    uint32_t index,
14385    Handle<Object> value) {
14386  uint8_t clamped_value = 0;
14387  if (index < static_cast<uint32_t>(array->length())) {
14388    if (value->IsSmi()) {
14389      int int_value = Handle<Smi>::cast(value)->value();
14390      if (int_value < 0) {
14391        clamped_value = 0;
14392      } else if (int_value > 255) {
14393        clamped_value = 255;
14394      } else {
14395        clamped_value = static_cast<uint8_t>(int_value);
14396      }
14397    } else if (value->IsHeapNumber()) {
14398      double double_value = Handle<HeapNumber>::cast(value)->value();
14399      if (!(double_value > 0)) {
14400        // NaN and less than zero clamp to zero.
14401        clamped_value = 0;
14402      } else if (double_value > 255) {
14403        // Greater than 255 clamp to 255.
14404        clamped_value = 255;
14405      } else {
14406        // Other doubles are rounded to the nearest integer.
14407        clamped_value = static_cast<uint8_t>(lrint(double_value));
14408      }
14409    } else {
14410      // Clamp undefined to zero (default). All other types have been
14411      // converted to a number type further up in the call chain.
14412      DCHECK(value->IsUndefined());
14413    }
14414    array->set(index, clamped_value);
14415  }
14416  return handle(Smi::FromInt(clamped_value), array->GetIsolate());
14417}
14418
14419
14420template<typename ExternalArrayClass, typename ValueType>
14421static Handle<Object> ExternalArrayIntSetter(
14422    Isolate* isolate,
14423    Handle<ExternalArrayClass> receiver,
14424    uint32_t index,
14425    Handle<Object> value) {
14426  ValueType cast_value = 0;
14427  if (index < static_cast<uint32_t>(receiver->length())) {
14428    if (value->IsSmi()) {
14429      int int_value = Handle<Smi>::cast(value)->value();
14430      cast_value = static_cast<ValueType>(int_value);
14431    } else if (value->IsHeapNumber()) {
14432      double double_value = Handle<HeapNumber>::cast(value)->value();
14433      cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
14434    } else {
14435      // Clamp undefined to zero (default). All other types have been
14436      // converted to a number type further up in the call chain.
14437      DCHECK(value->IsUndefined());
14438    }
14439    receiver->set(index, cast_value);
14440  }
14441  return isolate->factory()->NewNumberFromInt(cast_value);
14442}
14443
14444
14445Handle<Object> ExternalInt8Array::SetValue(Handle<ExternalInt8Array> array,
14446                                           uint32_t index,
14447                                           Handle<Object> value) {
14448  return ExternalArrayIntSetter<ExternalInt8Array, int8_t>(
14449      array->GetIsolate(), array, index, value);
14450}
14451
14452
14453Handle<Object> ExternalUint8Array::SetValue(Handle<ExternalUint8Array> array,
14454                                            uint32_t index,
14455                                            Handle<Object> value) {
14456  return ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(
14457      array->GetIsolate(), array, index, value);
14458}
14459
14460
14461Handle<Object> ExternalInt16Array::SetValue(Handle<ExternalInt16Array> array,
14462                                            uint32_t index,
14463                                            Handle<Object> value) {
14464  return ExternalArrayIntSetter<ExternalInt16Array, int16_t>(
14465      array->GetIsolate(), array, index, value);
14466}
14467
14468
14469Handle<Object> ExternalUint16Array::SetValue(Handle<ExternalUint16Array> array,
14470                                             uint32_t index,
14471                                             Handle<Object> value) {
14472  return ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(
14473      array->GetIsolate(), array, index, value);
14474}
14475
14476
14477Handle<Object> ExternalInt32Array::SetValue(Handle<ExternalInt32Array> array,
14478                                            uint32_t index,
14479                                            Handle<Object> value) {
14480  return ExternalArrayIntSetter<ExternalInt32Array, int32_t>(
14481      array->GetIsolate(), array, index, value);
14482}
14483
14484
14485Handle<Object> ExternalUint32Array::SetValue(
14486    Handle<ExternalUint32Array> array,
14487    uint32_t index,
14488    Handle<Object> value) {
14489  uint32_t cast_value = 0;
14490  if (index < static_cast<uint32_t>(array->length())) {
14491    if (value->IsSmi()) {
14492      int int_value = Handle<Smi>::cast(value)->value();
14493      cast_value = static_cast<uint32_t>(int_value);
14494    } else if (value->IsHeapNumber()) {
14495      double double_value = Handle<HeapNumber>::cast(value)->value();
14496      cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
14497    } else {
14498      // Clamp undefined to zero (default). All other types have been
14499      // converted to a number type further up in the call chain.
14500      DCHECK(value->IsUndefined());
14501    }
14502    array->set(index, cast_value);
14503  }
14504  return array->GetIsolate()->factory()->NewNumberFromUint(cast_value);
14505}
14506
14507
14508Handle<Object> ExternalFloat32Array::SetValue(
14509    Handle<ExternalFloat32Array> array,
14510    uint32_t index,
14511    Handle<Object> value) {
14512  float cast_value = static_cast<float>(base::OS::nan_value());
14513  if (index < static_cast<uint32_t>(array->length())) {
14514    if (value->IsSmi()) {
14515      int int_value = Handle<Smi>::cast(value)->value();
14516      cast_value = static_cast<float>(int_value);
14517    } else if (value->IsHeapNumber()) {
14518      double double_value = Handle<HeapNumber>::cast(value)->value();
14519      cast_value = static_cast<float>(double_value);
14520    } else {
14521      // Clamp undefined to NaN (default). All other types have been
14522      // converted to a number type further up in the call chain.
14523      DCHECK(value->IsUndefined());
14524    }
14525    array->set(index, cast_value);
14526  }
14527  return array->GetIsolate()->factory()->NewNumber(cast_value);
14528}
14529
14530
14531Handle<Object> ExternalFloat64Array::SetValue(
14532    Handle<ExternalFloat64Array> array,
14533    uint32_t index,
14534    Handle<Object> value) {
14535  double double_value = base::OS::nan_value();
14536  if (index < static_cast<uint32_t>(array->length())) {
14537    if (value->IsNumber()) {
14538      double_value = value->Number();
14539    } else {
14540      // Clamp undefined to NaN (default). All other types have been
14541      // converted to a number type further up in the call chain.
14542      DCHECK(value->IsUndefined());
14543    }
14544    array->set(index, double_value);
14545  }
14546  return array->GetIsolate()->factory()->NewNumber(double_value);
14547}
14548
14549
14550Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell(
14551    Handle<JSGlobalObject> global,
14552    Handle<Name> name) {
14553  DCHECK(!global->HasFastProperties());
14554  int entry = global->property_dictionary()->FindEntry(name);
14555  if (entry == NameDictionary::kNotFound) {
14556    Isolate* isolate = global->GetIsolate();
14557    Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(
14558        isolate->factory()->the_hole_value());
14559    PropertyDetails details(NONE, NORMAL, 0);
14560    details = details.AsDeleted();
14561    Handle<NameDictionary> dictionary = NameDictionary::Add(
14562        handle(global->property_dictionary()), name, cell, details);
14563    global->set_properties(*dictionary);
14564    return cell;
14565  } else {
14566    Object* value = global->property_dictionary()->ValueAt(entry);
14567    DCHECK(value->IsPropertyCell());
14568    return handle(PropertyCell::cast(value));
14569  }
14570}
14571
14572
14573// This class is used for looking up two character strings in the string table.
14574// If we don't have a hit we don't want to waste much time so we unroll the
14575// string hash calculation loop here for speed.  Doesn't work if the two
14576// characters form a decimal integer, since such strings have a different hash
14577// algorithm.
14578class TwoCharHashTableKey : public HashTableKey {
14579 public:
14580  TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
14581    : c1_(c1), c2_(c2) {
14582    // Char 1.
14583    uint32_t hash = seed;
14584    hash += c1;
14585    hash += hash << 10;
14586    hash ^= hash >> 6;
14587    // Char 2.
14588    hash += c2;
14589    hash += hash << 10;
14590    hash ^= hash >> 6;
14591    // GetHash.
14592    hash += hash << 3;
14593    hash ^= hash >> 11;
14594    hash += hash << 15;
14595    if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
14596    hash_ = hash;
14597#ifdef DEBUG
14598    // If this assert fails then we failed to reproduce the two-character
14599    // version of the string hashing algorithm above.  One reason could be
14600    // that we were passed two digits as characters, since the hash
14601    // algorithm is different in that case.
14602    uint16_t chars[2] = {c1, c2};
14603    uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
14604    hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
14605    DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
14606#endif
14607  }
14608
14609  bool IsMatch(Object* o) OVERRIDE {
14610    if (!o->IsString()) return false;
14611    String* other = String::cast(o);
14612    if (other->length() != 2) return false;
14613    if (other->Get(0) != c1_) return false;
14614    return other->Get(1) == c2_;
14615  }
14616
14617  uint32_t Hash() OVERRIDE { return hash_; }
14618  uint32_t HashForObject(Object* key) OVERRIDE {
14619    if (!key->IsString()) return 0;
14620    return String::cast(key)->Hash();
14621  }
14622
14623  Handle<Object> AsHandle(Isolate* isolate) OVERRIDE {
14624    // The TwoCharHashTableKey is only used for looking in the string
14625    // table, not for adding to it.
14626    UNREACHABLE();
14627    return MaybeHandle<Object>().ToHandleChecked();
14628  }
14629
14630 private:
14631  uint16_t c1_;
14632  uint16_t c2_;
14633  uint32_t hash_;
14634};
14635
14636
14637MaybeHandle<String> StringTable::InternalizeStringIfExists(
14638    Isolate* isolate,
14639    Handle<String> string) {
14640  if (string->IsInternalizedString()) {
14641    return string;
14642  }
14643  return LookupStringIfExists(isolate, string);
14644}
14645
14646
14647MaybeHandle<String> StringTable::LookupStringIfExists(
14648    Isolate* isolate,
14649    Handle<String> string) {
14650  Handle<StringTable> string_table = isolate->factory()->string_table();
14651  InternalizedStringKey key(string);
14652  int entry = string_table->FindEntry(&key);
14653  if (entry == kNotFound) {
14654    return MaybeHandle<String>();
14655  } else {
14656    Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14657    DCHECK(StringShape(*result).IsInternalized());
14658    return result;
14659  }
14660}
14661
14662
14663MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
14664    Isolate* isolate,
14665    uint16_t c1,
14666    uint16_t c2) {
14667  Handle<StringTable> string_table = isolate->factory()->string_table();
14668  TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
14669  int entry = string_table->FindEntry(&key);
14670  if (entry == kNotFound) {
14671    return MaybeHandle<String>();
14672  } else {
14673    Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14674    DCHECK(StringShape(*result).IsInternalized());
14675    return result;
14676  }
14677}
14678
14679
14680Handle<String> StringTable::LookupString(Isolate* isolate,
14681                                         Handle<String> string) {
14682  InternalizedStringKey key(string);
14683  return LookupKey(isolate, &key);
14684}
14685
14686
14687Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
14688  Handle<StringTable> table = isolate->factory()->string_table();
14689  int entry = table->FindEntry(key);
14690
14691  // String already in table.
14692  if (entry != kNotFound) {
14693    return handle(String::cast(table->KeyAt(entry)), isolate);
14694  }
14695
14696  // Adding new string. Grow table if needed.
14697  table = StringTable::EnsureCapacity(table, 1, key);
14698
14699  // Create string object.
14700  Handle<Object> string = key->AsHandle(isolate);
14701  // There must be no attempts to internalize strings that could throw
14702  // InvalidStringLength error.
14703  CHECK(!string.is_null());
14704
14705  // Add the new string and return it along with the string table.
14706  entry = table->FindInsertionEntry(key->Hash());
14707  table->set(EntryToIndex(entry), *string);
14708  table->ElementAdded();
14709
14710  isolate->factory()->set_string_table(table);
14711  return Handle<String>::cast(string);
14712}
14713
14714
14715Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
14716                                             Handle<Context> context) {
14717  Isolate* isolate = GetIsolate();
14718  Handle<SharedFunctionInfo> shared(context->closure()->shared());
14719  StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
14720                      RelocInfo::kNoPosition);
14721  int entry = FindEntry(&key);
14722  if (entry == kNotFound) return isolate->factory()->undefined_value();
14723  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14724}
14725
14726
14727Handle<Object> CompilationCacheTable::LookupEval(
14728    Handle<String> src, Handle<SharedFunctionInfo> outer_info,
14729    StrictMode strict_mode, int scope_position) {
14730  Isolate* isolate = GetIsolate();
14731  // Cache key is the tuple (source, outer shared function info, scope position)
14732  // to unambiguously identify the context chain the cached eval code assumes.
14733  StringSharedKey key(src, outer_info, strict_mode, scope_position);
14734  int entry = FindEntry(&key);
14735  if (entry == kNotFound) return isolate->factory()->undefined_value();
14736  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14737}
14738
14739
14740Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
14741                                                   JSRegExp::Flags flags) {
14742  Isolate* isolate = GetIsolate();
14743  DisallowHeapAllocation no_allocation;
14744  RegExpKey key(src, flags);
14745  int entry = FindEntry(&key);
14746  if (entry == kNotFound) return isolate->factory()->undefined_value();
14747  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14748}
14749
14750
14751Handle<CompilationCacheTable> CompilationCacheTable::Put(
14752    Handle<CompilationCacheTable> cache, Handle<String> src,
14753    Handle<Context> context, Handle<Object> value) {
14754  Isolate* isolate = cache->GetIsolate();
14755  Handle<SharedFunctionInfo> shared(context->closure()->shared());
14756  StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
14757                      RelocInfo::kNoPosition);
14758  cache = EnsureCapacity(cache, 1, &key);
14759  Handle<Object> k = key.AsHandle(isolate);
14760  int entry = cache->FindInsertionEntry(key.Hash());
14761  cache->set(EntryToIndex(entry), *k);
14762  cache->set(EntryToIndex(entry) + 1, *value);
14763  cache->ElementAdded();
14764  return cache;
14765}
14766
14767
14768Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
14769    Handle<CompilationCacheTable> cache, Handle<String> src,
14770    Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
14771    int scope_position) {
14772  Isolate* isolate = cache->GetIsolate();
14773  StringSharedKey key(src, outer_info, value->strict_mode(), scope_position);
14774  cache = EnsureCapacity(cache, 1, &key);
14775  Handle<Object> k = key.AsHandle(isolate);
14776  int entry = cache->FindInsertionEntry(key.Hash());
14777  cache->set(EntryToIndex(entry), *k);
14778  cache->set(EntryToIndex(entry) + 1, *value);
14779  cache->ElementAdded();
14780  return cache;
14781}
14782
14783
14784Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
14785      Handle<CompilationCacheTable> cache, Handle<String> src,
14786      JSRegExp::Flags flags, Handle<FixedArray> value) {
14787  RegExpKey key(src, flags);
14788  cache = EnsureCapacity(cache, 1, &key);
14789  int entry = cache->FindInsertionEntry(key.Hash());
14790  // We store the value in the key slot, and compare the search key
14791  // to the stored value with a custon IsMatch function during lookups.
14792  cache->set(EntryToIndex(entry), *value);
14793  cache->set(EntryToIndex(entry) + 1, *value);
14794  cache->ElementAdded();
14795  return cache;
14796}
14797
14798
14799void CompilationCacheTable::Remove(Object* value) {
14800  DisallowHeapAllocation no_allocation;
14801  Object* the_hole_value = GetHeap()->the_hole_value();
14802  for (int entry = 0, size = Capacity(); entry < size; entry++) {
14803    int entry_index = EntryToIndex(entry);
14804    int value_index = entry_index + 1;
14805    if (get(value_index) == value) {
14806      NoWriteBarrierSet(this, entry_index, the_hole_value);
14807      NoWriteBarrierSet(this, value_index, the_hole_value);
14808      ElementRemoved();
14809    }
14810  }
14811  return;
14812}
14813
14814
14815// StringsKey used for HashTable where key is array of internalized strings.
14816class StringsKey : public HashTableKey {
14817 public:
14818  explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
14819
14820  bool IsMatch(Object* strings) OVERRIDE {
14821    FixedArray* o = FixedArray::cast(strings);
14822    int len = strings_->length();
14823    if (o->length() != len) return false;
14824    for (int i = 0; i < len; i++) {
14825      if (o->get(i) != strings_->get(i)) return false;
14826    }
14827    return true;
14828  }
14829
14830  uint32_t Hash() OVERRIDE { return HashForObject(*strings_); }
14831
14832  uint32_t HashForObject(Object* obj) OVERRIDE {
14833    FixedArray* strings = FixedArray::cast(obj);
14834    int len = strings->length();
14835    uint32_t hash = 0;
14836    for (int i = 0; i < len; i++) {
14837      hash ^= String::cast(strings->get(i))->Hash();
14838    }
14839    return hash;
14840  }
14841
14842  Handle<Object> AsHandle(Isolate* isolate) OVERRIDE { return strings_; }
14843
14844 private:
14845  Handle<FixedArray> strings_;
14846};
14847
14848
14849Object* MapCache::Lookup(FixedArray* array) {
14850  DisallowHeapAllocation no_alloc;
14851  StringsKey key(handle(array));
14852  int entry = FindEntry(&key);
14853  if (entry == kNotFound) return GetHeap()->undefined_value();
14854  return get(EntryToIndex(entry) + 1);
14855}
14856
14857
14858Handle<MapCache> MapCache::Put(
14859    Handle<MapCache> map_cache, Handle<FixedArray> array, Handle<Map> value) {
14860  StringsKey key(array);
14861
14862  Handle<MapCache> new_cache = EnsureCapacity(map_cache, 1, &key);
14863  int entry = new_cache->FindInsertionEntry(key.Hash());
14864  new_cache->set(EntryToIndex(entry), *array);
14865  new_cache->set(EntryToIndex(entry) + 1, *value);
14866  new_cache->ElementAdded();
14867  return new_cache;
14868}
14869
14870
14871template<typename Derived, typename Shape, typename Key>
14872Handle<Derived> Dictionary<Derived, Shape, Key>::New(
14873    Isolate* isolate,
14874    int at_least_space_for,
14875    PretenureFlag pretenure) {
14876  DCHECK(0 <= at_least_space_for);
14877  Handle<Derived> dict = DerivedHashTable::New(isolate,
14878                                               at_least_space_for,
14879                                               USE_DEFAULT_MINIMUM_CAPACITY,
14880                                               pretenure);
14881
14882  // Initialize the next enumeration index.
14883  dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
14884  return dict;
14885}
14886
14887
14888template<typename Derived, typename Shape, typename Key>
14889void Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
14890    Handle<Derived> dictionary) {
14891  Factory* factory = dictionary->GetIsolate()->factory();
14892  int length = dictionary->NumberOfElements();
14893
14894  // Allocate and initialize iteration order array.
14895  Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
14896  for (int i = 0; i < length; i++) {
14897    iteration_order->set(i, Smi::FromInt(i));
14898  }
14899
14900  // Allocate array with enumeration order.
14901  Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
14902
14903  // Fill the enumeration order array with property details.
14904  int capacity = dictionary->Capacity();
14905  int pos = 0;
14906  for (int i = 0; i < capacity; i++) {
14907    if (dictionary->IsKey(dictionary->KeyAt(i))) {
14908      int index = dictionary->DetailsAt(i).dictionary_index();
14909      enumeration_order->set(pos++, Smi::FromInt(index));
14910    }
14911  }
14912
14913  // Sort the arrays wrt. enumeration order.
14914  iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
14915
14916  // Overwrite the enumeration_order with the enumeration indices.
14917  for (int i = 0; i < length; i++) {
14918    int index = Smi::cast(iteration_order->get(i))->value();
14919    int enum_index = PropertyDetails::kInitialIndex + i;
14920    enumeration_order->set(index, Smi::FromInt(enum_index));
14921  }
14922
14923  // Update the dictionary with new indices.
14924  capacity = dictionary->Capacity();
14925  pos = 0;
14926  for (int i = 0; i < capacity; i++) {
14927    if (dictionary->IsKey(dictionary->KeyAt(i))) {
14928      int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
14929      PropertyDetails details = dictionary->DetailsAt(i);
14930      PropertyDetails new_details = PropertyDetails(
14931          details.attributes(), details.type(), enum_index);
14932      dictionary->DetailsAtPut(i, new_details);
14933    }
14934  }
14935
14936  // Set the next enumeration index.
14937  dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
14938}
14939
14940
14941template<typename Derived, typename Shape, typename Key>
14942Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
14943    Handle<Derived> dictionary, int n, Key key) {
14944  // Check whether there are enough enumeration indices to add n elements.
14945  if (Shape::kIsEnumerable &&
14946      !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
14947    // If not, we generate new indices for the properties.
14948    GenerateNewEnumerationIndices(dictionary);
14949  }
14950  return DerivedHashTable::EnsureCapacity(dictionary, n, key);
14951}
14952
14953
14954template<typename Derived, typename Shape, typename Key>
14955Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
14956    Handle<Derived> dictionary,
14957    int entry,
14958    JSObject::DeleteMode mode) {
14959  Factory* factory = dictionary->GetIsolate()->factory();
14960  PropertyDetails details = dictionary->DetailsAt(entry);
14961  // Ignore attributes if forcing a deletion.
14962  if (!details.IsConfigurable() && mode != JSReceiver::FORCE_DELETION) {
14963    return factory->false_value();
14964  }
14965
14966  dictionary->SetEntry(
14967      entry, factory->the_hole_value(), factory->the_hole_value());
14968  dictionary->ElementRemoved();
14969  return factory->true_value();
14970}
14971
14972
14973template<typename Derived, typename Shape, typename Key>
14974Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
14975    Handle<Derived> dictionary, Key key, Handle<Object> value) {
14976  int entry = dictionary->FindEntry(key);
14977
14978  // If the entry is present set the value;
14979  if (entry != Dictionary::kNotFound) {
14980    dictionary->ValueAtPut(entry, *value);
14981    return dictionary;
14982  }
14983
14984  // Check whether the dictionary should be extended.
14985  dictionary = EnsureCapacity(dictionary, 1, key);
14986#ifdef DEBUG
14987  USE(Shape::AsHandle(dictionary->GetIsolate(), key));
14988#endif
14989  PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
14990
14991  AddEntry(dictionary, key, value, details, dictionary->Hash(key));
14992  return dictionary;
14993}
14994
14995
14996template<typename Derived, typename Shape, typename Key>
14997Handle<Derived> Dictionary<Derived, Shape, Key>::Add(
14998    Handle<Derived> dictionary,
14999    Key key,
15000    Handle<Object> value,
15001    PropertyDetails details) {
15002  // Valdate key is absent.
15003  SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
15004  // Check whether the dictionary should be extended.
15005  dictionary = EnsureCapacity(dictionary, 1, key);
15006
15007  AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15008  return dictionary;
15009}
15010
15011
15012// Add a key, value pair to the dictionary.
15013template<typename Derived, typename Shape, typename Key>
15014void Dictionary<Derived, Shape, Key>::AddEntry(
15015    Handle<Derived> dictionary,
15016    Key key,
15017    Handle<Object> value,
15018    PropertyDetails details,
15019    uint32_t hash) {
15020  // Compute the key object.
15021  Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
15022
15023  uint32_t entry = dictionary->FindInsertionEntry(hash);
15024  // Insert element at empty or deleted entry
15025  if (!details.IsDeleted() &&
15026      details.dictionary_index() == 0 &&
15027      Shape::kIsEnumerable) {
15028    // Assign an enumeration index to the property and update
15029    // SetNextEnumerationIndex.
15030    int index = dictionary->NextEnumerationIndex();
15031    details = PropertyDetails(details.attributes(), details.type(), index);
15032    dictionary->SetNextEnumerationIndex(index + 1);
15033  }
15034  dictionary->SetEntry(entry, k, value, details);
15035  DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
15036          dictionary->KeyAt(entry)->IsName()));
15037  dictionary->ElementAdded();
15038}
15039
15040
15041void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
15042  DisallowHeapAllocation no_allocation;
15043  // If the dictionary requires slow elements an element has already
15044  // been added at a high index.
15045  if (requires_slow_elements()) return;
15046  // Check if this index is high enough that we should require slow
15047  // elements.
15048  if (key > kRequiresSlowElementsLimit) {
15049    set_requires_slow_elements();
15050    return;
15051  }
15052  // Update max key value.
15053  Object* max_index_object = get(kMaxNumberKeyIndex);
15054  if (!max_index_object->IsSmi() || max_number_key() < key) {
15055    FixedArray::set(kMaxNumberKeyIndex,
15056                    Smi::FromInt(key << kRequiresSlowElementsTagSize));
15057  }
15058}
15059
15060
15061Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
15062    Handle<SeededNumberDictionary> dictionary,
15063    uint32_t key,
15064    Handle<Object> value,
15065    PropertyDetails details) {
15066  dictionary->UpdateMaxNumberKey(key);
15067  SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
15068  return Add(dictionary, key, value, details);
15069}
15070
15071
15072Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
15073    Handle<UnseededNumberDictionary> dictionary,
15074    uint32_t key,
15075    Handle<Object> value) {
15076  SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
15077  return Add(dictionary, key, value, PropertyDetails(NONE, NORMAL, 0));
15078}
15079
15080
15081Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
15082    Handle<SeededNumberDictionary> dictionary,
15083    uint32_t key,
15084    Handle<Object> value) {
15085  dictionary->UpdateMaxNumberKey(key);
15086  return AtPut(dictionary, key, value);
15087}
15088
15089
15090Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
15091    Handle<UnseededNumberDictionary> dictionary,
15092    uint32_t key,
15093    Handle<Object> value) {
15094  return AtPut(dictionary, key, value);
15095}
15096
15097
15098Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
15099    Handle<SeededNumberDictionary> dictionary,
15100    uint32_t key,
15101    Handle<Object> value,
15102    PropertyDetails details) {
15103  int entry = dictionary->FindEntry(key);
15104  if (entry == kNotFound) {
15105    return AddNumberEntry(dictionary, key, value, details);
15106  }
15107  // Preserve enumeration index.
15108  details = PropertyDetails(details.attributes(),
15109                            details.type(),
15110                            dictionary->DetailsAt(entry).dictionary_index());
15111  Handle<Object> object_key =
15112      SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15113  dictionary->SetEntry(entry, object_key, value, details);
15114  return dictionary;
15115}
15116
15117
15118Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
15119    Handle<UnseededNumberDictionary> dictionary,
15120    uint32_t key,
15121    Handle<Object> value) {
15122  int entry = dictionary->FindEntry(key);
15123  if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
15124  Handle<Object> object_key =
15125      UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15126  dictionary->SetEntry(entry, object_key, value);
15127  return dictionary;
15128}
15129
15130
15131
15132template<typename Derived, typename Shape, typename Key>
15133int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
15134    PropertyAttributes filter) {
15135  int capacity = DerivedHashTable::Capacity();
15136  int result = 0;
15137  for (int i = 0; i < capacity; i++) {
15138    Object* k = DerivedHashTable::KeyAt(i);
15139    if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15140      PropertyDetails details = DetailsAt(i);
15141      if (details.IsDeleted()) continue;
15142      PropertyAttributes attr = details.attributes();
15143      if ((attr & filter) == 0) result++;
15144    }
15145  }
15146  return result;
15147}
15148
15149
15150template<typename Derived, typename Shape, typename Key>
15151int Dictionary<Derived, Shape, Key>::NumberOfEnumElements() {
15152  return NumberOfElementsFilterAttributes(
15153      static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC));
15154}
15155
15156
15157template<typename Derived, typename Shape, typename Key>
15158void Dictionary<Derived, Shape, Key>::CopyKeysTo(
15159    FixedArray* storage,
15160    PropertyAttributes filter,
15161    typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
15162  DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
15163  int capacity = DerivedHashTable::Capacity();
15164  int index = 0;
15165  for (int i = 0; i < capacity; i++) {
15166     Object* k = DerivedHashTable::KeyAt(i);
15167     if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15168       PropertyDetails details = DetailsAt(i);
15169       if (details.IsDeleted()) continue;
15170       PropertyAttributes attr = details.attributes();
15171       if ((attr & filter) == 0) storage->set(index++, k);
15172     }
15173  }
15174  if (sort_mode == Dictionary::SORTED) {
15175    storage->SortPairs(storage, index);
15176  }
15177  DCHECK(storage->length() >= index);
15178}
15179
15180
15181struct EnumIndexComparator {
15182  explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { }
15183  bool operator() (Smi* a, Smi* b) {
15184    PropertyDetails da(dict->DetailsAt(a->value()));
15185    PropertyDetails db(dict->DetailsAt(b->value()));
15186    return da.dictionary_index() < db.dictionary_index();
15187  }
15188  NameDictionary* dict;
15189};
15190
15191
15192void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
15193  int length = storage->length();
15194  int capacity = Capacity();
15195  int properties = 0;
15196  for (int i = 0; i < capacity; i++) {
15197     Object* k = KeyAt(i);
15198     if (IsKey(k) && !k->IsSymbol()) {
15199       PropertyDetails details = DetailsAt(i);
15200       if (details.IsDeleted() || details.IsDontEnum()) continue;
15201       storage->set(properties, Smi::FromInt(i));
15202       properties++;
15203       if (properties == length) break;
15204     }
15205  }
15206  CHECK_EQ(length, properties);
15207  EnumIndexComparator cmp(this);
15208  Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
15209  std::sort(start, start + length, cmp);
15210  for (int i = 0; i < length; i++) {
15211    int index = Smi::cast(storage->get(i))->value();
15212    storage->set(i, KeyAt(index));
15213  }
15214}
15215
15216
15217template<typename Derived, typename Shape, typename Key>
15218void Dictionary<Derived, Shape, Key>::CopyKeysTo(
15219    FixedArray* storage,
15220    int index,
15221    PropertyAttributes filter,
15222    typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
15223  DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
15224  int capacity = DerivedHashTable::Capacity();
15225  for (int i = 0; i < capacity; i++) {
15226    Object* k = DerivedHashTable::KeyAt(i);
15227    if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15228      PropertyDetails details = DetailsAt(i);
15229      if (details.IsDeleted()) continue;
15230      PropertyAttributes attr = details.attributes();
15231      if ((attr & filter) == 0) storage->set(index++, k);
15232    }
15233  }
15234  if (sort_mode == Dictionary::SORTED) {
15235    storage->SortPairs(storage, index);
15236  }
15237  DCHECK(storage->length() >= index);
15238}
15239
15240
15241// Backwards lookup (slow).
15242template<typename Derived, typename Shape, typename Key>
15243Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
15244  int capacity = DerivedHashTable::Capacity();
15245  for (int i = 0; i < capacity; i++) {
15246    Object* k =  DerivedHashTable::KeyAt(i);
15247    if (Dictionary::IsKey(k)) {
15248      Object* e = ValueAt(i);
15249      if (e->IsPropertyCell()) {
15250        e = PropertyCell::cast(e)->value();
15251      }
15252      if (e == value) return k;
15253    }
15254  }
15255  Heap* heap = Dictionary::GetHeap();
15256  return heap->undefined_value();
15257}
15258
15259
15260Object* ObjectHashTable::Lookup(Handle<Object> key) {
15261  DisallowHeapAllocation no_gc;
15262  DCHECK(IsKey(*key));
15263
15264  // If the object does not have an identity hash, it was never used as a key.
15265  Object* hash = key->GetHash();
15266  if (hash->IsUndefined()) {
15267    return GetHeap()->the_hole_value();
15268  }
15269  int entry = FindEntry(key);
15270  if (entry == kNotFound) return GetHeap()->the_hole_value();
15271  return get(EntryToIndex(entry) + 1);
15272}
15273
15274
15275Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
15276                                             Handle<Object> key,
15277                                             Handle<Object> value) {
15278  DCHECK(table->IsKey(*key));
15279  DCHECK(!value->IsTheHole());
15280
15281  Isolate* isolate = table->GetIsolate();
15282
15283  // Make sure the key object has an identity hash code.
15284  Handle<Smi> hash = Object::GetOrCreateHash(isolate, key);
15285
15286  int entry = table->FindEntry(key);
15287
15288  // Key is already in table, just overwrite value.
15289  if (entry != kNotFound) {
15290    table->set(EntryToIndex(entry) + 1, *value);
15291    return table;
15292  }
15293
15294  // Check whether the hash table should be extended.
15295  table = EnsureCapacity(table, 1, key);
15296  table->AddEntry(table->FindInsertionEntry(hash->value()),
15297                  *key,
15298                  *value);
15299  return table;
15300}
15301
15302
15303Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
15304                                                Handle<Object> key,
15305                                                bool* was_present) {
15306  DCHECK(table->IsKey(*key));
15307
15308  Object* hash = key->GetHash();
15309  if (hash->IsUndefined()) {
15310    *was_present = false;
15311    return table;
15312  }
15313
15314  int entry = table->FindEntry(key);
15315  if (entry == kNotFound) {
15316    *was_present = false;
15317    return table;
15318  }
15319
15320  *was_present = true;
15321  table->RemoveEntry(entry);
15322  return Shrink(table, key);
15323}
15324
15325
15326void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
15327  set(EntryToIndex(entry), key);
15328  set(EntryToIndex(entry) + 1, value);
15329  ElementAdded();
15330}
15331
15332
15333void ObjectHashTable::RemoveEntry(int entry) {
15334  set_the_hole(EntryToIndex(entry));
15335  set_the_hole(EntryToIndex(entry) + 1);
15336  ElementRemoved();
15337}
15338
15339
15340Object* WeakHashTable::Lookup(Handle<Object> key) {
15341  DisallowHeapAllocation no_gc;
15342  DCHECK(IsKey(*key));
15343  int entry = FindEntry(key);
15344  if (entry == kNotFound) return GetHeap()->the_hole_value();
15345  return get(EntryToValueIndex(entry));
15346}
15347
15348
15349Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
15350                                         Handle<Object> key,
15351                                         Handle<Object> value) {
15352  DCHECK(table->IsKey(*key));
15353  int entry = table->FindEntry(key);
15354  // Key is already in table, just overwrite value.
15355  if (entry != kNotFound) {
15356    // TODO(ulan): Skipping write barrier is a temporary solution to avoid
15357    // memory leaks. Remove this once we have special visitor for weak fixed
15358    // arrays.
15359    table->set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
15360    return table;
15361  }
15362
15363  // Check whether the hash table should be extended.
15364  table = EnsureCapacity(table, 1, key, TENURED);
15365
15366  table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key, value);
15367  return table;
15368}
15369
15370
15371void WeakHashTable::AddEntry(int entry,
15372                             Handle<Object> key,
15373                             Handle<Object> value) {
15374  DisallowHeapAllocation no_allocation;
15375  // TODO(ulan): Skipping write barrier is a temporary solution to avoid
15376  // memory leaks. Remove this once we have special visitor for weak fixed
15377  // arrays.
15378  set(EntryToIndex(entry), *key, SKIP_WRITE_BARRIER);
15379  set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
15380  ElementAdded();
15381}
15382
15383
15384template<class Derived, class Iterator, int entrysize>
15385Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
15386    Isolate* isolate, int capacity, PretenureFlag pretenure) {
15387  // Capacity must be a power of two, since we depend on being able
15388  // to divide and multiple by 2 (kLoadFactor) to derive capacity
15389  // from number of buckets. If we decide to change kLoadFactor
15390  // to something other than 2, capacity should be stored as another
15391  // field of this object.
15392  capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
15393  if (capacity > kMaxCapacity) {
15394    v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
15395  }
15396  int num_buckets = capacity / kLoadFactor;
15397  Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
15398      kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
15399  backing_store->set_map_no_write_barrier(
15400      isolate->heap()->ordered_hash_table_map());
15401  Handle<Derived> table = Handle<Derived>::cast(backing_store);
15402  for (int i = 0; i < num_buckets; ++i) {
15403    table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
15404  }
15405  table->SetNumberOfBuckets(num_buckets);
15406  table->SetNumberOfElements(0);
15407  table->SetNumberOfDeletedElements(0);
15408  return table;
15409}
15410
15411
15412template<class Derived, class Iterator, int entrysize>
15413Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
15414    Handle<Derived> table) {
15415  DCHECK(!table->IsObsolete());
15416
15417  int nof = table->NumberOfElements();
15418  int nod = table->NumberOfDeletedElements();
15419  int capacity = table->Capacity();
15420  if ((nof + nod) < capacity) return table;
15421  // Don't need to grow if we can simply clear out deleted entries instead.
15422  // Note that we can't compact in place, though, so we always allocate
15423  // a new table.
15424  return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
15425}
15426
15427
15428template<class Derived, class Iterator, int entrysize>
15429Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
15430    Handle<Derived> table) {
15431  DCHECK(!table->IsObsolete());
15432
15433  int nof = table->NumberOfElements();
15434  int capacity = table->Capacity();
15435  if (nof >= (capacity >> 2)) return table;
15436  return Rehash(table, capacity / 2);
15437}
15438
15439
15440template<class Derived, class Iterator, int entrysize>
15441Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
15442    Handle<Derived> table) {
15443  DCHECK(!table->IsObsolete());
15444
15445  Handle<Derived> new_table =
15446      Allocate(table->GetIsolate(),
15447               kMinCapacity,
15448               table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15449
15450  table->SetNextTable(*new_table);
15451  table->SetNumberOfDeletedElements(-1);
15452
15453  return new_table;
15454}
15455
15456
15457template<class Derived, class Iterator, int entrysize>
15458Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Remove(
15459    Handle<Derived> table, Handle<Object> key, bool* was_present) {
15460  int entry = table->FindEntry(key);
15461  if (entry == kNotFound) {
15462    *was_present = false;
15463    return table;
15464  }
15465  *was_present = true;
15466  table->RemoveEntry(entry);
15467  return Shrink(table);
15468}
15469
15470
15471template<class Derived, class Iterator, int entrysize>
15472Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
15473    Handle<Derived> table, int new_capacity) {
15474  DCHECK(!table->IsObsolete());
15475
15476  Handle<Derived> new_table =
15477      Allocate(table->GetIsolate(),
15478               new_capacity,
15479               table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15480  int nof = table->NumberOfElements();
15481  int nod = table->NumberOfDeletedElements();
15482  int new_buckets = new_table->NumberOfBuckets();
15483  int new_entry = 0;
15484  int removed_holes_index = 0;
15485
15486  for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
15487    Object* key = table->KeyAt(old_entry);
15488    if (key->IsTheHole()) {
15489      table->SetRemovedIndexAt(removed_holes_index++, old_entry);
15490      continue;
15491    }
15492
15493    Object* hash = key->GetHash();
15494    int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
15495    Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
15496    new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
15497    int new_index = new_table->EntryToIndex(new_entry);
15498    int old_index = table->EntryToIndex(old_entry);
15499    for (int i = 0; i < entrysize; ++i) {
15500      Object* value = table->get(old_index + i);
15501      new_table->set(new_index + i, value);
15502    }
15503    new_table->set(new_index + kChainOffset, chain_entry);
15504    ++new_entry;
15505  }
15506
15507  DCHECK_EQ(nod, removed_holes_index);
15508
15509  new_table->SetNumberOfElements(nof);
15510  table->SetNextTable(*new_table);
15511
15512  return new_table;
15513}
15514
15515
15516template <class Derived, class Iterator, int entrysize>
15517int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(
15518    Handle<Object> key, int hash) {
15519  DCHECK(!IsObsolete());
15520
15521  DisallowHeapAllocation no_gc;
15522  DCHECK(!key->IsTheHole());
15523  for (int entry = HashToEntry(hash); entry != kNotFound;
15524       entry = ChainAt(entry)) {
15525    Object* candidate = KeyAt(entry);
15526    if (candidate->SameValueZero(*key))
15527      return entry;
15528  }
15529  return kNotFound;
15530}
15531
15532
15533template <class Derived, class Iterator, int entrysize>
15534int OrderedHashTable<Derived, Iterator, entrysize>::FindEntry(
15535    Handle<Object> key) {
15536  DisallowHeapAllocation no_gc;
15537  Object* hash = key->GetHash();
15538  if (!hash->IsSmi()) return kNotFound;
15539  return FindEntry(key, Smi::cast(hash)->value());
15540}
15541
15542
15543template <class Derived, class Iterator, int entrysize>
15544int OrderedHashTable<Derived, Iterator, entrysize>::AddEntry(int hash) {
15545  DCHECK(!IsObsolete());
15546
15547  int entry = UsedCapacity();
15548  int bucket = HashToBucket(hash);
15549  int index = EntryToIndex(entry);
15550  Object* chain_entry = get(kHashTableStartIndex + bucket);
15551  set(kHashTableStartIndex + bucket, Smi::FromInt(entry));
15552  set(index + kChainOffset, chain_entry);
15553  SetNumberOfElements(NumberOfElements() + 1);
15554  return index;
15555}
15556
15557
15558template<class Derived, class Iterator, int entrysize>
15559void OrderedHashTable<Derived, Iterator, entrysize>::RemoveEntry(int entry) {
15560  DCHECK(!IsObsolete());
15561
15562  int index = EntryToIndex(entry);
15563  for (int i = 0; i < entrysize; ++i) {
15564    set_the_hole(index + i);
15565  }
15566  SetNumberOfElements(NumberOfElements() - 1);
15567  SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
15568}
15569
15570
15571template Handle<OrderedHashSet>
15572OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
15573    Isolate* isolate, int capacity, PretenureFlag pretenure);
15574
15575template Handle<OrderedHashSet>
15576OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
15577    Handle<OrderedHashSet> table);
15578
15579template Handle<OrderedHashSet>
15580OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
15581    Handle<OrderedHashSet> table);
15582
15583template Handle<OrderedHashSet>
15584OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
15585    Handle<OrderedHashSet> table);
15586
15587template Handle<OrderedHashSet>
15588OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Remove(
15589    Handle<OrderedHashSet> table, Handle<Object> key, bool* was_present);
15590
15591template int OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(
15592    Handle<Object> key, int hash);
15593template int OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::FindEntry(
15594    Handle<Object> key);
15595
15596template int
15597OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::AddEntry(int hash);
15598
15599template void
15600OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::RemoveEntry(int entry);
15601
15602
15603template Handle<OrderedHashMap>
15604OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
15605    Isolate* isolate, int capacity, PretenureFlag pretenure);
15606
15607template Handle<OrderedHashMap>
15608OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
15609    Handle<OrderedHashMap> table);
15610
15611template Handle<OrderedHashMap>
15612OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
15613    Handle<OrderedHashMap> table);
15614
15615template Handle<OrderedHashMap>
15616OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
15617    Handle<OrderedHashMap> table);
15618
15619template Handle<OrderedHashMap>
15620OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Remove(
15621    Handle<OrderedHashMap> table, Handle<Object> key, bool* was_present);
15622
15623template int OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(
15624    Handle<Object> key, int hash);
15625template int OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::FindEntry(
15626    Handle<Object> key);
15627
15628template int
15629OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::AddEntry(int hash);
15630
15631template void
15632OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::RemoveEntry(int entry);
15633
15634
15635bool OrderedHashSet::Contains(Handle<Object> key) {
15636  return FindEntry(key) != kNotFound;
15637}
15638
15639
15640Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
15641                                           Handle<Object> key) {
15642  int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
15643  if (table->FindEntry(key, hash) != kNotFound) return table;
15644
15645  table = EnsureGrowable(table);
15646
15647  int index = table->AddEntry(hash);
15648  table->set(index, *key);
15649  return table;
15650}
15651
15652
15653Object* OrderedHashMap::Lookup(Handle<Object> key) {
15654  DisallowHeapAllocation no_gc;
15655  int entry = FindEntry(key);
15656  if (entry == kNotFound) return GetHeap()->the_hole_value();
15657  return ValueAt(entry);
15658}
15659
15660
15661Handle<OrderedHashMap> OrderedHashMap::Put(Handle<OrderedHashMap> table,
15662                                           Handle<Object> key,
15663                                           Handle<Object> value) {
15664  DCHECK(!key->IsTheHole());
15665
15666  int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
15667  int entry = table->FindEntry(key, hash);
15668
15669  if (entry != kNotFound) {
15670    table->set(table->EntryToIndex(entry) + kValueOffset, *value);
15671    return table;
15672  }
15673
15674  table = EnsureGrowable(table);
15675
15676  int index = table->AddEntry(hash);
15677  table->set(index, *key);
15678  table->set(index + kValueOffset, *value);
15679  return table;
15680}
15681
15682
15683template<class Derived, class TableType>
15684void OrderedHashTableIterator<Derived, TableType>::Transition() {
15685  DisallowHeapAllocation no_allocation;
15686  TableType* table = TableType::cast(this->table());
15687  if (!table->IsObsolete()) return;
15688
15689  int index = Smi::cast(this->index())->value();
15690  while (table->IsObsolete()) {
15691    TableType* next_table = table->NextTable();
15692
15693    if (index > 0) {
15694      int nod = table->NumberOfDeletedElements();
15695
15696      // When we clear the table we set the number of deleted elements to -1.
15697      if (nod == -1) {
15698        index = 0;
15699      } else {
15700        int old_index = index;
15701        for (int i = 0; i < nod; ++i) {
15702          int removed_index = table->RemovedIndexAt(i);
15703          if (removed_index >= old_index) break;
15704          --index;
15705        }
15706      }
15707    }
15708
15709    table = next_table;
15710  }
15711
15712  set_table(table);
15713  set_index(Smi::FromInt(index));
15714}
15715
15716
15717template<class Derived, class TableType>
15718bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
15719  DisallowHeapAllocation no_allocation;
15720  if (this->table()->IsUndefined()) return false;
15721
15722  Transition();
15723
15724  TableType* table = TableType::cast(this->table());
15725  int index = Smi::cast(this->index())->value();
15726  int used_capacity = table->UsedCapacity();
15727
15728  while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
15729    index++;
15730  }
15731
15732  set_index(Smi::FromInt(index));
15733
15734  if (index < used_capacity) return true;
15735
15736  set_table(GetHeap()->undefined_value());
15737  return false;
15738}
15739
15740
15741template<class Derived, class TableType>
15742Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
15743  DisallowHeapAllocation no_allocation;
15744  if (HasMore()) {
15745    FixedArray* array = FixedArray::cast(value_array->elements());
15746    static_cast<Derived*>(this)->PopulateValueArray(array);
15747    MoveNext();
15748    return Smi::cast(kind());
15749  }
15750  return Smi::FromInt(0);
15751}
15752
15753
15754template Smi*
15755OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
15756    JSArray* value_array);
15757
15758template bool
15759OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
15760
15761template void
15762OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
15763
15764template Object*
15765OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
15766
15767template void
15768OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
15769
15770
15771template Smi*
15772OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
15773    JSArray* value_array);
15774
15775template bool
15776OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
15777
15778template void
15779OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
15780
15781template Object*
15782OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
15783
15784template void
15785OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
15786
15787
15788DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator(
15789    DeclaredAccessorDescriptor* descriptor)
15790    : array_(descriptor->serialized_data()->GetDataStartAddress()),
15791      length_(descriptor->serialized_data()->length()),
15792      offset_(0) {
15793}
15794
15795
15796const DeclaredAccessorDescriptorData*
15797  DeclaredAccessorDescriptorIterator::Next() {
15798  DCHECK(offset_ < length_);
15799  uint8_t* ptr = &array_[offset_];
15800  DCHECK(reinterpret_cast<uintptr_t>(ptr) % sizeof(uintptr_t) == 0);
15801  const DeclaredAccessorDescriptorData* data =
15802      reinterpret_cast<const DeclaredAccessorDescriptorData*>(ptr);
15803  offset_ += sizeof(*data);
15804  DCHECK(offset_ <= length_);
15805  return data;
15806}
15807
15808
15809Handle<DeclaredAccessorDescriptor> DeclaredAccessorDescriptor::Create(
15810    Isolate* isolate,
15811    const DeclaredAccessorDescriptorData& descriptor,
15812    Handle<DeclaredAccessorDescriptor> previous) {
15813  int previous_length =
15814      previous.is_null() ? 0 : previous->serialized_data()->length();
15815  int length = sizeof(descriptor) + previous_length;
15816  Handle<ByteArray> serialized_descriptor =
15817      isolate->factory()->NewByteArray(length);
15818  Handle<DeclaredAccessorDescriptor> value =
15819      isolate->factory()->NewDeclaredAccessorDescriptor();
15820  value->set_serialized_data(*serialized_descriptor);
15821  // Copy in the data.
15822  {
15823    DisallowHeapAllocation no_allocation;
15824    uint8_t* array = serialized_descriptor->GetDataStartAddress();
15825    if (previous_length != 0) {
15826      uint8_t* previous_array =
15827          previous->serialized_data()->GetDataStartAddress();
15828      MemCopy(array, previous_array, previous_length);
15829      array += previous_length;
15830    }
15831    DCHECK(reinterpret_cast<uintptr_t>(array) % sizeof(uintptr_t) == 0);
15832    DeclaredAccessorDescriptorData* data =
15833        reinterpret_cast<DeclaredAccessorDescriptorData*>(array);
15834    *data = descriptor;
15835  }
15836  return value;
15837}
15838
15839
15840// Check if there is a break point at this code position.
15841bool DebugInfo::HasBreakPoint(int code_position) {
15842  // Get the break point info object for this code position.
15843  Object* break_point_info = GetBreakPointInfo(code_position);
15844
15845  // If there is no break point info object or no break points in the break
15846  // point info object there is no break point at this code position.
15847  if (break_point_info->IsUndefined()) return false;
15848  return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
15849}
15850
15851
15852// Get the break point info object for this code position.
15853Object* DebugInfo::GetBreakPointInfo(int code_position) {
15854  // Find the index of the break point info object for this code position.
15855  int index = GetBreakPointInfoIndex(code_position);
15856
15857  // Return the break point info object if any.
15858  if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
15859  return BreakPointInfo::cast(break_points()->get(index));
15860}
15861
15862
15863// Clear a break point at the specified code position.
15864void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
15865                                int code_position,
15866                                Handle<Object> break_point_object) {
15867  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15868                                  debug_info->GetIsolate());
15869  if (break_point_info->IsUndefined()) return;
15870  BreakPointInfo::ClearBreakPoint(
15871      Handle<BreakPointInfo>::cast(break_point_info),
15872      break_point_object);
15873}
15874
15875
15876void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
15877                              int code_position,
15878                              int source_position,
15879                              int statement_position,
15880                              Handle<Object> break_point_object) {
15881  Isolate* isolate = debug_info->GetIsolate();
15882  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15883                                  isolate);
15884  if (!break_point_info->IsUndefined()) {
15885    BreakPointInfo::SetBreakPoint(
15886        Handle<BreakPointInfo>::cast(break_point_info),
15887        break_point_object);
15888    return;
15889  }
15890
15891  // Adding a new break point for a code position which did not have any
15892  // break points before. Try to find a free slot.
15893  int index = kNoBreakPointInfo;
15894  for (int i = 0; i < debug_info->break_points()->length(); i++) {
15895    if (debug_info->break_points()->get(i)->IsUndefined()) {
15896      index = i;
15897      break;
15898    }
15899  }
15900  if (index == kNoBreakPointInfo) {
15901    // No free slot - extend break point info array.
15902    Handle<FixedArray> old_break_points =
15903        Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
15904    Handle<FixedArray> new_break_points =
15905        isolate->factory()->NewFixedArray(
15906            old_break_points->length() +
15907            DebugInfo::kEstimatedNofBreakPointsInFunction);
15908
15909    debug_info->set_break_points(*new_break_points);
15910    for (int i = 0; i < old_break_points->length(); i++) {
15911      new_break_points->set(i, old_break_points->get(i));
15912    }
15913    index = old_break_points->length();
15914  }
15915  DCHECK(index != kNoBreakPointInfo);
15916
15917  // Allocate new BreakPointInfo object and set the break point.
15918  Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
15919      isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
15920  new_break_point_info->set_code_position(Smi::FromInt(code_position));
15921  new_break_point_info->set_source_position(Smi::FromInt(source_position));
15922  new_break_point_info->
15923      set_statement_position(Smi::FromInt(statement_position));
15924  new_break_point_info->set_break_point_objects(
15925      isolate->heap()->undefined_value());
15926  BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
15927  debug_info->break_points()->set(index, *new_break_point_info);
15928}
15929
15930
15931// Get the break point objects for a code position.
15932Object* DebugInfo::GetBreakPointObjects(int code_position) {
15933  Object* break_point_info = GetBreakPointInfo(code_position);
15934  if (break_point_info->IsUndefined()) {
15935    return GetHeap()->undefined_value();
15936  }
15937  return BreakPointInfo::cast(break_point_info)->break_point_objects();
15938}
15939
15940
15941// Get the total number of break points.
15942int DebugInfo::GetBreakPointCount() {
15943  if (break_points()->IsUndefined()) return 0;
15944  int count = 0;
15945  for (int i = 0; i < break_points()->length(); i++) {
15946    if (!break_points()->get(i)->IsUndefined()) {
15947      BreakPointInfo* break_point_info =
15948          BreakPointInfo::cast(break_points()->get(i));
15949      count += break_point_info->GetBreakPointCount();
15950    }
15951  }
15952  return count;
15953}
15954
15955
15956Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
15957                                      Handle<Object> break_point_object) {
15958  Heap* heap = debug_info->GetHeap();
15959  if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
15960  for (int i = 0; i < debug_info->break_points()->length(); i++) {
15961    if (!debug_info->break_points()->get(i)->IsUndefined()) {
15962      Handle<BreakPointInfo> break_point_info =
15963          Handle<BreakPointInfo>(BreakPointInfo::cast(
15964              debug_info->break_points()->get(i)));
15965      if (BreakPointInfo::HasBreakPointObject(break_point_info,
15966                                              break_point_object)) {
15967        return *break_point_info;
15968      }
15969    }
15970  }
15971  return heap->undefined_value();
15972}
15973
15974
15975// Find the index of the break point info object for the specified code
15976// position.
15977int DebugInfo::GetBreakPointInfoIndex(int code_position) {
15978  if (break_points()->IsUndefined()) return kNoBreakPointInfo;
15979  for (int i = 0; i < break_points()->length(); i++) {
15980    if (!break_points()->get(i)->IsUndefined()) {
15981      BreakPointInfo* break_point_info =
15982          BreakPointInfo::cast(break_points()->get(i));
15983      if (break_point_info->code_position()->value() == code_position) {
15984        return i;
15985      }
15986    }
15987  }
15988  return kNoBreakPointInfo;
15989}
15990
15991
15992// Remove the specified break point object.
15993void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
15994                                     Handle<Object> break_point_object) {
15995  Isolate* isolate = break_point_info->GetIsolate();
15996  // If there are no break points just ignore.
15997  if (break_point_info->break_point_objects()->IsUndefined()) return;
15998  // If there is a single break point clear it if it is the same.
15999  if (!break_point_info->break_point_objects()->IsFixedArray()) {
16000    if (break_point_info->break_point_objects() == *break_point_object) {
16001      break_point_info->set_break_point_objects(
16002          isolate->heap()->undefined_value());
16003    }
16004    return;
16005  }
16006  // If there are multiple break points shrink the array
16007  DCHECK(break_point_info->break_point_objects()->IsFixedArray());
16008  Handle<FixedArray> old_array =
16009      Handle<FixedArray>(
16010          FixedArray::cast(break_point_info->break_point_objects()));
16011  Handle<FixedArray> new_array =
16012      isolate->factory()->NewFixedArray(old_array->length() - 1);
16013  int found_count = 0;
16014  for (int i = 0; i < old_array->length(); i++) {
16015    if (old_array->get(i) == *break_point_object) {
16016      DCHECK(found_count == 0);
16017      found_count++;
16018    } else {
16019      new_array->set(i - found_count, old_array->get(i));
16020    }
16021  }
16022  // If the break point was found in the list change it.
16023  if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
16024}
16025
16026
16027// Add the specified break point object.
16028void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
16029                                   Handle<Object> break_point_object) {
16030  Isolate* isolate = break_point_info->GetIsolate();
16031
16032  // If there was no break point objects before just set it.
16033  if (break_point_info->break_point_objects()->IsUndefined()) {
16034    break_point_info->set_break_point_objects(*break_point_object);
16035    return;
16036  }
16037  // If the break point object is the same as before just ignore.
16038  if (break_point_info->break_point_objects() == *break_point_object) return;
16039  // If there was one break point object before replace with array.
16040  if (!break_point_info->break_point_objects()->IsFixedArray()) {
16041    Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
16042    array->set(0, break_point_info->break_point_objects());
16043    array->set(1, *break_point_object);
16044    break_point_info->set_break_point_objects(*array);
16045    return;
16046  }
16047  // If there was more than one break point before extend array.
16048  Handle<FixedArray> old_array =
16049      Handle<FixedArray>(
16050          FixedArray::cast(break_point_info->break_point_objects()));
16051  Handle<FixedArray> new_array =
16052      isolate->factory()->NewFixedArray(old_array->length() + 1);
16053  for (int i = 0; i < old_array->length(); i++) {
16054    // If the break point was there before just ignore.
16055    if (old_array->get(i) == *break_point_object) return;
16056    new_array->set(i, old_array->get(i));
16057  }
16058  // Add the new break point.
16059  new_array->set(old_array->length(), *break_point_object);
16060  break_point_info->set_break_point_objects(*new_array);
16061}
16062
16063
16064bool BreakPointInfo::HasBreakPointObject(
16065    Handle<BreakPointInfo> break_point_info,
16066    Handle<Object> break_point_object) {
16067  // No break point.
16068  if (break_point_info->break_point_objects()->IsUndefined()) return false;
16069  // Single break point.
16070  if (!break_point_info->break_point_objects()->IsFixedArray()) {
16071    return break_point_info->break_point_objects() == *break_point_object;
16072  }
16073  // Multiple break points.
16074  FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
16075  for (int i = 0; i < array->length(); i++) {
16076    if (array->get(i) == *break_point_object) {
16077      return true;
16078    }
16079  }
16080  return false;
16081}
16082
16083
16084// Get the number of break points.
16085int BreakPointInfo::GetBreakPointCount() {
16086  // No break point.
16087  if (break_point_objects()->IsUndefined()) return 0;
16088  // Single break point.
16089  if (!break_point_objects()->IsFixedArray()) return 1;
16090  // Multiple break points.
16091  return FixedArray::cast(break_point_objects())->length();
16092}
16093
16094
16095Object* JSDate::GetField(Object* object, Smi* index) {
16096  return JSDate::cast(object)->DoGetField(
16097      static_cast<FieldIndex>(index->value()));
16098}
16099
16100
16101Object* JSDate::DoGetField(FieldIndex index) {
16102  DCHECK(index != kDateValue);
16103
16104  DateCache* date_cache = GetIsolate()->date_cache();
16105
16106  if (index < kFirstUncachedField) {
16107    Object* stamp = cache_stamp();
16108    if (stamp != date_cache->stamp() && stamp->IsSmi()) {
16109      // Since the stamp is not NaN, the value is also not NaN.
16110      int64_t local_time_ms =
16111          date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
16112      SetCachedFields(local_time_ms, date_cache);
16113    }
16114    switch (index) {
16115      case kYear: return year();
16116      case kMonth: return month();
16117      case kDay: return day();
16118      case kWeekday: return weekday();
16119      case kHour: return hour();
16120      case kMinute: return min();
16121      case kSecond: return sec();
16122      default: UNREACHABLE();
16123    }
16124  }
16125
16126  if (index >= kFirstUTCField) {
16127    return GetUTCField(index, value()->Number(), date_cache);
16128  }
16129
16130  double time = value()->Number();
16131  if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
16132
16133  int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
16134  int days = DateCache::DaysFromTime(local_time_ms);
16135
16136  if (index == kDays) return Smi::FromInt(days);
16137
16138  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16139  if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
16140  DCHECK(index == kTimeInDay);
16141  return Smi::FromInt(time_in_day_ms);
16142}
16143
16144
16145Object* JSDate::GetUTCField(FieldIndex index,
16146                            double value,
16147                            DateCache* date_cache) {
16148  DCHECK(index >= kFirstUTCField);
16149
16150  if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
16151
16152  int64_t time_ms = static_cast<int64_t>(value);
16153
16154  if (index == kTimezoneOffset) {
16155    return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
16156  }
16157
16158  int days = DateCache::DaysFromTime(time_ms);
16159
16160  if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
16161
16162  if (index <= kDayUTC) {
16163    int year, month, day;
16164    date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16165    if (index == kYearUTC) return Smi::FromInt(year);
16166    if (index == kMonthUTC) return Smi::FromInt(month);
16167    DCHECK(index == kDayUTC);
16168    return Smi::FromInt(day);
16169  }
16170
16171  int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
16172  switch (index) {
16173    case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
16174    case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
16175    case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
16176    case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
16177    case kDaysUTC: return Smi::FromInt(days);
16178    case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
16179    default: UNREACHABLE();
16180  }
16181
16182  UNREACHABLE();
16183  return NULL;
16184}
16185
16186
16187void JSDate::SetValue(Object* value, bool is_value_nan) {
16188  set_value(value);
16189  if (is_value_nan) {
16190    HeapNumber* nan = GetIsolate()->heap()->nan_value();
16191    set_cache_stamp(nan, SKIP_WRITE_BARRIER);
16192    set_year(nan, SKIP_WRITE_BARRIER);
16193    set_month(nan, SKIP_WRITE_BARRIER);
16194    set_day(nan, SKIP_WRITE_BARRIER);
16195    set_hour(nan, SKIP_WRITE_BARRIER);
16196    set_min(nan, SKIP_WRITE_BARRIER);
16197    set_sec(nan, SKIP_WRITE_BARRIER);
16198    set_weekday(nan, SKIP_WRITE_BARRIER);
16199  } else {
16200    set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
16201  }
16202}
16203
16204
16205void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
16206  int days = DateCache::DaysFromTime(local_time_ms);
16207  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16208  int year, month, day;
16209  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16210  int weekday = date_cache->Weekday(days);
16211  int hour = time_in_day_ms / (60 * 60 * 1000);
16212  int min = (time_in_day_ms / (60 * 1000)) % 60;
16213  int sec = (time_in_day_ms / 1000) % 60;
16214  set_cache_stamp(date_cache->stamp());
16215  set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
16216  set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
16217  set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
16218  set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
16219  set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
16220  set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
16221  set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
16222}
16223
16224
16225void JSArrayBuffer::Neuter() {
16226  DCHECK(is_external());
16227  set_backing_store(NULL);
16228  set_byte_length(Smi::FromInt(0));
16229}
16230
16231
16232void JSArrayBufferView::NeuterView() {
16233  set_byte_offset(Smi::FromInt(0));
16234  set_byte_length(Smi::FromInt(0));
16235}
16236
16237
16238void JSDataView::Neuter() {
16239  NeuterView();
16240}
16241
16242
16243void JSTypedArray::Neuter() {
16244  NeuterView();
16245  set_length(Smi::FromInt(0));
16246  set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
16247}
16248
16249
16250static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) {
16251  switch (elements_kind) {
16252#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
16253    case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
16254
16255    TYPED_ARRAYS(TYPED_ARRAY_CASE)
16256#undef TYPED_ARRAY_CASE
16257
16258    default:
16259      UNREACHABLE();
16260      return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
16261  }
16262}
16263
16264
16265Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
16266    Handle<JSTypedArray> typed_array) {
16267
16268  Handle<Map> map(typed_array->map());
16269  Isolate* isolate = typed_array->GetIsolate();
16270
16271  DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
16272
16273  Handle<Map> new_map = Map::TransitionElementsTo(
16274          map,
16275          FixedToExternalElementsKind(map->elements_kind()));
16276
16277  Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
16278  Handle<FixedTypedArrayBase> fixed_typed_array(
16279      FixedTypedArrayBase::cast(typed_array->elements()));
16280  Runtime::SetupArrayBufferAllocatingData(isolate, buffer,
16281      fixed_typed_array->DataSize(), false);
16282  memcpy(buffer->backing_store(),
16283         fixed_typed_array->DataPtr(),
16284         fixed_typed_array->DataSize());
16285  Handle<ExternalArray> new_elements =
16286      isolate->factory()->NewExternalArray(
16287          fixed_typed_array->length(), typed_array->type(),
16288          static_cast<uint8_t*>(buffer->backing_store()));
16289
16290  buffer->set_weak_first_view(*typed_array);
16291  DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value());
16292  typed_array->set_buffer(*buffer);
16293  JSObject::SetMapAndElements(typed_array, new_map, new_elements);
16294
16295  return buffer;
16296}
16297
16298
16299Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
16300  Handle<Object> result(buffer(), GetIsolate());
16301  if (*result != Smi::FromInt(0)) {
16302    DCHECK(IsExternalArrayElementsKind(map()->elements_kind()));
16303    return Handle<JSArrayBuffer>::cast(result);
16304  }
16305  Handle<JSTypedArray> self(this);
16306  return MaterializeArrayBuffer(self);
16307}
16308
16309
16310HeapType* PropertyCell::type() {
16311  return static_cast<HeapType*>(type_raw());
16312}
16313
16314
16315void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) {
16316  DCHECK(IsPropertyCell());
16317  set_type_raw(type, ignored);
16318}
16319
16320
16321Handle<HeapType> PropertyCell::UpdatedType(Handle<PropertyCell> cell,
16322                                           Handle<Object> value) {
16323  Isolate* isolate = cell->GetIsolate();
16324  Handle<HeapType> old_type(cell->type(), isolate);
16325  Handle<HeapType> new_type = HeapType::Constant(value, isolate);
16326
16327  if (new_type->Is(old_type)) return old_type;
16328
16329  cell->dependent_code()->DeoptimizeDependentCodeGroup(
16330      isolate, DependentCode::kPropertyCellChangedGroup);
16331
16332  if (old_type->Is(HeapType::None()) || old_type->Is(HeapType::Undefined())) {
16333    return new_type;
16334  }
16335
16336  return HeapType::Any(isolate);
16337}
16338
16339
16340void PropertyCell::SetValueInferType(Handle<PropertyCell> cell,
16341                                     Handle<Object> value) {
16342  cell->set_value(*value);
16343  if (!HeapType::Any()->Is(cell->type())) {
16344    Handle<HeapType> new_type = UpdatedType(cell, value);
16345    cell->set_type(*new_type);
16346  }
16347}
16348
16349
16350// static
16351void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell,
16352                                               CompilationInfo* info) {
16353  Handle<DependentCode> codes =
16354      DependentCode::Insert(handle(cell->dependent_code(), info->isolate()),
16355                            DependentCode::kPropertyCellChangedGroup,
16356                            info->object_wrapper());
16357  if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
16358  info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
16359      cell, info->zone());
16360}
16361
16362} }  // namespace v8::internal
16363