V8 Project
objects.cc
Go to the documentation of this file.
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"
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"
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 
44 namespace v8 {
45 namespace internal {
46 
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 
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 
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 
98 bool 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 
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: {
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;
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 
141  Handle<Name> key) {
142  LookupIterator it(object, key,
143  LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
144  return GetDataProperty(&it);
145 }
146 
147 
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();
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 
175 bool 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 
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 
211  if (!object->IsHeapObject()) return false;
212  return IsTemplateFor(HeapObject::cast(object)->map());
213 }
214 
215 
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 
235 template<typename To>
236 static 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 
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 
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 
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;
292  int32_value = *CheckedCast<uint8_t>(ptr);
293  break;
295  int32_value = *CheckedCast<int16_t>(ptr);
296  break;
298  int32_value = *CheckedCast<uint16_t>(ptr);
299  break;
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 
330  Handle<Object> receiver,
332  Isolate* isolate) {
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) {
340  DCHECK(iterator.Complete());
341  current = *CheckedCast<char*>(current);
342  return handle(*CheckedCast<Object*>(current), isolate);
343  }
345  DCHECK(!iterator.Complete());
346  current = *reinterpret_cast<char**>(current);
347  break;
349  DCHECK(!iterator.Complete());
350  current += data->pointer_shift_descriptor.byte_offset;
351  break;
353  DCHECK(!iterator.Complete());
354  Object* object = CheckedCast<Object>(current);
356  Object* smi = JSObject::cast(object)->GetInternalField(field);
357  DCHECK(smi->IsSmi());
358  current = reinterpret_cast<char*>(smi);
359  break;
360  }
362  DCHECK(iterator.Complete());
364  current,
365  isolate);
367  DCHECK(iterator.Complete());
369  current,
370  isolate);
372  DCHECK(iterator.Complete());
374  current,
375  isolate);
376  }
377  }
378  UNREACHABLE();
379  return isolate->factory()->undefined_value();
380 }
381 
382 
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 
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 
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()) {
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()) {
429  receiver,
431  isolate);
432  }
433 
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));
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...
460  receiver, Handle<JSReceiver>::cast(getter));
461  }
462  // Getter is not a function.
463  return isolate->factory()->undefined_value();
464 }
465 
466 
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 
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();
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,
506  v8::Utils::ToLocal(value));
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...
516  receiver, Handle<JSReceiver>::cast(setter), value);
517  } else {
518  if (strict_mode == SLOPPY) return value;
519  Handle<Object> args[2] = { name, holder };
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 
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 
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 
574 static 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 
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);
597  return it->factory()->undefined_value();
598 }
599 
600 
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);
609  return maybe(ABSENT);
610 }
611 
612 
613 static 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 
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);
637  return value;
638 }
639 
640 
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(
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 
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()) {
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 
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 
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()
743  || !HasFastProperties();
744 }
745 
746 
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()
763  !iter.IsAtEnd(); iter.Advance()) {
764  if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
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 =
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);
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;
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 
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 
836  // The object is either a number, a name, an odd-ball,
837  // a real JS object, or a Harmony proxy.
838  if (IsNumber()) {
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 
857  Handle<Object> hash(object->GetHash(), isolate);
858  if (hash->IsSmi()) return Handle<Smi>::cast(hash);
859 
860  DCHECK(object->IsJSReceiver());
862 }
863 
864 
865 bool 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 
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 
905 void Object::ShortPrint(FILE* out) {
906  OFStream os(out);
907  os << Brief(this);
908 }
909 
910 
911 void Object::ShortPrint(StringStream* accumulator) {
912  OStringStream os;
913  os << Brief(this);
914  accumulator->Add(os.c_str());
915 }
916 
917 
918 OStream& 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 
930 void 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".
940 static 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 
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();
972  WriteToFlat(*cons, flat->GetChars(), 0, length);
973  result = flat;
974  } else {
975  Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
976  length, tenure).ToHandleChecked();
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 
990  // Externalizing twice leaks the external resource, so it's
991  // prohibited by the API.
992  DCHECK(!this->IsExternalString());
993 #ifdef ENABLE_SLOW_DCHECKS
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 
1052  // Externalizing twice leaks the external resource, so it's
1053  // prohibited by the API.
1054  DCHECK(!this->IsExternalString());
1055 #ifdef ENABLE_SLOW_DCHECKS
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 
1111 void 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 
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 
1175 void String::PrintUC16(OStream& os, int start, int end) { // NOLINT
1176  if (end < 0) end = length();
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 
1185 void 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 {
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 
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 
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 ";
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 
1346  Map* original_map,
1347  Map* new_map) {
1348  PrintF(file, "[migrating ");
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 
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;
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 
1429 #undef TYPED_ARRAY_SHORT_PRINT
1430 
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  }
1443  os << "<JSMessageObject>";
1444  break;
1445 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1446  case NAME##_TYPE: \
1447  os << "<" #Name ">"; \
1448  break;
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 
1529 void 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 
1538 void 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 
1666 bool HeapNumber::HeapNumberBooleanValue() {
1667  return DoubleToBoolean(value());
1668 }
1669 
1670 
1671 void HeapNumber::HeapNumberPrint(OStream& os) { // NOLINT
1672  os << value();
1673 }
1674 
1675 
1676 String* 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 
1689 String* 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 
1705 String* JSReceiver::constructor_name() {
1706  return map()->constructor_name();
1707 }
1708 
1709 
1710 MaybeHandle<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 
1746 MaybeHandle<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 
1762 void 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 
1794 Context* 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 
1809 void 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 
1828 const 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 
1844 bool 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 
1879 void 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 
1886 void 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.
1930 void 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 
2085  int modify_index,
2086  Representation new_representation,
2087  Handle<HeapType> new_field_type) {
2089  handle(object->map()), modify_index, new_representation, new_field_type,
2090  FORCE_FIELD);
2091  MigrateToMap(object, new_map);
2092 }
2093 
2094 
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 
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
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 
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(
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.
2187 void 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) {
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 
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 
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 
2262 Map* 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 
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
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
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(
2347 
2348  if (FLAG_trace_generalization) {
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.
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;
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.
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
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
2706  if (!map->is_deprecated()) return map;
2707  return GeneralizeRepresentation(map, 0, Representation::None(),
2710 }
2711 
2712 
2713 // static
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 
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);
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));
2792  if (!result.IsEmpty()) return value;
2793 
2794  return MaybeHandle<Object>();
2795 }
2796 
2797 
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 
2808  Handle<Object> value,
2809  StrictMode strict_mode,
2810  StoreFromKeyed store_mode,
2811  StorePropertyMode data_store_mode) {
2812  // Make sure that the top context does not change when doing callbacks or
2813  // interceptor calls.
2814  AssertNoContextChange ncc(it->isolate());
2815 
2816  bool done = false;
2817  for (; it->IsFound(); it->Next()) {
2818  switch (it->state()) {
2819  case LookupIterator::NOT_FOUND:
2820  UNREACHABLE();
2821 
2822  case LookupIterator::ACCESS_CHECK:
2823  // TODO(verwaest): Remove the distinction. This is mostly bogus since we
2824  // don't know whether we'll want to fetch attributes or call a setter
2825  // until we find the property.
2826  if (it->HasAccess(v8::ACCESS_SET)) break;
2828  strict_mode);
2829 
2830  case LookupIterator::JSPROXY:
2831  if (it->HolderIsReceiverOrHiddenPrototype()) {
2832  return JSProxy::SetPropertyWithHandler(it->GetHolder<JSProxy>(),
2833  it->GetReceiver(), it->name(),
2834  value, strict_mode);
2835  } else {
2836  // TODO(verwaest): Use the MaybeHandle to indicate result.
2837  bool has_result = false;
2838  MaybeHandle<Object> maybe_result =
2840  it->GetHolder<JSProxy>(), it->GetReceiver(), it->name(),
2841  value, strict_mode, &has_result);
2842  if (has_result) return maybe_result;
2843  done = true;
2844  }
2845  break;
2846 
2847  case LookupIterator::INTERCEPTOR:
2848  if (it->HolderIsReceiverOrHiddenPrototype()) {
2849  MaybeHandle<Object> maybe_result =
2851  if (!maybe_result.is_null()) return maybe_result;
2852  if (it->isolate()->has_pending_exception()) return maybe_result;
2853  } else {
2854  Maybe<PropertyAttributes> maybe_attributes =
2856  it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
2857  if (!maybe_attributes.has_value) return MaybeHandle<Object>();
2858  done = maybe_attributes.value != ABSENT;
2859  if (done && (maybe_attributes.value & READ_ONLY) != 0) {
2860  return WriteToReadOnlyProperty(it, value, strict_mode);
2861  }
2862  }
2863  break;
2864 
2866  if (it->property_details().IsReadOnly()) {
2867  return WriteToReadOnlyProperty(it, value, strict_mode);
2868  }
2869  if (it->HolderIsReceiverOrHiddenPrototype() ||
2870  !it->GetAccessors()->IsDeclaredAccessorInfo()) {
2871  return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
2872  it->GetHolder<JSObject>(),
2873  it->GetAccessors(), strict_mode);
2874  }
2875  done = true;
2876  break;
2877 
2878  case LookupIterator::DATA:
2879  if (it->property_details().IsReadOnly()) {
2880  return WriteToReadOnlyProperty(it, value, strict_mode);
2881  }
2882  if (it->HolderIsReceiverOrHiddenPrototype()) {
2883  return SetDataProperty(it, value);
2884  }
2885  done = true;
2886  break;
2887 
2888  case LookupIterator::TRANSITION:
2889  done = true;
2890  break;
2891  }
2892 
2893  if (done) break;
2894  }
2895 
2896  // If the receiver is the JSGlobalObject, the store was contextual. In case
2897  // the property did not exist yet on the global object itself, we have to
2898  // throw a reference error in strict mode.
2899  if (it->GetReceiver()->IsJSGlobalObject() && strict_mode == STRICT) {
2900  Handle<Object> args[1] = {it->name()};
2901  THROW_NEW_ERROR(it->isolate(),
2902  NewReferenceError("not_defined", HandleVector(args, 1)),
2903  Object);
2904  }
2905 
2906  if (data_store_mode == SUPER_PROPERTY) {
2907  if (strict_mode == STRICT) {
2908  Handle<Object> args[1] = {it->name()};
2909  THROW_NEW_ERROR(it->isolate(),
2910  NewReferenceError("not_defined", HandleVector(args, 1)),
2911  Object);
2912  }
2913  return value;
2914  }
2915 
2916  return AddDataProperty(it, value, NONE, strict_mode, store_mode);
2917 }
2918 
2919 
2921  Handle<Object> value,
2922  StrictMode strict_mode) {
2923  if (strict_mode != STRICT) return value;
2924 
2925  Handle<Object> args[] = {it->name(), it->GetReceiver()};
2926  THROW_NEW_ERROR(it->isolate(),
2927  NewTypeError("strict_read_only_property",
2928  HandleVector(args, arraysize(args))),
2929  Object);
2930 }
2931 
2932 
2934  Handle<Object> value) {
2935  // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
2936  // have own properties.
2937  Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
2938 
2939  // Store on the holder which may be hidden behind the receiver.
2940  DCHECK(it->HolderIsReceiverOrHiddenPrototype());
2941 
2942  // Old value for the observation change record.
2943  // Fetch before transforming the object since the encoding may become
2944  // incompatible with what's cached in |it|.
2945  bool is_observed =
2946  receiver->map()->is_observed() &&
2947  !it->name().is_identical_to(it->factory()->hidden_string());
2948  MaybeHandle<Object> maybe_old;
2949  if (is_observed) maybe_old = it->GetDataValue();
2950 
2951  // Possibly migrate to the most up-to-date map that will be able to store
2952  // |value| under it->name().
2953  it->PrepareForDataProperty(value);
2954 
2955  // Write the property value.
2956  it->WriteDataValue(value);
2957 
2958  // Send the change record if there are observers.
2959  if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
2960  JSObject::EnqueueChangeRecord(receiver, "update", it->name(),
2961  maybe_old.ToHandleChecked());
2962  }
2963 
2964  return value;
2965 }
2966 
2967 
2969  Handle<Object> value,
2970  PropertyAttributes attributes,
2971  StrictMode strict_mode,
2972  StoreFromKeyed store_mode) {
2973  DCHECK(!it->GetReceiver()->IsJSProxy());
2974  if (!it->GetReceiver()->IsJSObject()) {
2975  // TODO(verwaest): Throw a TypeError with a more specific message.
2976  return WriteToReadOnlyProperty(it, value, strict_mode);
2977  }
2978 
2979  Handle<JSObject> receiver = it->GetStoreTarget();
2980 
2981  // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
2982  // instead. If the prototype is Null, the proxy is detached.
2983  if (receiver->IsJSGlobalProxy()) return value;
2984 
2985  // Possibly migrate to the most up-to-date map that will be able to store
2986  // |value| under it->name() with |attributes|.
2987  it->PrepareTransitionToDataProperty(value, attributes, store_mode);
2988  if (it->state() != LookupIterator::TRANSITION) {
2989  if (strict_mode == SLOPPY) return value;
2990 
2991  Handle<Object> args[1] = {it->name()};
2992  THROW_NEW_ERROR(it->isolate(),
2993  NewTypeError("object_not_extensible",
2994  HandleVector(args, arraysize(args))),
2995  Object);
2996  }
2997  it->ApplyTransitionToDataProperty();
2998 
2999  // TODO(verwaest): Encapsulate dictionary handling better.
3000  if (receiver->map()->is_dictionary_map()) {
3001  // TODO(verwaest): Probably should ensure this is done beforehand.
3002  it->InternalizeName();
3003  JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3004  } else {
3005  // Write the property value.
3006  it->WriteDataValue(value);
3007  }
3008 
3009  // Send the change record if there are observers.
3010  if (receiver->map()->is_observed() &&
3011  !it->name().is_identical_to(it->factory()->hidden_string())) {
3012  JSObject::EnqueueChangeRecord(receiver, "add", it->name(),
3013  it->factory()->the_hole_value());
3014  }
3015 
3016  return value;
3017 }
3018 
3019 
3021  Handle<JSObject> object,
3022  uint32_t index,
3023  Handle<Object> value,
3024  bool* found,
3025  StrictMode strict_mode) {
3026  Isolate *isolate = object->GetIsolate();
3027  for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
3028  iter.Advance()) {
3029  if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
3032  isolate->factory()->Uint32ToString(index), // name
3033  value, strict_mode, found);
3034  }
3035  Handle<JSObject> js_proto =
3037  if (!js_proto->HasDictionaryElements()) {
3038  continue;
3039  }
3040  Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary());
3041  int entry = dictionary->FindEntry(index);
3042  if (entry != SeededNumberDictionary::kNotFound) {
3043  PropertyDetails details = dictionary->DetailsAt(entry);
3044  if (details.type() == CALLBACKS) {
3045  *found = true;
3046  Handle<Object> structure(dictionary->ValueAt(entry), isolate);
3047  return SetElementWithCallback(object, structure, index, value, js_proto,
3048  strict_mode);
3049  }
3050  }
3051  }
3052  *found = false;
3053  return isolate->factory()->the_hole_value();
3054 }
3055 
3056 
3058  // Only supports adding slack to owned descriptors.
3060 
3061  Handle<DescriptorArray> descriptors(map->instance_descriptors());
3062  int old_size = map->NumberOfOwnDescriptors();
3063  if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3064 
3066  descriptors, old_size, slack);
3067 
3068  if (old_size == 0) {
3069  map->set_instance_descriptors(*new_descriptors);
3070  return;
3071  }
3072 
3073  // If the source descriptors had an enum cache we copy it. This ensures
3074  // that the maps to which we push the new descriptor array back can rely
3075  // on a cache always being available once it is set. If the map has more
3076  // enumerated descriptors than available in the original cache, the cache
3077  // will be lazily replaced by the extended cache when needed.
3078  if (descriptors->HasEnumCache()) {
3079  new_descriptors->CopyEnumCacheFrom(*descriptors);
3080  }
3081 
3082  // Replace descriptors by new_descriptors in all maps that share it.
3083  map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
3084 
3085  Map* walk_map;
3086  for (Object* current = map->GetBackPointer();
3087  !current->IsUndefined();
3088  current = walk_map->GetBackPointer()) {
3089  walk_map = Map::cast(current);
3090  if (walk_map->instance_descriptors() != *descriptors) break;
3091  walk_map->set_instance_descriptors(*new_descriptors);
3092  }
3093 
3094  map->set_instance_descriptors(*new_descriptors);
3095 }
3096 
3097 
3098 template<class T>
3099 static int AppendUniqueCallbacks(NeanderArray* callbacks,
3101  int valid_descriptors) {
3102  int nof_callbacks = callbacks->length();
3103 
3104  Isolate* isolate = array->GetIsolate();
3105  // Ensure the keys are unique names before writing them into the
3106  // instance descriptor. Since it may cause a GC, it has to be done before we
3107  // temporarily put the heap in an invalid state while appending descriptors.
3108  for (int i = 0; i < nof_callbacks; ++i) {
3109  Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3110  if (entry->name()->IsUniqueName()) continue;
3111  Handle<String> key =
3112  isolate->factory()->InternalizeString(
3113  Handle<String>(String::cast(entry->name())));
3114  entry->set_name(*key);
3115  }
3116 
3117  // Fill in new callback descriptors. Process the callbacks from
3118  // back to front so that the last callback with a given name takes
3119  // precedence over previously added callbacks with that name.
3120  for (int i = nof_callbacks - 1; i >= 0; i--) {
3121  Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
3122  Handle<Name> key(Name::cast(entry->name()));
3123  // Check if a descriptor with this name already exists before writing.
3124  if (!T::Contains(key, entry, valid_descriptors, array)) {
3125  T::Insert(key, entry, valid_descriptors, array);
3126  valid_descriptors++;
3127  }
3128  }
3129 
3130  return valid_descriptors;
3131 }
3132 
3135  static bool Contains(Handle<Name> key,
3136  Handle<AccessorInfo> entry,
3137  int valid_descriptors,
3138  Handle<DescriptorArray> array) {
3139  DisallowHeapAllocation no_gc;
3140  return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
3141  }
3142  static void Insert(Handle<Name> key,
3143  Handle<AccessorInfo> entry,
3144  int valid_descriptors,
3145  Handle<DescriptorArray> array) {
3146  DisallowHeapAllocation no_gc;
3147  CallbacksDescriptor desc(key, entry, entry->property_attributes());
3148  array->Append(&desc);
3149  }
3150 };
3151 
3152 
3155  static bool Contains(Handle<Name> key,
3156  Handle<AccessorInfo> entry,
3157  int valid_descriptors,
3158  Handle<FixedArray> array) {
3159  for (int i = 0; i < valid_descriptors; i++) {
3160  if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
3161  }
3162  return false;
3163  }
3164  static void Insert(Handle<Name> key,
3165  Handle<AccessorInfo> entry,
3166  int valid_descriptors,
3167  Handle<FixedArray> array) {
3168  DisallowHeapAllocation no_gc;
3169  array->set(valid_descriptors, *entry);
3170  }
3171 };
3172 
3173 
3175  Handle<Object> descriptors) {
3176  int nof = map->NumberOfOwnDescriptors();
3177  Handle<DescriptorArray> array(map->instance_descriptors());
3178  NeanderArray callbacks(descriptors);
3179  DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
3180  nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
3182 }
3183 
3184 
3186  Handle<FixedArray> array,
3187  int valid_descriptors) {
3188  NeanderArray callbacks(descriptors);
3189  DCHECK(array->length() >= callbacks.length() + valid_descriptors);
3190  return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
3191  array,
3192  valid_descriptors);
3193 }
3194 
3195 
3197  DCHECK(!map.is_null());
3198  for (int i = 0; i < maps->length(); ++i) {
3199  if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
3200  }
3201  return false;
3202 }
3203 
3204 
3205 template <class T>
3206 static Handle<T> MaybeNull(T* p) {
3207  if (p == NULL) return Handle<T>::null();
3208  return Handle<T>(p);
3209 }
3210 
3211 
3213  ElementsKind kind = elements_kind();
3214  Handle<Map> transitioned_map = Handle<Map>::null();
3215  Handle<Map> current_map(this);
3216  bool packed = IsFastPackedElementsKind(kind);
3218  while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
3219  kind = GetNextMoreGeneralFastElementsKind(kind, false);
3220  Handle<Map> maybe_transitioned_map =
3221  MaybeNull(current_map->LookupElementsTransitionMap(kind));
3222  if (maybe_transitioned_map.is_null()) break;
3223  if (ContainsMap(candidates, maybe_transitioned_map) &&
3224  (packed || !IsFastPackedElementsKind(kind))) {
3225  transitioned_map = maybe_transitioned_map;
3226  if (!IsFastPackedElementsKind(kind)) packed = false;
3227  }
3228  current_map = maybe_transitioned_map;
3229  }
3230  }
3231  return transitioned_map;
3232 }
3233 
3234 
3236  Map* current_map = map;
3237  int target_kind =
3238  IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
3239  ? to_kind
3241 
3242  // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
3243  // allows to change elements from arbitrary kind to any ExternalArray
3244  // elements kind. Satisfy its requirements, checking whether we already
3245  // have the cached transition.
3246  if (IsExternalArrayElementsKind(to_kind) &&
3248  if (map->HasElementsTransition()) {
3249  Map* next_map = map->elements_transition_map();
3250  if (next_map->elements_kind() == to_kind) return next_map;
3251  }
3252  return map;
3253  }
3254 
3255  ElementsKind kind = map->elements_kind();
3256  while (kind != target_kind) {
3257  kind = GetNextTransitionElementsKind(kind);
3258  if (!current_map->HasElementsTransition()) return current_map;
3259  current_map = current_map->elements_transition_map();
3260  }
3262  if (to_kind != kind && current_map->HasElementsTransition()) {
3263  DCHECK(to_kind == DICTIONARY_ELEMENTS);
3264  Map* next_map = current_map->elements_transition_map();
3265  if (next_map->elements_kind() == to_kind) return next_map;
3266  }
3267 
3268  DCHECK(current_map->elements_kind() == target_kind);
3269  return current_map;
3270 }
3271 
3272 
3274  Map* to_map = FindClosestElementsTransition(this, to_kind);
3275  if (to_map->elements_kind() == to_kind) return to_map;
3276  return NULL;
3277 }
3278 
3279 
3281  Isolate* isolate = GetIsolate();
3282  if (isolate->initial_array_prototype()->map() == this) {
3283  return true;
3284  }
3285 
3286  if (isolate->initial_object_prototype()->map() == this) {
3287  return true;
3288  }
3289 
3290  return false;
3291 }
3292 
3293 
3295  ElementsKind to_kind) {
3297 
3298  Handle<Map> current_map = map;
3299 
3300  ElementsKind kind = map->elements_kind();
3301  if (!map->is_prototype_map()) {
3302  while (kind != to_kind && !IsTerminalElementsKind(kind)) {
3304  current_map =
3305  Map::CopyAsElementsKind(current_map, kind, INSERT_TRANSITION);
3306  }
3307  }
3308 
3309  // In case we are exiting the fast elements kind system, just add the map in
3310  // the end.
3311  if (kind != to_kind) {
3312  current_map = Map::CopyAsElementsKind(
3313  current_map, to_kind, INSERT_TRANSITION);
3314  }
3315 
3316  DCHECK(current_map->elements_kind() == to_kind);
3317  return current_map;
3318 }
3319 
3320 
3322  ElementsKind to_kind) {
3323  ElementsKind from_kind = map->elements_kind();
3324  if (from_kind == to_kind) return map;
3325 
3326  Isolate* isolate = map->GetIsolate();
3327  Context* native_context = isolate->context()->native_context();
3328  Object* maybe_array_maps = native_context->js_array_maps();
3329  if (maybe_array_maps->IsFixedArray()) {
3330  DisallowHeapAllocation no_gc;
3331  FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
3332  if (array_maps->get(from_kind) == *map) {
3333  Object* maybe_transitioned_map = array_maps->get(to_kind);
3334  if (maybe_transitioned_map->IsMap()) {
3335  return handle(Map::cast(maybe_transitioned_map));
3336  }
3337  }
3338  }
3339 
3340  return TransitionElementsToSlow(map, to_kind);
3341 }
3342 
3343 
3345  ElementsKind to_kind) {
3346  ElementsKind from_kind = map->elements_kind();
3348  if (from_kind == to_kind) {
3349  return map;
3350  }
3351 
3352  bool allow_store_transition =
3353  // Only remember the map transition if there is not an already existing
3354  // non-matching element transition.
3355  !map->IsUndefined() && !map->is_dictionary_map() &&
3356  IsTransitionElementsKind(from_kind);
3357 
3358  // Only store fast element maps in ascending generality.
3359  if (IsFastElementsKind(to_kind)) {
3360  allow_store_transition &=
3361  IsTransitionableFastElementsKind(from_kind) &&
3363  }
3364 
3365  if (!allow_store_transition) {
3366  return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
3367  }
3368 
3369  return Map::AsElementsKind(map, to_kind);
3370 }
3371 
3372 
3373 // static
3375  Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
3376 
3377  if (closest_map->elements_kind() == kind) {
3378  return closest_map;
3379  }
3380 
3381  return AddMissingElementsTransitions(closest_map, kind);
3382 }
3383 
3384 
3386  ElementsKind to_kind) {
3387  Handle<Map> map(object->map());
3388  return Map::TransitionElementsTo(map, to_kind);
3389 }
3390 
3391 
3393  Handle<Name> name) {
3394  Isolate* isolate = proxy->GetIsolate();
3395 
3396  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3397  if (name->IsSymbol()) return maybe(false);
3398 
3399  Handle<Object> args[] = { name };
3400  Handle<Object> result;
3402  isolate, result, CallTrap(proxy, "has", isolate->derived_has_trap(),
3403  arraysize(args), args),
3404  Maybe<bool>());
3405 
3406  return maybe(result->BooleanValue());
3407 }
3408 
3409 
3411  Handle<Object> receiver,
3413  Handle<Object> value,
3414  StrictMode strict_mode) {
3415  Isolate* isolate = proxy->GetIsolate();
3416 
3417  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3418  if (name->IsSymbol()) return value;
3419 
3420  Handle<Object> args[] = { receiver, name, value };
3422  isolate,
3423  CallTrap(proxy,
3424  "set",
3425  isolate->derived_set_trap(),
3426  arraysize(args),
3427  args),
3428  Object);
3429 
3430  return value;
3431 }
3432 
3433 
3436  Handle<Object> value, StrictMode strict_mode, bool* done) {
3437  Isolate* isolate = proxy->GetIsolate();
3438  Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy.
3439 
3440  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3441  if (name->IsSymbol()) {
3442  *done = false;
3443  return isolate->factory()->the_hole_value();
3444  }
3445 
3446  *done = true; // except where redefined...
3447  Handle<Object> args[] = { name };
3448  Handle<Object> result;
3450  isolate, result,
3451  CallTrap(proxy,
3452  "getPropertyDescriptor",
3453  Handle<Object>(),
3454  arraysize(args),
3455  args),
3456  Object);
3457 
3458  if (result->IsUndefined()) {
3459  *done = false;
3460  return isolate->factory()->the_hole_value();
3461  }
3462 
3463  // Emulate [[GetProperty]] semantics for proxies.
3464  Handle<Object> argv[] = { result };
3465  Handle<Object> desc;
3467  isolate, desc,
3468  Execution::Call(isolate,
3469  isolate->to_complete_property_descriptor(),
3470  result,
3471  arraysize(argv),
3472  argv),
3473  Object);
3474 
3475  // [[GetProperty]] requires to check that all properties are configurable.
3476  Handle<String> configurable_name =
3477  isolate->factory()->InternalizeOneByteString(
3478  STATIC_CHAR_VECTOR("configurable_"));
3479  Handle<Object> configurable =
3480  Object::GetProperty(desc, configurable_name).ToHandleChecked();
3481  DCHECK(configurable->IsBoolean());
3482  if (configurable->IsFalse()) {
3483  Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3484  STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3485  Handle<Object> args[] = { handler, trap, name };
3486  THROW_NEW_ERROR(isolate, NewTypeError("proxy_prop_not_configurable",
3487  HandleVector(args, arraysize(args))),
3488  Object);
3489  }
3490  DCHECK(configurable->IsTrue());
3491 
3492  // Check for DataDescriptor.
3493  Handle<String> hasWritable_name =
3494  isolate->factory()->InternalizeOneByteString(
3495  STATIC_CHAR_VECTOR("hasWritable_"));
3496  Handle<Object> hasWritable =
3497  Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
3498  DCHECK(hasWritable->IsBoolean());
3499  if (hasWritable->IsTrue()) {
3500  Handle<String> writable_name = isolate->factory()->InternalizeOneByteString(
3501  STATIC_CHAR_VECTOR("writable_"));
3502  Handle<Object> writable =
3503  Object::GetProperty(desc, writable_name).ToHandleChecked();
3504  DCHECK(writable->IsBoolean());
3505  *done = writable->IsFalse();
3506  if (!*done) return isolate->factory()->the_hole_value();
3507  if (strict_mode == SLOPPY) return value;
3508  Handle<Object> args[] = { name, receiver };
3509  THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
3510  HandleVector(args, arraysize(args))),
3511  Object);
3512  }
3514  // We have an AccessorDescriptor.
3515  Handle<String> set_name =
3516  isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("set_"));
3517  Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
3518  if (!setter->IsUndefined()) {
3519  // TODO(rossberg): nicer would be to cast to some JSCallable here...
3521  receiver, Handle<JSReceiver>::cast(setter), value);
3522  }
3523 
3524  if (strict_mode == SLOPPY) return value;
3525  Handle<Object> args2[] = { name, proxy };
3526  THROW_NEW_ERROR(isolate, NewTypeError("no_setter_in_callback",
3527  HandleVector(args2, arraysize(args2))),
3528  Object);
3529 }
3531 
3533  Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) {
3534  Isolate* isolate = proxy->GetIsolate();
3535 
3536  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3537  if (name->IsSymbol()) return isolate->factory()->false_value();
3538 
3539  Handle<Object> args[] = { name };
3540  Handle<Object> result;
3542  isolate, result,
3543  CallTrap(proxy,
3544  "delete",
3545  Handle<Object>(),
3546  arraysize(args),
3547  args),
3548  Object);
3549 
3550  bool result_bool = result->BooleanValue();
3551  if (mode == STRICT_DELETION && !result_bool) {
3552  Handle<Object> handler(proxy->handler(), isolate);
3553  Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
3554  STATIC_CHAR_VECTOR("delete"));
3555  Handle<Object> args[] = { handler, trap_name };
3556  THROW_NEW_ERROR(isolate, NewTypeError("handler_failed",
3557  HandleVector(args, arraysize(args))),
3558  Object);
3559  }
3560  return isolate->factory()->ToBoolean(result_bool);
3561 }
3562 
3565  Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) {
3566  Isolate* isolate = proxy->GetIsolate();
3567  Handle<String> name = isolate->factory()->Uint32ToString(index);
3570 
3571 
3573  Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name) {
3574  Isolate* isolate = proxy->GetIsolate();
3575  HandleScope scope(isolate);
3576 
3577  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3578  if (name->IsSymbol()) return maybe(ABSENT);
3579 
3580  Handle<Object> args[] = { name };
3581  Handle<Object> result;
3583  isolate, result,
3584  proxy->CallTrap(proxy, "getPropertyDescriptor", Handle<Object>(),
3585  arraysize(args), args),
3587 
3588  if (result->IsUndefined()) return maybe(ABSENT);
3589 
3590  Handle<Object> argv[] = { result };
3591  Handle<Object> desc;
3593  isolate, desc,
3594  Execution::Call(isolate, isolate->to_complete_property_descriptor(),
3595  result, arraysize(argv), argv),
3597 
3598  // Convert result to PropertyAttributes.
3599  Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
3600  STATIC_CHAR_VECTOR("enumerable_"));
3601  Handle<Object> enumerable;
3603  Object::GetProperty(desc, enum_n),
3605  Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
3606  STATIC_CHAR_VECTOR("configurable_"));
3607  Handle<Object> configurable;
3608  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, configurable,
3609  Object::GetProperty(desc, conf_n),
3611  Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
3612  STATIC_CHAR_VECTOR("writable_"));
3613  Handle<Object> writable;
3614  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, writable,
3615  Object::GetProperty(desc, writ_n),
3617  if (!writable->BooleanValue()) {
3618  Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
3619  STATIC_CHAR_VECTOR("set_"));
3620  Handle<Object> setter;
3621  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, setter,
3622  Object::GetProperty(desc, set_n),
3624  writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
3625  }
3626 
3627  if (configurable->IsFalse()) {
3628  Handle<Object> handler(proxy->handler(), isolate);
3629  Handle<String> trap = isolate->factory()->InternalizeOneByteString(
3630  STATIC_CHAR_VECTOR("getPropertyDescriptor"));
3631  Handle<Object> args[] = { handler, trap, name };
3632  Handle<Object> error;
3633  MaybeHandle<Object> maybe_error = isolate->factory()->NewTypeError(
3634  "proxy_prop_not_configurable", HandleVector(args, arraysize(args)));
3635  if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
3636  return maybe(NONE);
3637  }
3638 
3639  int attributes = NONE;
3640  if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
3641  if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
3642  if (!writable->BooleanValue()) attributes |= READ_ONLY;
3643  return maybe(static_cast<PropertyAttributes>(attributes));
3644 }
3645 
3646 
3648  Handle<JSProxy> proxy, Handle<JSReceiver> receiver, uint32_t index) {
3649  Isolate* isolate = proxy->GetIsolate();
3650  Handle<String> name = isolate->factory()->Uint32ToString(index);
3651  return GetPropertyAttributesWithHandler(proxy, receiver, name);
3652 }
3653 
3654 
3656  Isolate* isolate = proxy->GetIsolate();
3657 
3658  // Save identity hash.
3659  Handle<Object> hash(proxy->GetIdentityHash(), isolate);
3660 
3661  if (proxy->IsJSFunctionProxy()) {
3662  isolate->factory()->BecomeJSFunction(proxy);
3663  // Code will be set on the JavaScript side.
3664  } else {
3665  isolate->factory()->BecomeJSObject(proxy);
3666  }
3667  DCHECK(proxy->IsJSObject());
3668 
3669  // Inherit identity, if it was present.
3670  if (hash->IsSmi()) {
3672  Handle<Smi>::cast(hash));
3673  }
3674 }
3675 
3676 
3678  const char* name,
3679  Handle<Object> derived,
3680  int argc,
3681  Handle<Object> argv[]) {
3682  Isolate* isolate = proxy->GetIsolate();
3683  Handle<Object> handler(proxy->handler(), isolate);
3684 
3685  Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
3686  Handle<Object> trap;
3688  isolate, trap,
3689  Object::GetPropertyOrElement(handler, trap_name),
3690  Object);
3691 
3692  if (trap->IsUndefined()) {
3693  if (derived.is_null()) {
3694  Handle<Object> args[] = { handler, trap_name };
3695  THROW_NEW_ERROR(isolate,
3696  NewTypeError("handler_trap_missing",
3697  HandleVector(args, arraysize(args))),
3698  Object);
3699  }
3700  trap = Handle<Object>(derived);
3701  }
3702 
3703  return Execution::Call(isolate, trap, handler, argc, argv);
3704 }
3705 
3706 
3708  DCHECK(object->map()->inobject_properties() == map->inobject_properties());
3709  ElementsKind obj_kind = object->map()->elements_kind();
3710  ElementsKind map_kind = map->elements_kind();
3711  if (map_kind != obj_kind) {
3712  ElementsKind to_kind = map_kind;
3713  if (IsMoreGeneralElementsKindTransition(map_kind, obj_kind) ||
3714  IsDictionaryElementsKind(obj_kind)) {
3715  to_kind = obj_kind;
3716  }
3717  if (IsDictionaryElementsKind(to_kind)) {
3718  NormalizeElements(object);
3719  } else {
3720  TransitionElementsKind(object, to_kind);
3721  }
3722  map = Map::AsElementsKind(map, to_kind);
3723  }
3724  JSObject::MigrateToMap(object, map);
3725 }
3726 
3727 
3729  Handle<Map> original_map(object->map());
3730  Handle<Map> map = Map::Update(original_map);
3731  map->set_migration_target(true);
3732  MigrateToMap(object, map);
3733  if (FLAG_trace_migration) {
3734  object->PrintInstanceMigration(stdout, *original_map, *map);
3735  }
3736 }
3737 
3738 
3739 // static
3741  Isolate* isolate = object->GetIsolate();
3742  DisallowDeoptimization no_deoptimization(isolate);
3743  Handle<Map> original_map(object->map(), isolate);
3744  Handle<Map> new_map;
3745  if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
3746  return false;
3747  }
3748  JSObject::MigrateToMap(object, new_map);
3749  if (FLAG_trace_migration) {
3750  object->PrintInstanceMigration(stdout, *original_map, object->map());
3751  }
3752  return true;
3753 }
3754 
3755 
3757  Handle<Map> map,
3758  Handle<Object> value) {
3759  JSObject::MigrateToMap(object, map);
3760  if (map->GetLastDescriptorDetails().type() != FIELD) return;
3761  object->WriteToField(map->LastAdded(), *value);
3762 }
3763 
3764 
3765 void JSObject::WriteToField(int descriptor, Object* value) {
3766  DisallowHeapAllocation no_gc;
3767 
3768  DescriptorArray* desc = map()->instance_descriptors();
3769  PropertyDetails details = desc->GetDetails(descriptor);
3770 
3771  DCHECK(details.type() == FIELD);
3772 
3773  FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
3774  if (details.representation().IsDouble()) {
3775  // Nothing more to be done.
3776  if (value->IsUninitialized()) return;
3777  HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
3778  DCHECK(box->IsMutableHeapNumber());
3779  box->set_value(value->Number());
3780  } else {
3781  FastPropertyAtPut(index, value);
3782  }
3783 }
3784 
3785 
3787  Handle<Object> value,
3788  PropertyAttributes attributes) {
3789  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
3790  CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
3791 #ifdef DEBUG
3792  uint32_t index;
3793  DCHECK(!object->IsJSProxy());
3794  DCHECK(!name->AsArrayIndex(&index));
3795  Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
3796  DCHECK(maybe.has_value);
3797  DCHECK(!it.IsFound());
3798  DCHECK(object->map()->is_extensible() ||
3799  name.is_identical_to(it.isolate()->factory()->hidden_string()));
3800 #endif
3801  AddDataProperty(&it, value, attributes, STRICT,
3803 }
3804 
3805 
3806 // Reconfigures a property to a data property with attributes, even if it is not
3807 // reconfigurable.
3809  Handle<JSObject> object,
3811  Handle<Object> value,
3812  PropertyAttributes attributes,
3813  ExecutableAccessorInfoHandling handling) {
3814  DCHECK(!value->IsTheHole());
3815  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
3816  bool is_observed = object->map()->is_observed() &&
3817  *name != it.isolate()->heap()->hidden_string();
3818  for (; it.IsFound(); it.Next()) {
3819  switch (it.state()) {
3820  case LookupIterator::INTERCEPTOR:
3821  case LookupIterator::JSPROXY:
3822  case LookupIterator::NOT_FOUND:
3823  case LookupIterator::TRANSITION:
3824  UNREACHABLE();
3825 
3826  case LookupIterator::ACCESS_CHECK:
3827  if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) {
3828  return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
3829  }
3830  break;
3831 
3832  case LookupIterator::ACCESSOR: {
3833  PropertyDetails details = it.property_details();
3834  Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
3835  // Ensure the context isn't changed after calling into accessors.
3836  AssertNoContextChange ncc(it.isolate());
3838  Handle<Object> accessors = it.GetAccessors();
3839 
3840  if (is_observed && accessors->IsAccessorInfo()) {
3842  it.isolate(), old_value,
3843  GetPropertyWithAccessor(it.GetReceiver(), it.name(),
3844  it.GetHolder<JSObject>(), accessors),
3845  Object);
3846  }
3847 
3848  // Special handling for ExecutableAccessorInfo, which behaves like a
3849  // data property.
3850  if (handling == DONT_FORCE_FIELD &&
3851  accessors->IsExecutableAccessorInfo()) {
3852  Handle<Object> result;
3854  it.isolate(), result,
3855  JSObject::SetPropertyWithAccessor(it.GetReceiver(), it.name(),
3856  value, it.GetHolder<JSObject>(),
3857  accessors, STRICT),
3859  DCHECK(result->SameValue(*value));
3860 
3861  if (details.attributes() == attributes) {
3862  // Regular property update if the attributes match.
3863  if (is_observed && !old_value->SameValue(*value)) {
3864  // If we are setting the prototype of a function and are
3865  // observed, don't send change records because the prototype
3866  // handles that itself.
3867  if (!object->IsJSFunction() ||
3868  !Name::Equals(it.isolate()->factory()->prototype_string(),
3869  name) ||
3870  !Handle<JSFunction>::cast(object)->should_have_prototype()) {
3871  EnqueueChangeRecord(object, "update", name, old_value);
3872  }
3873  }
3874  return value;
3875  }
3876 
3877  // Reconfigure the accessor if attributes mismatch.
3879  it.isolate(), Handle<ExecutableAccessorInfo>::cast(accessors));
3880  new_data->set_property_attributes(attributes);
3881  // By clearing the setter we don't have to introduce a lookup to
3882  // the setter, simply make it unavailable to reflect the
3883  // attributes.
3884  if (attributes & READ_ONLY) new_data->clear_setter();
3885  SetPropertyCallback(object, name, new_data, attributes);
3886  if (is_observed) {
3887  if (old_value->SameValue(*value)) {
3888  old_value = it.isolate()->factory()->the_hole_value();
3889  }
3890  EnqueueChangeRecord(object, "reconfigure", name, old_value);
3891  }
3892  return value;
3893  }
3894 
3895  it.ReconfigureDataProperty(value, attributes);
3896  it.PrepareForDataProperty(value);
3897  it.WriteDataValue(value);
3898 
3899  if (is_observed) {
3900  if (old_value->SameValue(*value)) {
3901  old_value = it.isolate()->factory()->the_hole_value();
3902  }
3903  EnqueueChangeRecord(object, "reconfigure", name, old_value);
3904  }
3905 
3906  return value;
3907  }
3908 
3909  case LookupIterator::DATA: {
3910  PropertyDetails details = it.property_details();
3911  Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
3912  // Regular property update if the attributes match.
3913  if (details.attributes() == attributes) {
3914  return SetDataProperty(&it, value);
3915  }
3916  // Reconfigure the data property if the attributes mismatch.
3917  if (is_observed) old_value = it.GetDataValue();
3918 
3919  it.ReconfigureDataProperty(value, attributes);
3920  it.PrepareForDataProperty(value);
3921  it.WriteDataValue(value);
3922 
3923  if (is_observed) {
3924  if (old_value->SameValue(*value)) {
3925  old_value = it.isolate()->factory()->the_hole_value();
3926  }
3927  EnqueueChangeRecord(object, "reconfigure", name, old_value);
3928  }
3929 
3930  return value;
3931  }
3932  }
3933  }
3934 
3935  return AddDataProperty(&it, value, attributes, STRICT,
3937 }
3938 
3939 
3941  Handle<JSObject> holder,
3942  Handle<Object> receiver,
3943  Handle<Name> name) {
3944  // TODO(rossberg): Support symbols in the API.
3945  if (name->IsSymbol()) return maybe(ABSENT);
3946 
3947  Isolate* isolate = holder->GetIsolate();
3948  HandleScope scope(isolate);
3949 
3950  // Make sure that the top context does not change when doing
3951  // callbacks or interceptor calls.
3952  AssertNoContextChange ncc(isolate);
3953 
3954  Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
3956  isolate, interceptor->data(), *receiver, *holder);
3957  if (!interceptor->query()->IsUndefined()) {
3959  v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query());
3960  LOG(isolate,
3961  ApiNamedPropertyAccess("interceptor-named-has", *holder, *name));
3962  v8::Handle<v8::Integer> result =
3963  args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name)));
3964  if (!result.IsEmpty()) {
3965  DCHECK(result->IsInt32());
3966  return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
3967  }
3968  } else if (!interceptor->getter()->IsUndefined()) {
3970  v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
3971  LOG(isolate,
3972  ApiNamedPropertyAccess("interceptor-named-get-has", *holder, *name));
3973  v8::Handle<v8::Value> result =
3974  args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name)));
3975  if (!result.IsEmpty()) return maybe(DONT_ENUM);
3976  }
3977 
3979  return maybe(ABSENT);
3980 }
3981 
3982 
3985  // Check whether the name is an array index.
3986  uint32_t index = 0;
3987  if (object->IsJSObject() && name->AsArrayIndex(&index)) {
3988  return GetOwnElementAttribute(object, index);
3989  }
3990  LookupIterator it(object, name, LookupIterator::HIDDEN);
3991  return GetPropertyAttributes(&it);
3992 }
3993 
3994 
3996  LookupIterator* it) {
3997  for (; it->IsFound(); it->Next()) {
3998  switch (it->state()) {
3999  case LookupIterator::NOT_FOUND:
4000  case LookupIterator::TRANSITION:
4001  UNREACHABLE();
4002  case LookupIterator::JSPROXY:
4004  it->GetHolder<JSProxy>(), it->GetReceiver(), it->name());
4005  case LookupIterator::INTERCEPTOR: {
4006  Maybe<PropertyAttributes> result =
4008  it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
4009  if (!result.has_value) return result;
4010  if (result.value != ABSENT) return result;
4011  break;
4012  }
4013  case LookupIterator::ACCESS_CHECK:
4014  if (it->HasAccess(v8::ACCESS_HAS)) break;
4017  case LookupIterator::DATA:
4018  return maybe(it->property_details().attributes());
4019  }
4020  }
4021  return maybe(ABSENT);
4022 }
4023 
4024 
4026  Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4027  bool check_prototype) {
4028  Isolate* isolate = object->GetIsolate();
4029 
4030  // Check access rights if needed.
4031  if (object->IsAccessCheckNeeded()) {
4032  if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
4033  isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
4035  return maybe(ABSENT);
4036  }
4037  }
4038 
4039  if (object->IsJSGlobalProxy()) {
4040  PrototypeIterator iter(isolate, object);
4041  if (iter.IsAtEnd()) return maybe(ABSENT);
4042  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4045  index, check_prototype);
4046  }
4047 
4048  // Check for lookup interceptor except when bootstrapping.
4049  if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
4051  object, receiver, index, check_prototype);
4052  }
4053 
4054  return GetElementAttributeWithoutInterceptor(
4055  object, receiver, index, check_prototype);
4056 }
4057 
4058 
4060  Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4061  bool check_prototype) {
4062  Isolate* isolate = object->GetIsolate();
4063  HandleScope scope(isolate);
4064 
4065  // Make sure that the top context does not change when doing
4066  // callbacks or interceptor calls.
4067  AssertNoContextChange ncc(isolate);
4068 
4069  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
4071  isolate, interceptor->data(), *receiver, *object);
4072  if (!interceptor->query()->IsUndefined()) {
4074  v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
4075  LOG(isolate,
4076  ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index));
4077  v8::Handle<v8::Integer> result = args.Call(query, index);
4078  if (!result.IsEmpty())
4079  return maybe(static_cast<PropertyAttributes>(result->Int32Value()));
4080  } else if (!interceptor->getter()->IsUndefined()) {
4082  v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
4083  LOG(isolate,
4084  ApiIndexedPropertyAccess(
4085  "interceptor-indexed-get-has", *object, index));
4086  v8::Handle<v8::Value> result = args.Call(getter, index);
4087  if (!result.IsEmpty()) return maybe(NONE);
4088  }
4089 
4090  return GetElementAttributeWithoutInterceptor(
4091  object, receiver, index, check_prototype);
4092 }
4093 
4094 
4096  Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index,
4097  bool check_prototype) {
4098  PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes(
4099  receiver, object, index);
4100  if (attr != ABSENT) return maybe(attr);
4101 
4102  // Handle [] on String objects.
4103  if (object->IsStringObjectWithCharacterAt(index)) {
4104  return maybe(static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE));
4105  }
4106 
4107  if (!check_prototype) return maybe(ABSENT);
4108 
4109  PrototypeIterator iter(object->GetIsolate(), object);
4110  if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
4111  // We need to follow the spec and simulate a call to [[GetOwnProperty]].
4114  index);
4115  }
4116  if (iter.IsAtEnd()) return maybe(ABSENT);
4117  return GetElementAttributeWithReceiver(
4119  index, true);
4120 }
4121 
4122 
4124  Handle<FixedArray> array(
4125  isolate->factory()->NewFixedArray(kEntries, TENURED));
4126  return Handle<NormalizedMapCache>::cast(array);
4127 }
4128 
4129 
4132  DisallowHeapAllocation no_gc;
4133  Object* value = FixedArray::get(GetIndex(fast_map));
4134  if (!value->IsMap() ||
4135  !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
4136  return MaybeHandle<Map>();
4137  }
4138  return handle(Map::cast(value));
4139 }
4140 
4141 
4143  Handle<Map> normalized_map) {
4144  DisallowHeapAllocation no_gc;
4145  DCHECK(normalized_map->is_dictionary_map());
4146  FixedArray::set(GetIndex(fast_map), *normalized_map);
4147 }
4148 
4149 
4151  int entries = length();
4152  for (int i = 0; i != entries; i++) {
4153  set_undefined(i);
4154  }
4155 }
4156 
4157 
4160  Handle<Code> code) {
4161  Handle<Map> map(object->map());
4162  Map::UpdateCodeCache(map, name, code);
4163 }
4164 
4165 
4168  int expected_additional_properties) {
4169  if (!object->HasFastProperties()) return;
4170 
4171  Handle<Map> map(object->map());
4172  Handle<Map> new_map = Map::Normalize(map, mode);
4173 
4174  MigrateFastToSlow(object, new_map, expected_additional_properties);
4175 }
4176 
4177 
4179  Handle<Map> new_map,
4180  int expected_additional_properties) {
4181  // The global object is always normalized.
4182  DCHECK(!object->IsGlobalObject());
4183  // JSGlobalProxy must never be normalized
4184  DCHECK(!object->IsJSGlobalProxy());
4185 
4186  Isolate* isolate = object->GetIsolate();
4187  HandleScope scope(isolate);
4188  Handle<Map> map(object->map());
4189 
4190  // Allocate new content.
4191  int real_size = map->NumberOfOwnDescriptors();
4192  int property_count = real_size;
4193  if (expected_additional_properties > 0) {
4194  property_count += expected_additional_properties;
4195  } else {
4196  property_count += 2; // Make space for two more properties.
4197  }
4198  Handle<NameDictionary> dictionary =
4199  NameDictionary::New(isolate, property_count);
4200 
4201  Handle<DescriptorArray> descs(map->instance_descriptors());
4202  for (int i = 0; i < real_size; i++) {
4203  PropertyDetails details = descs->GetDetails(i);
4204  switch (details.type()) {
4205  case CONSTANT: {
4206  Handle<Name> key(descs->GetKey(i));
4207  Handle<Object> value(descs->GetConstant(i), isolate);
4208  PropertyDetails d = PropertyDetails(
4209  details.attributes(), NORMAL, i + 1);
4210  dictionary = NameDictionary::Add(dictionary, key, value, d);
4211  break;
4212  }
4213  case FIELD: {
4214  Handle<Name> key(descs->GetKey(i));
4215  FieldIndex index = FieldIndex::ForDescriptor(*map, i);
4216  Handle<Object> value(
4217  object->RawFastPropertyAt(index), isolate);
4218  if (details.representation().IsDouble()) {
4219  DCHECK(value->IsMutableHeapNumber());
4221  value = isolate->factory()->NewHeapNumber(old->value());
4222  }
4223  PropertyDetails d =
4224  PropertyDetails(details.attributes(), NORMAL, i + 1);
4225  dictionary = NameDictionary::Add(dictionary, key, value, d);
4226  break;
4227  }
4228  case CALLBACKS: {
4229  Handle<Name> key(descs->GetKey(i));
4230  Handle<Object> value(descs->GetCallbacksObject(i), isolate);
4231  PropertyDetails d = PropertyDetails(
4232  details.attributes(), CALLBACKS, i + 1);
4233  dictionary = NameDictionary::Add(dictionary, key, value, d);
4234  break;
4235  }
4236  case NORMAL:
4237  UNREACHABLE();
4238  break;
4239  }
4240  }
4241 
4242  // Copy the next enumeration index from instance descriptor.
4243  dictionary->SetNextEnumerationIndex(real_size + 1);
4244 
4245  // From here on we cannot fail and we shouldn't GC anymore.
4246  DisallowHeapAllocation no_allocation;
4247 
4248  // Resize the object in the heap if necessary.
4249  int new_instance_size = new_map->instance_size();
4250  int instance_size_delta = map->instance_size() - new_instance_size;
4251  DCHECK(instance_size_delta >= 0);
4252 
4253  if (instance_size_delta > 0) {
4254  Heap* heap = isolate->heap();
4255  heap->CreateFillerObjectAt(object->address() + new_instance_size,
4256  instance_size_delta);
4257  heap->AdjustLiveBytes(object->address(), -instance_size_delta,
4259  }
4260 
4261  // We are storing the new map using release store after creating a filler for
4262  // the left-over space to avoid races with the sweeper thread.
4263  object->synchronized_set_map(*new_map);
4264 
4265  object->set_properties(*dictionary);
4266 
4267  isolate->counters()->props_to_dictionary()->Increment();
4268 
4269 #ifdef DEBUG
4270  if (FLAG_trace_normalization) {
4271  OFStream os(stdout);
4272  os << "Object properties have been normalized:\n";
4273  object->Print(os);
4274  }
4275 #endif
4276 }
4277 
4278 
4280  int unused_property_fields) {
4281  if (object->HasFastProperties()) return;
4282  DCHECK(!object->IsGlobalObject());
4283  Isolate* isolate = object->GetIsolate();
4284  Factory* factory = isolate->factory();
4285  Handle<NameDictionary> dictionary(object->property_dictionary());
4286 
4287  // Make sure we preserve dictionary representation if there are too many
4288  // descriptors.
4289  int number_of_elements = dictionary->NumberOfElements();
4290  if (number_of_elements > kMaxNumberOfDescriptors) return;
4291 
4292  if (number_of_elements != dictionary->NextEnumerationIndex()) {
4294  }
4295 
4296  int instance_descriptor_length = 0;
4297  int number_of_fields = 0;
4298 
4299  // Compute the length of the instance descriptor.
4300  int capacity = dictionary->Capacity();
4301  for (int i = 0; i < capacity; i++) {
4302  Object* k = dictionary->KeyAt(i);
4303  if (dictionary->IsKey(k)) {
4304  Object* value = dictionary->ValueAt(i);
4305  PropertyType type = dictionary->DetailsAt(i).type();
4306  DCHECK(type != FIELD);
4307  instance_descriptor_length++;
4308  if (type == NORMAL && !value->IsJSFunction()) {
4309  number_of_fields += 1;
4310  }
4311  }
4312  }
4313 
4314  int inobject_props = object->map()->inobject_properties();
4315 
4316  // Allocate new map.
4317  Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
4318  new_map->set_dictionary_map(false);
4319 
4320  if (instance_descriptor_length == 0) {
4321  DisallowHeapAllocation no_gc;
4322  DCHECK_LE(unused_property_fields, inobject_props);
4323  // Transform the object.
4324  new_map->set_unused_property_fields(inobject_props);
4325  object->synchronized_set_map(*new_map);
4326  object->set_properties(isolate->heap()->empty_fixed_array());
4327  // Check that it really works.
4328  DCHECK(object->HasFastProperties());
4329  return;
4330  }
4331 
4332  // Allocate the instance descriptor.
4334  isolate, instance_descriptor_length);
4335 
4336  int number_of_allocated_fields =
4337  number_of_fields + unused_property_fields - inobject_props;
4338  if (number_of_allocated_fields < 0) {
4339  // There is enough inobject space for all fields (including unused).
4340  number_of_allocated_fields = 0;
4341  unused_property_fields = inobject_props - number_of_fields;
4342  }
4343 
4344  // Allocate the fixed array for the fields.
4345  Handle<FixedArray> fields = factory->NewFixedArray(
4346  number_of_allocated_fields);
4347 
4348  // Fill in the instance descriptor and the fields.
4349  int current_offset = 0;
4350  for (int i = 0; i < capacity; i++) {
4351  Object* k = dictionary->KeyAt(i);
4352  if (dictionary->IsKey(k)) {
4353  Object* value = dictionary->ValueAt(i);
4354  Handle<Name> key;
4355  if (k->IsSymbol()) {
4356  key = handle(Symbol::cast(k));
4357  } else {
4358  // Ensure the key is a unique name before writing into the
4359  // instance descriptor.
4360  key = factory->InternalizeString(handle(String::cast(k)));
4361  }
4362 
4363  PropertyDetails details = dictionary->DetailsAt(i);
4364  int enumeration_index = details.dictionary_index();
4365  PropertyType type = details.type();
4366 
4367  if (value->IsJSFunction()) {
4368  ConstantDescriptor d(key,
4369  handle(value, isolate),
4370  details.attributes());
4371  descriptors->Set(enumeration_index - 1, &d);
4372  } else if (type == NORMAL) {
4373  if (current_offset < inobject_props) {
4374  object->InObjectPropertyAtPut(current_offset,
4375  value,
4377  } else {
4378  int offset = current_offset - inobject_props;
4379  fields->set(offset, value);
4380  }
4381  FieldDescriptor d(key,
4382  current_offset++,
4383  details.attributes(),
4384  // TODO(verwaest): value->OptimalRepresentation();
4386  descriptors->Set(enumeration_index - 1, &d);
4387  } else if (type == CALLBACKS) {
4388  CallbacksDescriptor d(key,
4389  handle(value, isolate),
4390  details.attributes());
4391  descriptors->Set(enumeration_index - 1, &d);
4392  } else {
4393  UNREACHABLE();
4394  }
4395  }
4396  }
4397  DCHECK(current_offset == number_of_fields);
4398 
4399  descriptors->Sort();
4400 
4401  DisallowHeapAllocation no_gc;
4402  new_map->InitializeDescriptors(*descriptors);
4403  new_map->set_unused_property_fields(unused_property_fields);
4404 
4405  // Transform the object.
4406  object->synchronized_set_map(*new_map);
4407 
4408  object->set_properties(*fields);
4409  DCHECK(object->IsJSObject());
4410 
4411  // Check that it really works.
4412  DCHECK(object->HasFastProperties());
4413 }
4414 
4415 
4417  Isolate* isolate = object->GetIsolate();
4418  CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
4419  if (object->map()->has_dictionary_elements()) {
4420  Handle<SeededNumberDictionary> new_elements =
4421  SeededNumberDictionary::New(isolate, 0);
4422  object->set_elements(*new_elements);
4423  } else {
4424  object->set_elements(object->map()->GetInitialElements());
4425  }
4426 }
4427 
4428 
4430  Handle<FixedArrayBase> array,
4431  int length,
4432  Handle<SeededNumberDictionary> dictionary) {
4433  Isolate* isolate = array->GetIsolate();
4434  Factory* factory = isolate->factory();
4435  bool has_double_elements = array->IsFixedDoubleArray();
4436  for (int i = 0; i < length; i++) {
4437  Handle<Object> value;
4438  if (has_double_elements) {
4439  Handle<FixedDoubleArray> double_array =
4441  if (double_array->is_the_hole(i)) {
4442  value = factory->the_hole_value();
4443  } else {
4444  value = factory->NewHeapNumber(double_array->get_scalar(i));
4445  }
4446  } else {
4447  value = handle(Handle<FixedArray>::cast(array)->get(i), isolate);
4448  }
4449  if (!value->IsTheHole()) {
4450  PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
4451  dictionary =
4452  SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details);
4453  }
4454  }
4455  return dictionary;
4456 }
4457 
4458 
4460  Handle<JSObject> object) {
4461  DCHECK(!object->HasExternalArrayElements() &&
4462  !object->HasFixedTypedArrayElements());
4463  Isolate* isolate = object->GetIsolate();
4464 
4465  // Find the backing store.
4466  Handle<FixedArrayBase> array(FixedArrayBase::cast(object->elements()));
4467  bool is_arguments =
4468  (array->map() == isolate->heap()->sloppy_arguments_elements_map());
4469  if (is_arguments) {
4470  array = handle(FixedArrayBase::cast(
4471  Handle<FixedArray>::cast(array)->get(1)));
4472  }
4473  if (array->IsDictionary()) return Handle<SeededNumberDictionary>::cast(array);
4474 
4475  DCHECK(object->HasFastSmiOrObjectElements() ||
4476  object->HasFastDoubleElements() ||
4477  object->HasFastArgumentsElements());
4478  // Compute the effective length and allocate a new backing store.
4479  int length = object->IsJSArray()
4480  ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
4481  : array->length();
4482  int old_capacity = 0;
4483  int used_elements = 0;
4484  object->GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4485  Handle<SeededNumberDictionary> dictionary =
4486  SeededNumberDictionary::New(isolate, used_elements);
4487 
4488  dictionary = CopyFastElementsToDictionary(array, length, dictionary);
4489 
4490  // Switch to using the dictionary as the backing storage for elements.
4491  if (is_arguments) {
4492  FixedArray::cast(object->elements())->set(1, *dictionary);
4493  } else {
4494  // Set the new map first to satify the elements type assert in
4495  // set_elements().
4496  Handle<Map> new_map =
4498 
4499  JSObject::MigrateToMap(object, new_map);
4500  object->set_elements(*dictionary);
4501  }
4502 
4503  isolate->counters()->elements_to_dictionary()->Increment();
4504 
4505 #ifdef DEBUG
4506  if (FLAG_trace_normalization) {
4507  OFStream os(stdout);
4508  os << "Object elements have been normalized:\n";
4509  object->Print(os);
4510  }
4511 #endif
4512 
4513  DCHECK(object->HasDictionaryElements() ||
4514  object->HasDictionaryArgumentsElements());
4515  return dictionary;
4516 }
4517 
4518 
4519 static Smi* GenerateIdentityHash(Isolate* isolate) {
4520  int hash_value;
4521  int attempts = 0;
4522  do {
4523  // Generate a random 32-bit hash value but limit range to fit
4524  // within a smi.
4525  hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4526  attempts++;
4527  } while (hash_value == 0 && attempts < 30);
4528  hash_value = hash_value != 0 ? hash_value : 1; // never return 0
4529 
4530  return Smi::FromInt(hash_value);
4531 }
4532 
4533 
4535  DCHECK(!object->IsJSGlobalProxy());
4536  Isolate* isolate = object->GetIsolate();
4537  SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4538 }
4539 
4540 
4541 template<typename ProxyType>
4543  Isolate* isolate = proxy->GetIsolate();
4544 
4545  Handle<Object> maybe_hash(proxy->hash(), isolate);
4546  if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4547 
4548  Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4549  proxy->set_hash(*hash);
4550  return hash;
4551 }
4552 
4553 
4555  DisallowHeapAllocation no_gc;
4556  Isolate* isolate = GetIsolate();
4557  if (IsJSGlobalProxy()) {
4558  return JSGlobalProxy::cast(this)->hash();
4559  }
4560  Object* stored_value =
4561  GetHiddenProperty(isolate->factory()->identity_hash_string());
4562  return stored_value->IsSmi()
4563  ? stored_value
4564  : isolate->heap()->undefined_value();
4565 }
4566 
4567 
4569  if (object->IsJSGlobalProxy()) {
4571  }
4572 
4573  Isolate* isolate = object->GetIsolate();
4574 
4575  Handle<Object> maybe_hash(object->GetIdentityHash(), isolate);
4576  if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
4577 
4578  Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
4579  SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4580  return hash;
4581 }
4582 
4583 
4585  return this->hash();
4586 }
4587 
4588 
4590  return GetOrCreateIdentityHashHelper(proxy);
4591 }
4592 
4593 
4595  DisallowHeapAllocation no_gc;
4596  DCHECK(key->IsUniqueName());
4597  if (IsJSGlobalProxy()) {
4598  // JSGlobalProxies store their hash internally.
4599  DCHECK(*key != GetHeap()->identity_hash_string());
4600  // For a proxy, use the prototype as target object.
4601  PrototypeIterator iter(GetIsolate(), this);
4602  // If the proxy is detached, return undefined.
4603  if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
4604  DCHECK(iter.GetCurrent()->IsJSGlobalObject());
4605  return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key);
4606  }
4607  DCHECK(!IsJSGlobalProxy());
4608  Object* inline_value = GetHiddenPropertiesHashTable();
4609 
4610  if (inline_value->IsSmi()) {
4611  // Handle inline-stored identity hash.
4612  if (*key == GetHeap()->identity_hash_string()) {
4613  return inline_value;
4614  } else {
4615  return GetHeap()->the_hole_value();
4616  }
4617  }
4618 
4619  if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
4620 
4621  ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
4622  Object* entry = hashtable->Lookup(key);
4623  return entry;
4624 }
4625 
4626 
4628  Handle<Name> key,
4629  Handle<Object> value) {
4630  Isolate* isolate = object->GetIsolate();
4631 
4632  DCHECK(key->IsUniqueName());
4633  if (object->IsJSGlobalProxy()) {
4634  // JSGlobalProxies store their hash internally.
4635  DCHECK(*key != *isolate->factory()->identity_hash_string());
4636  // For a proxy, use the prototype as target object.
4637  PrototypeIterator iter(isolate, object);
4638  // If the proxy is detached, return undefined.
4639  if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
4640  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4641  return SetHiddenProperty(
4643  value);
4644  }
4645  DCHECK(!object->IsJSGlobalProxy());
4646 
4647  Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
4648 
4649  // If there is no backing store yet, store the identity hash inline.
4650  if (value->IsSmi() &&
4651  *key == *isolate->factory()->identity_hash_string() &&
4652  (inline_value->IsUndefined() || inline_value->IsSmi())) {
4653  return JSObject::SetHiddenPropertiesHashTable(object, value);
4654  }
4655 
4656  Handle<ObjectHashTable> hashtable =
4657  GetOrCreateHiddenPropertiesHashtable(object);
4658 
4659  // If it was found, check if the key is already in the dictionary.
4660  Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
4661  value);
4662  if (*new_table != *hashtable) {
4663  // If adding the key expanded the dictionary (i.e., Add returned a new
4664  // dictionary), store it back to the object.
4665  SetHiddenPropertiesHashTable(object, new_table);
4666  }
4667 
4668  // Return this to mark success.
4669  return object;
4670 }
4671 
4672 
4674  Isolate* isolate = object->GetIsolate();
4675  DCHECK(key->IsUniqueName());
4676 
4677  if (object->IsJSGlobalProxy()) {
4678  PrototypeIterator iter(isolate, object);
4679  if (iter.IsAtEnd()) return;
4680  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4681  return DeleteHiddenProperty(
4683  }
4684 
4685  Object* inline_value = object->GetHiddenPropertiesHashTable();
4686 
4687  // We never delete (inline-stored) identity hashes.
4688  DCHECK(*key != *isolate->factory()->identity_hash_string());
4689  if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
4690 
4691  Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
4692  bool was_present = false;
4693  ObjectHashTable::Remove(hashtable, key, &was_present);
4694 }
4695 
4696 
4698  Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
4699  LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR);
4700  Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
4701  // Cannot get an exception since the hidden_string isn't accessible to JS.
4702  DCHECK(maybe.has_value);
4703  return maybe.value != ABSENT;
4704 }
4705 
4706 
4708  DCHECK(!IsJSGlobalProxy());
4709  if (HasFastProperties()) {
4710  // If the object has fast properties, check whether the first slot
4711  // in the descriptor array matches the hidden string. Since the
4712  // hidden strings hash code is zero (and no other name has hash
4713  // code zero) it will always occupy the first entry if present.
4714  DescriptorArray* descriptors = this->map()->instance_descriptors();
4715  if (descriptors->number_of_descriptors() > 0) {
4716  int sorted_index = descriptors->GetSortedKeyIndex(0);
4717  if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
4718  sorted_index < map()->NumberOfOwnDescriptors()) {
4719  DCHECK(descriptors->GetType(sorted_index) == FIELD);
4720  DCHECK(descriptors->GetDetails(sorted_index).representation().
4721  IsCompatibleForLoad(Representation::Tagged()));
4722  FieldIndex index = FieldIndex::ForDescriptor(this->map(),
4723  sorted_index);
4724  return this->RawFastPropertyAt(index);
4725  } else {
4726  return GetHeap()->undefined_value();
4727  }
4728  } else {
4729  return GetHeap()->undefined_value();
4730  }
4731  } else {
4732  Isolate* isolate = GetIsolate();
4733  LookupIterator it(handle(this), isolate->factory()->hidden_string(),
4734  LookupIterator::OWN_SKIP_INTERCEPTOR);
4735  // Access check is always skipped for the hidden string anyways.
4736  return *GetDataProperty(&it);
4737  }
4738 }
4739 
4741  Handle<JSObject> object) {
4742  Isolate* isolate = object->GetIsolate();
4743 
4744  static const int kInitialCapacity = 4;
4745  Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
4746  if (inline_value->IsHashTable()) {
4747  return Handle<ObjectHashTable>::cast(inline_value);
4748  }
4749 
4751  isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
4752 
4753  if (inline_value->IsSmi()) {
4754  // We were storing the identity hash inline and now allocated an actual
4755  // dictionary. Put the identity hash into the new dictionary.
4756  hashtable = ObjectHashTable::Put(hashtable,
4757  isolate->factory()->identity_hash_string(),
4758  inline_value);
4759  }
4760 
4761  SetHiddenPropertiesHashTable(object, hashtable);
4762  return hashtable;
4763 }
4764 
4765 
4767  Handle<Object> value) {
4768  DCHECK(!object->IsJSGlobalProxy());
4769  Isolate* isolate = object->GetIsolate();
4770  Handle<Name> name = isolate->factory()->hidden_string();
4771  SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
4772  return object;
4773 }
4774 
4775 
4777  Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name) {
4778  Isolate* isolate = holder->GetIsolate();
4779 
4780  // TODO(rossberg): Support symbols in the API.
4781  if (name->IsSymbol()) return MaybeHandle<Object>();
4782 
4783  Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
4784  if (interceptor->deleter()->IsUndefined()) return MaybeHandle<Object>();
4785 
4787  v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter());
4788  LOG(isolate,
4789  ApiNamedPropertyAccess("interceptor-named-delete", *holder, *name));
4790  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
4791  *holder);
4792  v8::Handle<v8::Boolean> result =
4793  args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name)));
4795  if (result.IsEmpty()) return MaybeHandle<Object>();
4796 
4797  DCHECK(result->IsBoolean());
4798  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
4799  result_internal->VerifyApiCallResultType();
4800  // Rebox CustomArguments::kReturnValueOffset before returning.
4801  return handle(*result_internal, isolate);
4802 }
4803 
4804 
4806  Handle<JSObject> object,
4807  uint32_t index) {
4808  Isolate* isolate = object->GetIsolate();
4809  Factory* factory = isolate->factory();
4810 
4811  // Make sure that the top context does not change when doing
4812  // callbacks or interceptor calls.
4813  AssertNoContextChange ncc(isolate);
4814 
4815  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
4816  if (interceptor->deleter()->IsUndefined()) return factory->false_value();
4818  v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
4819  LOG(isolate,
4820  ApiIndexedPropertyAccess("interceptor-indexed-delete", *object, index));
4822  isolate, interceptor->data(), *object, *object);
4823  v8::Handle<v8::Boolean> result = args.Call(deleter, index);
4825  if (!result.IsEmpty()) {
4826  DCHECK(result->IsBoolean());
4827  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
4828  result_internal->VerifyApiCallResultType();
4829  // Rebox CustomArguments::kReturnValueOffset before returning.
4830  return handle(*result_internal, isolate);
4831  }
4832  MaybeHandle<Object> delete_result = object->GetElementsAccessor()->Delete(
4833  object, index, NORMAL_DELETION);
4834  return delete_result;
4835 }
4836 
4837 
4839  uint32_t index,
4840  DeleteMode mode) {
4841  Isolate* isolate = object->GetIsolate();
4842  Factory* factory = isolate->factory();
4843 
4844  // Check access rights if needed.
4845  if (object->IsAccessCheckNeeded() &&
4846  !isolate->MayIndexedAccess(object, index, v8::ACCESS_DELETE)) {
4847  isolate->ReportFailedAccessCheck(object, v8::ACCESS_DELETE);
4849  return factory->false_value();
4850  }
4851 
4852  if (object->IsStringObjectWithCharacterAt(index)) {
4853  if (mode == STRICT_DELETION) {
4854  // Deleting a non-configurable property in strict mode.
4855  Handle<Object> name = factory->NewNumberFromUint(index);
4856  Handle<Object> args[2] = { name, object };
4857  THROW_NEW_ERROR(isolate, NewTypeError("strict_delete_property",
4858  HandleVector(args, 2)),
4859  Object);
4860  }
4861  return factory->false_value();
4862  }
4863 
4864  if (object->IsJSGlobalProxy()) {
4865  PrototypeIterator iter(isolate, object);
4866  if (iter.IsAtEnd()) return factory->false_value();
4867  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4868  return DeleteElement(
4870  mode);
4871  }
4872 
4873  Handle<Object> old_value;
4874  bool should_enqueue_change_record = false;
4875  if (object->map()->is_observed()) {
4876  Maybe<bool> maybe = HasOwnElement(object, index);
4877  if (!maybe.has_value) return MaybeHandle<Object>();
4878  should_enqueue_change_record = maybe.value;
4879  if (should_enqueue_change_record) {
4880  if (!GetOwnElementAccessorPair(object, index).is_null()) {
4881  old_value = Handle<Object>::cast(factory->the_hole_value());
4882  } else {
4883  old_value = Object::GetElement(
4884  isolate, object, index).ToHandleChecked();
4885  }
4886  }
4887  }
4888 
4889  // Skip interceptor if forcing deletion.
4890  MaybeHandle<Object> maybe_result;
4891  if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) {
4892  maybe_result = DeleteElementWithInterceptor(object, index);
4893  } else {
4894  maybe_result = object->GetElementsAccessor()->Delete(object, index, mode);
4895  }
4896  Handle<Object> result;
4897  ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
4898 
4899  if (should_enqueue_change_record) {
4900  Maybe<bool> maybe = HasOwnElement(object, index);
4901  if (!maybe.has_value) return MaybeHandle<Object>();
4902  if (!maybe.value) {
4903  Handle<String> name = factory->Uint32ToString(index);
4904  EnqueueChangeRecord(object, "delete", name, old_value);
4905  }
4906  }
4907 
4908  return result;
4909 }
4910 
4911 
4914  DeleteMode delete_mode) {
4915  // ECMA-262, 3rd, 8.6.2.5
4916  DCHECK(name->IsName());
4917 
4918  uint32_t index = 0;
4919  if (name->AsArrayIndex(&index)) {
4920  return DeleteElement(object, index, delete_mode);
4921  }
4922 
4923  // Skip interceptors on FORCE_DELETION.
4924  LookupIterator::Configuration config =
4925  delete_mode == FORCE_DELETION ? LookupIterator::HIDDEN_SKIP_INTERCEPTOR
4926  : LookupIterator::HIDDEN;
4927 
4928  LookupIterator it(object, name, config);
4929 
4930  bool is_observed = object->map()->is_observed() &&
4931  *name != it.isolate()->heap()->hidden_string();
4932  Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
4933 
4934  for (; it.IsFound(); it.Next()) {
4935  switch (it.state()) {
4936  case LookupIterator::JSPROXY:
4937  case LookupIterator::NOT_FOUND:
4938  case LookupIterator::TRANSITION:
4939  UNREACHABLE();
4940  case LookupIterator::ACCESS_CHECK:
4941  if (it.HasAccess(v8::ACCESS_DELETE)) break;
4942  it.isolate()->ReportFailedAccessCheck(it.GetHolder<JSObject>(),
4945  return it.isolate()->factory()->false_value();
4946  case LookupIterator::INTERCEPTOR: {
4947  MaybeHandle<Object> maybe_result =
4949  object, it.name());
4950  // Delete with interceptor succeeded. Return result.
4951  if (!maybe_result.is_null()) return maybe_result;
4952  // An exception was thrown in the interceptor. Propagate.
4953  if (it.isolate()->has_pending_exception()) return maybe_result;
4954  break;
4955  }
4956  case LookupIterator::DATA:
4957  if (is_observed) {
4958  old_value = it.GetDataValue();
4959  }
4960  // Fall through.
4961  case LookupIterator::ACCESSOR: {
4962  if (delete_mode != FORCE_DELETION && !it.IsConfigurable()) {
4963  // Fail if the property is not configurable.
4964  if (delete_mode == STRICT_DELETION) {
4965  Handle<Object> args[2] = {name, object};
4966  THROW_NEW_ERROR(it.isolate(),
4967  NewTypeError("strict_delete_property",
4968  HandleVector(args, arraysize(args))),
4969  Object);
4970  }
4971  return it.isolate()->factory()->false_value();
4972  }
4973 
4974  PropertyNormalizationMode mode = object->map()->is_prototype_map()
4977  Handle<JSObject> holder = it.GetHolder<JSObject>();
4978  // TODO(verwaest): Remove this temporary compatibility hack when blink
4979  // tests are updated.
4980  if (!holder.is_identical_to(object) &&
4981  !(object->IsJSGlobalProxy() && holder->IsJSGlobalObject())) {
4982  return it.isolate()->factory()->true_value();
4983  }
4984  NormalizeProperties(holder, mode, 0);
4985  Handle<Object> result =
4986  DeleteNormalizedProperty(holder, name, delete_mode);
4987  ReoptimizeIfPrototype(holder);
4988 
4989  if (is_observed) {
4990  EnqueueChangeRecord(object, "delete", name, old_value);
4991  }
4992 
4993  return result;
4994  }
4995  }
4996  }
4997 
4998  return it.isolate()->factory()->true_value();
4999 }
5000 
5001 
5003  uint32_t index,
5004  DeleteMode mode) {
5005  if (object->IsJSProxy()) {
5007  Handle<JSProxy>::cast(object), index, mode);
5008  }
5009  return JSObject::DeleteElement(Handle<JSObject>::cast(object), index, mode);
5010 }
5011 
5012 
5015  DeleteMode mode) {
5016  if (object->IsJSProxy()) {
5018  Handle<JSProxy>::cast(object), name, mode);
5019  }
5021 }
5022 
5023 
5025  ElementsKind kind,
5026  Object* object) {
5028  kind == DICTIONARY_ELEMENTS);
5029  if (IsFastObjectElementsKind(kind)) {
5030  int length = IsJSArray()
5031  ? Smi::cast(JSArray::cast(this)->length())->value()
5032  : elements->length();
5033  for (int i = 0; i < length; ++i) {
5034  Object* element = elements->get(i);
5035  if (!element->IsTheHole() && element == object) return true;
5036  }
5037  } else {
5038  Object* key =
5039  SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
5040  if (!key->IsUndefined()) return true;
5041  }
5042  return false;
5043 }
5044 
5045 
5046 // Check whether this object references another object.
5048  Map* map_of_this = map();
5049  Heap* heap = GetHeap();
5050  DisallowHeapAllocation no_allocation;
5051 
5052  // Is the object the constructor for this object?
5053  if (map_of_this->constructor() == obj) {
5054  return true;
5055  }
5056 
5057  // Is the object the prototype for this object?
5058  if (map_of_this->prototype() == obj) {
5059  return true;
5060  }
5061 
5062  // Check if the object is among the named properties.
5063  Object* key = SlowReverseLookup(obj);
5064  if (!key->IsUndefined()) {
5065  return true;
5066  }
5067 
5068  // Check if the object is among the indexed properties.
5069  ElementsKind kind = GetElementsKind();
5070  switch (kind) {
5071  // Raw pixels and external arrays do not reference other
5072  // objects.
5073 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
5074  case EXTERNAL_##TYPE##_ELEMENTS: \
5075  case TYPE##_ELEMENTS: \
5076  break;
5077 
5079 #undef TYPED_ARRAY_CASE
5080 
5081  case FAST_DOUBLE_ELEMENTS:
5083  break;
5084  case FAST_SMI_ELEMENTS:
5086  break;
5087  case FAST_ELEMENTS:
5088  case FAST_HOLEY_ELEMENTS:
5089  case DICTIONARY_ELEMENTS: {
5090  FixedArray* elements = FixedArray::cast(this->elements());
5091  if (ReferencesObjectFromElements(elements, kind, obj)) return true;
5092  break;
5093  }
5095  FixedArray* parameter_map = FixedArray::cast(elements());
5096  // Check the mapped parameters.
5097  int length = parameter_map->length();
5098  for (int i = 2; i < length; ++i) {
5099  Object* value = parameter_map->get(i);
5100  if (!value->IsTheHole() && value == obj) return true;
5101  }
5102  // Check the arguments.
5103  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5104  kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
5106  if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
5107  break;
5108  }
5109  }
5110 
5111  // For functions check the context.
5112  if (IsJSFunction()) {
5113  // Get the constructor function for arguments array.
5114  Map* arguments_map =
5115  heap->isolate()->context()->native_context()->sloppy_arguments_map();
5116  JSFunction* arguments_function =
5117  JSFunction::cast(arguments_map->constructor());
5118 
5119  // Get the context and don't check if it is the native context.
5120  JSFunction* f = JSFunction::cast(this);
5121  Context* context = f->context();
5122  if (context->IsNativeContext()) {
5123  return false;
5124  }
5125 
5126  // Check the non-special context slots.
5127  for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
5128  // Only check JS objects.
5129  if (context->get(i)->IsJSObject()) {
5130  JSObject* ctxobj = JSObject::cast(context->get(i));
5131  // If it is an arguments array check the content.
5132  if (ctxobj->map()->constructor() == arguments_function) {
5133  if (ctxobj->ReferencesObject(obj)) {
5134  return true;
5135  }
5136  } else if (ctxobj == obj) {
5137  return true;
5138  }
5139  }
5140  }
5141 
5142  // Check the context extension (if any) if it can have references.
5143  if (context->has_extension() && !context->IsCatchContext()) {
5144  // With harmony scoping, a JSFunction may have a global context.
5145  // TODO(mvstanton): walk into the ScopeInfo.
5146  if (FLAG_harmony_scoping && context->IsGlobalContext()) {
5147  return false;
5148  }
5149 
5150  return JSObject::cast(context->extension())->ReferencesObject(obj);
5151  }
5152  }
5153 
5154  // No references to object.
5155  return false;
5156 }
5157 
5158 
5160  Isolate* isolate = object->GetIsolate();
5161 
5162  if (!object->map()->is_extensible()) return object;
5163 
5164  if (object->IsAccessCheckNeeded() &&
5165  !isolate->MayNamedAccess(
5166  object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5167  isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5169  return isolate->factory()->false_value();
5170  }
5171 
5172  if (object->IsJSGlobalProxy()) {
5173  PrototypeIterator iter(isolate, object);
5174  if (iter.IsAtEnd()) return object;
5175  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5176  return PreventExtensions(
5178  }
5179 
5180  // It's not possible to seal objects with external array elements
5181  if (object->HasExternalArrayElements() ||
5182  object->HasFixedTypedArrayElements()) {
5183  THROW_NEW_ERROR(isolate,
5184  NewTypeError("cant_prevent_ext_external_array_elements",
5185  HandleVector(&object, 1)),
5186  Object);
5187  }
5188 
5189  // If there are fast elements we normalize.
5190  Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
5191  DCHECK(object->HasDictionaryElements() ||
5192  object->HasDictionaryArgumentsElements());
5193 
5194  // Make sure that we never go back to fast case.
5195  dictionary->set_requires_slow_elements();
5196 
5197  // Do a map transition, other objects with this map may still
5198  // be extensible.
5199  // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5200  Handle<Map> new_map = Map::Copy(handle(object->map()));
5201 
5202  new_map->set_is_extensible(false);
5203  JSObject::MigrateToMap(object, new_map);
5204  DCHECK(!object->map()->is_extensible());
5205 
5206  if (object->map()->is_observed()) {
5207  EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5208  isolate->factory()->the_hole_value());
5209  }
5210  return object;
5211 }
5212 
5213 
5214 template<typename Dictionary>
5215 static void FreezeDictionary(Dictionary* dictionary) {
5216  int capacity = dictionary->Capacity();
5217  for (int i = 0; i < capacity; i++) {
5218  Object* k = dictionary->KeyAt(i);
5219  if (dictionary->IsKey(k) &&
5220  !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
5221  PropertyDetails details = dictionary->DetailsAt(i);
5222  int attrs = DONT_DELETE;
5223  // READ_ONLY is an invalid attribute for JS setters/getters.
5224  if (details.type() == CALLBACKS) {
5225  Object* v = dictionary->ValueAt(i);
5226  if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
5227  if (!v->IsAccessorPair()) attrs |= READ_ONLY;
5228  } else {
5229  attrs |= READ_ONLY;
5230  }
5231  details = details.CopyAddAttributes(
5232  static_cast<PropertyAttributes>(attrs));
5233  dictionary->DetailsAtPut(i, details);
5234  }
5235  }
5236 }
5237 
5238 
5240  // Freezing sloppy arguments should be handled elsewhere.
5241  DCHECK(!object->HasSloppyArgumentsElements());
5242  DCHECK(!object->map()->is_observed());
5243 
5244  if (object->map()->is_frozen()) return object;
5245 
5246  Isolate* isolate = object->GetIsolate();
5247  if (object->IsAccessCheckNeeded() &&
5248  !isolate->MayNamedAccess(
5249  object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5250  isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5252  return isolate->factory()->false_value();
5253  }
5254 
5255  if (object->IsJSGlobalProxy()) {
5256  PrototypeIterator iter(isolate, object);
5257  if (iter.IsAtEnd()) return object;
5258  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
5260  }
5261 
5262  // It's not possible to freeze objects with external array elements
5263  if (object->HasExternalArrayElements() ||
5264  object->HasFixedTypedArrayElements()) {
5265  THROW_NEW_ERROR(isolate,
5266  NewTypeError("cant_prevent_ext_external_array_elements",
5267  HandleVector(&object, 1)),
5268  Object);
5269  }
5270 
5271  Handle<SeededNumberDictionary> new_element_dictionary;
5272  if (!object->elements()->IsDictionary()) {
5273  int length = object->IsJSArray()
5274  ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
5275  : object->elements()->length();
5276  if (length > 0) {
5277  int capacity = 0;
5278  int used = 0;
5279  object->GetElementsCapacityAndUsage(&capacity, &used);
5280  new_element_dictionary = SeededNumberDictionary::New(isolate, used);
5281 
5282  // Move elements to a dictionary; avoid calling NormalizeElements to avoid
5283  // unnecessary transitions.
5284  new_element_dictionary = CopyFastElementsToDictionary(
5285  handle(object->elements()), length, new_element_dictionary);
5286  } else {
5287  // No existing elements, use a pre-allocated empty backing store
5288  new_element_dictionary =
5289  isolate->factory()->empty_slow_element_dictionary();
5290  }
5291  }
5292 
5293  Handle<Map> old_map(object->map(), isolate);
5294  int transition_index = old_map->SearchTransition(
5295  isolate->heap()->frozen_symbol());
5296  if (transition_index != TransitionArray::kNotFound) {
5297  Handle<Map> transition_map(old_map->GetTransition(transition_index));
5298  DCHECK(transition_map->has_dictionary_elements());
5299  DCHECK(transition_map->is_frozen());
5300  DCHECK(!transition_map->is_extensible());
5301  JSObject::MigrateToMap(object, transition_map);
5302  } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5303  // Create a new descriptor array with fully-frozen properties
5304  Handle<Map> new_map = Map::CopyForFreeze(old_map);
5305  JSObject::MigrateToMap(object, new_map);
5306  } else {
5307  DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5308  // Slow path: need to normalize properties for safety
5309  NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5310 
5311  // Create a new map, since other objects with this map may be extensible.
5312  // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5313  Handle<Map> new_map = Map::Copy(handle(object->map()));
5314  new_map->freeze();
5315  new_map->set_is_extensible(false);
5316  new_map->set_elements_kind(DICTIONARY_ELEMENTS);
5317  JSObject::MigrateToMap(object, new_map);
5318 
5319  // Freeze dictionary-mode properties
5320  FreezeDictionary(object->property_dictionary());
5321  }
5322 
5323  DCHECK(object->map()->has_dictionary_elements());
5324  if (!new_element_dictionary.is_null()) {
5325  object->set_elements(*new_element_dictionary);
5326  }
5327 
5328  if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
5329  SeededNumberDictionary* dictionary = object->element_dictionary();
5330  // Make sure we never go back to the fast case
5331  dictionary->set_requires_slow_elements();
5332  // Freeze all elements in the dictionary
5333  FreezeDictionary(dictionary);
5334  }
5335 
5336  return object;
5337 }
5338 
5339 
5341  DCHECK(!object->IsJSGlobalProxy());
5342  DCHECK(!object->IsJSGlobalObject());
5343  Isolate* isolate = object->GetIsolate();
5344  Handle<Map> new_map;
5345  Handle<Map> old_map(object->map(), isolate);
5346  DCHECK(!old_map->is_observed());
5347  int transition_index = old_map->SearchTransition(
5348  isolate->heap()->observed_symbol());
5349  if (transition_index != TransitionArray::kNotFound) {
5350  new_map = handle(old_map->GetTransition(transition_index), isolate);
5351  DCHECK(new_map->is_observed());
5352  } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5353  new_map = Map::CopyForObserved(old_map);
5354  } else {
5355  new_map = Map::Copy(old_map);
5356  new_map->set_is_observed();
5357  }
5358  JSObject::MigrateToMap(object, new_map);
5359 }
5360 
5361 
5363  Representation representation,
5364  FieldIndex index) {
5365  Isolate* isolate = object->GetIsolate();
5366  Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
5367  return Object::WrapForRead(isolate, raw_value, representation);
5368 }
5369 
5370 
5371 template<class ContextObject>
5373  public:
5374  JSObjectWalkVisitor(ContextObject* site_context, bool copying,
5376  : site_context_(site_context),
5377  copying_(copying),
5378  hints_(hints) {}
5379 
5381 
5382  protected:
5384  Handle<JSObject> object,
5385  Handle<JSObject> value) {
5386  Handle<AllocationSite> current_site = site_context()->EnterNewScope();
5387  MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
5388  site_context()->ExitScope(current_site, value);
5389  return copy_of_value;
5390  }
5391 
5392  inline ContextObject* site_context() { return site_context_; }
5393  inline Isolate* isolate() { return site_context()->isolate(); }
5394 
5395  inline bool copying() const { return copying_; }
5396 
5397  private:
5398  ContextObject* site_context_;
5399  const bool copying_;
5401 };
5402 
5403 
5404 template <class ContextObject>
5406  Handle<JSObject> object) {
5407  Isolate* isolate = this->isolate();
5408  bool copying = this->copying();
5409  bool shallow = hints_ == JSObject::kObjectIsShallow;
5410 
5411  if (!shallow) {
5412  StackLimitCheck check(isolate);
5413 
5414  if (check.HasOverflowed()) {
5415  isolate->StackOverflow();
5416  return MaybeHandle<JSObject>();
5417  }
5418  }
5419 
5420  if (object->map()->is_deprecated()) {
5421  JSObject::MigrateInstance(object);
5422  }
5423 
5424  Handle<JSObject> copy;
5425  if (copying) {
5426  Handle<AllocationSite> site_to_pass;
5427  if (site_context()->ShouldCreateMemento(object)) {
5428  site_to_pass = site_context()->current();
5429  }
5430  copy = isolate->factory()->CopyJSObjectWithAllocationSite(
5431  object, site_to_pass);
5432  } else {
5433  copy = object;
5434  }
5435 
5436  DCHECK(copying || copy.is_identical_to(object));
5437 
5438  ElementsKind kind = copy->GetElementsKind();
5439  if (copying && IsFastSmiOrObjectElementsKind(kind) &&
5440  FixedArray::cast(copy->elements())->map() ==
5441  isolate->heap()->fixed_cow_array_map()) {
5442  isolate->counters()->cow_arrays_created_runtime()->Increment();
5443  }
5444 
5445  if (!shallow) {
5446  HandleScope scope(isolate);
5447 
5448  // Deep copy own properties.
5449  if (copy->HasFastProperties()) {
5450  Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
5451  int limit = copy->map()->NumberOfOwnDescriptors();
5452  for (int i = 0; i < limit; i++) {
5453  PropertyDetails details = descriptors->GetDetails(i);
5454  if (details.type() != FIELD) continue;
5455  FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
5456  Handle<Object> value(object->RawFastPropertyAt(index), isolate);
5457  if (value->IsJSObject()) {
5459  isolate, value,
5460  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5461  JSObject);
5462  } else {
5463  Representation representation = details.representation();
5464  value = Object::NewStorageFor(isolate, value, representation);
5465  }
5466  if (copying) {
5467  copy->FastPropertyAtPut(index, *value);
5468  }
5469  }
5470  } else {
5471  Handle<FixedArray> names =
5472  isolate->factory()->NewFixedArray(copy->NumberOfOwnProperties());
5473  copy->GetOwnPropertyNames(*names, 0);
5474  for (int i = 0; i < names->length(); i++) {
5475  DCHECK(names->get(i)->IsString());
5476  Handle<String> key_string(String::cast(names->get(i)));
5478  JSReceiver::GetOwnPropertyAttributes(copy, key_string);
5479  DCHECK(maybe.has_value);
5480  PropertyAttributes attributes = maybe.value;
5481  // Only deep copy fields from the object literal expression.
5482  // In particular, don't try to copy the length attribute of
5483  // an array.
5484  if (attributes != NONE) continue;
5485  Handle<Object> value =
5486  Object::GetProperty(copy, key_string).ToHandleChecked();
5487  if (value->IsJSObject()) {
5488  Handle<JSObject> result;
5490  isolate, result,
5491  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5492  JSObject);
5493  if (copying) {
5494  // Creating object copy for literals. No strict mode needed.
5495  JSObject::SetProperty(copy, key_string, result, SLOPPY).Assert();
5496  }
5497  }
5498  }
5499  }
5500 
5501  // Deep copy own elements.
5502  // Pixel elements cannot be created using an object literal.
5503  DCHECK(!copy->HasExternalArrayElements());
5504  switch (kind) {
5505  case FAST_SMI_ELEMENTS:
5506  case FAST_ELEMENTS:
5508  case FAST_HOLEY_ELEMENTS: {
5509  Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5510  if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5511 #ifdef DEBUG
5512  for (int i = 0; i < elements->length(); i++) {
5513  DCHECK(!elements->get(i)->IsJSObject());
5514  }
5515 #endif
5516  } else {
5517  for (int i = 0; i < elements->length(); i++) {
5518  Handle<Object> value(elements->get(i), isolate);
5519  DCHECK(value->IsSmi() ||
5520  value->IsTheHole() ||
5521  (IsFastObjectElementsKind(copy->GetElementsKind())));
5522  if (value->IsJSObject()) {
5523  Handle<JSObject> result;
5525  isolate, result,
5526  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5527  JSObject);
5528  if (copying) {
5529  elements->set(i, *result);
5530  }
5531  }
5532  }
5533  }
5534  break;
5535  }
5536  case DICTIONARY_ELEMENTS: {
5537  Handle<SeededNumberDictionary> element_dictionary(
5538  copy->element_dictionary());
5539  int capacity = element_dictionary->Capacity();
5540  for (int i = 0; i < capacity; i++) {
5541  Object* k = element_dictionary->KeyAt(i);
5542  if (element_dictionary->IsKey(k)) {
5543  Handle<Object> value(element_dictionary->ValueAt(i), isolate);
5544  if (value->IsJSObject()) {
5545  Handle<JSObject> result;
5547  isolate, result,
5548  VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
5549  JSObject);
5550  if (copying) {
5551  element_dictionary->ValueAtPut(i, *result);
5552  }
5553  }
5554  }
5555  }
5556  break;
5557  }
5559  UNIMPLEMENTED();
5560  break;
5561 
5562 
5563 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
5564  case EXTERNAL_##TYPE##_ELEMENTS: \
5565  case TYPE##_ELEMENTS: \
5566 
5568 #undef TYPED_ARRAY_CASE
5569 
5570  case FAST_DOUBLE_ELEMENTS:
5572  // No contained objects, nothing to do.
5573  break;
5574  }
5575  }
5576 
5577  return copy;
5578 }
5579 
5580 
5582  Handle<JSObject> object,
5583  AllocationSiteCreationContext* site_context) {
5585  kNoHints);
5586  MaybeHandle<JSObject> result = v.StructureWalk(object);
5587  Handle<JSObject> for_assert;
5588  DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
5589  return result;
5590 }
5591 
5592 
5594  Handle<JSObject> object,
5595  AllocationSiteUsageContext* site_context,
5596  DeepCopyHints hints) {
5597  JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
5598  MaybeHandle<JSObject> copy = v.StructureWalk(object);
5599  Handle<JSObject> for_assert;
5600  DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
5601  return copy;
5602 }
5603 
5604 
5605 // Tests for the fast common case for property enumeration:
5606 // - This object and all prototypes has an enum cache (which means that
5607 // it is no proxy, has no interceptors and needs no access checks).
5608 // - This object has no elements.
5609 // - No prototype has enumerable properties/elements.
5611  for (PrototypeIterator iter(GetIsolate(), this,
5613  !iter.IsAtEnd(); iter.Advance()) {
5614  if (!iter.GetCurrent()->IsJSObject()) return false;
5615  JSObject* curr = JSObject::cast(iter.GetCurrent());
5616  int enum_length = curr->map()->EnumLength();
5617  if (enum_length == kInvalidEnumCacheSentinel) return false;
5618  if (curr->IsAccessCheckNeeded()) return false;
5619  DCHECK(!curr->HasNamedInterceptor());
5620  DCHECK(!curr->HasIndexedInterceptor());
5621  if (curr->NumberOfEnumElements() > 0) return false;
5622  if (curr != this && enum_length != 0) return false;
5623  }
5624  return true;
5625 }
5626 
5627 
5628 static bool FilterKey(Object* key, PropertyAttributes filter) {
5629  if ((filter & SYMBOLIC) && key->IsSymbol()) {
5630  return true;
5631  }
5632 
5633  if ((filter & PRIVATE_SYMBOL) &&
5634  key->IsSymbol() && Symbol::cast(key)->is_private()) {
5635  return true;
5636  }
5637 
5638  if ((filter & STRING) && !key->IsSymbol()) {
5639  return true;
5640  }
5641 
5642  return false;
5643 }
5644 
5645 
5647  PropertyAttributes filter) {
5648  int result = 0;
5649  DescriptorArray* descs = instance_descriptors();
5650  int limit = which == ALL_DESCRIPTORS
5651  ? descs->number_of_descriptors()
5652  : NumberOfOwnDescriptors();
5653  for (int i = 0; i < limit; i++) {
5654  if ((descs->GetDetails(i).attributes() & filter) == 0 &&
5655  !FilterKey(descs->GetKey(i), filter)) {
5656  result++;
5657  }
5658  }
5659  return result;
5660 }
5661 
5662 
5664  int max_index = -1;
5665  int number_of_own_descriptors = NumberOfOwnDescriptors();
5666  DescriptorArray* descs = instance_descriptors();
5667  for (int i = 0; i < number_of_own_descriptors; i++) {
5668  if (descs->GetType(i) == FIELD) {
5669  int current_index = descs->GetFieldIndex(i);
5670  if (current_index > max_index) max_index = current_index;
5671  }
5672  }
5673  return max_index + 1;
5674 }
5675 
5676 
5678  int len = array->length();
5679  for (int i = 0; i < len; i++) {
5680  Object* e = array->get(i);
5681  if (!(e->IsString() || e->IsNumber())) return false;
5682  }
5683  return true;
5684 }
5685 
5686 
5688  Handle<FixedArray> array, int length) {
5689  DCHECK(array->length() >= length);
5690  if (array->length() == length) return array;
5691 
5692  Handle<FixedArray> new_array =
5693  array->GetIsolate()->factory()->NewFixedArray(length);
5694  for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
5695  return new_array;
5696 }
5697 
5698 
5700  bool cache_result) {
5701  Isolate* isolate = object->GetIsolate();
5702  if (object->HasFastProperties()) {
5703  int own_property_count = object->map()->EnumLength();
5704  // If the enum length of the given map is set to kInvalidEnumCache, this
5705  // means that the map itself has never used the present enum cache. The
5706  // first step to using the cache is to set the enum length of the map by
5707  // counting the number of own descriptors that are not DONT_ENUM or
5708  // SYMBOLIC.
5709  if (own_property_count == kInvalidEnumCacheSentinel) {
5710  own_property_count = object->map()->NumberOfDescribedProperties(
5712  } else {
5713  DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
5715  }
5716 
5717  if (object->map()->instance_descriptors()->HasEnumCache()) {
5718  DescriptorArray* desc = object->map()->instance_descriptors();
5719  Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
5720 
5721  // In case the number of properties required in the enum are actually
5722  // present, we can reuse the enum cache. Otherwise, this means that the
5723  // enum cache was generated for a previous (smaller) version of the
5724  // Descriptor Array. In that case we regenerate the enum cache.
5725  if (own_property_count <= keys->length()) {
5726  if (cache_result) object->map()->SetEnumLength(own_property_count);
5727  isolate->counters()->enum_cache_hits()->Increment();
5728  return ReduceFixedArrayTo(keys, own_property_count);
5729  }
5730  }
5731 
5732  Handle<Map> map(object->map());
5733 
5734  if (map->instance_descriptors()->IsEmpty()) {
5735  isolate->counters()->enum_cache_hits()->Increment();
5736  if (cache_result) map->SetEnumLength(0);
5737  return isolate->factory()->empty_fixed_array();
5738  }
5739 
5740  isolate->counters()->enum_cache_misses()->Increment();
5741 
5742  Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
5743  own_property_count);
5744  Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
5745  own_property_count);
5746 
5747  Handle<DescriptorArray> descs =
5748  Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
5749 
5750  int size = map->NumberOfOwnDescriptors();
5751  int index = 0;
5752 
5753  for (int i = 0; i < size; i++) {
5754  PropertyDetails details = descs->GetDetails(i);
5755  Object* key = descs->GetKey(i);
5756  if (!(details.IsDontEnum() || key->IsSymbol())) {
5757  storage->set(index, key);
5758  if (!indices.is_null()) {
5759  if (details.type() != FIELD) {
5760  indices = Handle<FixedArray>();
5761  } else {
5762  FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
5763  int load_by_field_index = field_index.GetLoadByFieldIndex();
5764  indices->set(index, Smi::FromInt(load_by_field_index));
5765  }
5766  }
5767  index++;
5768  }
5769  }
5770  DCHECK(index == storage->length());
5771 
5772  Handle<FixedArray> bridge_storage =
5773  isolate->factory()->NewFixedArray(
5775  DescriptorArray* desc = object->map()->instance_descriptors();
5776  desc->SetEnumCache(*bridge_storage,
5777  *storage,
5778  indices.is_null() ? Object::cast(Smi::FromInt(0))
5779  : Object::cast(*indices));
5780  if (cache_result) {
5781  object->map()->SetEnumLength(own_property_count);
5782  }
5783  return storage;
5784  } else {
5785  Handle<NameDictionary> dictionary(object->property_dictionary());
5786  int length = dictionary->NumberOfEnumElements();
5787  if (length == 0) {
5788  return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
5789  }
5790  Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
5791  dictionary->CopyEnumKeysTo(*storage);
5792  return storage;
5793  }
5794 }
5795 
5796 
5798  KeyCollectionType type) {
5800  Isolate* isolate = object->GetIsolate();
5801  Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
5802  Handle<JSFunction> arguments_function(
5803  JSFunction::cast(isolate->sloppy_arguments_map()->constructor()));
5804 
5805  // Only collect keys if access is permitted.
5806  for (PrototypeIterator iter(isolate, object,
5808  !iter.IsAtEnd(); iter.Advance()) {
5809  if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
5810  Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
5811  isolate);
5812  Handle<Object> args[] = { proxy };
5813  Handle<Object> names;
5815  isolate, names,
5816  Execution::Call(isolate,
5817  isolate->proxy_enumerate(),
5818  object,
5819  arraysize(args),
5820  args),
5821  FixedArray);
5823  isolate, content,
5825  content, Handle<JSObject>::cast(names)),
5826  FixedArray);
5827  break;
5828  }
5829 
5830  Handle<JSObject> current =
5832 
5833  // Check access rights if required.
5834  if (current->IsAccessCheckNeeded() &&
5835  !isolate->MayNamedAccess(
5836  current, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5837  isolate->ReportFailedAccessCheck(current, v8::ACCESS_KEYS);
5839  break;
5840  }
5841 
5842  // Compute the element keys.
5843  Handle<FixedArray> element_keys =
5844  isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
5845  current->GetEnumElementKeys(*element_keys);
5847  isolate, content,
5848  FixedArray::UnionOfKeys(content, element_keys),
5849  FixedArray);
5850  DCHECK(ContainsOnlyValidKeys(content));
5851 
5852  // Add the element keys from the interceptor.
5853  if (current->HasIndexedInterceptor()) {
5854  Handle<JSObject> result;
5856  current, object).ToHandle(&result)) {
5858  isolate, content,
5859  FixedArray::AddKeysFromArrayLike(content, result),
5860  FixedArray);
5861  }
5862  DCHECK(ContainsOnlyValidKeys(content));
5863  }
5864 
5865  // We can cache the computed property keys if access checks are
5866  // not needed and no interceptors are involved.
5867  //
5868  // We do not use the cache if the object has elements and
5869  // therefore it does not make sense to cache the property names
5870  // for arguments objects. Arguments objects will always have
5871  // elements.
5872  // Wrapped strings have elements, but don't have an elements
5873  // array or dictionary. So the fast inline test for whether to
5874  // use the cache says yes, so we should not create a cache.
5875  bool cache_enum_keys =
5876  ((current->map()->constructor() != *arguments_function) &&
5877  !current->IsJSValue() &&
5878  !current->IsAccessCheckNeeded() &&
5879  !current->HasNamedInterceptor() &&
5880  !current->HasIndexedInterceptor());
5881  // Compute the property keys and cache them if possible.
5883  isolate, content,
5885  content, GetEnumPropertyKeys(current, cache_enum_keys)),
5886  FixedArray);
5887  DCHECK(ContainsOnlyValidKeys(content));
5888 
5889  // Add the property keys from the interceptor.
5890  if (current->HasNamedInterceptor()) {
5891  Handle<JSObject> result;
5893  current, object).ToHandle(&result)) {
5895  isolate, content,
5896  FixedArray::AddKeysFromArrayLike(content, result),
5897  FixedArray);
5898  }
5899  DCHECK(ContainsOnlyValidKeys(content));
5900  }
5901 
5902  // If we only want own properties we bail out after the first
5903  // iteration.
5904  if (type == OWN_ONLY) break;
5905  }
5906  return content;
5907 }
5908 
5909 
5910 // Try to update an accessor in an elements dictionary. Return true if the
5911 // update succeeded, and false otherwise.
5913  SeededNumberDictionary* dictionary,
5914  uint32_t index,
5915  Object* getter,
5916  Object* setter,
5917  PropertyAttributes attributes) {
5918  int entry = dictionary->FindEntry(index);
5919  if (entry != SeededNumberDictionary::kNotFound) {
5920  Object* result = dictionary->ValueAt(entry);
5921  PropertyDetails details = dictionary->DetailsAt(entry);
5922  if (details.type() == CALLBACKS && result->IsAccessorPair()) {
5923  DCHECK(details.IsConfigurable());
5924  if (details.attributes() != attributes) {
5925  dictionary->DetailsAtPut(
5926  entry,
5927  PropertyDetails(attributes, CALLBACKS, index));
5928  }
5929  AccessorPair::cast(result)->SetComponents(getter, setter);
5930  return true;
5931  }
5932  }
5933  return false;
5934 }
5935 
5936 
5938  uint32_t index,
5939  Handle<Object> getter,
5940  Handle<Object> setter,
5941  PropertyAttributes attributes) {
5942  switch (object->GetElementsKind()) {
5943  case FAST_SMI_ELEMENTS:
5944  case FAST_ELEMENTS:
5945  case FAST_DOUBLE_ELEMENTS:
5947  case FAST_HOLEY_ELEMENTS:
5949  break;
5950 
5951 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
5952  case EXTERNAL_##TYPE##_ELEMENTS: \
5953  case TYPE##_ELEMENTS: \
5954 
5956 #undef TYPED_ARRAY_CASE
5957  // Ignore getters and setters on pixel and external array elements.
5958  return;
5959 
5960  case DICTIONARY_ELEMENTS:
5961  if (UpdateGetterSetterInDictionary(object->element_dictionary(),
5962  index,
5963  *getter,
5964  *setter,
5965  attributes)) {
5966  return;
5967  }
5968  break;
5970  // Ascertain whether we have read-only properties or an existing
5971  // getter/setter pair in an arguments elements dictionary backing
5972  // store.
5973  FixedArray* parameter_map = FixedArray::cast(object->elements());
5974  uint32_t length = parameter_map->length();
5975  Object* probe =
5976  index < (length - 2) ? parameter_map->get(index + 2) : NULL;
5977  if (probe == NULL || probe->IsTheHole()) {
5978  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
5979  if (arguments->IsDictionary()) {
5980  SeededNumberDictionary* dictionary =
5981  SeededNumberDictionary::cast(arguments);
5982  if (UpdateGetterSetterInDictionary(dictionary,
5983  index,
5984  *getter,
5985  *setter,
5986  attributes)) {
5987  return;
5988  }
5989  }
5990  }
5991  break;
5992  }
5993  }
5994 
5995  Isolate* isolate = object->GetIsolate();
5996  Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair();
5997  accessors->SetComponents(*getter, *setter);
5998 
5999  SetElementCallback(object, index, accessors, attributes);
6000 }
6001 
6002 
6004  if (IsDictionaryElementsKind(elements_kind())) {
6005  return false;
6006  }
6007 
6008  for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
6009  if (iter.GetCurrent()->IsJSProxy()) {
6010  // Be conservative, don't walk into proxies.
6011  return true;
6012  }
6013 
6015  JSObject::cast(iter.GetCurrent())->map()->elements_kind())) {
6016  return true;
6017  }
6018  }
6019 
6020  return false;
6021 }
6022 
6023 
6025  uint32_t index,
6026  Handle<Object> structure,
6027  PropertyAttributes attributes) {
6028  Heap* heap = object->GetHeap();
6029  PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6030 
6031  // Normalize elements to make this operation simple.
6032  bool had_dictionary_elements = object->HasDictionaryElements();
6033  Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
6034  DCHECK(object->HasDictionaryElements() ||
6035  object->HasDictionaryArgumentsElements());
6036  // Update the dictionary with the new CALLBACKS property.
6037  dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
6038  details);
6039  dictionary->set_requires_slow_elements();
6040 
6041  // Update the dictionary backing store on the object.
6042  if (object->elements()->map() == heap->sloppy_arguments_elements_map()) {
6043  // Also delete any parameter alias.
6044  //
6045  // TODO(kmillikin): when deleting the last parameter alias we could
6046  // switch to a direct backing store without the parameter map. This
6047  // would allow GC of the context.
6048  FixedArray* parameter_map = FixedArray::cast(object->elements());
6049  if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
6050  parameter_map->set(index + 2, heap->the_hole_value());
6051  }
6052  parameter_map->set(1, *dictionary);
6053  } else {
6054  object->set_elements(*dictionary);
6055 
6056  if (!had_dictionary_elements) {
6057  // KeyedStoreICs (at least the non-generic ones) need a reset.
6058  heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
6059  }
6060  }
6061 }
6062 
6063 
6066  Handle<Object> structure,
6067  PropertyAttributes attributes) {
6068  PropertyNormalizationMode mode = object->map()->is_prototype_map()
6071  // Normalize object to make this operation simple.
6072  NormalizeProperties(object, mode, 0);
6073 
6074  // For the global object allocate a new map to invalidate the global inline
6075  // caches which have a global property cell reference directly in the code.
6076  if (object->IsGlobalObject()) {
6077  Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
6078  DCHECK(new_map->is_dictionary_map());
6079  JSObject::MigrateToMap(object, new_map);
6080 
6081  // When running crankshaft, changing the map is not enough. We
6082  // need to deoptimize all functions that rely on this global
6083  // object.
6085  }
6086 
6087  // Update the dictionary with the new CALLBACKS property.
6088  PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6089  SetNormalizedProperty(object, name, structure, details);
6090 
6091  ReoptimizeIfPrototype(object);
6092 }
6093 
6094 
6097  Handle<Object> getter,
6098  Handle<Object> setter,
6099  PropertyAttributes attributes) {
6100  Isolate* isolate = object->GetIsolate();
6101  // Check access rights if needed.
6102  if (object->IsAccessCheckNeeded() &&
6103  !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6104  isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6106  return isolate->factory()->undefined_value();
6107  }
6108 
6109  if (object->IsJSGlobalProxy()) {
6110  PrototypeIterator iter(isolate, object);
6111  if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
6112  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6114  name, getter, setter, attributes);
6115  return isolate->factory()->undefined_value();
6116  }
6117 
6118  // Make sure that the top context does not change when doing callbacks or
6119  // interceptor calls.
6120  AssertNoContextChange ncc(isolate);
6121 
6122  // Try to flatten before operating on the string.
6123  if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6124 
6125  uint32_t index = 0;
6126  bool is_element = name->AsArrayIndex(&index);
6127 
6128  Handle<Object> old_value = isolate->factory()->the_hole_value();
6129  bool is_observed = object->map()->is_observed() &&
6130  *name != isolate->heap()->hidden_string();
6131  bool preexists = false;
6132  if (is_observed) {
6133  if (is_element) {
6134  Maybe<bool> maybe = HasOwnElement(object, index);
6135  // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used
6136  // uninitialized in this function".
6137  if (!maybe.has_value) {
6138  DCHECK(false);
6139  return isolate->factory()->undefined_value();
6140  }
6141  preexists = maybe.value;
6142  if (preexists && GetOwnElementAccessorPair(object, index).is_null()) {
6143  old_value =
6144  Object::GetElement(isolate, object, index).ToHandleChecked();
6145  }
6146  } else {
6147  LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6148  CHECK(GetPropertyAttributes(&it).has_value);
6149  preexists = it.IsFound();
6150  if (preexists && (it.state() == LookupIterator::DATA ||
6151  it.GetAccessors()->IsAccessorInfo())) {
6152  old_value = GetProperty(&it).ToHandleChecked();
6153  }
6154  }
6155  }
6156 
6157  if (is_element) {
6158  DefineElementAccessor(object, index, getter, setter, attributes);
6159  } else {
6160  DCHECK(getter->IsSpecFunction() || getter->IsUndefined() ||
6161  getter->IsNull());
6162  DCHECK(setter->IsSpecFunction() || setter->IsUndefined() ||
6163  setter->IsNull());
6164  // At least one of the accessors needs to be a new value.
6165  DCHECK(!getter->IsNull() || !setter->IsNull());
6166  LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
6167  if (it.state() == LookupIterator::ACCESS_CHECK) {
6168  // We already did an access check before. We do have access.
6169  it.Next();
6170  }
6171  if (!getter->IsNull()) {
6172  it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
6173  }
6174  if (!setter->IsNull()) {
6175  it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
6176  }
6177  }
6178 
6179  if (is_observed) {
6180  const char* type = preexists ? "reconfigure" : "add";
6181  EnqueueChangeRecord(object, type, name, old_value);
6182  }
6183 
6184  return isolate->factory()->undefined_value();
6185 }
6186 
6187 
6189  Handle<AccessorInfo> info) {
6190  Isolate* isolate = object->GetIsolate();
6191  Factory* factory = isolate->factory();
6192  Handle<Name> name(Name::cast(info->name()));
6193 
6194  // Check access rights if needed.
6195  if (object->IsAccessCheckNeeded() &&
6196  !isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
6197  isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
6199  return factory->undefined_value();
6200  }
6201 
6202  if (object->IsJSGlobalProxy()) {
6203  PrototypeIterator iter(isolate, object);
6204  if (iter.IsAtEnd()) return object;
6205  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
6206  return SetAccessor(
6208  }
6209 
6210  // Make sure that the top context does not change when doing callbacks or
6211  // interceptor calls.
6212  AssertNoContextChange ncc(isolate);
6213 
6214  // Try to flatten before operating on the string.
6215  if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
6216 
6217  uint32_t index = 0;
6218  bool is_element = name->AsArrayIndex(&index);
6219 
6220  if (is_element) {
6221  if (object->IsJSArray()) return factory->undefined_value();
6222 
6223  // Accessors overwrite previous callbacks (cf. with getters/setters).
6224  switch (object->GetElementsKind()) {
6225  case FAST_SMI_ELEMENTS:
6226  case FAST_ELEMENTS:
6227  case FAST_DOUBLE_ELEMENTS:
6229  case FAST_HOLEY_ELEMENTS:
6231  break;
6232 
6233 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
6234  case EXTERNAL_##TYPE##_ELEMENTS: \
6235  case TYPE##_ELEMENTS: \
6236 
6238 #undef TYPED_ARRAY_CASE
6239  // Ignore getters and setters on pixel and external array
6240  // elements.
6241  return factory->undefined_value();
6242 
6243  case DICTIONARY_ELEMENTS:
6244  break;
6246  UNIMPLEMENTED();
6247  break;
6248  }
6249 
6250  SetElementCallback(object, index, info, info->property_attributes());
6251  } else {
6252  // Lookup the name.
6253  LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
6254  CHECK(GetPropertyAttributes(&it).has_value);
6255  // ES5 forbids turning a property into an accessor if it's not
6256  // configurable. See 8.6.1 (Table 5).
6257  if (it.IsFound() && (it.IsReadOnly() || !it.IsConfigurable())) {
6258  return factory->undefined_value();
6259  }
6260 
6261  SetPropertyCallback(object, name, info, info->property_attributes());
6262  }
6263 
6264  return object;
6265 }
6266 
6267 
6270  AccessorComponent component) {
6271  Isolate* isolate = object->GetIsolate();
6272 
6273  // Make sure that the top context does not change when doing callbacks or
6274  // interceptor calls.
6275  AssertNoContextChange ncc(isolate);
6276 
6277  // Make the lookup and include prototypes.
6278  uint32_t index = 0;
6279  if (name->AsArrayIndex(&index)) {
6280  for (PrototypeIterator iter(isolate, object,
6282  !iter.IsAtEnd(); iter.Advance()) {
6284  // Check access rights if needed.
6285  if (current->IsAccessCheckNeeded() &&
6286  !isolate->MayNamedAccess(Handle<JSObject>::cast(current), name,
6287  v8::ACCESS_HAS)) {
6289  v8::ACCESS_HAS);
6291  return isolate->factory()->undefined_value();
6292  }
6293 
6294  if (current->IsJSObject() &&
6295  Handle<JSObject>::cast(current)->HasDictionaryElements()) {
6296  JSObject* js_object = JSObject::cast(*current);
6297  SeededNumberDictionary* dictionary = js_object->element_dictionary();
6298  int entry = dictionary->FindEntry(index);
6299  if (entry != SeededNumberDictionary::kNotFound) {
6300  Object* element = dictionary->ValueAt(entry);
6301  if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
6302  element->IsAccessorPair()) {
6303  return handle(AccessorPair::cast(element)->GetComponent(component),
6304  isolate);
6305  }
6306  }
6307  }
6308  }
6309  } else {
6310  LookupIterator it(object, name,
6311  LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
6312  for (; it.IsFound(); it.Next()) {
6313  switch (it.state()) {
6314  case LookupIterator::INTERCEPTOR:
6315  case LookupIterator::NOT_FOUND:
6316  case LookupIterator::TRANSITION:
6317  UNREACHABLE();
6318 
6319  case LookupIterator::ACCESS_CHECK:
6320  if (it.HasAccess(v8::ACCESS_HAS)) continue;
6321  isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>(),
6322  v8::ACCESS_HAS);
6324  return isolate->factory()->undefined_value();
6325 
6326  case LookupIterator::JSPROXY:
6327  return isolate->factory()->undefined_value();
6328 
6329  case LookupIterator::DATA:
6330  continue;
6331  case LookupIterator::ACCESSOR: {
6332  Handle<Object> maybe_pair = it.GetAccessors();
6333  if (maybe_pair->IsAccessorPair()) {
6334  return handle(
6335  AccessorPair::cast(*maybe_pair)->GetComponent(component),
6336  isolate);
6337  }
6338  }
6339  }
6340  }
6341  }
6342  return isolate->factory()->undefined_value();
6343 }
6344 
6345 
6347  if (HasFastProperties()) {
6348  int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
6349  DescriptorArray* descs = map()->instance_descriptors();
6350  for (int i = 0; i < number_of_own_descriptors; i++) {
6351  if (descs->GetType(i) == FIELD) {
6352  Object* property =
6353  RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i));
6354  if (descs->GetDetails(i).representation().IsDouble()) {
6355  DCHECK(property->IsMutableHeapNumber());
6356  if (value->IsNumber() && property->Number() == value->Number()) {
6357  return descs->GetKey(i);
6358  }
6359  } else if (property == value) {
6360  return descs->GetKey(i);
6361  }
6362  } else if (descs->GetType(i) == CONSTANT) {
6363  if (descs->GetConstant(i) == value) {
6364  return descs->GetKey(i);
6365  }
6366  }
6367  }
6368  return GetHeap()->undefined_value();
6369  } else {
6370  return property_dictionary()->SlowReverseLookup(value);
6371  }
6372 }
6373 
6374 
6376  Handle<Map> result = map->GetIsolate()->factory()->NewMap(
6377  map->instance_type(), instance_size);
6378  result->set_prototype(map->prototype());
6379  result->set_constructor(map->constructor());
6380  result->set_bit_field(map->bit_field());
6381  result->set_bit_field2(map->bit_field2());
6382  int new_bit_field3 = map->bit_field3();
6383  new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6384  new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6385  new_bit_field3 = EnumLengthBits::update(new_bit_field3,
6387  new_bit_field3 = Deprecated::update(new_bit_field3, false);
6388  if (!map->is_dictionary_map()) {
6389  new_bit_field3 = IsUnstable::update(new_bit_field3, false);
6390  }
6391  new_bit_field3 = ConstructionCount::update(new_bit_field3,
6393  result->set_bit_field3(new_bit_field3);
6394  return result;
6395 }
6396 
6397 
6400  DCHECK(!fast_map->is_dictionary_map());
6401 
6402  Isolate* isolate = fast_map->GetIsolate();
6403  Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
6404  isolate);
6405  bool use_cache = !maybe_cache->IsUndefined();
6407  if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
6408 
6409  Handle<Map> new_map;
6410  if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
6411 #ifdef VERIFY_HEAP
6412  if (FLAG_verify_heap) new_map->DictionaryMapVerify();
6413 #endif
6414 #ifdef ENABLE_SLOW_DCHECKS
6416  // The cached map should match newly created normalized map bit-by-bit,
6417  // except for the code cache, which can contain some ics which can be
6418  // applied to the shared map.
6419  Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
6420 
6421  DCHECK(memcmp(fresh->address(),
6422  new_map->address(),
6423  Map::kCodeCacheOffset) == 0);
6426  int offset = Map::kDependentCodeOffset + kPointerSize;
6427  DCHECK(memcmp(fresh->address() + offset,
6428  new_map->address() + offset,
6429  Map::kSize - offset) == 0);
6430  }
6431 #endif
6432  } else {
6433  new_map = Map::CopyNormalized(fast_map, mode);
6434  if (use_cache) {
6435  cache->Set(fast_map, new_map);
6436  isolate->counters()->normalized_maps()->Increment();
6437  }
6438  }
6439  fast_map->NotifyLeafMapLayoutChange();
6440  return new_map;
6441 }
6442 
6443 
6446  int new_instance_size = map->instance_size();
6448  new_instance_size -= map->inobject_properties() * kPointerSize;
6449  }
6450 
6451  Handle<Map> result = RawCopy(map, new_instance_size);
6452 
6454  result->set_inobject_properties(map->inobject_properties());
6455  }
6456 
6457  result->set_dictionary_map(true);
6458  result->set_migration_target(false);
6459 
6460 #ifdef VERIFY_HEAP
6461  if (FLAG_verify_heap) result->DictionaryMapVerify();
6462 #endif
6463 
6464  return result;
6465 }
6466 
6467 
6469  Handle<Map> result = RawCopy(map, map->instance_size());
6470 
6471  // Please note instance_type and instance_size are set when allocated.
6472  result->set_inobject_properties(map->inobject_properties());
6473  result->set_unused_property_fields(map->unused_property_fields());
6474 
6475  result->set_pre_allocated_property_fields(
6477  result->ClearCodeCache(map->GetHeap());
6479  return result;
6480 }
6481 
6482 
6484  Handle<DescriptorArray> descriptors,
6485  Descriptor* descriptor) {
6486  // Sanity check. This path is only to be taken if the map owns its descriptor
6487  // array, implying that its NumberOfOwnDescriptors equals the number of
6488  // descriptors in the descriptor array.
6490  map->instance_descriptors()->number_of_descriptors());
6491 
6492  Handle<Map> result = CopyDropDescriptors(map);
6493  Handle<Name> name = descriptor->GetKey();
6494 
6495  // Ensure there's space for the new descriptor in the shared descriptor array.
6496  if (descriptors->NumberOfSlackDescriptors() == 0) {
6497  int old_size = descriptors->number_of_descriptors();
6498  if (old_size == 0) {
6499  descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
6500  } else {
6501  EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2);
6502  descriptors = handle(map->instance_descriptors());
6503  }
6504  }
6505 
6506  {
6507  DisallowHeapAllocation no_gc;
6508  descriptors->Append(descriptor);
6509  result->InitializeDescriptors(*descriptors);
6510  }
6511 
6512  DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
6513  ConnectTransition(map, result, name, SIMPLE_TRANSITION);
6514 
6515  return result;
6516 }
6517 
6518 
6521  parent->set_owns_descriptors(false);
6522  if (parent->is_prototype_map()) {
6523  DCHECK(child->is_prototype_map());
6524  } else {
6525  Handle<TransitionArray> transitions =
6526  TransitionArray::CopyInsert(parent, name, child, flag);
6527  parent->set_transitions(*transitions);
6528  child->SetBackPointer(*parent);
6529  }
6530 }
6531 
6532 
6534  Handle<DescriptorArray> descriptors,
6536  MaybeHandle<Name> maybe_name,
6537  SimpleTransitionFlag simple_flag) {
6538  DCHECK(descriptors->IsSortedNoDuplicates());
6539 
6540  Handle<Map> result = CopyDropDescriptors(map);
6541  result->InitializeDescriptors(*descriptors);
6542 
6543  if (!map->is_prototype_map()) {
6546  CHECK(maybe_name.ToHandle(&name));
6547  ConnectTransition(map, result, name, simple_flag);
6548  } else {
6549  int length = descriptors->number_of_descriptors();
6550  for (int i = 0; i < length; i++) {
6551  descriptors->SetRepresentation(i, Representation::Tagged());
6552  if (descriptors->GetDetails(i).type() == FIELD) {
6553  descriptors->SetValue(i, HeapType::Any());
6554  }
6555  }
6556  }
6557  }
6558 
6559  return result;
6560 }
6561 
6562 
6563 // Since this method is used to rewrite an existing transition tree, it can
6564 // always insert transitions without checking.
6566  int new_descriptor,
6567  Handle<DescriptorArray> descriptors) {
6568  DCHECK(descriptors->IsSortedNoDuplicates());
6569 
6570  Handle<Map> result = CopyDropDescriptors(map);
6571 
6572  result->InitializeDescriptors(*descriptors);
6573  result->SetNumberOfOwnDescriptors(new_descriptor + 1);
6574 
6575  int unused_property_fields = map->unused_property_fields();
6576  if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
6577  unused_property_fields = map->unused_property_fields() - 1;
6578  if (unused_property_fields < 0) {
6579  unused_property_fields += JSObject::kFieldsAdded;
6580  }
6581  }
6582 
6583  result->set_unused_property_fields(unused_property_fields);
6584 
6585  Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
6586  ConnectTransition(map, result, name, SIMPLE_TRANSITION);
6587 
6588  return result;
6589 }
6590 
6591 
6593  TransitionFlag flag) {
6594  if (flag == INSERT_TRANSITION) {
6600  (kind == DICTIONARY_ELEMENTS ||
6601  IsExternalArrayElementsKind(kind))));
6602  DCHECK(!IsFastElementsKind(kind) ||
6604  DCHECK(kind != map->elements_kind());
6605  }
6606 
6607  bool insert_transition =
6609 
6610  if (insert_transition && map->owns_descriptors()) {
6611  // In case the map owned its own descriptors, share the descriptors and
6612  // transfer ownership to the new map.
6613  Handle<Map> new_map = CopyDropDescriptors(map);
6614 
6615  ConnectElementsTransition(map, new_map);
6616 
6617  new_map->set_elements_kind(kind);
6618  new_map->InitializeDescriptors(map->instance_descriptors());
6619  return new_map;
6620  }
6621 
6622  // In case the map did not own its own descriptors, a split is forced by
6623  // copying the map; creating a new descriptor array cell.
6624  // Create a new free-floating map only if we are not allowed to store it.
6625  Handle<Map> new_map = Copy(map);
6626 
6627  new_map->set_elements_kind(kind);
6628 
6629  if (insert_transition) {
6630  ConnectElementsTransition(map, new_map);
6631  }
6632 
6633  return new_map;
6634 }
6635 
6636 
6638  DCHECK(!map->is_observed());
6639 
6640  Isolate* isolate = map->GetIsolate();
6641 
6642  // In case the map owned its own descriptors, share the descriptors and
6643  // transfer ownership to the new map.
6644  Handle<Map> new_map;
6645  if (map->owns_descriptors()) {
6646  new_map = CopyDropDescriptors(map);
6647  } else {
6649  new_map = Copy(map);
6650  }
6651 
6652  new_map->set_is_observed();
6653  if (map->owns_descriptors()) {
6654  new_map->InitializeDescriptors(map->instance_descriptors());
6655  }
6656 
6657  Handle<Name> name = isolate->factory()->observed_symbol();
6658  ConnectTransition(map, new_map, name, FULL_TRANSITION);
6659 
6660  return new_map;
6661 }
6662 
6663 
6665  Handle<DescriptorArray> descriptors(map->instance_descriptors());
6666  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
6667  Handle<DescriptorArray> new_descriptors =
6668  DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
6669  return CopyReplaceDescriptors(
6670  map, new_descriptors, OMIT_TRANSITION, MaybeHandle<Name>());
6671 }
6672 
6673 
6674 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
6675  Handle<Map> copy = Copy(handle(isolate->object_function()->initial_map()));
6676 
6677  // Check that we do not overflow the instance size when adding the extra
6678  // inobject properties. If the instance size overflows, we allocate as many
6679  // properties as we can as inobject properties.
6680  int max_extra_properties =
6682 
6683  if (inobject_properties > max_extra_properties) {
6684  inobject_properties = max_extra_properties;
6685  }
6686 
6687  int new_instance_size =
6688  JSObject::kHeaderSize + kPointerSize * inobject_properties;
6689 
6690  // Adjust the map with the extra inobject properties.
6691  copy->set_inobject_properties(inobject_properties);
6692  copy->set_unused_property_fields(inobject_properties);
6693  copy->set_instance_size(new_instance_size);
6694  copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
6695  return copy;
6696 }
6697 
6698 
6700  int num_descriptors = map->NumberOfOwnDescriptors();
6701  Isolate* isolate = map->GetIsolate();
6703  handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN);
6704  Handle<Map> new_map = CopyReplaceDescriptors(
6705  map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol());
6706  new_map->freeze();
6707  new_map->set_is_extensible(false);
6708  new_map->set_elements_kind(DICTIONARY_ELEMENTS);
6709  return new_map;
6710 }
6711 
6712 
6713 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
6714  PropertyDetails details = GetDetails(descriptor);
6715  switch (details.type()) {
6716  case FIELD:
6717  return value->FitsRepresentation(details.representation()) &&
6718  GetFieldType(descriptor)->NowContains(value);
6719 
6720  case CONSTANT:
6721  DCHECK(GetConstant(descriptor) != value ||
6722  value->FitsRepresentation(details.representation()));
6723  return GetConstant(descriptor) == value;
6724 
6725  case CALLBACKS:
6726  return false;
6727 
6728  case NORMAL:
6729  UNREACHABLE();
6730  break;
6731  }
6732 
6733  UNREACHABLE();
6734  return false;
6735 }
6736 
6737 
6739  Handle<Object> value) {
6740  // Dictionaries can store any property value.
6741  if (map->is_dictionary_map()) return map;
6742 
6743  // Migrate to the newest map before storing the property.
6744  map = Update(map);
6745 
6746  Handle<DescriptorArray> descriptors(map->instance_descriptors());
6747 
6748  if (descriptors->CanHoldValue(descriptor, *value)) return map;
6749 
6750  Isolate* isolate = map->GetIsolate();
6751  Representation representation = value->OptimalRepresentation();
6752  Handle<HeapType> type = value->OptimalType(isolate, representation);
6753 
6754  return GeneralizeRepresentation(map, descriptor, representation, type,
6755  FORCE_FIELD);
6756 }
6757 
6758 
6760  Handle<Object> value,
6761  PropertyAttributes attributes,
6762  StoreFromKeyed store_mode) {
6763  // Dictionary maps can always have additional data properties.
6764  if (map->is_dictionary_map()) return map;
6765 
6766  // Migrate to the newest map before storing the property.
6767  map = Update(map);
6768 
6769  int index = map->SearchTransition(*name);
6770  if (index != TransitionArray::kNotFound) {
6771  Handle<Map> transition(map->GetTransition(index));
6772  int descriptor = transition->LastAdded();
6773 
6774  // TODO(verwaest): Handle attributes better.
6775  DescriptorArray* descriptors = transition->instance_descriptors();
6776  if (descriptors->GetDetails(descriptor).attributes() != attributes) {
6778  }
6779 
6780  return Map::PrepareForDataProperty(transition, descriptor, value);
6781  }
6782 
6784  MaybeHandle<Map> maybe_map;
6785  if (value->IsJSFunction()) {
6786  maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
6787  } else if (!map->TooManyFastProperties(store_mode)) {
6788  Isolate* isolate = name->GetIsolate();
6789  Representation representation = value->OptimalRepresentation();
6790  Handle<HeapType> type = value->OptimalType(isolate, representation);
6791  maybe_map =
6792  Map::CopyWithField(map, name, type, attributes, representation, flag);
6793  }
6794 
6795  Handle<Map> result;
6796  if (!maybe_map.ToHandle(&result)) {
6798  }
6799 
6800  return result;
6801 }
6802 
6803 
6805  PropertyAttributes attributes) {
6806  // Dictionaries have to be reconfigured in-place.
6808 
6809  // For now, give up on transitioning and just create a unique map.
6810  // TODO(verwaest/ishell): Cache transitions with different attributes.
6811  return CopyGeneralizeAllRepresentations(map, descriptor, FORCE_FIELD,
6812  attributes, "attributes mismatch");
6813 }
6814 
6815 
6818  AccessorComponent component,
6819  Handle<Object> accessor,
6820  PropertyAttributes attributes) {
6821  Isolate* isolate = name->GetIsolate();
6822 
6823  // Dictionary maps can always have additional data properties.
6824  if (map->is_dictionary_map()) {
6825  // For global objects, property cells are inlined. We need to change the
6826  // map.
6827  if (map->IsGlobalObjectMap()) return Copy(map);
6828  return map;
6829  }
6830 
6831  // Migrate to the newest map before transitioning to the new property.
6832  map = Update(map);
6833 
6837 
6838  int index = map->SearchTransition(*name);
6839  if (index != TransitionArray::kNotFound) {
6840  Handle<Map> transition(map->GetTransition(index));
6841  DescriptorArray* descriptors = transition->instance_descriptors();
6842  // Fast path, assume that we're modifying the last added descriptor.
6843  int descriptor = transition->LastAdded();
6844  if (descriptors->GetKey(descriptor) != *name) {
6845  // If not, search for the descriptor.
6846  descriptor = descriptors->SearchWithCache(*name, *transition);
6847  }
6848 
6849  if (descriptors->GetDetails(descriptor).type() != CALLBACKS) {
6850  return Map::Normalize(map, mode);
6851  }
6852 
6853  // TODO(verwaest): Handle attributes better.
6854  if (descriptors->GetDetails(descriptor).attributes() != attributes) {
6855  return Map::Normalize(map, mode);
6856  }
6857 
6858  Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
6859  if (!maybe_pair->IsAccessorPair()) {
6860  return Map::Normalize(map, mode);
6861  }
6862 
6864  if (pair->get(component) != *accessor) {
6865  return Map::Normalize(map, mode);
6866  }
6867 
6868  return transition;
6869  }
6870 
6871  Handle<AccessorPair> pair;
6872  DescriptorArray* old_descriptors = map->instance_descriptors();
6873  int descriptor = old_descriptors->SearchWithCache(*name, *map);
6874  if (descriptor != DescriptorArray::kNotFound) {
6875  PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
6876  if (old_details.type() != CALLBACKS) {
6877  return Map::Normalize(map, mode);
6878  }
6879 
6880  if (old_details.attributes() != attributes) {
6881  return Map::Normalize(map, mode);
6882  }
6883 
6884  Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
6885  if (!maybe_pair->IsAccessorPair()) {
6886  return Map::Normalize(map, mode);
6887  }
6888 
6889  Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component);
6890  if (current == *accessor) return map;
6891 
6892  if (!current->IsTheHole()) {
6893  return Map::Normalize(map, mode);
6894  }
6895 
6896  pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
6900  } else {
6901  pair = isolate->factory()->NewAccessorPair();
6902  }
6903 
6904  pair->set(component, *accessor);
6906  CallbacksDescriptor new_desc(name, pair, attributes);
6907  return Map::CopyInsertDescriptor(map, &new_desc, flag);
6908 }
6909 
6910 
6912  Descriptor* descriptor,
6913  TransitionFlag flag) {
6914  Handle<DescriptorArray> descriptors(map->instance_descriptors());
6915 
6916  // Ensure the key is unique.
6917  descriptor->KeyToUniqueName();
6918 
6919  if (flag == INSERT_TRANSITION &&
6920  map->owns_descriptors() &&
6922  return ShareDescriptor(map, descriptors, descriptor);
6923  }
6924 
6926  descriptors, map->NumberOfOwnDescriptors(), 1);
6927  new_descriptors->Append(descriptor);
6928 
6929  return CopyReplaceDescriptors(
6930  map, new_descriptors, flag, descriptor->GetKey(), SIMPLE_TRANSITION);
6931 }
6932 
6933 
6935  Descriptor* descriptor,
6936  TransitionFlag flag) {
6937  Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
6938 
6939  // Ensure the key is unique.
6940  descriptor->KeyToUniqueName();
6941 
6942  // We replace the key if it is already present.
6943  int index = old_descriptors->SearchWithCache(*descriptor->GetKey(), *map);
6944  if (index != DescriptorArray::kNotFound) {
6945  return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
6946  }
6947  return CopyAddDescriptor(map, descriptor, flag);
6948 }
6949 
6950 
6953  int enumeration_index,
6954  int slack) {
6956  desc, enumeration_index, NONE, slack);
6957 }
6958 
6959 
6962  int enumeration_index,
6963  PropertyAttributes attributes,
6964  int slack) {
6965  if (enumeration_index + slack == 0) {
6966  return desc->GetIsolate()->factory()->empty_descriptor_array();
6967  }
6968 
6969  int size = enumeration_index;
6970 
6971  Handle<DescriptorArray> descriptors =
6972  DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
6973  DescriptorArray::WhitenessWitness witness(*descriptors);
6974 
6975  if (attributes != NONE) {
6976  for (int i = 0; i < size; ++i) {
6977  Object* value = desc->GetValue(i);
6978  Name* key = desc->GetKey(i);
6979  PropertyDetails details = desc->GetDetails(i);
6980  // Bulk attribute changes never affect private properties.
6981  if (!key->IsSymbol() || !Symbol::cast(key)->is_private()) {
6982  int mask = DONT_DELETE | DONT_ENUM;
6983  // READ_ONLY is an invalid attribute for JS setters/getters.
6984  if (details.type() != CALLBACKS || !value->IsAccessorPair()) {
6985  mask |= READ_ONLY;
6986  }
6987  details = details.CopyAddAttributes(
6988  static_cast<PropertyAttributes>(attributes & mask));
6989  }
6990  Descriptor inner_desc(
6991  handle(key), handle(value, desc->GetIsolate()), details);
6992  descriptors->Set(i, &inner_desc, witness);
6993  }
6994  } else {
6995  for (int i = 0; i < size; ++i) {
6996  descriptors->CopyFrom(i, *desc, witness);
6997  }
6998  }
6999 
7000  if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
7001 
7002  return descriptors;
7003 }
7004 
7005 
7007  Handle<DescriptorArray> descriptors,
7008  Descriptor* descriptor,
7009  int insertion_index,
7010  TransitionFlag flag) {
7011  // Ensure the key is unique.
7012  descriptor->KeyToUniqueName();
7013 
7014  Handle<Name> key = descriptor->GetKey();
7015  DCHECK(*key == descriptors->GetKey(insertion_index));
7016 
7018  descriptors, map->NumberOfOwnDescriptors());
7019 
7020  new_descriptors->Replace(insertion_index, descriptor);
7021 
7022  SimpleTransitionFlag simple_flag =
7023  (insertion_index == descriptors->number_of_descriptors() - 1)
7025  : FULL_TRANSITION;
7026  return CopyReplaceDescriptors(map, new_descriptors, flag, key, simple_flag);
7027 }
7028 
7029 
7032  Handle<Code> code) {
7033  Isolate* isolate = map->GetIsolate();
7034  HandleScope scope(isolate);
7035  // Allocate the code cache if not present.
7036  if (map->code_cache()->IsFixedArray()) {
7037  Handle<Object> result = isolate->factory()->NewCodeCache();
7038  map->set_code_cache(*result);
7039  }
7040 
7041  // Update the code cache.
7042  Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
7043  CodeCache::Update(code_cache, name, code);
7044 }
7045 
7046 
7048  // Do a lookup if a code cache exists.
7049  if (!code_cache()->IsFixedArray()) {
7050  return CodeCache::cast(code_cache())->Lookup(name, flags);
7051  } else {
7052  return GetHeap()->undefined_value();
7053  }
7054 }
7055 
7056 
7058  // Get the internal index if a code cache exists.
7059  if (!code_cache()->IsFixedArray()) {
7060  return CodeCache::cast(code_cache())->GetIndex(name, code);
7061  }
7062  return -1;
7063 }
7064 
7065 
7066 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7067  // No GC is supposed to happen between a call to IndexInCodeCache and
7068  // RemoveFromCodeCache so the code cache must be there.
7069  DCHECK(!code_cache()->IsFixedArray());
7070  CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7071 }
7072 
7073 
7074 // An iterator over all map transitions in an descriptor array, reusing the
7075 // constructor field of the map while it is running. Negative values in
7076 // the constructor field indicate an active map transition iteration. The
7077 // original constructor is restored after iterating over all entries.
7079  public:
7081  Map* map, TransitionArray* transition_array, Object* constructor)
7082  : map_(map),
7083  transition_array_(transition_array),
7084  constructor_(constructor) { }
7085 
7087  DCHECK(!(*IteratorField())->IsSmi() || IsIterating());
7088  if (!(*IteratorField())->IsSmi()) {
7089  DCHECK(*IteratorField() == constructor_);
7090  *IteratorField() = Smi::FromInt(-1);
7091  }
7092  }
7093 
7094  bool IsIterating() {
7095  return (*IteratorField())->IsSmi() &&
7096  Smi::cast(*IteratorField())->value() < 0;
7097  }
7098 
7099  Map* Next() {
7100  DCHECK(IsIterating());
7101  int value = Smi::cast(*IteratorField())->value();
7102  int index = -value - 1;
7103  int number_of_transitions = transition_array_->number_of_transitions();
7104  while (index < number_of_transitions) {
7105  *IteratorField() = Smi::FromInt(value - 1);
7106  return transition_array_->GetTarget(index);
7107  }
7108 
7109  *IteratorField() = constructor_;
7110  return NULL;
7111  }
7112 
7113  private:
7116  }
7117 
7121 };
7122 
7123 
7124 // An iterator over all prototype transitions, reusing the constructor field
7125 // of the map while it is running. Positive values in the constructor field
7126 // indicate an active prototype transition iteration. The original constructor
7127 // is restored after iterating over all entries.
7129  public:
7131  Map* map, HeapObject* proto_trans, Object* constructor)
7132  : map_(map), proto_trans_(proto_trans), constructor_(constructor) { }
7133 
7135  if (!(*IteratorField())->IsSmi()) {
7136  DCHECK(*IteratorField() == constructor_);
7137  *IteratorField() = Smi::FromInt(0);
7138  }
7139  }
7140 
7141  bool IsIterating() {
7142  return (*IteratorField())->IsSmi() &&
7143  Smi::cast(*IteratorField())->value() >= 0;
7144  }
7145 
7146  Map* Next() {
7147  DCHECK(IsIterating());
7148  int transitionNumber = Smi::cast(*IteratorField())->value();
7149  if (transitionNumber < NumberOfTransitions()) {
7150  *IteratorField() = Smi::FromInt(transitionNumber + 1);
7151  return GetTransition(transitionNumber);
7152  }
7153  *IteratorField() = constructor_;
7154  return NULL;
7155  }
7156 
7157  private:
7160  }
7161 
7163  FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7165  return Smi::cast(num)->value();
7166  }
7167 
7168  Map* GetTransition(int transitionNumber) {
7169  FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
7170  return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
7171  }
7172 
7173  int IndexFor(int transitionNumber) {
7176  transitionNumber * Map::kProtoTransitionElementsPerEntry;
7177  }
7178 
7182 };
7183 
7184 
7185 // To traverse the transition tree iteratively, we have to store two kinds of
7186 // information in a map: The parent map in the traversal and which children of a
7187 // node have already been visited. To do this without additional memory, we
7188 // temporarily reuse two fields with known values:
7189 //
7190 // (1) The map of the map temporarily holds the parent, and is restored to the
7191 // meta map afterwards.
7192 //
7193 // (2) The info which children have already been visited depends on which part
7194 // of the map we currently iterate. We use the constructor field of the
7195 // map to store the current index. We can do that because the constructor
7196 // is the same for all involved maps.
7197 //
7198 // (a) If we currently follow normal map transitions, we temporarily store
7199 // the current index in the constructor field, and restore it to the
7200 // original constructor afterwards. Note that a single descriptor can
7201 // have 0, 1, or 2 transitions.
7202 //
7203 // (b) If we currently follow prototype transitions, we temporarily store
7204 // the current index in the constructor field, and restore it to the
7205 // original constructor afterwards.
7206 //
7207 // Note that the child iterator is just a concatenation of two iterators: One
7208 // iterating over map transitions and one iterating over prototype transisitons.
7209 class TraversableMap : public Map {
7210  public:
7211  // Record the parent in the traversal within this map. Note that this destroys
7212  // this map's map!
7214 
7215  // Reset the current map's map, returning the parent previously stored in it.
7217  TraversableMap* old_parent = static_cast<TraversableMap*>(map());
7218  set_map_no_write_barrier(GetHeap()->meta_map());
7219  return old_parent;
7220  }
7221 
7222  // If we have an unvisited child map, return that one and advance. If we have
7223  // none, return NULL and restore the overwritten constructor field.
7225  if (!HasTransitionArray()) return NULL;
7226 
7227  TransitionArray* transition_array = transitions();
7228  if (transition_array->HasPrototypeTransitions()) {
7229  HeapObject* proto_transitions =
7230  transition_array->GetPrototypeTransitions();
7231  IntrusivePrototypeTransitionIterator proto_iterator(this,
7232  proto_transitions,
7233  constructor);
7234  proto_iterator.StartIfNotStarted();
7235  if (proto_iterator.IsIterating()) {
7236  Map* next = proto_iterator.Next();
7237  if (next != NULL) return static_cast<TraversableMap*>(next);
7238  }
7239  }
7240 
7241  IntrusiveMapTransitionIterator transition_iterator(this,
7242  transition_array,
7243  constructor);
7244  transition_iterator.StartIfNotStarted();
7245  if (transition_iterator.IsIterating()) {
7246  Map* next = transition_iterator.Next();
7247  if (next != NULL) return static_cast<TraversableMap*>(next);
7248  }
7249 
7250  return NULL;
7251  }
7252 };
7253 
7254 
7255 // Traverse the transition tree in postorder without using the C++ stack by
7256 // doing pointer reversal.
7257 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
7258  // Make sure that we do not allocate in the callback.
7259  DisallowHeapAllocation no_allocation;
7260 
7261  TraversableMap* current = static_cast<TraversableMap*>(this);
7262  // Get the root constructor here to restore it later when finished iterating
7263  // over maps.
7264  Object* root_constructor = constructor();
7265  while (true) {
7266  TraversableMap* child = current->ChildIteratorNext(root_constructor);
7267  if (child != NULL) {
7268  child->SetParent(current);
7269  current = child;
7270  } else {
7271  TraversableMap* parent = current->GetAndResetParent();
7272  callback(current, data);
7273  if (current == this) break;
7274  current = parent;
7275  }
7276  }
7277 }
7278 
7279 
7281  Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7282  // The number of monomorphic stubs for normal load/store/call IC's can grow to
7283  // a large number and therefore they need to go into a hash table. They are
7284  // used to load global properties from cells.
7285  if (code->type() == Code::NORMAL) {
7286  // Make sure that a hash table is allocated for the normal load code cache.
7287  if (code_cache->normal_type_cache()->IsUndefined()) {
7288  Handle<Object> result =
7289  CodeCacheHashTable::New(code_cache->GetIsolate(),
7291  code_cache->set_normal_type_cache(*result);
7292  }
7293  UpdateNormalTypeCache(code_cache, name, code);
7294  } else {
7295  DCHECK(code_cache->default_cache()->IsFixedArray());
7296  UpdateDefaultCache(code_cache, name, code);
7297  }
7298 }
7299 
7300 
7302  Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7303  // When updating the default code cache we disregard the type encoded in the
7304  // flags. This allows call constant stubs to overwrite call field
7305  // stubs, etc.
7306  Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
7307 
7308  // First check whether we can update existing code cache without
7309  // extending it.
7310  Handle<FixedArray> cache = handle(code_cache->default_cache());
7311  int length = cache->length();
7312  {
7313  DisallowHeapAllocation no_alloc;
7314  int deleted_index = -1;
7315  for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7316  Object* key = cache->get(i);
7317  if (key->IsNull()) {
7318  if (deleted_index < 0) deleted_index = i;
7319  continue;
7320  }
7321  if (key->IsUndefined()) {
7322  if (deleted_index >= 0) i = deleted_index;
7323  cache->set(i + kCodeCacheEntryNameOffset, *name);
7324  cache->set(i + kCodeCacheEntryCodeOffset, *code);
7325  return;
7326  }
7327  if (name->Equals(Name::cast(key))) {
7328  Code::Flags found =
7329  Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
7330  if (Code::RemoveTypeFromFlags(found) == flags) {
7331  cache->set(i + kCodeCacheEntryCodeOffset, *code);
7332  return;
7333  }
7334  }
7335  }
7336 
7337  // Reached the end of the code cache. If there were deleted
7338  // elements, reuse the space for the first of them.
7339  if (deleted_index >= 0) {
7340  cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
7341  cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
7342  return;
7343  }
7344  }
7345 
7346  // Extend the code cache with some new entries (at least one). Must be a
7347  // multiple of the entry size.
7348  int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
7349  new_length = new_length - new_length % kCodeCacheEntrySize;
7350  DCHECK((new_length % kCodeCacheEntrySize) == 0);
7351  cache = FixedArray::CopySize(cache, new_length);
7352 
7353  // Add the (name, code) pair to the new cache.
7354  cache->set(length + kCodeCacheEntryNameOffset, *name);
7355  cache->set(length + kCodeCacheEntryCodeOffset, *code);
7356  code_cache->set_default_cache(*cache);
7357 }
7358 
7359 
7361  Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7362  // Adding a new entry can cause a new cache to be allocated.
7364  CodeCacheHashTable::cast(code_cache->normal_type_cache()));
7365  Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
7366  code_cache->set_normal_type_cache(*new_cache);
7367 }
7368 
7369 
7371  Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
7372  if (result->IsCode()) {
7373  if (Code::cast(result)->flags() == flags) return result;
7374  return GetHeap()->undefined_value();
7375  }
7376  return LookupNormalTypeCache(name, flags);
7377 }
7378 
7379 
7381  FixedArray* cache = default_cache();
7382  int length = cache->length();
7383  for (int i = 0; i < length; i += kCodeCacheEntrySize) {
7384  Object* key = cache->get(i + kCodeCacheEntryNameOffset);
7385  // Skip deleted elements.
7386  if (key->IsNull()) continue;
7387  if (key->IsUndefined()) return key;
7388  if (name->Equals(Name::cast(key))) {
7389  Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
7390  if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
7391  return code;
7392  }
7393  }
7394  }
7395  return GetHeap()->undefined_value();
7396 }
7397 
7398 
7400  if (!normal_type_cache()->IsUndefined()) {
7401  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7402  return cache->Lookup(name, flags);
7403  } else {
7404  return GetHeap()->undefined_value();
7405  }
7406 }
7407 
7408 
7410  if (code->type() == Code::NORMAL) {
7411  if (normal_type_cache()->IsUndefined()) return -1;
7412  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7413  return cache->GetIndex(Name::cast(name), code->flags());
7414  }
7415 
7416  FixedArray* array = default_cache();
7417  int len = array->length();
7418  for (int i = 0; i < len; i += kCodeCacheEntrySize) {
7419  if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
7420  }
7421  return -1;
7422 }
7423 
7424 
7425 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
7426  if (code->type() == Code::NORMAL) {
7427  DCHECK(!normal_type_cache()->IsUndefined());
7428  CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
7429  DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
7430  cache->RemoveByIndex(index);
7431  } else {
7432  FixedArray* array = default_cache();
7433  DCHECK(array->length() >= index && array->get(index)->IsCode());
7434  // Use null instead of undefined for deleted elements to distinguish
7435  // deleted elements from unused elements. This distinction is used
7436  // when looking up in the cache and when updating the cache.
7437  DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
7438  array->set_null(index - 1); // Name.
7439  array->set_null(index); // Code.
7440  }
7441 }
7442 
7443 
7444 // The key in the code cache hash table consists of the property name and the
7445 // code object. The actual match is on the name and the code flags. If a key
7446 // is created using the flags and not a code object it can only be used for
7447 // lookup not to create a new entry.
7449  public:
7451  : name_(name), flags_(flags), code_() { }
7452 
7454  : name_(name), flags_(code->flags()), code_(code) { }
7455 
7456  bool IsMatch(Object* other) OVERRIDE {
7457  if (!other->IsFixedArray()) return false;
7458  FixedArray* pair = FixedArray::cast(other);
7459  Name* name = Name::cast(pair->get(0));
7460  Code::Flags flags = Code::cast(pair->get(1))->flags();
7461  if (flags != flags_) {
7462  return false;
7463  }
7464  return name_->Equals(name);
7465  }
7466 
7468  return name->Hash() ^ flags;
7469  }
7470 
7471  uint32_t Hash() OVERRIDE { return NameFlagsHashHelper(*name_, flags_); }
7472 
7474  FixedArray* pair = FixedArray::cast(obj);
7475  Name* name = Name::cast(pair->get(0));
7476  Code* code = Code::cast(pair->get(1));
7477  return NameFlagsHashHelper(name, code->flags());
7478  }
7479 
7481  Handle<Code> code = code_.ToHandleChecked();
7482  Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
7483  pair->set(0, *name_);
7484  pair->set(1, *code);
7485  return pair;
7486  }
7487 
7488  private:
7491  // TODO(jkummerow): We should be able to get by without this.
7493 };
7494 
7495 
7497  DisallowHeapAllocation no_alloc;
7499  int entry = FindEntry(&key);
7500  if (entry == kNotFound) return GetHeap()->undefined_value();
7501  return get(EntryToIndex(entry) + 1);
7502 }
7503 
7504 
7507  CodeCacheHashTableKey key(name, code);
7508 
7509  Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
7510 
7511  int entry = new_cache->FindInsertionEntry(key.Hash());
7512  Handle<Object> k = key.AsHandle(cache->GetIsolate());
7513 
7514  new_cache->set(EntryToIndex(entry), *k);
7515  new_cache->set(EntryToIndex(entry) + 1, *code);
7516  new_cache->ElementAdded();
7517  return new_cache;
7518 }
7519 
7520 
7522  DisallowHeapAllocation no_alloc;
7524  int entry = FindEntry(&key);
7525  return (entry == kNotFound) ? -1 : entry;
7526 }
7527 
7528 
7530  DCHECK(index >= 0);
7531  Heap* heap = GetHeap();
7532  set(EntryToIndex(index), heap->the_hole_value());
7533  set(EntryToIndex(index) + 1, heap->the_hole_value());
7534  ElementRemoved();
7535 }
7536 
7537 
7539  MapHandleList* maps,
7541  Handle<Code> code) {
7542  Isolate* isolate = code_cache->GetIsolate();
7543  if (code_cache->cache()->IsUndefined()) {
7546  isolate,
7548  code_cache->set_cache(*result);
7549  } else {
7550  // This entry shouldn't be contained in the cache yet.
7551  DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
7552  ->Lookup(maps, flags)->IsUndefined());
7553  }
7555  handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
7557  PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
7558  code_cache->set_cache(*new_cache);
7559 }
7560 
7561 
7563  Code::Flags flags) {
7564  if (!cache()->IsUndefined()) {
7565  PolymorphicCodeCacheHashTable* hash_table =
7566  PolymorphicCodeCacheHashTable::cast(cache());
7567  return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
7568  } else {
7569  return GetIsolate()->factory()->undefined_value();
7570  }
7571 }
7572 
7573 
7574 // Despite their name, object of this class are not stored in the actual
7575 // hash table; instead they're temporarily used for lookups. It is therefore
7576 // safe to have a weak (non-owning) pointer to a MapList as a member field.
7578  public:
7579  // Callers must ensure that |maps| outlives the newly constructed object.
7581  : maps_(maps),
7582  code_flags_(code_flags) {}
7583 
7584  bool IsMatch(Object* other) OVERRIDE {
7585  MapHandleList other_maps(kDefaultListAllocationSize);
7586  int other_flags;
7587  FromObject(other, &other_flags, &other_maps);
7588  if (code_flags_ != other_flags) return false;
7589  if (maps_->length() != other_maps.length()) return false;
7590  // Compare just the hashes first because it's faster.
7591  int this_hash = MapsHashHelper(maps_, code_flags_);
7592  int other_hash = MapsHashHelper(&other_maps, other_flags);
7593  if (this_hash != other_hash) return false;
7594 
7595  // Full comparison: for each map in maps_, look for an equivalent map in
7596  // other_maps. This implementation is slow, but probably good enough for
7597  // now because the lists are short (<= 4 elements currently).
7598  for (int i = 0; i < maps_->length(); ++i) {
7599  bool match_found = false;
7600  for (int j = 0; j < other_maps.length(); ++j) {
7601  if (*(maps_->at(i)) == *(other_maps.at(j))) {
7602  match_found = true;
7603  break;
7604  }
7605  }
7606  if (!match_found) return false;
7607  }
7608  return true;
7609  }
7610 
7611  static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
7612  uint32_t hash = code_flags;
7613  for (int i = 0; i < maps->length(); ++i) {
7614  hash ^= maps->at(i)->Hash();
7615  }
7616  return hash;
7617  }
7618 
7620  return MapsHashHelper(maps_, code_flags_);
7621  }
7622 
7624  MapHandleList other_maps(kDefaultListAllocationSize);
7625  int other_flags;
7626  FromObject(obj, &other_flags, &other_maps);
7627  return MapsHashHelper(&other_maps, other_flags);
7628  }
7629 
7631  // The maps in |maps_| must be copied to a newly allocated FixedArray,
7632  // both because the referenced MapList is short-lived, and because C++
7633  // objects can't be stored in the heap anyway.
7634  Handle<FixedArray> list =
7635  isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
7636  list->set(0, Smi::FromInt(code_flags_));
7637  for (int i = 0; i < maps_->length(); ++i) {
7638  list->set(i + 1, *maps_->at(i));
7639  }
7640  return list;
7641  }
7642 
7643  private:
7645  int* code_flags,
7646  MapHandleList* maps) {
7647  FixedArray* list = FixedArray::cast(obj);
7648  maps->Rewind(0);
7649  *code_flags = Smi::cast(list->get(0))->value();
7650  for (int i = 1; i < list->length(); ++i) {
7651  maps->Add(Handle<Map>(Map::cast(list->get(i))));
7652  }
7653  return maps;
7654  }
7655 
7658  static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
7659 };
7660 
7661 
7663  int code_kind) {
7664  DisallowHeapAllocation no_alloc;
7665  PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7666  int entry = FindEntry(&key);
7667  if (entry == kNotFound) return GetHeap()->undefined_value();
7668  return get(EntryToIndex(entry) + 1);
7669 }
7670 
7671 
7674  MapHandleList* maps,
7675  int code_kind,
7676  Handle<Code> code) {
7677  PolymorphicCodeCacheHashTableKey key(maps, code_kind);
7679  EnsureCapacity(hash_table, 1, &key);
7680  int entry = cache->FindInsertionEntry(key.Hash());
7681 
7682  Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
7683  cache->set(EntryToIndex(entry), *obj);
7684  cache->set(EntryToIndex(entry) + 1, *code);
7685  cache->ElementAdded();
7686  return cache;
7687 }
7688 
7689 
7690 void FixedArray::Shrink(int new_length) {
7691  DCHECK(0 <= new_length && new_length <= length());
7692  if (new_length < length()) {
7694  this, length() - new_length);
7695  }
7696 }
7697 
7698 
7700  Handle<FixedArray> content,
7701  Handle<JSObject> array) {
7702  DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements());
7703  ElementsAccessor* accessor = array->GetElementsAccessor();
7704  Handle<FixedArray> result;
7706  array->GetIsolate(), result,
7707  accessor->AddElementsToFixedArray(array, array, content),
7708  FixedArray);
7709 
7710 #ifdef ENABLE_SLOW_DCHECKS
7712  DisallowHeapAllocation no_allocation;
7713  for (int i = 0; i < result->length(); i++) {
7714  Object* current = result->get(i);
7715  DCHECK(current->IsNumber() || current->IsName());
7716  }
7717  }
7718 #endif
7719  return result;
7720 }
7721 
7722 
7724  Handle<FixedArray> second) {
7725  ElementsAccessor* accessor = ElementsAccessor::ForArray(second);
7726  Handle<FixedArray> result;
7728  first->GetIsolate(), result,
7729  accessor->AddElementsToFixedArray(
7730  Handle<Object>::null(), // receiver
7731  Handle<JSObject>::null(), // holder
7732  first,
7734  FixedArray);
7735 
7736 #ifdef ENABLE_SLOW_DCHECKS
7738  DisallowHeapAllocation no_allocation;
7739  for (int i = 0; i < result->length(); i++) {
7740  Object* current = result->get(i);
7741  DCHECK(current->IsNumber() || current->IsName());
7742  }
7743  }
7744 #endif
7745  return result;
7746 }
7747 
7748 
7750  Handle<FixedArray> array, int new_length, PretenureFlag pretenure) {
7751  Isolate* isolate = array->GetIsolate();
7752  if (new_length == 0) return isolate->factory()->empty_fixed_array();
7753  Handle<FixedArray> result =
7754  isolate->factory()->NewFixedArray(new_length, pretenure);
7755  // Copy the content
7756  DisallowHeapAllocation no_gc;
7757  int len = array->length();
7758  if (new_length < len) len = new_length;
7759  // We are taking the map from the old fixed array so the map is sure to
7760  // be an immortal immutable object.
7761  result->set_map_no_write_barrier(array->map());
7762  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
7763  for (int i = 0; i < len; i++) {
7764  result->set(i, array->get(i), mode);
7765  }
7766  return result;
7767 }
7768 
7769 
7770 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
7771  DisallowHeapAllocation no_gc;
7772  WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
7773  for (int index = 0; index < len; index++) {
7774  dest->set(dest_pos+index, get(pos+index), mode);
7775  }
7776 }
7777 
7778 
7779 #ifdef DEBUG
7780 bool FixedArray::IsEqualTo(FixedArray* other) {
7781  if (length() != other->length()) return false;
7782  for (int i = 0 ; i < length(); ++i) {
7783  if (get(i) != other->get(i)) return false;
7784  }
7785  return true;
7786 }
7787 #endif
7788 
7789 
7791  int number_of_descriptors,
7792  int slack) {
7793  DCHECK(0 <= number_of_descriptors);
7794  Factory* factory = isolate->factory();
7795  // Do not use DescriptorArray::cast on incomplete object.
7796  int size = number_of_descriptors + slack;
7797  if (size == 0) return factory->empty_descriptor_array();
7798  // Allocate the array of keys.
7799  Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
7800 
7801  result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
7802  result->set(kEnumCacheIndex, Smi::FromInt(0));
7803  return Handle<DescriptorArray>::cast(result);
7804 }
7805 
7806 
7808  set(kEnumCacheIndex, Smi::FromInt(0));
7809 }
7810 
7811 
7812 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
7813  descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
7814  Set(index, descriptor);
7815 }
7816 
7817 
7819  FixedArray* new_cache,
7820  Object* new_index_cache) {
7821  DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
7822  DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
7823  DCHECK(!IsEmpty());
7824  DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
7825  FixedArray::cast(bridge_storage)->
7826  set(kEnumCacheBridgeCacheIndex, new_cache);
7827  FixedArray::cast(bridge_storage)->
7828  set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
7829  set(kEnumCacheIndex, bridge_storage);
7830 }
7831 
7832 
7834  DescriptorArray* src,
7835  const WhitenessWitness& witness) {
7836  Object* value = src->GetValue(index);
7837  PropertyDetails details = src->GetDetails(index);
7838  Descriptor desc(handle(src->GetKey(index)),
7839  handle(value, src->GetIsolate()),
7840  details);
7841  Set(index, &desc, witness);
7842 }
7843 
7844 
7845 // We need the whiteness witness since sort will reshuffle the entries in the
7846 // descriptor array. If the descriptor array were to be black, the shuffling
7847 // would move a slot that was already recorded as pointing into an evacuation
7848 // candidate. This would result in missing updates upon evacuation.
7850  // In-place heap sort.
7851  int len = number_of_descriptors();
7852  // Reset sorting since the descriptor array might contain invalid pointers.
7853  for (int i = 0; i < len; ++i) SetSortedKey(i, i);
7854  // Bottom-up max-heap construction.
7855  // Index of the last node with children
7856  const int max_parent_index = (len / 2) - 1;
7857  for (int i = max_parent_index; i >= 0; --i) {
7858  int parent_index = i;
7859  const uint32_t parent_hash = GetSortedKey(i)->Hash();
7860  while (parent_index <= max_parent_index) {
7861  int child_index = 2 * parent_index + 1;
7862  uint32_t child_hash = GetSortedKey(child_index)->Hash();
7863  if (child_index + 1 < len) {
7864  uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
7865  if (right_child_hash > child_hash) {
7866  child_index++;
7867  child_hash = right_child_hash;
7868  }
7869  }
7870  if (child_hash <= parent_hash) break;
7871  SwapSortedKeys(parent_index, child_index);
7872  // Now element at child_index could be < its children.
7873  parent_index = child_index; // parent_hash remains correct.
7874  }
7875  }
7876 
7877  // Extract elements and create sorted array.
7878  for (int i = len - 1; i > 0; --i) {
7879  // Put max element at the back of the array.
7880  SwapSortedKeys(0, i);
7881  // Shift down the new top element.
7882  int parent_index = 0;
7883  const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
7884  const int max_parent_index = (i / 2) - 1;
7885  while (parent_index <= max_parent_index) {
7886  int child_index = parent_index * 2 + 1;
7887  uint32_t child_hash = GetSortedKey(child_index)->Hash();
7888  if (child_index + 1 < i) {
7889  uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
7890  if (right_child_hash > child_hash) {
7891  child_index++;
7892  child_hash = right_child_hash;
7893  }
7894  }
7895  if (child_hash <= parent_hash) break;
7896  SwapSortedKeys(parent_index, child_index);
7897  parent_index = child_index;
7898  }
7899  }
7900  DCHECK(IsSortedNoDuplicates());
7901 }
7902 
7903 
7905  Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
7906  copy->set_getter(pair->getter());
7907  copy->set_setter(pair->setter());
7908  return copy;
7909 }
7910 
7911 
7913  Object* accessor = get(component);
7914  return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
7915 }
7916 
7917 
7919  Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
7920  DCHECK(deopt_entry_count > 0);
7922  isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
7923  pretenure));
7924 }
7925 
7926 
7928  Isolate* isolate,
7929  int number_of_deopt_points,
7930  PretenureFlag pretenure) {
7931  Handle<FixedArray> result;
7932  if (number_of_deopt_points == 0) {
7933  result = isolate->factory()->empty_fixed_array();
7934  } else {
7935  result = isolate->factory()->NewFixedArray(
7936  LengthOfFixedArray(number_of_deopt_points), pretenure);
7937  }
7939 }
7940 
7941 
7942 #ifdef DEBUG
7943 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
7944  if (IsEmpty()) return other->IsEmpty();
7945  if (other->IsEmpty()) return false;
7946  if (length() != other->length()) return false;
7947  for (int i = 0; i < length(); ++i) {
7948  if (get(i) != other->get(i)) return false;
7949  }
7950  return true;
7951 }
7952 #endif
7953 
7954 
7956  if (!GetIsolate()->heap()->Contains(this)) return false;
7957  return true;
7958 }
7959 
7960 
7962  DCHECK(!AllowHeapAllocation::IsAllowed());
7963  int length = this->length();
7964  StringShape shape(this);
7965  String* string = this;
7966  int offset = 0;
7967  if (shape.representation_tag() == kConsStringTag) {
7968  ConsString* cons = ConsString::cast(string);
7969  if (cons->second()->length() != 0) {
7970  return FlatContent();
7971  }
7972  string = cons->first();
7973  shape = StringShape(string);
7974  }
7975  if (shape.representation_tag() == kSlicedStringTag) {
7976  SlicedString* slice = SlicedString::cast(string);
7977  offset = slice->offset();
7978  string = slice->parent();
7979  shape = StringShape(string);
7980  DCHECK(shape.representation_tag() != kConsStringTag &&
7981  shape.representation_tag() != kSlicedStringTag);
7982  }
7983  if (shape.encoding_tag() == kOneByteStringTag) {
7984  const uint8_t* start;
7985  if (shape.representation_tag() == kSeqStringTag) {
7986  start = SeqOneByteString::cast(string)->GetChars();
7987  } else {
7988  start = ExternalOneByteString::cast(string)->GetChars();
7989  }
7990  return FlatContent(start + offset, length);
7991  } else {
7992  DCHECK(shape.encoding_tag() == kTwoByteStringTag);
7993  const uc16* start;
7994  if (shape.representation_tag() == kSeqStringTag) {
7995  start = SeqTwoByteString::cast(string)->GetChars();
7996  } else {
7997  start = ExternalTwoByteString::cast(string)->GetChars();
7998  }
7999  return FlatContent(start + offset, length);
8000  }
8001 }
8002 
8003 
8005  RobustnessFlag robust_flag,
8006  int offset,
8007  int length,
8008  int* length_return) {
8009  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8010  return SmartArrayPointer<char>(NULL);
8011  }
8012  Heap* heap = GetHeap();
8013 
8014  // Negative length means the to the end of the string.
8015  if (length < 0) length = kMaxInt - offset;
8016 
8017  // Compute the size of the UTF-8 string. Start at the specified offset.
8019  heap->isolate()->objects_string_iterator());
8020  StringCharacterStream stream(this, op.value(), offset);
8021  int character_position = offset;
8022  int utf8_bytes = 0;
8024  while (stream.HasMore() && character_position++ < offset + length) {
8025  uint16_t character = stream.GetNext();
8026  utf8_bytes += unibrow::Utf8::Length(character, last);
8027  last = character;
8028  }
8029 
8030  if (length_return) {
8031  *length_return = utf8_bytes;
8032  }
8033 
8034  char* result = NewArray<char>(utf8_bytes + 1);
8035 
8036  // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
8037  stream.Reset(this, offset);
8038  character_position = offset;
8039  int utf8_byte_position = 0;
8041  while (stream.HasMore() && character_position++ < offset + length) {
8042  uint16_t character = stream.GetNext();
8043  if (allow_nulls == DISALLOW_NULLS && character == 0) {
8044  character = ' ';
8045  }
8046  utf8_byte_position +=
8047  unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
8048  last = character;
8049  }
8050  result[utf8_byte_position] = 0;
8051  return SmartArrayPointer<char>(result);
8052 }
8053 
8054 
8056  RobustnessFlag robust_flag,
8057  int* length_return) {
8058  return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
8059 }
8060 
8061 
8062 const uc16* String::GetTwoByteData(unsigned start) {
8063  DCHECK(!IsOneByteRepresentationUnderneath());
8064  switch (StringShape(this).representation_tag()) {
8065  case kSeqStringTag:
8066  return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
8067  case kExternalStringTag:
8068  return ExternalTwoByteString::cast(this)->
8069  ExternalTwoByteStringGetData(start);
8070  case kSlicedStringTag: {
8071  SlicedString* slice = SlicedString::cast(this);
8072  return slice->parent()->GetTwoByteData(start + slice->offset());
8073  }
8074  case kConsStringTag:
8075  UNREACHABLE();
8076  return NULL;
8077  }
8078  UNREACHABLE();
8079  return NULL;
8080 }
8081 
8082 
8084  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
8085  return SmartArrayPointer<uc16>();
8086  }
8087  Heap* heap = GetHeap();
8088 
8090  heap->isolate()->objects_string_iterator());
8091  StringCharacterStream stream(this, op.value());
8092 
8093  uc16* result = NewArray<uc16>(length() + 1);
8094 
8095  int i = 0;
8096  while (stream.HasMore()) {
8097  uint16_t character = stream.GetNext();
8098  result[i++] = character;
8099  }
8100  result[i] = 0;
8101  return SmartArrayPointer<uc16>(result);
8102 }
8103 
8104 
8106  return reinterpret_cast<uc16*>(
8107  reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
8108 }
8109 
8110 
8111 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
8112  Relocatable* current = isolate->relocatable_top();
8113  while (current != NULL) {
8114  current->PostGarbageCollection();
8115  current = current->prev_;
8116  }
8117 }
8118 
8119 
8120 // Reserve space for statics needing saving and restoring.
8122  return sizeof(Relocatable*); // NOLINT
8123 }
8124 
8125 
8126 // Archive statics that are thread-local.
8127 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
8128  *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
8129  isolate->set_relocatable_top(NULL);
8130  return to + ArchiveSpacePerThread();
8131 }
8132 
8133 
8134 // Restore statics that are thread-local.
8135 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
8136  isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
8137  return from + ArchiveSpacePerThread();
8138 }
8139 
8140 
8141 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
8142  Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
8143  Iterate(v, top);
8144  return thread_storage + ArchiveSpacePerThread();
8145 }
8146 
8147 
8148 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
8149  Iterate(v, isolate->relocatable_top());
8150 }
8151 
8152 
8153 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
8154  Relocatable* current = top;
8155  while (current != NULL) {
8156  current->IterateInstance(v);
8157  current = current->prev_;
8158  }
8159 }
8160 
8161 
8163  : Relocatable(isolate),
8164  str_(str.location()),
8165  length_(str->length()) {
8167 }
8168 
8169 
8171  : Relocatable(isolate),
8172  str_(0),
8173  is_one_byte_(true),
8174  length_(input.length()),
8175  start_(input.start()) {}
8176 
8177 
8179  if (str_ == NULL) return;
8180  Handle<String> str(str_);
8181  DCHECK(str->IsFlat());
8182  DisallowHeapAllocation no_gc;
8183  // This does not actually prevent the vector from being relocated later.
8184  String::FlatContent content = str->GetFlatContent();
8185  DCHECK(content.IsFlat());
8186  is_one_byte_ = content.IsOneByte();
8187  if (is_one_byte_) {
8188  start_ = content.ToOneByteVector().start();
8189  } else {
8190  start_ = content.ToUC16Vector().start();
8191  }
8192 }
8193 
8194 
8195 void ConsStringIteratorOp::Initialize(ConsString* cons_string, int offset) {
8196  DCHECK(cons_string != NULL);
8197  root_ = cons_string;
8198  consumed_ = offset;
8199  // Force stack blown condition to trigger restart.
8200  depth_ = 1;
8202  DCHECK(StackBlown());
8203 }
8204 
8205 
8207  DCHECK(depth_ != 0);
8208  DCHECK_EQ(0, *offset_out);
8209  bool blew_stack = StackBlown();
8210  String* string = NULL;
8211  // Get the next leaf if there is one.
8212  if (!blew_stack) string = NextLeaf(&blew_stack);
8213  // Restart search from root.
8214  if (blew_stack) {
8215  DCHECK(string == NULL);
8216  string = Search(offset_out);
8217  }
8218  // Ensure future calls return null immediately.
8219  if (string == NULL) Reset(NULL);
8220  return string;
8221 }
8222 
8223 
8225  ConsString* cons_string = root_;
8226  // Reset the stack, pushing the root string.
8227  depth_ = 1;
8228  maximum_depth_ = 1;
8229  frames_[0] = cons_string;
8230  const int consumed = consumed_;
8231  int offset = 0;
8232  while (true) {
8233  // Loop until the string is found which contains the target offset.
8234  String* string = cons_string->first();
8235  int length = string->length();
8236  int32_t type;
8237  if (consumed < offset + length) {
8238  // Target offset is in the left branch.
8239  // Keep going if we're still in a ConString.
8240  type = string->map()->instance_type();
8241  if ((type & kStringRepresentationMask) == kConsStringTag) {
8242  cons_string = ConsString::cast(string);
8243  PushLeft(cons_string);
8244  continue;
8245  }
8246  // Tell the stack we're done descending.
8248  } else {
8249  // Descend right.
8250  // Update progress through the string.
8251  offset += length;
8252  // Keep going if we're still in a ConString.
8253  string = cons_string->second();
8254  type = string->map()->instance_type();
8255  if ((type & kStringRepresentationMask) == kConsStringTag) {
8256  cons_string = ConsString::cast(string);
8257  PushRight(cons_string);
8258  continue;
8259  }
8260  // Need this to be updated for the current string.
8261  length = string->length();
8262  // Account for the possibility of an empty right leaf.
8263  // This happens only if we have asked for an offset outside the string.
8264  if (length == 0) {
8265  // Reset so future operations will return null immediately.
8266  Reset(NULL);
8267  return NULL;
8268  }
8269  // Tell the stack we're done descending.
8271  // Pop stack so next iteration is in correct place.
8272  Pop();
8273  }
8274  DCHECK(length != 0);
8275  // Adjust return values and exit.
8276  consumed_ = offset + length;
8277  *offset_out = consumed - offset;
8278  return string;
8279  }
8280  UNREACHABLE();
8281  return NULL;
8282 }
8283 
8284 
8286  while (true) {
8287  // Tree traversal complete.
8288  if (depth_ == 0) {
8289  *blew_stack = false;
8290  return NULL;
8291  }
8292  // We've lost track of higher nodes.
8293  if (StackBlown()) {
8294  *blew_stack = true;
8295  return NULL;
8296  }
8297  // Go right.
8298  ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
8299  String* string = cons_string->second();
8300  int32_t type = string->map()->instance_type();
8301  if ((type & kStringRepresentationMask) != kConsStringTag) {
8302  // Pop stack so next iteration is in correct place.
8303  Pop();
8304  int length = string->length();
8305  // Could be a flattened ConsString.
8306  if (length == 0) continue;
8307  consumed_ += length;
8308  return string;
8309  }
8310  cons_string = ConsString::cast(string);
8311  PushRight(cons_string);
8312  // Need to traverse all the way left.
8313  while (true) {
8314  // Continue left.
8315  string = cons_string->first();
8316  type = string->map()->instance_type();
8317  if ((type & kStringRepresentationMask) != kConsStringTag) {
8319  int length = string->length();
8320  DCHECK(length != 0);
8321  consumed_ += length;
8322  return string;
8323  }
8324  cons_string = ConsString::cast(string);
8325  PushLeft(cons_string);
8326  }
8327  }
8328  UNREACHABLE();
8329  return NULL;
8330 }
8331 
8332 
8334  DCHECK(index >= 0 && index < this->length());
8335 
8336  // Check for a flattened cons string
8337  if (second()->length() == 0) {
8338  String* left = first();
8339  return left->Get(index);
8340  }
8341 
8342  String* string = String::cast(this);
8343 
8344  while (true) {
8345  if (StringShape(string).IsCons()) {
8346  ConsString* cons_string = ConsString::cast(string);
8347  String* left = cons_string->first();
8348  if (left->length() > index) {
8349  string = left;
8350  } else {
8351  index -= left->length();
8352  string = cons_string->second();
8353  }
8354  } else {
8355  return string->Get(index);
8356  }
8357  }
8358 
8359  UNREACHABLE();
8360  return 0;
8361 }
8362 
8363 
8365  return parent()->Get(offset() + index);
8366 }
8367 
8368 
8369 template <typename sinkchar>
8371  sinkchar* sink,
8372  int f,
8373  int t) {
8374  String* source = src;
8375  int from = f;
8376  int to = t;
8377  while (true) {
8378  DCHECK(0 <= from && from <= to && to <= source->length());
8379  switch (StringShape(source).full_representation_tag()) {
8381  CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
8382  to - from);
8383  return;
8384  }
8386  const uc16* data =
8387  ExternalTwoByteString::cast(source)->GetChars();
8388  CopyChars(sink,
8389  data + from,
8390  to - from);
8391  return;
8392  }
8394  CopyChars(sink,
8395  SeqOneByteString::cast(source)->GetChars() + from,
8396  to - from);
8397  return;
8398  }
8400  CopyChars(sink,
8401  SeqTwoByteString::cast(source)->GetChars() + from,
8402  to - from);
8403  return;
8404  }
8407  ConsString* cons_string = ConsString::cast(source);
8408  String* first = cons_string->first();
8409  int boundary = first->length();
8410  if (to - boundary >= boundary - from) {
8411  // Right hand side is longer. Recurse over left.
8412  if (from < boundary) {
8413  WriteToFlat(first, sink, from, boundary);
8414  sink += boundary - from;
8415  from = 0;
8416  } else {
8417  from -= boundary;
8418  }
8419  to -= boundary;
8420  source = cons_string->second();
8421  } else {
8422  // Left hand side is longer. Recurse over right.
8423  if (to > boundary) {
8424  String* second = cons_string->second();
8425  // When repeatedly appending to a string, we get a cons string that
8426  // is unbalanced to the left, a list, essentially. We inline the
8427  // common case of sequential one-byte right child.
8428  if (to - boundary == 1) {
8429  sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
8430  } else if (second->IsSeqOneByteString()) {
8431  CopyChars(sink + boundary - from,
8432  SeqOneByteString::cast(second)->GetChars(),
8433  to - boundary);
8434  } else {
8435  WriteToFlat(second,
8436  sink + boundary - from,
8437  0,
8438  to - boundary);
8439  }
8440  to = boundary;
8441  }
8442  source = first;
8443  }
8444  break;
8445  }
8448  SlicedString* slice = SlicedString::cast(source);
8449  unsigned offset = slice->offset();
8450  WriteToFlat(slice->parent(), sink, from + offset, to + offset);
8451  return;
8452  }
8453  }
8454  }
8455 }
8456 
8457 
8458 
8459 template <typename SourceChar>
8460 static void CalculateLineEndsImpl(Isolate* isolate,
8461  List<int>* line_ends,
8463  bool include_ending_line) {
8464  const int src_len = src.length();
8466 
8467  // Find and record line ends.
8468  int position = 0;
8469  while (position != -1 && position < src_len) {
8470  position = search.Search(src, position);
8471  if (position != -1) {
8472  line_ends->Add(position);
8473  position++;
8474  } else if (include_ending_line) {
8475  // Even if the last line misses a line end, it is counted.
8476  line_ends->Add(src_len);
8477  return;
8478  }
8479  }
8480 }
8481 
8482 
8484  bool include_ending_line) {
8485  src = Flatten(src);
8486  // Rough estimate of line count based on a roughly estimated average
8487  // length of (unpacked) code.
8488  int line_count_estimate = src->length() >> 4;
8489  List<int> line_ends(line_count_estimate);
8490  Isolate* isolate = src->GetIsolate();
8491  { DisallowHeapAllocation no_allocation; // ensure vectors stay valid.
8492  // Dispatch on type of strings.
8493  String::FlatContent content = src->GetFlatContent();
8494  DCHECK(content.IsFlat());
8495  if (content.IsOneByte()) {
8496  CalculateLineEndsImpl(isolate,
8497  &line_ends,
8498  content.ToOneByteVector(),
8499  include_ending_line);
8500  } else {
8501  CalculateLineEndsImpl(isolate,
8502  &line_ends,
8503  content.ToUC16Vector(),
8504  include_ending_line);
8505  }
8506  }
8507  int line_count = line_ends.length();
8508  Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
8509  for (int i = 0; i < line_count; i++) {
8510  array->set(i, Smi::FromInt(line_ends[i]));
8511  }
8512  return array;
8513 }
8514 
8515 
8516 // Compares the contents of two strings by reading and comparing
8517 // int-sized blocks of characters.
8518 template <typename Char>
8519 static inline bool CompareRawStringContents(const Char* const a,
8520  const Char* const b,
8521  int length) {
8522  return CompareChars(a, b, length) == 0;
8523 }
8524 
8525 
8526 template<typename Chars1, typename Chars2>
8528  public:
8529  static inline bool compare(const Chars1* a, const Chars2* b, int len) {
8530  DCHECK(sizeof(Chars1) != sizeof(Chars2));
8531  for (int i = 0; i < len; i++) {
8532  if (a[i] != b[i]) {
8533  return false;
8534  }
8535  }
8536  return true;
8537  }
8538 };
8539 
8540 
8541 template<>
8543  public:
8544  static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
8545  return CompareRawStringContents(a, b, len);
8546  }
8547 };
8548 
8549 
8550 template<>
8551 class RawStringComparator<uint8_t, uint8_t> {
8552  public:
8553  static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
8554  return CompareRawStringContents(a, b, len);
8555  }
8556 };
8557 
8558 
8560  class State {
8561  public:
8562  explicit inline State(ConsStringIteratorOp* op)
8563  : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {}
8564 
8565  inline void Init(String* string) {
8566  ConsString* cons_string = String::VisitFlat(this, string);
8567  op_->Reset(cons_string);
8568  if (cons_string != NULL) {
8569  int offset;
8570  string = op_->Next(&offset);
8571  String::VisitFlat(this, string, offset);
8572  }
8573  }
8574 
8575  inline void VisitOneByteString(const uint8_t* chars, int length) {
8576  is_one_byte_ = true;
8577  buffer8_ = chars;
8578  length_ = length;
8579  }
8580 
8581  inline void VisitTwoByteString(const uint16_t* chars, int length) {
8582  is_one_byte_ = false;
8583  buffer16_ = chars;
8584  length_ = length;
8585  }
8586 
8587  void Advance(int consumed) {
8588  DCHECK(consumed <= length_);
8589  // Still in buffer.
8590  if (length_ != consumed) {
8591  if (is_one_byte_) {
8592  buffer8_ += consumed;
8593  } else {
8594  buffer16_ += consumed;
8595  }
8596  length_ -= consumed;
8597  return;
8598  }
8599  // Advance state.
8600  int offset;
8601  String* next = op_->Next(&offset);
8602  DCHECK_EQ(0, offset);
8603  DCHECK(next != NULL);
8604  String::VisitFlat(this, next);
8605  }
8606 
8609  int length_;
8610  union {
8611  const uint8_t* buffer8_;
8613  };
8614 
8615  private:
8617  };
8618 
8619  public:
8621  ConsStringIteratorOp* op_2)
8622  : state_1_(op_1),
8623  state_2_(op_2) {
8624  }
8625 
8626  template<typename Chars1, typename Chars2>
8627  static inline bool Equals(State* state_1, State* state_2, int to_check) {
8628  const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
8629  const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
8630  return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
8631  }
8632 
8633  bool Equals(String* string_1, String* string_2) {
8634  int length = string_1->length();
8635  state_1_.Init(string_1);
8636  state_2_.Init(string_2);
8637  while (true) {
8638  int to_check = Min(state_1_.length_, state_2_.length_);
8639  DCHECK(to_check > 0 && to_check <= length);
8640  bool is_equal;
8641  if (state_1_.is_one_byte_) {
8642  if (state_2_.is_one_byte_) {
8643  is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
8644  } else {
8645  is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
8646  }
8647  } else {
8648  if (state_2_.is_one_byte_) {
8649  is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
8650  } else {
8651  is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
8652  }
8653  }
8654  // Looping done.
8655  if (!is_equal) return false;
8656  length -= to_check;
8657  // Exit condition. Strings are equal.
8658  if (length == 0) return true;
8659  state_1_.Advance(to_check);
8660  state_2_.Advance(to_check);
8661  }
8662  }
8663 
8664  private:
8668 };
8669 
8670 
8672  DisallowHeapAllocation no_gc;
8673  // Fast check: negative check with lengths.
8674  int len = length();
8675  if (len != other->length()) return false;
8676  if (len == 0) return true;
8677 
8678  // Fast check: if hash code is computed for both strings
8679  // a fast negative check can be performed.
8680  if (HasHashCode() && other->HasHashCode()) {
8681 #ifdef ENABLE_SLOW_DCHECKS
8683  if (Hash() != other->Hash()) {
8684  bool found_difference = false;
8685  for (int i = 0; i < len; i++) {
8686  if (Get(i) != other->Get(i)) {
8687  found_difference = true;
8688  break;
8689  }
8690  }
8691  DCHECK(found_difference);
8692  }
8693  }
8694 #endif
8695  if (Hash() != other->Hash()) return false;
8696  }
8697 
8698  // We know the strings are both non-empty. Compare the first chars
8699  // before we try to flatten the strings.
8700  if (this->Get(0) != other->Get(0)) return false;
8701 
8702  if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
8703  const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
8704  const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
8705  return CompareRawStringContents(str1, str2, len);
8706  }
8707 
8708  Isolate* isolate = GetIsolate();
8711 
8712  return comparator.Equals(this, other);
8713 }
8714 
8715 
8717  // Fast check: negative check with lengths.
8718  int one_length = one->length();
8719  if (one_length != two->length()) return false;
8720  if (one_length == 0) return true;
8721 
8722  // Fast check: if hash code is computed for both strings
8723  // a fast negative check can be performed.
8724  if (one->HasHashCode() && two->HasHashCode()) {
8725 #ifdef ENABLE_SLOW_DCHECKS
8727  if (one->Hash() != two->Hash()) {
8728  bool found_difference = false;
8729  for (int i = 0; i < one_length; i++) {
8730  if (one->Get(i) != two->Get(i)) {
8731  found_difference = true;
8732  break;
8733  }
8734  }
8735  DCHECK(found_difference);
8736  }
8737  }
8738 #endif
8739  if (one->Hash() != two->Hash()) return false;
8740  }
8741 
8742  // We know the strings are both non-empty. Compare the first chars
8743  // before we try to flatten the strings.
8744  if (one->Get(0) != two->Get(0)) return false;
8745 
8746  one = String::Flatten(one);
8747  two = String::Flatten(two);
8748 
8749  DisallowHeapAllocation no_gc;
8750  String::FlatContent flat1 = one->GetFlatContent();
8751  String::FlatContent flat2 = two->GetFlatContent();
8752 
8753  if (flat1.IsOneByte() && flat2.IsOneByte()) {
8754  return CompareRawStringContents(flat1.ToOneByteVector().start(),
8755  flat2.ToOneByteVector().start(),
8756  one_length);
8757  } else {
8758  for (int i = 0; i < one_length; i++) {
8759  if (flat1.Get(i) != flat2.Get(i)) return false;
8760  }
8761  return true;
8762  }
8763 }
8764 
8765 
8767  if (StringShape(this).IsInternalized()) return false;
8768 
8769  Map* map = this->map();
8770  Heap* heap = GetHeap();
8771  if (map == heap->string_map()) {
8772  this->set_map(heap->undetectable_string_map());
8773  return true;
8774  } else if (map == heap->one_byte_string_map()) {
8775  this->set_map(heap->undetectable_one_byte_string_map());
8776  return true;
8777  }
8778  // Rest cannot be marked as undetectable
8779  return false;
8780 }
8781 
8782 
8783 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
8784  int slen = length();
8785  // Can't check exact length equality, but we can check bounds.
8786  int str_len = str.length();
8787  if (!allow_prefix_match &&
8788  (str_len < slen ||
8789  str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
8790  return false;
8791  }
8792  int i;
8793  unsigned remaining_in_str = static_cast<unsigned>(str_len);
8794  const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
8795  for (i = 0; i < slen && remaining_in_str > 0; i++) {
8796  unsigned cursor = 0;
8797  uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
8798  DCHECK(cursor > 0 && cursor <= remaining_in_str);
8800  if (i > slen - 1) return false;
8801  if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
8802  if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
8803  } else {
8804  if (Get(i) != r) return false;
8805  }
8806  utf8_data += cursor;
8807  remaining_in_str -= cursor;
8808  }
8809  return (allow_prefix_match || i == slen) && remaining_in_str == 0;
8810 }
8811 
8812 
8814  int slen = length();
8815  if (str.length() != slen) return false;
8816  DisallowHeapAllocation no_gc;
8817  FlatContent content = GetFlatContent();
8818  if (content.IsOneByte()) {
8819  return CompareChars(content.ToOneByteVector().start(),
8820  str.start(), slen) == 0;
8821  }
8822  for (int i = 0; i < slen; i++) {
8823  if (Get(i) != static_cast<uint16_t>(str[i])) return false;
8824  }
8825  return true;
8826 }
8827 
8828 
8830  int slen = length();
8831  if (str.length() != slen) return false;
8832  DisallowHeapAllocation no_gc;
8833  FlatContent content = GetFlatContent();
8834  if (content.IsTwoByte()) {
8835  return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
8836  }
8837  for (int i = 0; i < slen; i++) {
8838  if (Get(i) != str[i]) return false;
8839  }
8840  return true;
8841 }
8842 
8843 
8845  // Should only be called if hash code has not yet been computed.
8846  DCHECK(!HasHashCode());
8847 
8848  // Store the hash code in the object.
8849  uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
8850  set_hash_field(field);
8851 
8852  // Check the hash code is there.
8853  DCHECK(HasHashCode());
8854  uint32_t result = field >> kHashShift;
8855  DCHECK(result != 0); // Ensure that the hash value of 0 is never computed.
8856  return result;
8857 }
8858 
8859 
8861  int length = this->length();
8862  if (length == 0 || length > kMaxArrayIndexSize) return false;
8864  StringCharacterStream stream(this, &op);
8865  return StringToArrayIndex(&stream, index);
8866 }
8867 
8868 
8871  Hash(); // force computation of hash code
8872  uint32_t field = hash_field();
8873  if ((field & kIsNotArrayIndexMask) != 0) return false;
8874  // Isolate the array index form the full hash field.
8875  *index = ArrayIndexValueBits::decode(field);
8876  return true;
8877  } else {
8878  return ComputeArrayIndex(index);
8879  }
8880 }
8881 
8882 
8884  int new_size, old_size;
8885  int old_length = string->length();
8886  if (old_length <= new_length) return string;
8887 
8888  if (string->IsSeqOneByteString()) {
8889  old_size = SeqOneByteString::SizeFor(old_length);
8890  new_size = SeqOneByteString::SizeFor(new_length);
8891  } else {
8892  DCHECK(string->IsSeqTwoByteString());
8893  old_size = SeqTwoByteString::SizeFor(old_length);
8894  new_size = SeqTwoByteString::SizeFor(new_length);
8895  }
8896 
8897  int delta = old_size - new_size;
8898 
8899  Address start_of_string = string->address();
8900  DCHECK_OBJECT_ALIGNED(start_of_string);
8901  DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
8902 
8903  Heap* heap = string->GetHeap();
8904  NewSpace* newspace = heap->new_space();
8905  if (newspace->Contains(start_of_string) &&
8906  newspace->top() == start_of_string + old_size) {
8907  // Last allocated object in new space. Simply lower allocation top.
8908  newspace->set_top(start_of_string + new_size);
8909  } else {
8910  // Sizes are pointer size aligned, so that we can use filler objects
8911  // that are a multiple of pointer size.
8912  heap->CreateFillerObjectAt(start_of_string + new_size, delta);
8913  }
8914  heap->AdjustLiveBytes(start_of_string, -delta, Heap::FROM_MUTATOR);
8915 
8916  // We are storing the new length using release store after creating a filler
8917  // for the left-over space to avoid races with the sweeper thread.
8918  string->synchronized_set_length(new_length);
8919 
8920  if (new_length == 0) return heap->isolate()->factory()->empty_string();
8921  return string;
8922 }
8923 
8924 
8926  // For array indexes mix the length into the hash as an array index could
8927  // be zero.
8928  DCHECK(length > 0);
8932 
8934  value |= length << String::ArrayIndexLengthBits::kShift;
8935 
8936  DCHECK((value & String::kIsNotArrayIndexMask) == 0);
8938  (value & String::kContainsCachedArrayIndexMask) == 0);
8939  return value;
8940 }
8941 
8942 
8945  if (is_array_index_) {
8947  }
8948  return (GetHashCore(raw_running_hash_) << String::kHashShift) |
8950  } else {
8952  }
8953 }
8954 
8955 
8957  uint32_t seed,
8958  int* utf16_length_out) {
8959  int vector_length = chars.length();
8960  // Handle some edge cases
8961  if (vector_length <= 1) {
8962  DCHECK(vector_length == 0 ||
8963  static_cast<uint8_t>(chars.start()[0]) <=
8965  *utf16_length_out = vector_length;
8966  return HashSequentialString(chars.start(), vector_length, seed);
8967  }
8968  // Start with a fake length which won't affect computation.
8969  // It will be updated later.
8971  unsigned remaining = static_cast<unsigned>(vector_length);
8972  const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
8973  int utf16_length = 0;
8974  bool is_index = true;
8975  DCHECK(hasher.is_array_index_);
8976  while (remaining > 0) {
8977  unsigned consumed = 0;
8978  uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
8979  DCHECK(consumed > 0 && consumed <= remaining);
8980  stream += consumed;
8981  remaining -= consumed;
8982  bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
8983  utf16_length += is_two_characters ? 2 : 1;
8984  // No need to keep hashing. But we do need to calculate utf16_length.
8985  if (utf16_length > String::kMaxHashCalcLength) continue;
8986  if (is_two_characters) {
8989  hasher.AddCharacter(c1);
8990  hasher.AddCharacter(c2);
8991  if (is_index) is_index = hasher.UpdateIndex(c1);
8992  if (is_index) is_index = hasher.UpdateIndex(c2);
8993  } else {
8994  hasher.AddCharacter(c);
8995  if (is_index) is_index = hasher.UpdateIndex(c);
8996  }
8997  }
8998  *utf16_length_out = static_cast<int>(utf16_length);
8999  // Must set length here so that hash computation is correct.
9000  hasher.length_ = utf16_length;
9001  return hasher.GetHashField();
9002 }
9003 
9004 
9005 void String::PrintOn(FILE* file) {
9006  int length = this->length();
9007  for (int i = 0; i < length; i++) {
9008  PrintF(file, "%c", Get(i));
9009  }
9010 }
9011 
9012 
9013 inline static uint32_t ObjectAddressForHashing(Object* object) {
9014  uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
9015  return value & MemoryChunk::kAlignmentMask;
9016 }
9017 
9018 
9019 int Map::Hash() {
9020  // For performance reasons we only hash the 3 most variable fields of a map:
9021  // constructor, prototype and bit_field2. For predictability reasons we
9022  // use objects' offsets in respective pages for hashing instead of raw
9023  // addresses.
9024 
9025  // Shift away the tag.
9026  int hash = ObjectAddressForHashing(constructor()) >> 2;
9027 
9028  // XOR-ing the prototype and constructor directly yields too many zero bits
9029  // when the two pointers are close (which is fairly common).
9030  // To avoid this we shift the prototype bits relatively to the constructor.
9031  hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
9032 
9033  return hash ^ (hash >> 16) ^ bit_field2();
9034 }
9035 
9036 
9037 static bool CheckEquivalent(Map* first, Map* second) {
9038  return
9039  first->constructor() == second->constructor() &&
9040  first->prototype() == second->prototype() &&
9041  first->instance_type() == second->instance_type() &&
9042  first->bit_field() == second->bit_field() &&
9043  first->bit_field2() == second->bit_field2() &&
9044  first->is_frozen() == second->is_frozen() &&
9046 }
9047 
9048 
9050  return CheckEquivalent(this, other);
9051 }
9052 
9053 
9056  int properties = mode == CLEAR_INOBJECT_PROPERTIES
9057  ? 0 : other->inobject_properties();
9058  return CheckEquivalent(this, other) && inobject_properties() == properties;
9059 }
9060 
9061 
9063  // Unfortunately the serializer relies on pointers within an object being
9064  // visited in-order, so we have to iterate both the code and heap pointers in
9065  // the small section before doing so in the extended section.
9066  for (int s = 0; s <= final_section(); ++s) {
9067  LayoutSection section = static_cast<LayoutSection>(s);
9068  ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR,
9069  section);
9070  while (!code_iter.is_finished()) {
9071  v->VisitCodeEntry(reinterpret_cast<Address>(
9072  RawFieldOfElementAt(code_iter.next_index())));
9073  }
9074 
9075  ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR,
9076  section);
9077  while (!heap_iter.is_finished()) {
9078  v->VisitPointer(RawFieldOfElementAt(heap_iter.next_index()));
9079  }
9080  }
9081 }
9082 
9083 
9085  Type type[] = { CODE_PTR, HEAP_PTR };
9086  Address default_value[] = {
9087  isolate->builtins()->builtin(Builtins::kIllegal)->entry(),
9088  reinterpret_cast<Address>(isolate->heap()->undefined_value()) };
9089 
9090  for (int i = 0; i < 2; ++i) {
9091  for (int s = 0; s <= final_section(); ++s) {
9092  LayoutSection section = static_cast<LayoutSection>(s);
9093  if (number_of_entries(type[i], section) > 0) {
9094  int offset = OffsetOfElementAt(first_index(type[i], section));
9095  MemsetPointer(
9096  reinterpret_cast<Address*>(HeapObject::RawField(this, offset)),
9097  default_value[i],
9098  number_of_entries(type[i], section));
9099  }
9100  }
9101  }
9102 }
9103 
9104 
9106  // Iterate over all fields in the body but take care in dealing with
9107  // the code entry.
9109  v->VisitCodeEntry(this->address() + kCodeEntryOffset);
9110  IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
9111 }
9112 
9113 
9115  DCHECK(!IsOptimized());
9116  DCHECK(shared()->allows_lazy_compilation() ||
9117  code()->optimizable());
9118  DCHECK(!shared()->is_generator());
9120  GetIsolate()->builtins()->builtin(Builtins::kCompileOptimized));
9121  // No write barrier required, since the builtin is part of the root set.
9122 }
9123 
9124 
9126  DCHECK(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
9127  DCHECK(!IsOptimized());
9128  DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9129  DCHECK(!shared()->is_generator());
9130  DCHECK(GetIsolate()->concurrent_recompilation_enabled());
9131  if (FLAG_trace_concurrent_recompilation) {
9132  PrintF(" ** Marking ");
9133  ShortPrint();
9134  PrintF(" for concurrent recompilation.\n");
9135  }
9137  GetIsolate()->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
9138  // No write barrier required, since the builtin is part of the root set.
9139 }
9140 
9141 
9143  // We can only arrive here via the concurrent-recompilation builtin. If
9144  // break points were set, the code would point to the lazy-compile builtin.
9145  DCHECK(!GetIsolate()->DebuggerHasBreakPoints());
9147  DCHECK(shared()->allows_lazy_compilation() || code()->optimizable());
9148  DCHECK(GetIsolate()->concurrent_recompilation_enabled());
9149  if (FLAG_trace_concurrent_recompilation) {
9150  PrintF(" ** Queueing ");
9151  ShortPrint();
9152  PrintF(" for concurrent recompilation.\n");
9153  }
9155  GetIsolate()->builtins()->builtin(Builtins::kInOptimizationQueue));
9156  // No write barrier required, since the builtin is part of the root set.
9157 }
9158 
9159 
9161  Isolate* isolate = function->GetIsolate();
9162  Handle<Map> map(function->map());
9163  Handle<SharedFunctionInfo> shared(function->shared());
9164  Handle<Context> context(function->context());
9165  Handle<JSFunction> clone =
9166  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
9167 
9168  if (shared->bound()) {
9169  clone->set_function_bindings(function->function_bindings());
9170  }
9171 
9172  // In typical case, __proto__ of ``function`` is the default Function
9173  // prototype, which means that SetPrototype below is a no-op.
9174  // In rare cases when that is not true, we mutate the clone's __proto__.
9175  Handle<Object> original_prototype(map->prototype(), isolate);
9176  if (*original_prototype != clone->map()->prototype()) {
9177  JSObject::SetPrototype(clone, original_prototype, false).Assert();
9178  }
9179 
9180  return clone;
9181 }
9182 
9183 
9186  Handle<Context> native_context,
9187  Handle<Code> code,
9189  BailoutId osr_ast_id) {
9190  Isolate* isolate = shared->GetIsolate();
9191  DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
9192  DCHECK(native_context->IsNativeContext());
9194  Handle<FixedArray> new_code_map;
9195  Handle<Object> value(shared->optimized_code_map(), isolate);
9196  int old_length;
9197  if (value->IsSmi()) {
9198  // No optimized code map.
9199  DCHECK_EQ(0, Smi::cast(*value)->value());
9200  // Create 3 entries per context {context, code, literals}.
9201  new_code_map = isolate->factory()->NewFixedArray(kInitialLength);
9202  old_length = kEntriesStart;
9203  } else {
9204  // Copy old map and append one new entry.
9205  Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value);
9206  DCHECK_EQ(-1, shared->SearchOptimizedCodeMap(*native_context, osr_ast_id));
9207  old_length = old_code_map->length();
9208  new_code_map = FixedArray::CopySize(
9209  old_code_map, old_length + kEntryLength);
9210  // Zap the old map for the sake of the heap verifier.
9211  if (Heap::ShouldZapGarbage()) {
9212  Object** data = old_code_map->data_start();
9213  MemsetPointer(data, isolate->heap()->the_hole_value(), old_length);
9214  }
9215  }
9216  new_code_map->set(old_length + kContextOffset, *native_context);
9217  new_code_map->set(old_length + kCachedCodeOffset, *code);
9218  new_code_map->set(old_length + kLiteralsOffset, *literals);
9219  new_code_map->set(old_length + kOsrAstIdOffset,
9220  Smi::FromInt(osr_ast_id.ToInt()));
9221 
9222 #ifdef DEBUG
9223  for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
9224  DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext());
9225  DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode());
9226  DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
9227  Code::OPTIMIZED_FUNCTION);
9228  DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
9229  DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
9230  }
9231 #endif
9232  shared->set_optimized_code_map(*new_code_map);
9233 }
9234 
9235 
9237  DCHECK(index > kEntriesStart);
9238  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9239  if (!bound()) {
9240  FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
9241  DCHECK_NE(NULL, cached_literals);
9242  return cached_literals;
9243  }
9244  return NULL;
9245 }
9246 
9247 
9249  DCHECK(index > kEntriesStart);
9250  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9251  Code* code = Code::cast(code_map->get(index));
9252  DCHECK_NE(NULL, code);
9253  return code;
9254 }
9255 
9256 
9258  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9259 
9260  // If the next map link slot is already used then the function was
9261  // enqueued with code flushing and we remove it now.
9262  if (!code_map->get(kNextMapIndex)->IsUndefined()) {
9264  flusher->EvictOptimizedCodeMap(this);
9265  }
9266 
9267  DCHECK(code_map->get(kNextMapIndex)->IsUndefined());
9268  set_optimized_code_map(Smi::FromInt(0));
9269 }
9270 
9271 
9273  const char* reason) {
9274  DisallowHeapAllocation no_gc;
9275  if (optimized_code_map()->IsSmi()) return;
9276 
9277  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9278  int dst = kEntriesStart;
9279  int length = code_map->length();
9280  for (int src = kEntriesStart; src < length; src += kEntryLength) {
9281  DCHECK(code_map->get(src)->IsNativeContext());
9282  if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
9283  // Evict the src entry by not copying it to the dst entry.
9284  if (FLAG_trace_opt) {
9285  PrintF("[evicting entry from optimizing code map (%s) for ", reason);
9286  ShortPrint();
9287  BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
9288  if (osr.IsNone()) {
9289  PrintF("]\n");
9290  } else {
9291  PrintF(" (osr ast id %d)]\n", osr.ToInt());
9292  }
9293  }
9294  } else {
9295  // Keep the src entry by copying it to the dst entry.
9296  if (dst != src) {
9297  code_map->set(dst + kContextOffset,
9298  code_map->get(src + kContextOffset));
9299  code_map->set(dst + kCachedCodeOffset,
9300  code_map->get(src + kCachedCodeOffset));
9301  code_map->set(dst + kLiteralsOffset,
9302  code_map->get(src + kLiteralsOffset));
9303  code_map->set(dst + kOsrAstIdOffset,
9304  code_map->get(src + kOsrAstIdOffset));
9305  }
9306  dst += kEntryLength;
9307  }
9308  }
9309  if (dst != length) {
9310  // Always trim even when array is cleared because of heap verifier.
9312  if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap();
9313  }
9314 }
9315 
9316 
9318  FixedArray* code_map = FixedArray::cast(optimized_code_map());
9319  DCHECK(shrink_by % kEntryLength == 0);
9320  DCHECK(shrink_by <= code_map->length() - kEntriesStart);
9321  // Always trim even when array is cleared because of heap verifier.
9322  GetHeap()->RightTrimFixedArray<Heap::FROM_GC>(code_map, shrink_by);
9323  if (code_map->length() == kEntriesStart) {
9325  }
9326 }
9327 
9328 
9331  if (object->IsGlobalObject()) return;
9332  if (object->IsJSGlobalProxy()) return;
9333  if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) {
9334  // First normalize to ensure all JSFunctions are CONSTANT.
9336  }
9337  if (!object->HasFastProperties()) {
9338  JSObject::MigrateSlowToFast(object, 0);
9339  }
9340  if (mode == FAST_PROTOTYPE && object->HasFastProperties() &&
9341  !object->map()->is_prototype_map()) {
9342  Handle<Map> new_map = Map::Copy(handle(object->map()));
9343  JSObject::MigrateToMap(object, new_map);
9344  object->map()->set_is_prototype_map(true);
9345  }
9346 }
9347 
9348 
9350  if (!object->map()->is_prototype_map()) return;
9352 }
9353 
9354 
9356  Handle<Context> native_context, Handle<Map> initial_map) {
9357  // Replace all of the cached initial array maps in the native context with
9358  // the appropriate transitioned elements kind maps.
9359  Factory* factory = native_context->GetIsolate()->factory();
9360  Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9362 
9363  Handle<Map> current_map = initial_map;
9364  ElementsKind kind = current_map->elements_kind();
9366  maps->set(kind, *current_map);
9367  for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
9368  i < kFastElementsKindCount; ++i) {
9369  Handle<Map> new_map;
9371  if (current_map->HasElementsTransition()) {
9372  new_map = handle(current_map->elements_transition_map());
9373  DCHECK(new_map->elements_kind() == next_kind);
9374  } else {
9375  new_map = Map::CopyAsElementsKind(
9376  current_map, next_kind, INSERT_TRANSITION);
9377  }
9378  maps->set(next_kind, *new_map);
9379  current_map = new_map;
9380  }
9381  native_context->set_js_array_maps(*maps);
9382  return initial_map;
9383 }
9384 
9385 
9387  Handle<Object> value) {
9388  Isolate* isolate = function->GetIsolate();
9389 
9390  DCHECK(value->IsJSReceiver());
9391 
9392  // Now some logic for the maps of the objects that are created by using this
9393  // function as a constructor.
9394  if (function->has_initial_map()) {
9395  // If the function has allocated the initial map replace it with a
9396  // copy containing the new prototype. Also complete any in-object
9397  // slack tracking that is in progress at this point because it is
9398  // still tracking the old copy.
9399  if (function->IsInobjectSlackTrackingInProgress()) {
9400  function->CompleteInobjectSlackTracking();
9401  }
9402 
9403  Handle<Map> initial_map(function->initial_map(), isolate);
9404 
9405  if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
9407  // Put the value in the initial map field until an initial map is needed.
9408  // At that point, a new initial map is created and the prototype is put
9409  // into the initial map where it belongs.
9410  function->set_prototype_or_initial_map(*value);
9411  } else {
9412  Handle<Map> new_map = Map::Copy(initial_map);
9413  JSFunction::SetInitialMap(function, new_map, value);
9414 
9415  // If the function is used as the global Array function, cache the
9416  // initial map (and transitioned versions) in the native context.
9417  Context* native_context = function->context()->native_context();
9418  Object* array_function =
9419  native_context->get(Context::ARRAY_FUNCTION_INDEX);
9420  if (array_function->IsJSFunction() &&
9421  *function == JSFunction::cast(array_function)) {
9422  CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
9423  }
9424  }
9425 
9426  // Deoptimize all code that embeds the previous initial map.
9427  initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
9429  } else {
9430  // Put the value in the initial map field until an initial map is
9431  // needed. At that point, a new initial map is created and the
9432  // prototype is put into the initial map where it belongs.
9433  function->set_prototype_or_initial_map(*value);
9434  }
9435  isolate->heap()->ClearInstanceofCache();
9436 }
9437 
9438 
9440  Handle<Object> value) {
9441  DCHECK(function->should_have_prototype());
9442  Handle<Object> construct_prototype = value;
9443 
9444  // If the value is not a JSReceiver, store the value in the map's
9445  // constructor field so it can be accessed. Also, set the prototype
9446  // used for constructing objects to the original object prototype.
9447  // See ECMA-262 13.2.2.
9448  if (!value->IsJSReceiver()) {
9449  // Copy the map so this does not affect unrelated functions.
9450  // Remove map transitions because they point to maps with a
9451  // different prototype.
9452  Handle<Map> new_map = Map::Copy(handle(function->map()));
9453 
9454  JSObject::MigrateToMap(function, new_map);
9455  new_map->set_constructor(*value);
9456  new_map->set_non_instance_prototype(true);
9457  Isolate* isolate = new_map->GetIsolate();
9458  construct_prototype = handle(
9459  isolate->context()->native_context()->initial_object_prototype(),
9460  isolate);
9461  } else {
9462  function->map()->set_non_instance_prototype(false);
9463  }
9464 
9465  return SetInstancePrototype(function, construct_prototype);
9466 }
9467 
9468 
9470  Context* native_context = context()->native_context();
9471  Map* no_prototype_map = shared()->strict_mode() == SLOPPY
9472  ? native_context->sloppy_function_without_prototype_map()
9473  : native_context->strict_function_without_prototype_map();
9474 
9475  if (map() == no_prototype_map) return true;
9476 
9477 #ifdef DEBUG
9478  if (map() != (shared()->strict_mode() == SLOPPY
9479  ? native_context->sloppy_function_map()
9480  : native_context->strict_function_map())) {
9481  return false;
9482  }
9483 #endif
9484 
9485  set_map(no_prototype_map);
9486  set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9487  return true;
9488 }
9489 
9490 
9492  Handle<Object> prototype) {
9493  if (prototype->IsJSObject()) {
9496  }
9497  map->set_prototype(*prototype);
9498  function->set_prototype_or_initial_map(*map);
9499  map->set_constructor(*function);
9500 }
9501 
9502 
9504  if (function->has_initial_map()) return;
9505  Isolate* isolate = function->GetIsolate();
9506 
9507  // First create a new map with the size and number of in-object properties
9508  // suggested by the function.
9509  InstanceType instance_type;
9510  int instance_size;
9511  int in_object_properties;
9512  if (function->shared()->is_generator()) {
9513  instance_type = JS_GENERATOR_OBJECT_TYPE;
9514  instance_size = JSGeneratorObject::kSize;
9515  in_object_properties = 0;
9516  } else {
9517  instance_type = JS_OBJECT_TYPE;
9518  instance_size = function->shared()->CalculateInstanceSize();
9519  in_object_properties = function->shared()->CalculateInObjectProperties();
9520  }
9521  Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
9522 
9523  // Fetch or allocate prototype.
9525  if (function->has_instance_prototype()) {
9526  prototype = handle(function->instance_prototype(), isolate);
9527  } else {
9528  prototype = isolate->factory()->NewFunctionPrototype(function);
9529  }
9530  map->set_inobject_properties(in_object_properties);
9531  map->set_unused_property_fields(in_object_properties);
9533 
9534  // Finally link initial map and constructor function.
9536 
9537  if (!function->shared()->is_generator()) {
9538  function->StartInobjectSlackTracking();
9539  }
9540 }
9541 
9542 
9544  shared()->set_instance_class_name(name);
9545 }
9546 
9547 
9548 void JSFunction::PrintName(FILE* out) {
9549  SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
9550  PrintF(out, "%s", name.get());
9551 }
9552 
9553 
9556 }
9557 
9558 
9559 // The filter is a pattern that matches function names in this way:
9560 // "*" all; the default
9561 // "-" all but the top-level function
9562 // "-name" all but the function "name"
9563 // "" only the top-level function
9564 // "name" only the function "name"
9565 // "name*" only functions starting with "name"
9566 // "~" none; the tilde is not an identifier
9567 bool JSFunction::PassesFilter(const char* raw_filter) {
9568  if (*raw_filter == '*') return true;
9569  String* name = shared()->DebugName();
9570  Vector<const char> filter = CStrVector(raw_filter);
9571  if (filter.length() == 0) return name->length() == 0;
9572  if (filter[0] == '-') {
9573  // Negative filter.
9574  if (filter.length() == 1) {
9575  return (name->length() != 0);
9576  } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
9577  return false;
9578  }
9579  if (filter[filter.length() - 1] == '*' &&
9580  name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
9581  return false;
9582  }
9583  return true;
9584 
9585  } else if (name->IsUtf8EqualTo(filter)) {
9586  return true;
9587  }
9588  if (filter[filter.length() - 1] == '*' &&
9589  name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
9590  return true;
9591  }
9592  return false;
9593 }
9594 
9595 
9597  Handle<Oddball> oddball,
9598  const char* to_string,
9599  Handle<Object> to_number,
9600  byte kind) {
9601  Handle<String> internalized_to_string =
9602  isolate->factory()->InternalizeUtf8String(to_string);
9603  oddball->set_to_string(*internalized_to_string);
9604  oddball->set_to_number(*to_number);
9605  oddball->set_kind(kind);
9606 }
9607 
9608 
9610  if (!script->line_ends()->IsUndefined()) return;
9611 
9612  Isolate* isolate = script->GetIsolate();
9613 
9614  if (!script->source()->IsString()) {
9615  DCHECK(script->source()->IsUndefined());
9616  Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
9617  script->set_line_ends(*empty);
9618  DCHECK(script->line_ends()->IsFixedArray());
9619  return;
9620  }
9621 
9622  Handle<String> src(String::cast(script->source()), isolate);
9623 
9624  Handle<FixedArray> array = String::CalculateLineEnds(src, true);
9625 
9626  if (*array != isolate->heap()->empty_fixed_array()) {
9627  array->set_map(isolate->heap()->fixed_cow_array_map());
9628  }
9629 
9630  script->set_line_ends(*array);
9631  DCHECK(script->line_ends()->IsFixedArray());
9632 }
9633 
9634 
9635 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
9636  int line_number = GetLineNumber(script, code_pos);
9637  if (line_number == -1) return -1;
9638 
9639  DisallowHeapAllocation no_allocation;
9640  FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
9641  line_number = line_number - script->line_offset()->value();
9642  if (line_number == 0) return code_pos + script->column_offset()->value();
9643  int prev_line_end_pos =
9644  Smi::cast(line_ends_array->get(line_number - 1))->value();
9645  return code_pos - (prev_line_end_pos + 1);
9646 }
9647 
9648 
9650  DisallowHeapAllocation no_allocation;
9651  DCHECK(line_ends()->IsFixedArray());
9652  FixedArray* line_ends_array = FixedArray::cast(line_ends());
9653  int line_ends_len = line_ends_array->length();
9654  if (line_ends_len == 0) return -1;
9655 
9656  if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
9657  return line_offset()->value();
9658  }
9659 
9660  int left = 0;
9661  int right = line_ends_len;
9662  while (int half = (right - left) / 2) {
9663  if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
9664  right -= half;
9665  } else {
9666  left += half;
9667  }
9668  }
9669  return right + line_offset()->value();
9670 }
9671 
9672 
9673 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
9674  InitLineEnds(script);
9675  return script->GetLineNumberWithArray(code_pos);
9676 }
9677 
9678 
9679 int Script::GetLineNumber(int code_pos) {
9680  DisallowHeapAllocation no_allocation;
9681  if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
9682 
9683  // Slow mode: we do not have line_ends. We have to iterate through source.
9684  if (!source()->IsString()) return -1;
9685 
9686  String* source_string = String::cast(source());
9687  int line = 0;
9688  int len = source_string->length();
9689  for (int pos = 0; pos < len; pos++) {
9690  if (pos == code_pos) break;
9691  if (source_string->Get(pos) == '\n') line++;
9692  }
9693  return line;
9694 }
9695 
9696 
9698  Isolate* isolate = script->GetIsolate();
9699  Handle<String> name_or_source_url_key =
9700  isolate->factory()->InternalizeOneByteString(
9701  STATIC_CHAR_VECTOR("nameOrSourceURL"));
9702  Handle<JSObject> script_wrapper = Script::GetWrapper(script);
9704  script_wrapper, name_or_source_url_key).ToHandleChecked();
9705  DCHECK(property->IsJSFunction());
9706  Handle<JSFunction> method = Handle<JSFunction>::cast(property);
9707  Handle<Object> result;
9708  // Do not check against pending exception, since this function may be called
9709  // when an exception has already been pending.
9710  if (!Execution::TryCall(method, script_wrapper, 0, NULL).ToHandle(&result)) {
9711  return isolate->factory()->undefined_value();
9712  }
9713  return result;
9714 }
9715 
9716 
9717 // Wrappers for scripts are kept alive and cached in weak global
9718 // handles referred from foreign objects held by the scripts as long as
9719 // they are used. When they are not used anymore, the garbage
9720 // collector will call the weak callback on the global handle
9721 // associated with the wrapper and get rid of both the wrapper and the
9722 // handle.
9725  Object** location = reinterpret_cast<Object**>(data.GetParameter());
9726  JSValue* wrapper = JSValue::cast(*location);
9727  Script::cast(wrapper->value())->ClearWrapperCache();
9728 }
9729 
9730 
9732  Foreign* foreign = wrapper();
9733  Object** location = reinterpret_cast<Object**>(foreign->foreign_address());
9734  DCHECK_EQ(foreign->foreign_address(), reinterpret_cast<Address>(location));
9735  foreign->set_foreign_address(0);
9736  GlobalHandles::Destroy(location);
9737  GetIsolate()->counters()->script_wrappers()->Decrement();
9738 }
9739 
9740 
9742  if (script->wrapper()->foreign_address() != NULL) {
9743  // Return a handle for the existing script wrapper from the cache.
9744  return Handle<JSValue>(
9745  *reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
9746  }
9747  Isolate* isolate = script->GetIsolate();
9748  // Construct a new script wrapper.
9749  isolate->counters()->script_wrappers()->Increment();
9750  Handle<JSFunction> constructor = isolate->script_function();
9751  Handle<JSValue> result =
9752  Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
9753 
9754  result->set_value(*script);
9755 
9756  // Create a new weak global handle and use it to cache the wrapper
9757  // for future use. The cache will automatically be cleared by the
9758  // garbage collector when it is not used anymore.
9759  Handle<Object> handle = isolate->global_handles()->Create(*result);
9760  GlobalHandles::MakeWeak(handle.location(),
9761  reinterpret_cast<void*>(handle.location()),
9763  script->wrapper()->set_foreign_address(
9764  reinterpret_cast<Address>(handle.location()));
9765  return result;
9766 }
9767 
9768 
9770  Object* n = name();
9771  if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
9772  return String::cast(n);
9773 }
9774 
9775 
9777  return !script()->IsUndefined() &&
9778  !reinterpret_cast<Script*>(script())->source()->IsUndefined();
9779 }
9780 
9781 
9783  if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
9784  Handle<String> source(String::cast(Script::cast(script())->source()));
9785  return GetIsolate()->factory()->NewSubString(
9786  source, start_position(), end_position());
9787 }
9788 
9789 
9791  // Check that the function has a script associated with it.
9792  if (!script()->IsScript()) return false;
9793  if (optimization_disabled()) return false;
9794  // If we never ran this (unlikely) then lets try to optimize it.
9795  if (code()->kind() != Code::FUNCTION) return true;
9796  return code()->optimizable();
9797 }
9798 
9799 
9801  return end_position() - start_position();
9802 }
9803 
9804 
9806  int instance_size =
9809  if (instance_size > JSObject::kMaxInstanceSize) {
9810  instance_size = JSObject::kMaxInstanceSize;
9811  }
9812  return instance_size;
9813 }
9814 
9815 
9818 }
9819 
9820 
9821 // Output the source code without any allocation in the heap.
9823  const SharedFunctionInfo* s = v.value;
9824  // For some native functions there is no source.
9825  if (!s->HasSourceCode()) return os << "<No Source>";
9826 
9827  // Get the source for the script which this function came from.
9828  // Don't use String::cast because we don't want more assertion errors while
9829  // we are already creating a stack dump.
9830  String* script_source =
9831  reinterpret_cast<String*>(Script::cast(s->script())->source());
9832 
9833  if (!script_source->LooksValid()) return os << "<Invalid Source>";
9834 
9835  if (!s->is_toplevel()) {
9836  os << "function ";
9837  Object* name = s->name();
9838  if (name->IsString() && String::cast(name)->length() > 0) {
9839  String::cast(name)->PrintUC16(os);
9840  }
9841  }
9842 
9843  int len = s->end_position() - s->start_position();
9844  if (len <= v.max_length || v.max_length < 0) {
9845  script_source->PrintUC16(os, s->start_position(), s->end_position());
9846  return os;
9847  } else {
9848  script_source->PrintUC16(os, s->start_position(),
9849  s->start_position() + v.max_length);
9850  return os << "...\n";
9851  }
9852 }
9853 
9854 
9855 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
9856  if (code->instruction_size() != recompiled->instruction_size()) return false;
9857  ByteArray* code_relocation = code->relocation_info();
9858  ByteArray* recompiled_relocation = recompiled->relocation_info();
9859  int length = code_relocation->length();
9860  if (length != recompiled_relocation->length()) return false;
9861  int compare = memcmp(code_relocation->GetDataStartAddress(),
9862  recompiled_relocation->GetDataStartAddress(),
9863  length);
9864  return compare == 0;
9865 }
9866 
9867 
9870  DisallowHeapAllocation no_allocation;
9871  Code* code = this->code();
9872  if (IsCodeEquivalent(code, recompiled)) {
9873  // Copy the deoptimization data from the recompiled code.
9874  code->set_deoptimization_data(recompiled->deoptimization_data());
9875  code->set_has_deoptimization_support(true);
9876  } else {
9877  // TODO(3025757): In case the recompiled isn't equivalent to the
9878  // old code, we have to replace it. We should try to avoid this
9879  // altogether because it flushes valuable type feedback by
9880  // effectively resetting all IC state.
9881  ReplaceCode(recompiled);
9882  }
9884 }
9885 
9886 
9888  // Disable optimization for the shared function info and mark the
9889  // code as non-optimizable. The marker on the shared function info
9890  // is there because we flush non-optimized code thereby loosing the
9891  // non-optimizable information for the code. When the code is
9892  // regenerated and set on the shared function info it is marked as
9893  // non-optimizable if optimization is disabled for the shared
9894  // function info.
9895  set_optimization_disabled(true);
9896  set_bailout_reason(reason);
9897  // Code should be the lazy compilation stub or else unoptimized. If the
9898  // latter, disable optimization for the code too.
9899  DCHECK(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
9900  if (code()->kind() == Code::FUNCTION) {
9901  code()->set_optimizable(false);
9902  }
9903  PROFILE(GetIsolate(), CodeDisableOptEvent(code(), this));
9904  if (FLAG_trace_opt) {
9905  PrintF("[disabled optimization for ");
9906  ShortPrint();
9907  PrintF(", reason: %s]\n", GetBailoutReason(reason));
9908  }
9909 }
9910 
9911 
9913  DCHECK(!id.IsNone());
9914  Code* unoptimized = code();
9915  DeoptimizationOutputData* data =
9916  DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
9917  unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
9918  USE(ignore);
9919  return true; // Return true if there was no DCHECK.
9920 }
9921 
9922 
9925 
9926  if (!FLAG_clever_optimizations) return;
9927  Map* map = initial_map();
9928 
9929  // Only initiate the tracking the first time.
9930  if (map->done_inobject_slack_tracking()) return;
9932 
9933  // No tracking during the snapshot construction phase.
9934  Isolate* isolate = GetIsolate();
9935  if (isolate->serializer_enabled()) return;
9936 
9937  if (map->unused_property_fields() == 0) return;
9938 
9940 }
9941 
9942 
9944  code()->ClearInlineCaches();
9945  // If we clear ICs, we need to clear the type feedback vector too, since
9946  // CallICs are synced with a feedback vector slot.
9948  set_ic_age(new_ic_age);
9949  if (code()->kind() == Code::FUNCTION) {
9950  code()->set_profiler_ticks(0);
9951  if (optimization_disabled() &&
9952  opt_count() >= FLAG_max_opt_count) {
9953  // Re-enable optimizations if they were disabled due to opt_count limit.
9954  set_optimization_disabled(false);
9955  code()->set_optimizable(true);
9956  }
9957  set_opt_count(0);
9958  set_deopt_count(0);
9959  }
9960 }
9961 
9962 
9963 static void GetMinInobjectSlack(Map* map, void* data) {
9964  int slack = map->unused_property_fields();
9965  if (*reinterpret_cast<int*>(data) > slack) {
9966  *reinterpret_cast<int*>(data) = slack;
9967  }
9968 }
9969 
9970 
9971 static void ShrinkInstanceSize(Map* map, void* data) {
9972  int slack = *reinterpret_cast<int*>(data);
9973  map->set_inobject_properties(map->inobject_properties() - slack);
9974  map->set_unused_property_fields(map->unused_property_fields() - slack);
9975  map->set_instance_size(map->instance_size() - slack * kPointerSize);
9976 
9977  // Visitor id might depend on the instance size, recalculate it.
9978  map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
9979 }
9980 
9981 
9984  Map* map = initial_map();
9985 
9988 
9989  int slack = map->unused_property_fields();
9991  if (slack != 0) {
9992  // Resize the initial map and all maps in its transition tree.
9994  }
9995 }
9996 
9997 
9999  BailoutId osr_ast_id) {
10000  DisallowHeapAllocation no_gc;
10001  DCHECK(native_context->IsNativeContext());
10002  if (!FLAG_cache_optimized_code) return -1;
10003  Object* value = optimized_code_map();
10004  if (!value->IsSmi()) {
10005  FixedArray* optimized_code_map = FixedArray::cast(value);
10006  int length = optimized_code_map->length();
10007  Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
10008  for (int i = kEntriesStart; i < length; i += kEntryLength) {
10009  if (optimized_code_map->get(i + kContextOffset) == native_context &&
10010  optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
10011  return i + kCachedCodeOffset;
10012  }
10013  }
10014  if (FLAG_trace_opt) {
10015  PrintF("[didn't find optimized code in optimized code map for ");
10016  ShortPrint();
10017  PrintF("]\n");
10018  }
10019  }
10020  return -1;
10021 }
10022 
10023 
10024 #define DECLARE_TAG(ignore1, name, ignore2) name,
10025 const char* const VisitorSynchronization::kTags[
10028 };
10029 #undef DECLARE_TAG
10030 
10031 
10032 #define DECLARE_TAG(ignore1, ignore2, name) name,
10033 const char* const VisitorSynchronization::kTagNames[
10036 };
10037 #undef DECLARE_TAG
10038 
10039 
10040 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
10041  DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
10042  Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
10043  Object* old_target = target;
10044  VisitPointer(&target);
10045  CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target.
10046 }
10047 
10048 
10049 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
10050  DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
10051  Object* stub = rinfo->code_age_stub();
10052  if (stub) {
10053  VisitPointer(&stub);
10054  }
10055 }
10056 
10057 
10058 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
10059  Object* code = Code::GetObjectFromEntryAddress(entry_address);
10060  Object* old_code = code;
10061  VisitPointer(&code);
10062  if (code != old_code) {
10063  Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
10064  }
10065 }
10066 
10067 
10068 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
10069  DCHECK(rinfo->rmode() == RelocInfo::CELL);
10070  Object* cell = rinfo->target_cell();
10071  Object* old_cell = cell;
10072  VisitPointer(&cell);
10073  if (cell != old_cell) {
10074  rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
10075  }
10076 }
10077 
10078 
10079 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
10080  DCHECK((RelocInfo::IsJSReturn(rinfo->rmode()) &&
10081  rinfo->IsPatchedReturnSequence()) ||
10082  (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
10083  rinfo->IsPatchedDebugBreakSlotSequence()));
10084  Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
10085  Object* old_target = target;
10086  VisitPointer(&target);
10087  CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target.
10088 }
10089 
10090 
10091 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10092  DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10093  Object* p = rinfo->target_object();
10094  VisitPointer(&p);
10095 }
10096 
10097 
10098 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10099  Address p = rinfo->target_reference();
10100  VisitExternalReference(&p);
10101 }
10102 
10103 
10106  set_relocation_info(GetHeap()->empty_byte_array());
10107 }
10108 
10109 
10111  Object* undefined = GetHeap()->undefined_value();
10112  Cell* undefined_cell = GetHeap()->undefined_cell();
10115  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10116  RelocInfo::Mode mode = it.rinfo()->rmode();
10118  it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
10119  } else if (mode == RelocInfo::CELL) {
10120  it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
10121  }
10122  }
10123 }
10124 
10125 
10126 void Code::Relocate(intptr_t delta) {
10127  for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
10128  it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10129  }
10131 }
10132 
10133 
10134 void Code::CopyFrom(const CodeDesc& desc) {
10135  DCHECK(Marking::Color(this) == Marking::WHITE_OBJECT);
10136 
10137  // copy code
10139  static_cast<size_t>(desc.instr_size));
10140 
10141  // copy reloc info
10143  desc.buffer + desc.buffer_size - desc.reloc_size,
10144  static_cast<size_t>(desc.reloc_size));
10145 
10146  // unbox handles and relocate
10147  intptr_t delta = instruction_start() - desc.buffer;
10148  int mode_mask = RelocInfo::kCodeTargetMask |
10153  // Needed to find target_object and runtime_entry on X64
10154  Assembler* origin = desc.origin;
10155  AllowDeferredHandleDereference embedding_raw_address;
10156  for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
10157  RelocInfo::Mode mode = it.rinfo()->rmode();
10159  Handle<Object> p = it.rinfo()->target_object_handle(origin);
10160  it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10161  } else if (mode == RelocInfo::CELL) {
10162  Handle<Cell> cell = it.rinfo()->target_cell_handle();
10163  it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
10164  } else if (RelocInfo::IsCodeTarget(mode)) {
10165  // rewrite code handles in inline cache targets to direct
10166  // pointers to the first instruction in the code object
10167  Handle<Object> p = it.rinfo()->target_object_handle(origin);
10168  Code* code = Code::cast(*p);
10169  it.rinfo()->set_target_address(code->instruction_start(),
10172  } else if (RelocInfo::IsRuntimeEntry(mode)) {
10173  Address p = it.rinfo()->target_runtime_entry(origin);
10174  it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
10176  } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
10177  Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
10178  Code* code = Code::cast(*p);
10179  it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
10180  } else {
10181  it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
10182  }
10183  }
10185 }
10186 
10187 
10188 // Locate the source position which is closest to the address in the code. This
10189 // is using the source position information embedded in the relocation info.
10190 // The position returned is relative to the beginning of the script where the
10191 // source for this function is found.
10193  int distance = kMaxInt;
10194  int position = RelocInfo::kNoPosition; // Initially no position found.
10195  // Run through all the relocation info to find the best matching source
10196  // position. All the code needs to be considered as the sequence of the
10197  // instructions in the code does not necessarily follow the same order as the
10198  // source.
10200  while (!it.done()) {
10201  // Only look at positions after the current pc.
10202  if (it.rinfo()->pc() < pc) {
10203  // Get position and distance.
10204 
10205  int dist = static_cast<int>(pc - it.rinfo()->pc());
10206  int pos = static_cast<int>(it.rinfo()->data());
10207  // If this position is closer than the current candidate or if it has the
10208  // same distance as the current candidate and the position is higher then
10209  // this position is the new candidate.
10210  if ((dist < distance) ||
10211  (dist == distance && pos > position)) {
10212  position = pos;
10213  distance = dist;
10214  }
10215  }
10216  it.next();
10217  }
10218  return position;
10219 }
10220 
10221 
10222 // Same as Code::SourcePosition above except it only looks for statement
10223 // positions.
10225  // First find the position as close as possible using all position
10226  // information.
10227  int position = SourcePosition(pc);
10228  // Now find the closest statement position before the position.
10229  int statement_position = 0;
10231  while (!it.done()) {
10233  int p = static_cast<int>(it.rinfo()->data());
10234  if (statement_position < p && p <= position) {
10235  statement_position = p;
10236  }
10237  }
10238  it.next();
10239  }
10240  return statement_position;
10241 }
10242 
10243 
10245  SafepointTable table(this);
10246  return table.FindEntry(pc);
10247 }
10248 
10249 
10250 Object* Code::FindNthObject(int n, Map* match_map) {
10252  DisallowHeapAllocation no_allocation;
10254  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10255  RelocInfo* info = it.rinfo();
10256  Object* object = info->target_object();
10257  if (object->IsHeapObject()) {
10258  if (HeapObject::cast(object)->map() == match_map) {
10259  if (--n == 0) return object;
10260  }
10261  }
10262  }
10263  return NULL;
10264 }
10265 
10266 
10268  Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
10269  return (result != NULL) ? AllocationSite::cast(result) : NULL;
10270 }
10271 
10272 
10274  Object* result = FindNthObject(1, GetHeap()->meta_map());
10275  return (result != NULL) ? Map::cast(result) : NULL;
10276 }
10277 
10278 
10281  DisallowHeapAllocation no_allocation;
10284  int current_pattern = 0;
10285  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10286  RelocInfo* info = it.rinfo();
10287  Object* object = info->target_object();
10288  if (object->IsHeapObject()) {
10289  Map* map = HeapObject::cast(object)->map();
10290  if (map == *pattern.find_[current_pattern]) {
10291  info->set_target_object(*pattern.replace_[current_pattern]);
10292  if (++current_pattern == pattern.count_) return;
10293  }
10294  }
10295  }
10296  UNREACHABLE();
10297 }
10298 
10299 
10302  DisallowHeapAllocation no_allocation;
10304  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10305  RelocInfo* info = it.rinfo();
10306  Object* object = info->target_object();
10307  if (object->IsMap()) maps->Add(handle(Map::cast(object)));
10308  }
10309 }
10310 
10311 
10314  DisallowHeapAllocation no_allocation;
10316  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10317  RelocInfo* info = it.rinfo();
10318  Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10319  if (code->kind() == Code::HANDLER) return code;
10320  }
10321  return NULL;
10322 }
10323 
10324 
10325 bool Code::FindHandlers(CodeHandleList* code_list, int length) {
10327  DisallowHeapAllocation no_allocation;
10329  int i = 0;
10330  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10331  if (i == length) return true;
10332  RelocInfo* info = it.rinfo();
10333  Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10334  // IC stubs with handlers never contain non-handler code objects before
10335  // handler targets.
10336  if (code->kind() != Code::HANDLER) break;
10337  code_list->Add(Handle<Code>(code));
10338  i++;
10339  }
10340  return i == length;
10341 }
10342 
10343 
10348  bool return_next = false;
10349  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10350  RelocInfo* info = it.rinfo();
10351  if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
10352  Object* object = info->target_object();
10353  if (object == map) return_next = true;
10354  } else if (return_next) {
10355  Code* code = Code::GetCodeFromTargetAddress(info->target_address());
10356  DCHECK(code->kind() == Code::HANDLER);
10357  return handle(code);
10358  }
10359  }
10360  return MaybeHandle<Code>();
10361 }
10362 
10363 
10366  DisallowHeapAllocation no_allocation;
10368  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10369  RelocInfo* info = it.rinfo();
10370  Object* object = info->target_object();
10371  if (object->IsName()) return Name::cast(object);
10372  }
10373  return NULL;
10374 }
10375 
10376 
10379 }
10380 
10381 
10384 }
10385 
10386 
10391  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10392  RelocInfo* info = it.rinfo();
10393  Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10394  if (target->is_inline_cache_stub()) {
10395  if (kind == NULL || *kind == target->kind()) {
10396  IC::Clear(this->GetIsolate(), info->pc(),
10397  info->host()->constant_pool());
10398  }
10399  }
10400  }
10401 }
10402 
10403 
10405  TypeFeedbackVector* vector = feedback_vector();
10406  Heap* heap = GetHeap();
10407  int length = vector->length();
10408 
10409  for (int i = 0; i < length; i++) {
10410  Object* obj = vector->get(i);
10411  if (obj->IsHeapObject()) {
10412  InstanceType instance_type =
10413  HeapObject::cast(obj)->map()->instance_type();
10414  switch (instance_type) {
10415  case ALLOCATION_SITE_TYPE:
10416  // AllocationSites are not cleared because they do not store
10417  // information that leaks.
10418  break;
10419  // Fall through...
10420  default:
10423  }
10424  }
10425  }
10426 }
10427 
10428 
10430  DisallowHeapAllocation no_gc;
10431  DCHECK(kind() == FUNCTION);
10432  BackEdgeTable back_edges(this, &no_gc);
10433  for (uint32_t i = 0; i < back_edges.length(); i++) {
10434  if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
10435  }
10436  return BailoutId::None();
10437 }
10438 
10439 
10441  DisallowHeapAllocation no_gc;
10442  DCHECK(kind() == FUNCTION);
10443  BackEdgeTable back_edges(this, &no_gc);
10444  for (uint32_t i = 0; i < back_edges.length(); i++) {
10445  if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
10446  }
10447  UNREACHABLE(); // We expect to find the back edge.
10448  return 0;
10449 }
10450 
10451 
10452 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
10454 }
10455 
10456 
10457 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
10458  PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
10460 }
10461 
10462 
10464  if (age == Code::kNotExecutedCodeAge) {
10465  // Treat that's never been executed as old immediately.
10466  age = Code::kIsOldCodeAge;
10467  } else if (age == Code::kExecutedOnceCodeAge) {
10468  // Pre-age code that has only been executed once.
10469  age = Code::kPreAgedCodeAge;
10470  }
10471  return age;
10472 }
10473 
10474 
10475 void Code::MakeOlder(MarkingParity current_parity) {
10476  byte* sequence = FindCodeAgeSequence();
10477  if (sequence != NULL) {
10478  Age age;
10479  MarkingParity code_parity;
10480  Isolate* isolate = GetIsolate();
10481  GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
10482  age = EffectiveAge(age);
10483  if (age != kLastCodeAge && code_parity != current_parity) {
10484  PatchPlatformCodeAge(isolate,
10485  sequence,
10486  static_cast<Age>(age + 1),
10487  current_parity);
10488  }
10489  }
10490 }
10491 
10492 
10493 bool Code::IsOld() {
10494  return GetAge() >= kIsOldCodeAge;
10495 }
10496 
10497 
10499  return FLAG_age_code &&
10501  (kind() == OPTIMIZED_FUNCTION ||
10502  (kind() == FUNCTION && !has_debug_break_slots()))
10504  : NULL;
10505 }
10506 
10507 
10509  return EffectiveAge(GetRawAge());
10510 }
10511 
10512 
10514  byte* sequence = FindCodeAgeSequence();
10515  if (sequence == NULL) {
10516  return kNoAgeCodeAge;
10517  }
10518  Age age;
10519  MarkingParity parity;
10520  GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
10521  return age;
10522 }
10523 
10524 
10526  MarkingParity* parity) {
10527  Isolate* isolate = code->GetIsolate();
10528  Builtins* builtins = isolate->builtins();
10529  Code* stub = NULL;
10530 #define HANDLE_CODE_AGE(AGE) \
10531  stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking(); \
10532  if (code == stub) { \
10533  *age = k##AGE##CodeAge; \
10534  *parity = EVEN_MARKING_PARITY; \
10535  return; \
10536  } \
10537  stub = *builtins->Make##AGE##CodeYoungAgainOddMarking(); \
10538  if (code == stub) { \
10539  *age = k##AGE##CodeAge; \
10540  *parity = ODD_MARKING_PARITY; \
10541  return; \
10542  }
10544 #undef HANDLE_CODE_AGE
10545  stub = *builtins->MarkCodeAsExecutedOnce();
10546  if (code == stub) {
10547  *age = kNotExecutedCodeAge;
10548  *parity = NO_MARKING_PARITY;
10549  return;
10550  }
10551  stub = *builtins->MarkCodeAsExecutedTwice();
10552  if (code == stub) {
10553  *age = kExecutedOnceCodeAge;
10554  *parity = NO_MARKING_PARITY;
10555  return;
10556  }
10557  UNREACHABLE();
10558 }
10559 
10560 
10562  Builtins* builtins = isolate->builtins();
10563  switch (age) {
10564 #define HANDLE_CODE_AGE(AGE) \
10565  case k##AGE##CodeAge: { \
10566  Code* stub = parity == EVEN_MARKING_PARITY \
10567  ? *builtins->Make##AGE##CodeYoungAgainEvenMarking() \
10568  : *builtins->Make##AGE##CodeYoungAgainOddMarking(); \
10569  return stub; \
10570  }
10572 #undef HANDLE_CODE_AGE
10573  case kNotExecutedCodeAge: {
10574  DCHECK(parity == NO_MARKING_PARITY);
10575  return *builtins->MarkCodeAsExecutedOnce();
10576  }
10577  case kExecutedOnceCodeAge: {
10578  DCHECK(parity == NO_MARKING_PARITY);
10579  return *builtins->MarkCodeAsExecutedTwice();
10580  }
10581  default:
10582  UNREACHABLE();
10583  break;
10584  }
10585  return NULL;
10586 }
10587 
10588 
10589 void Code::PrintDeoptLocation(FILE* out, int bailout_id) {
10590  const char* last_comment = NULL;
10593  for (RelocIterator it(this, mask); !it.done(); it.next()) {
10594  RelocInfo* info = it.rinfo();
10595  if (info->rmode() == RelocInfo::COMMENT) {
10596  last_comment = reinterpret_cast<const char*>(info->data());
10597  } else if (last_comment != NULL) {
10598  if ((bailout_id == Deoptimizer::GetDeoptimizationId(
10599  GetIsolate(), info->target_address(), Deoptimizer::EAGER)) ||
10600  (bailout_id == Deoptimizer::GetDeoptimizationId(
10601  GetIsolate(), info->target_address(), Deoptimizer::SOFT)) ||
10602  (bailout_id == Deoptimizer::GetDeoptimizationId(
10603  GetIsolate(), info->target_address(), Deoptimizer::LAZY))) {
10605  PrintF(out, " %s\n", last_comment);
10606  return;
10607  }
10608  }
10609  }
10610 }
10611 
10612 
10614  DeoptimizationInputData* deopt_data =
10615  DeoptimizationInputData::cast(deoptimization_data());
10616  Address code_start_address = instruction_start();
10617  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
10618  if (deopt_data->Pc(i)->value() == -1) continue;
10619  Address address = code_start_address + deopt_data->Pc(i)->value();
10620  if (address == pc) return true;
10621  }
10622  return false;
10623 }
10624 
10625 
10626 // Identify kind of code.
10627 const char* Code::Kind2String(Kind kind) {
10628  switch (kind) {
10629 #define CASE(name) case name: return #name;
10631 #undef CASE
10632  case NUMBER_OF_KINDS: break;
10633  }
10634  UNREACHABLE();
10635  return NULL;
10636 }
10637 
10638 
10639 #ifdef ENABLE_DISASSEMBLER
10640 
10641 void DeoptimizationInputData::DeoptimizationInputDataPrint(
10642  OStream& os) { // NOLINT
10643  disasm::NameConverter converter;
10644  int deopt_count = DeoptCount();
10645  os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
10646  if (0 != deopt_count) {
10647  os << " index ast id argc pc";
10648  if (FLAG_print_code_verbose) os << " commands";
10649  os << "\n";
10650  }
10651  for (int i = 0; i < deopt_count; i++) {
10652  // TODO(svenpanne) Add some basic formatting to our streams.
10653  Vector<char> buf1 = Vector<char>::New(128);
10654  SNPrintF(buf1, "%6d %6d %6d %6d", i, AstId(i).ToInt(),
10655  ArgumentsStackHeight(i)->value(), Pc(i)->value());
10656  os << buf1.start();
10657 
10658  if (!FLAG_print_code_verbose) {
10659  os << "\n";
10660  continue;
10661  }
10662  // Print details of the frame translation.
10663  int translation_index = TranslationIndex(i)->value();
10664  TranslationIterator iterator(TranslationByteArray(), translation_index);
10665  Translation::Opcode opcode =
10666  static_cast<Translation::Opcode>(iterator.Next());
10667  DCHECK(Translation::BEGIN == opcode);
10668  int frame_count = iterator.Next();
10669  int jsframe_count = iterator.Next();
10670  os << " " << Translation::StringFor(opcode)
10671  << " {frame count=" << frame_count
10672  << ", js frame count=" << jsframe_count << "}\n";
10673 
10674  while (iterator.HasNext() &&
10675  Translation::BEGIN !=
10676  (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
10677  Vector<char> buf2 = Vector<char>::New(128);
10678  SNPrintF(buf2, "%27s %s ", "", Translation::StringFor(opcode));
10679  os << buf2.start();
10680 
10681  switch (opcode) {
10682  case Translation::BEGIN:
10683  UNREACHABLE();
10684  break;
10685 
10686  case Translation::JS_FRAME: {
10687  int ast_id = iterator.Next();
10688  int function_id = iterator.Next();
10689  unsigned height = iterator.Next();
10690  os << "{ast_id=" << ast_id << ", function=";
10691  if (function_id != Translation::kSelfLiteralId) {
10692  Object* function = LiteralArray()->get(function_id);
10693  os << Brief(JSFunction::cast(function)->shared()->DebugName());
10694  } else {
10695  os << "<self>";
10696  }
10697  os << ", height=" << height << "}";
10698  break;
10699  }
10700 
10701  case Translation::COMPILED_STUB_FRAME: {
10702  Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
10703  os << "{kind=" << stub_kind << "}";
10704  break;
10705  }
10706 
10707  case Translation::ARGUMENTS_ADAPTOR_FRAME:
10708  case Translation::CONSTRUCT_STUB_FRAME: {
10709  int function_id = iterator.Next();
10710  JSFunction* function =
10711  JSFunction::cast(LiteralArray()->get(function_id));
10712  unsigned height = iterator.Next();
10713  os << "{function=" << Brief(function->shared()->DebugName())
10714  << ", height=" << height << "}";
10715  break;
10716  }
10717 
10718  case Translation::GETTER_STUB_FRAME:
10719  case Translation::SETTER_STUB_FRAME: {
10720  int function_id = iterator.Next();
10721  JSFunction* function =
10722  JSFunction::cast(LiteralArray()->get(function_id));
10723  os << "{function=" << Brief(function->shared()->DebugName()) << "}";
10724  break;
10725  }
10726 
10727  case Translation::REGISTER: {
10728  int reg_code = iterator.Next();
10729  os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
10730  break;
10731  }
10732 
10733  case Translation::INT32_REGISTER: {
10734  int reg_code = iterator.Next();
10735  os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
10736  break;
10737  }
10738 
10739  case Translation::UINT32_REGISTER: {
10740  int reg_code = iterator.Next();
10741  os << "{input=" << converter.NameOfCPURegister(reg_code)
10742  << " (unsigned)}";
10743  break;
10744  }
10745 
10746  case Translation::DOUBLE_REGISTER: {
10747  int reg_code = iterator.Next();
10748  os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
10749  << "}";
10750  break;
10751  }
10752 
10753  case Translation::STACK_SLOT: {
10754  int input_slot_index = iterator.Next();
10755  os << "{input=" << input_slot_index << "}";
10756  break;
10757  }
10758 
10759  case Translation::INT32_STACK_SLOT: {
10760  int input_slot_index = iterator.Next();
10761  os << "{input=" << input_slot_index << "}";
10762  break;
10763  }
10764 
10765  case Translation::UINT32_STACK_SLOT: {
10766  int input_slot_index = iterator.Next();
10767  os << "{input=" << input_slot_index << " (unsigned)}";
10768  break;
10769  }
10770 
10771  case Translation::DOUBLE_STACK_SLOT: {
10772  int input_slot_index = iterator.Next();
10773  os << "{input=" << input_slot_index << "}";
10774  break;
10775  }
10776 
10777  case Translation::LITERAL: {
10778  unsigned literal_index = iterator.Next();
10779  os << "{literal_id=" << literal_index << "}";
10780  break;
10781  }
10782 
10783  case Translation::DUPLICATED_OBJECT: {
10784  int object_index = iterator.Next();
10785  os << "{object_index=" << object_index << "}";
10786  break;
10787  }
10788 
10789  case Translation::ARGUMENTS_OBJECT:
10790  case Translation::CAPTURED_OBJECT: {
10791  int args_length = iterator.Next();
10792  os << "{length=" << args_length << "}";
10793  break;
10794  }
10795  }
10796  os << "\n";
10797  }
10798  }
10799 }
10800 
10801 
10802 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
10803  OStream& os) { // NOLINT
10804  os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
10805  << ")\n";
10806  if (this->DeoptPoints() == 0) return;
10807 
10808  os << "ast id pc state\n";
10809  for (int i = 0; i < this->DeoptPoints(); i++) {
10810  int pc_and_state = this->PcAndState(i)->value();
10811  // TODO(svenpanne) Add some basic formatting to our streams.
10812  Vector<char> buf = Vector<char>::New(100);
10813  SNPrintF(buf, "%6d %8d %s\n", this->AstId(i).ToInt(),
10814  FullCodeGenerator::PcField::decode(pc_and_state),
10816  FullCodeGenerator::StateField::decode(pc_and_state)));
10817  os << buf.start();
10818  }
10819 }
10820 
10821 
10822 const char* Code::ICState2String(InlineCacheState state) {
10823  switch (state) {
10824  case UNINITIALIZED: return "UNINITIALIZED";
10825  case PREMONOMORPHIC: return "PREMONOMORPHIC";
10826  case MONOMORPHIC: return "MONOMORPHIC";
10827  case PROTOTYPE_FAILURE:
10828  return "PROTOTYPE_FAILURE";
10829  case POLYMORPHIC: return "POLYMORPHIC";
10830  case MEGAMORPHIC: return "MEGAMORPHIC";
10831  case GENERIC: return "GENERIC";
10832  case DEBUG_STUB: return "DEBUG_STUB";
10833  case DEFAULT:
10834  return "DEFAULT";
10835  }
10836  UNREACHABLE();
10837  return NULL;
10838 }
10839 
10840 
10841 const char* Code::StubType2String(StubType type) {
10842  switch (type) {
10843  case NORMAL: return "NORMAL";
10844  case FAST: return "FAST";
10845  }
10846  UNREACHABLE(); // keep the compiler happy
10847  return NULL;
10848 }
10849 
10850 
10851 void Code::PrintExtraICState(OStream& os, // NOLINT
10852  Kind kind, ExtraICState extra) {
10853  os << "extra_ic_state = ";
10854  if ((kind == STORE_IC || kind == KEYED_STORE_IC) && (extra == STRICT)) {
10855  os << "STRICT\n";
10856  } else {
10857  os << extra << "\n";
10858  }
10859 }
10860 
10861 
10862 void Code::Disassemble(const char* name, OStream& os) { // NOLINT
10863  os << "kind = " << Kind2String(kind()) << "\n";
10864  if (IsCodeStubOrIC()) {
10865  const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this), true);
10866  os << "major_key = " << (n == NULL ? "null" : n) << "\n";
10867  }
10868  if (is_inline_cache_stub()) {
10869  os << "ic_state = " << ICState2String(ic_state()) << "\n";
10870  PrintExtraICState(os, kind(), extra_ic_state());
10871  if (ic_state() == MONOMORPHIC) {
10872  os << "type = " << StubType2String(type()) << "\n";
10873  }
10874  if (is_compare_ic_stub()) {
10875  DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
10876  CompareICStub stub(stub_key(), GetIsolate());
10877  os << "compare_state = " << CompareICState::GetStateName(stub.left())
10878  << "*" << CompareICState::GetStateName(stub.right()) << " -> "
10879  << CompareICState::GetStateName(stub.state()) << "\n";
10880  os << "compare_operation = " << Token::Name(stub.op()) << "\n";
10881  }
10882  }
10883  if ((name != NULL) && (name[0] != '\0')) {
10884  os << "name = " << name << "\n";
10885  }
10886  if (kind() == OPTIMIZED_FUNCTION) {
10887  os << "stack_slots = " << stack_slots() << "\n";
10888  }
10889 
10890  os << "Instructions (size = " << instruction_size() << ")\n";
10891  {
10892  Isolate* isolate = GetIsolate();
10893  int decode_size = is_crankshafted()
10894  ? static_cast<int>(safepoint_table_offset())
10895  : instruction_size();
10896  // If there might be a back edge table, stop before reaching it.
10897  if (kind() == Code::FUNCTION) {
10898  decode_size =
10899  Min(decode_size, static_cast<int>(back_edge_table_offset()));
10900  }
10901  byte* begin = instruction_start();
10902  byte* end = begin + decode_size;
10903  Disassembler::Decode(isolate, &os, begin, end, this);
10904  }
10905  os << "\n";
10906 
10907  if (kind() == FUNCTION) {
10908  DeoptimizationOutputData* data =
10909  DeoptimizationOutputData::cast(this->deoptimization_data());
10910  data->DeoptimizationOutputDataPrint(os);
10911  } else if (kind() == OPTIMIZED_FUNCTION) {
10912  DeoptimizationInputData* data =
10913  DeoptimizationInputData::cast(this->deoptimization_data());
10914  data->DeoptimizationInputDataPrint(os);
10915  }
10916  os << "\n";
10917 
10918  if (is_crankshafted()) {
10919  SafepointTable table(this);
10920  os << "Safepoints (size = " << table.size() << ")\n";
10921  for (unsigned i = 0; i < table.length(); i++) {
10922  unsigned pc_offset = table.GetPcOffset(i);
10923  os << (instruction_start() + pc_offset) << " ";
10924  // TODO(svenpanne) Add some basic formatting to our streams.
10925  Vector<char> buf1 = Vector<char>::New(30);
10926  SNPrintF(buf1, "%4d", pc_offset);
10927  os << buf1.start() << " ";
10928  table.PrintEntry(i, os);
10929  os << " (sp -> fp) ";
10930  SafepointEntry entry = table.GetEntry(i);
10931  if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
10932  Vector<char> buf2 = Vector<char>::New(30);
10933  SNPrintF(buf2, "%6d", entry.deoptimization_index());
10934  os << buf2.start();
10935  } else {
10936  os << "<none>";
10937  }
10938  if (entry.argument_count() > 0) {
10939  os << " argc: " << entry.argument_count();
10940  }
10941  os << "\n";
10942  }
10943  os << "\n";
10944  } else if (kind() == FUNCTION) {
10945  unsigned offset = back_edge_table_offset();
10946  // If there is no back edge table, the "table start" will be at or after
10947  // (due to alignment) the end of the instruction stream.
10948  if (static_cast<int>(offset) < instruction_size()) {
10949  DisallowHeapAllocation no_gc;
10950  BackEdgeTable back_edges(this, &no_gc);
10951 
10952  os << "Back edges (size = " << back_edges.length() << ")\n";
10953  os << "ast_id pc_offset loop_depth\n";
10954 
10955  for (uint32_t i = 0; i < back_edges.length(); i++) {
10956  Vector<char> buf = Vector<char>::New(100);
10957  SNPrintF(buf, "%6d %9u %10u\n", back_edges.ast_id(i).ToInt(),
10958  back_edges.pc_offset(i), back_edges.loop_depth(i));
10959  os << buf.start();
10960  }
10961 
10962  os << "\n";
10963  }
10964 #ifdef OBJECT_PRINT
10965  if (!type_feedback_info()->IsUndefined()) {
10966  OFStream os(stdout);
10967  TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
10968  os << "\n";
10969  }
10970 #endif
10971  }
10972 
10973  os << "RelocInfo (size = " << relocation_size() << ")\n";
10974  for (RelocIterator it(this); !it.done(); it.next()) {
10975  it.rinfo()->Print(GetIsolate(), os);
10976  }
10977  os << "\n";
10978 }
10979 #endif // ENABLE_DISASSEMBLER
10980 
10981 
10983  Handle<JSObject> object,
10984  int capacity,
10985  int length,
10986  SetFastElementsCapacitySmiMode smi_mode) {
10987  // We should never end in here with a pixel or external array.
10988  DCHECK(!object->HasExternalArrayElements());
10989 
10990  // Allocate a new fast elements backing store.
10991  Handle<FixedArray> new_elements =
10992  object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
10993 
10994  ElementsKind elements_kind = object->GetElementsKind();
10995  ElementsKind new_elements_kind;
10996  // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
10997  // or if it's allowed and the old elements array contained only SMIs.
10998  bool has_fast_smi_elements =
10999  (smi_mode == kForceSmiElements) ||
11000  ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements());
11001  if (has_fast_smi_elements) {
11002  if (IsHoleyElementsKind(elements_kind)) {
11003  new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
11004  } else {
11005  new_elements_kind = FAST_SMI_ELEMENTS;
11006  }
11007  } else {
11008  if (IsHoleyElementsKind(elements_kind)) {
11009  new_elements_kind = FAST_HOLEY_ELEMENTS;
11010  } else {
11011  new_elements_kind = FAST_ELEMENTS;
11012  }
11013  }
11014  Handle<FixedArrayBase> old_elements(object->elements());
11015  ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
11016  accessor->CopyElements(object, new_elements, elements_kind);
11017 
11018  if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
11019  Handle<Map> new_map = (new_elements_kind != elements_kind)
11020  ? GetElementsTransitionMap(object, new_elements_kind)
11021  : handle(object->map());
11023  JSObject::SetMapAndElements(object, new_map, new_elements);
11024 
11025  // Transition through the allocation site as well if present.
11026  JSObject::UpdateAllocationSite(object, new_elements_kind);
11027  } else {
11028  Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11029  parameter_map->set(1, *new_elements);
11030  }
11031 
11032  if (FLAG_trace_elements_transitions) {
11033  PrintElementsTransition(stdout, object, elements_kind, old_elements,
11034  object->GetElementsKind(), new_elements);
11035  }
11036 
11037  if (object->IsJSArray()) {
11038  Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11039  }
11040  return new_elements;
11041 }
11042 
11043 
11045  int capacity,
11046  int length) {
11047  // We should never end in here with a pixel or external array.
11048  DCHECK(!object->HasExternalArrayElements());
11049 
11050  Handle<FixedArrayBase> elems =
11051  object->GetIsolate()->factory()->NewFixedDoubleArray(capacity);
11052 
11053  ElementsKind elements_kind = object->GetElementsKind();
11054  CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS);
11055  ElementsKind new_elements_kind = elements_kind;
11056  if (IsHoleyElementsKind(elements_kind)) {
11057  new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
11058  } else {
11059  new_elements_kind = FAST_DOUBLE_ELEMENTS;
11060  }
11061 
11062  Handle<Map> new_map = GetElementsTransitionMap(object, new_elements_kind);
11063 
11064  Handle<FixedArrayBase> old_elements(object->elements());
11066  accessor->CopyElements(object, elems, elements_kind);
11067 
11069  JSObject::SetMapAndElements(object, new_map, elems);
11070 
11071  if (FLAG_trace_elements_transitions) {
11072  PrintElementsTransition(stdout, object, elements_kind, old_elements,
11073  object->GetElementsKind(), elems);
11074  }
11075 
11076  if (object->IsJSArray()) {
11077  Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11078  }
11079 }
11080 
11081 
11082 // static
11083 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11084  DCHECK(capacity >= 0);
11085  array->GetIsolate()->factory()->NewJSArrayStorage(
11086  array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11087 }
11088 
11089 
11090 void JSArray::Expand(Handle<JSArray> array, int required_size) {
11091  ElementsAccessor* accessor = array->GetElementsAccessor();
11092  accessor->SetCapacityAndLength(array, required_size, required_size);
11093 }
11094 
11095 
11096 // Returns false if the passed-in index is marked non-configurable,
11097 // which will cause the ES5 truncation operation to halt, and thus
11098 // no further old values need be collected.
11099 static bool GetOldValue(Isolate* isolate,
11100  Handle<JSObject> object,
11101  uint32_t index,
11102  List<Handle<Object> >* old_values,
11103  List<uint32_t>* indices) {
11105  JSReceiver::GetOwnElementAttribute(object, index);
11106  DCHECK(maybe.has_value);
11107  DCHECK(maybe.value != ABSENT);
11108  if (maybe.value == DONT_DELETE) return false;
11109  Handle<Object> value;
11110  if (!JSObject::GetOwnElementAccessorPair(object, index).is_null()) {
11111  value = Handle<Object>::cast(isolate->factory()->the_hole_value());
11112  } else {
11113  value = Object::GetElement(isolate, object, index).ToHandleChecked();
11114  }
11115  old_values->Add(value);
11116  indices->Add(index);
11117  return true;
11118 }
11119 
11121  uint32_t index,
11122  Handle<JSArray> deleted,
11123  uint32_t add_count) {
11124  Isolate* isolate = object->GetIsolate();
11125  HandleScope scope(isolate);
11126  Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
11127  Handle<Object> add_count_object =
11128  isolate->factory()->NewNumberFromUint(add_count);
11129 
11130  Handle<Object> args[] =
11131  { object, index_object, deleted, add_count_object };
11132 
11133  Execution::Call(isolate,
11134  Handle<JSFunction>(isolate->observers_enqueue_splice()),
11135  isolate->factory()->undefined_value(),
11136  arraysize(args),
11137  args).Assert();
11138 }
11139 
11140 
11142  Isolate* isolate = object->GetIsolate();
11143  HandleScope scope(isolate);
11144  Handle<Object> args[] = { object };
11145 
11146  Execution::Call(isolate,
11147  Handle<JSFunction>(isolate->observers_begin_perform_splice()),
11148  isolate->factory()->undefined_value(),
11149  arraysize(args),
11150  args).Assert();
11151 }
11152 
11153 
11154 static void EndPerformSplice(Handle<JSArray> object) {
11155  Isolate* isolate = object->GetIsolate();
11156  HandleScope scope(isolate);
11157  Handle<Object> args[] = { object };
11158 
11159  Execution::Call(isolate,
11160  Handle<JSFunction>(isolate->observers_end_perform_splice()),
11161  isolate->factory()->undefined_value(),
11162  arraysize(args),
11163  args).Assert();
11164 }
11165 
11166 
11168  Handle<JSArray> array,
11169  Handle<Object> new_length_handle) {
11170  if (array->HasFastElements()) {
11171  // If the new array won't fit in a some non-trivial fraction of the max old
11172  // space size, then force it to go dictionary mode.
11173  int max_fast_array_size = static_cast<int>(
11174  (array->GetHeap()->MaxOldGenerationSize() / kDoubleSize) / 4);
11175  if (new_length_handle->IsNumber() &&
11176  NumberToInt32(*new_length_handle) >= max_fast_array_size) {
11177  NormalizeElements(array);
11178  }
11179  }
11180 
11181  // We should never end in here with a pixel or external array.
11182  DCHECK(array->AllowsSetElementsLength());
11183  if (!array->map()->is_observed()) {
11184  return array->GetElementsAccessor()->SetLength(array, new_length_handle);
11185  }
11186 
11187  Isolate* isolate = array->GetIsolate();
11188  List<uint32_t> indices;
11189  List<Handle<Object> > old_values;
11190  Handle<Object> old_length_handle(array->length(), isolate);
11191  uint32_t old_length = 0;
11192  CHECK(old_length_handle->ToArrayIndex(&old_length));
11193  uint32_t new_length = 0;
11194  CHECK(new_length_handle->ToArrayIndex(&new_length));
11195 
11196  static const PropertyAttributes kNoAttrFilter = NONE;
11197  int num_elements = array->NumberOfOwnElements(kNoAttrFilter);
11198  if (num_elements > 0) {
11199  if (old_length == static_cast<uint32_t>(num_elements)) {
11200  // Simple case for arrays without holes.
11201  for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
11202  if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
11203  }
11204  } else {
11205  // For sparse arrays, only iterate over existing elements.
11206  // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
11207  // the to-be-removed indices twice.
11208  Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
11209  array->GetOwnElementKeys(*keys, kNoAttrFilter);
11210  while (num_elements-- > 0) {
11211  uint32_t index = NumberToUint32(keys->get(num_elements));
11212  if (index < new_length) break;
11213  if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
11214  }
11215  }
11216  }
11217 
11218  Handle<Object> hresult;
11220  isolate, hresult,
11221  array->GetElementsAccessor()->SetLength(array, new_length_handle),
11222  Object);
11223 
11224  CHECK(array->length()->ToArrayIndex(&new_length));
11225  if (old_length == new_length) return hresult;
11226 
11227  BeginPerformSplice(array);
11228 
11229  for (int i = 0; i < indices.length(); ++i) {
11230  // For deletions where the property was an accessor, old_values[i]
11231  // will be the hole, which instructs EnqueueChangeRecord to elide
11232  // the "oldValue" property.
11234  array, "delete", isolate->factory()->Uint32ToString(indices[i]),
11235  old_values[i]);
11236  }
11238  array, "update", isolate->factory()->length_string(),
11239  old_length_handle);
11240 
11241  EndPerformSplice(array);
11242 
11243  uint32_t index = Min(old_length, new_length);
11244  uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11245  uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11246  Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11247  if (delete_count > 0) {
11248  for (int i = indices.length() - 1; i >= 0; i--) {
11249  // Skip deletions where the property was an accessor, leaving holes
11250  // in the array of old values.
11251  if (old_values[i]->IsTheHole()) continue;
11253  deleted, indices[i] - index, old_values[i], NONE, SLOPPY).Assert();
11254  }
11255 
11256  SetProperty(deleted, isolate->factory()->length_string(),
11257  isolate->factory()->NewNumberFromUint(delete_count),
11258  STRICT).Assert();
11259  }
11260 
11261  EnqueueSpliceRecord(array, index, deleted, add_count);
11262 
11263  return hresult;
11264 }
11265 
11266 
11268  Handle<Object> prototype) {
11270  int number_of_transitions = map->NumberOfProtoTransitions();
11271  const int proto_offset =
11273  const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
11274  const int step = kProtoTransitionElementsPerEntry;
11275  for (int i = 0; i < number_of_transitions; i++) {
11276  if (cache->get(proto_offset + i * step) == *prototype) {
11277  Object* result = cache->get(map_offset + i * step);
11278  return Handle<Map>(Map::cast(result));
11279  }
11280  }
11281  return Handle<Map>();
11282 }
11283 
11284 
11286  Handle<Object> prototype,
11287  Handle<Map> target_map) {
11288  DCHECK(target_map->IsMap());
11289  DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
11290  // Don't cache prototype transition if this map is either shared, or a map of
11291  // a prototype.
11292  if (map->is_prototype_map()) return map;
11293  if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;
11294 
11295  const int step = kProtoTransitionElementsPerEntry;
11296  const int header = kProtoTransitionHeaderSize;
11297 
11299  int capacity = (cache->length() - header) / step;
11300  int transitions = map->NumberOfProtoTransitions() + 1;
11301 
11302  if (transitions > capacity) {
11303  if (capacity > kMaxCachedPrototypeTransitions) return map;
11304 
11305  // Grow array by factor 2 over and above what we need.
11306  cache = FixedArray::CopySize(cache, transitions * 2 * step + header);
11307 
11308  SetPrototypeTransitions(map, cache);
11309  }
11310 
11311  // Reload number of transitions as GC might shrink them.
11312  int last = map->NumberOfProtoTransitions();
11313  int entry = header + last * step;
11314 
11315  cache->set(entry + kProtoTransitionPrototypeOffset, *prototype);
11316  cache->set(entry + kProtoTransitionMapOffset, *target_map);
11317  map->SetNumberOfProtoTransitions(last + 1);
11318 
11319  return map;
11320 }
11321 
11322 
11324  TransitionArray* transition_array = transitions();
11325  // TODO(mstarzinger): Temporarily use a slower version instead of the faster
11326  // MemsetPointer to investigate a crasher. Switch back to MemsetPointer.
11327  Object** data = transition_array->data_start();
11328  Object* the_hole = GetHeap()->the_hole_value();
11329  int length = transition_array->length();
11330  for (int i = 0; i < length; i++) {
11331  data[i] = the_hole;
11332  }
11333 }
11334 
11335 
11337  FixedArray* proto_transitions = GetPrototypeTransitions();
11338  MemsetPointer(proto_transitions->data_start(),
11339  GetHeap()->the_hole_value(),
11340  proto_transitions->length());
11341 }
11342 
11343 
11344 // static
11347  CompilationInfo* info) {
11348  Handle<DependentCode> codes =
11349  DependentCode::Insert(handle(map->dependent_code(), info->isolate()),
11350  group, info->object_wrapper());
11351  if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11352  info->dependencies(group)->Add(map, info->zone());
11353 }
11354 
11355 
11356 // static
11359  Handle<Code> code) {
11361  Handle<DependentCode>(map->dependent_code()), group, code);
11362  if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
11363 }
11364 
11365 
11366 // static
11368  Handle<Code> stub) {
11369  DCHECK(stub->next_code_link()->IsUndefined());
11370  int n = map->dependent_code()->number_of_entries(DependentCode::kWeakICGroup);
11371  if (n == 0) {
11372  // Slow path: insert the head of the list with possible heap allocation.
11374  } else {
11375  // Fast path: link the stub to the existing head of the list without any
11376  // heap allocation.
11377  DCHECK(n == 1);
11378  map->dependent_code()->AddToDependentICList(stub);
11379  }
11380 }
11381 
11382 
11384  Recompute(entries);
11385 }
11386 
11387 
11389  start_indexes_[0] = 0;
11390  for (int g = 1; g <= kGroupCount; g++) {
11391  int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
11392  start_indexes_[g] = start_indexes_[g - 1] + count;
11393  }
11394 }
11395 
11396 
11398  DependencyGroup group) {
11399  AllowDeferredHandleDereference dependencies_are_safe;
11401  return Handle<PropertyCell>::cast(object)->dependent_code();
11404  return Handle<AllocationSite>::cast(object)->dependent_code();
11405  }
11406  return Handle<Map>::cast(object)->dependent_code();
11407 }
11408 
11409 
11411  DependencyGroup group,
11412  Handle<Object> object) {
11413  GroupStartIndexes starts(*entries);
11414  int start = starts.at(group);
11415  int end = starts.at(group + 1);
11416  int number_of_entries = starts.number_of_entries();
11417  // Check for existing entry to avoid duplicates.
11418  for (int i = start; i < end; i++) {
11419  if (entries->object_at(i) == *object) return entries;
11420  }
11421  if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
11422  int capacity = kCodesStartIndex + number_of_entries + 1;
11423  if (capacity > 5) capacity = capacity * 5 / 4;
11425  FixedArray::CopySize(entries, capacity, TENURED));
11426  // The number of codes can change after GC.
11427  starts.Recompute(*entries);
11428  start = starts.at(group);
11429  end = starts.at(group + 1);
11431  for (int i = 0; i < number_of_entries; i++) {
11432  entries->clear_at(i);
11433  }
11434  // If the old fixed array was empty, we need to reset counters of the
11435  // new array.
11436  if (number_of_entries == 0) {
11437  for (int g = 0; g < kGroupCount; g++) {
11438  new_entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
11439  }
11440  }
11441  entries = new_entries;
11442  }
11443  entries->ExtendGroup(group);
11444  entries->set_object_at(end, *object);
11445  entries->set_number_of_entries(group, end + 1 - start);
11446  return entries;
11447 }
11448 
11449 
11451  CompilationInfo* info,
11452  Code* code) {
11453  DisallowHeapAllocation no_gc;
11454  AllowDeferredHandleDereference get_object_wrapper;
11455  Foreign* info_wrapper = *info->object_wrapper();
11456  GroupStartIndexes starts(this);
11457  int start = starts.at(group);
11458  int end = starts.at(group + 1);
11459  for (int i = start; i < end; i++) {
11460  if (object_at(i) == info_wrapper) {
11461  set_object_at(i, code);
11462  break;
11463  }
11464  }
11465 
11466 #ifdef DEBUG
11467  for (int i = start; i < end; i++) {
11468  DCHECK(is_code_at(i) || compilation_info_at(i) != info);
11469  }
11470 #endif
11471 }
11472 
11473 
11475  CompilationInfo* info) {
11476  DisallowHeapAllocation no_allocation;
11477  AllowDeferredHandleDereference get_object_wrapper;
11478  Foreign* info_wrapper = *info->object_wrapper();
11479  GroupStartIndexes starts(this);
11480  int start = starts.at(group);
11481  int end = starts.at(group + 1);
11482  // Find compilation info wrapper.
11483  int info_pos = -1;
11484  for (int i = start; i < end; i++) {
11485  if (object_at(i) == info_wrapper) {
11486  info_pos = i;
11487  break;
11488  }
11489  }
11490  if (info_pos == -1) return; // Not found.
11491  int gap = info_pos;
11492  // Use the last of each group to fill the gap in the previous group.
11493  for (int i = group; i < kGroupCount; i++) {
11494  int last_of_group = starts.at(i + 1) - 1;
11495  DCHECK(last_of_group >= gap);
11496  if (last_of_group == gap) continue;
11497  copy(last_of_group, gap);
11498  gap = last_of_group;
11499  }
11500  DCHECK(gap == starts.number_of_entries() - 1);
11501  clear_at(gap); // Clear last gap.
11502  set_number_of_entries(group, end - start - 1);
11503 
11504 #ifdef DEBUG
11505  for (int i = start; i < end - 1; i++) {
11506  DCHECK(is_code_at(i) || compilation_info_at(i) != info);
11507  }
11508 #endif
11509 }
11510 
11511 
11512 static bool CodeListContains(Object* head, Code* code) {
11513  while (!head->IsUndefined()) {
11514  if (head == code) return true;
11515  head = Code::cast(head)->next_code_link();
11516  }
11517  return false;
11518 }
11519 
11520 
11522  GroupStartIndexes starts(this);
11523  int start = starts.at(group);
11524  int end = starts.at(group + 1);
11525  if (group == kWeakICGroup) {
11526  return CodeListContains(object_at(start), code);
11527  }
11528  for (int i = start; i < end; i++) {
11529  if (object_at(i) == code) return true;
11530  }
11531  return false;
11532 }
11533 
11534 
11536  Isolate* isolate,
11538  DisallowHeapAllocation no_allocation_scope;
11539  DependentCode::GroupStartIndexes starts(this);
11540  int start = starts.at(group);
11541  int end = starts.at(group + 1);
11542  int code_entries = starts.number_of_entries();
11543  if (start == end) return false;
11544 
11545  // Mark all the code that needs to be deoptimized.
11546  bool marked = false;
11547  for (int i = start; i < end; i++) {
11548  if (is_code_at(i)) {
11549  Code* code = code_at(i);
11550  if (!code->marked_for_deoptimization()) {
11551  SetMarkedForDeoptimization(code, group);
11552  marked = true;
11553  }
11554  } else {
11557  }
11558  }
11559  // Compact the array by moving all subsequent groups to fill in the new holes.
11560  for (int src = end, dst = start; src < code_entries; src++, dst++) {
11561  copy(src, dst);
11562  }
11563  // Now the holes are at the end of the array, zap them for heap-verifier.
11564  int removed = end - start;
11565  for (int i = code_entries - removed; i < code_entries; i++) {
11566  clear_at(i);
11567  }
11568  set_number_of_entries(group, 0);
11569  return marked;
11570 }
11571 
11572 
11574  Isolate* isolate,
11576  DCHECK(AllowCodeDependencyChange::IsAllowed());
11577  DisallowHeapAllocation no_allocation_scope;
11578  bool marked = MarkCodeForDeoptimization(isolate, group);
11579 
11580  if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
11581 }
11582 
11583 
11585  DisallowHeapAllocation no_heap_allocation;
11586  GroupStartIndexes starts(this);
11587  int i = starts.at(kWeakICGroup);
11588  Object* head = object_at(i);
11589  // Try to insert the stub after the head of the list to minimize number of
11590  // writes to the DependentCode array, since a write to the array can make it
11591  // strong if it was alread marked by incremental marker.
11592  if (head->IsCode()) {
11593  stub->set_next_code_link(Code::cast(head)->next_code_link());
11594  Code::cast(head)->set_next_code_link(*stub);
11595  } else {
11596  stub->set_next_code_link(head);
11597  set_object_at(i, *stub);
11598  }
11599 }
11600 
11601 
11603  DependencyGroup group) {
11604  code->set_marked_for_deoptimization(true);
11605  if (FLAG_trace_deopt &&
11606  (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
11607  DeoptimizationInputData* deopt_data =
11608  DeoptimizationInputData::cast(code->deoptimization_data());
11609  CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
11610  PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
11611  " (opt #%d) for deoptimization, reason: %s]\n",
11612  reinterpret_cast<intptr_t>(code),
11613  deopt_data->OptimizationId()->value(), DependencyGroupName(group));
11614  }
11615 }
11616 
11617 
11619  switch (group) {
11620  case kWeakICGroup:
11621  return "weak-ic";
11622  case kWeakCodeGroup:
11623  return "weak-code";
11624  case kTransitionGroup:
11625  return "transition";
11626  case kPrototypeCheckGroup:
11627  return "prototype-check";
11629  return "elements-cant-be-added";
11631  return "property-cell-changed";
11632  case kFieldTypeGroup:
11633  return "field-type";
11635  return "initial-map-changed";
11637  return "allocation-site-tenuring-changed";
11639  return "allocation-site-transition-changed";
11640  }
11641  UNREACHABLE();
11642  return "?";
11643 }
11644 
11645 
11647  Handle<Object> prototype) {
11648  Handle<Map> new_map = GetPrototypeTransition(map, prototype);
11649  if (new_map.is_null()) {
11650  new_map = Copy(map);
11651  PutPrototypeTransition(map, prototype, new_map);
11652  new_map->set_prototype(*prototype);
11653  }
11654  return new_map;
11655 }
11656 
11657 
11659  Handle<Object> value,
11660  bool from_javascript) {
11661 #ifdef DEBUG
11662  int size = object->Size();
11663 #endif
11664 
11665  Isolate* isolate = object->GetIsolate();
11666  Heap* heap = isolate->heap();
11667  // Silently ignore the change if value is not a JSObject or null.
11668  // SpiderMonkey behaves this way.
11669  if (!value->IsJSReceiver() && !value->IsNull()) return value;
11670 
11671  // From 8.6.2 Object Internal Methods
11672  // ...
11673  // In addition, if [[Extensible]] is false the value of the [[Class]] and
11674  // [[Prototype]] internal properties of the object may not be modified.
11675  // ...
11676  // Implementation specific extensions that modify [[Class]], [[Prototype]]
11677  // or [[Extensible]] must not violate the invariants defined in the preceding
11678  // paragraph.
11679  if (!object->map()->is_extensible()) {
11680  Handle<Object> args[] = { object };
11681  THROW_NEW_ERROR(isolate, NewTypeError("non_extensible_proto",
11682  HandleVector(args, arraysize(args))),
11683  Object);
11684  }
11685 
11686  // Before we can set the prototype we need to be sure
11687  // prototype cycles are prevented.
11688  // It is sufficient to validate that the receiver is not in the new prototype
11689  // chain.
11690  for (PrototypeIterator iter(isolate, *value,
11692  !iter.IsAtEnd(); iter.Advance()) {
11693  if (JSReceiver::cast(iter.GetCurrent()) == *object) {
11694  // Cycle detected.
11695  THROW_NEW_ERROR(isolate,
11696  NewError("cyclic_proto", HandleVector<Object>(NULL, 0)),
11697  Object);
11698  }
11699  }
11700 
11701  bool dictionary_elements_in_chain =
11702  object->map()->DictionaryElementsInPrototypeChainOnly();
11703  Handle<JSObject> real_receiver = object;
11704 
11705  if (from_javascript) {
11706  // Find the first object in the chain whose prototype object is not
11707  // hidden and set the new prototype on that object.
11708  PrototypeIterator iter(isolate, real_receiver);
11710  real_receiver =
11712  iter.Advance();
11713  }
11714  }
11715 
11716  // Set the new prototype of the object.
11717  Handle<Map> map(real_receiver->map());
11718 
11719  // Nothing to do if prototype is already set.
11720  if (map->prototype() == *value) return value;
11721 
11722  if (value->IsJSObject()) {
11724  from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
11726  }
11727 
11728  Handle<Map> new_map = Map::TransitionToPrototype(map, value);
11729  DCHECK(new_map->prototype() == *value);
11730  JSObject::MigrateToMap(real_receiver, new_map);
11731 
11732  if (!dictionary_elements_in_chain &&
11733  new_map->DictionaryElementsInPrototypeChainOnly()) {
11734  // If the prototype chain didn't previously have element callbacks, then
11735  // KeyedStoreICs need to be cleared to ensure any that involve this
11736  // map go generic.
11737  object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
11738  }
11739 
11740  heap->ClearInstanceofCache();
11741  DCHECK(size == object->Size());
11742  return value;
11743 }
11744 
11745 
11747  Arguments* args,
11748  uint32_t first_arg,
11749  uint32_t arg_count,
11751  // Elements in |Arguments| are ordered backwards (because they're on the
11752  // stack), but the method that's called here iterates over them in forward
11753  // direction.
11754  return EnsureCanContainElements(
11755  object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
11756 }
11757 
11758 
11760  Handle<JSObject> object,
11761  uint32_t index) {
11762  if (object->IsJSGlobalProxy()) {
11763  PrototypeIterator iter(object->GetIsolate(), object);
11764  if (iter.IsAtEnd()) return MaybeHandle<AccessorPair>();
11765  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
11766  return GetOwnElementAccessorPair(
11768  }
11769 
11770  // Check for lookup interceptor.
11771  if (object->HasIndexedInterceptor()) return MaybeHandle<AccessorPair>();
11772 
11773  return object->GetElementsAccessor()->GetAccessorPair(object, object, index);
11774 }
11775 
11776 
11778  Handle<JSObject> object,
11779  uint32_t index,
11780  Handle<Object> value,
11781  PropertyAttributes attributes,
11782  StrictMode strict_mode,
11783  bool check_prototype,
11784  SetPropertyMode set_mode) {
11785  Isolate* isolate = object->GetIsolate();
11786 
11787  // Make sure that the top context does not change when doing
11788  // callbacks or interceptor calls.
11789  AssertNoContextChange ncc(isolate);
11790 
11791  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
11792  if (!interceptor->setter()->IsUndefined()) {
11794  v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
11795  LOG(isolate,
11796  ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index));
11797  PropertyCallbackArguments args(isolate, interceptor->data(), *object,
11798  *object);
11799  v8::Handle<v8::Value> result =
11800  args.Call(setter, index, v8::Utils::ToLocal(value));
11802  if (!result.IsEmpty()) return value;
11803  }
11804 
11805  return SetElementWithoutInterceptor(object, index, value, attributes,
11806  strict_mode,
11807  check_prototype,
11808  set_mode);
11809 }
11810 
11811 
11813  Handle<JSObject> object,
11814  Handle<Object> receiver,
11815  Handle<Object> structure,
11816  uint32_t index,
11817  Handle<Object> holder) {
11818  Isolate* isolate = object->GetIsolate();
11819  DCHECK(!structure->IsForeign());
11820  // api style callbacks.
11821  if (structure->IsExecutableAccessorInfo()) {
11824  Object* fun_obj = data->getter();
11826  v8::ToCData<v8::AccessorNameGetterCallback>(fun_obj);
11827  if (call_fun == NULL) return isolate->factory()->undefined_value();
11828  Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder);
11829  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
11830  Handle<String> key = isolate->factory()->NumberToString(number);
11831  LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key));
11833  args(isolate, data->data(), *receiver, *holder_handle);
11834  v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
11836  if (result.IsEmpty()) return isolate->factory()->undefined_value();
11837  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
11838  result_internal->VerifyApiCallResultType();
11839  // Rebox handle before return.
11840  return handle(*result_internal, isolate);
11841  }
11842 
11843  // __defineGetter__ callback
11844  if (structure->IsAccessorPair()) {
11845  Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(),
11846  isolate);
11847  if (getter->IsSpecFunction()) {
11848  // TODO(rossberg): nicer would be to cast to some JSCallable here...
11850  receiver, Handle<JSReceiver>::cast(getter));
11851  }
11852  // Getter is not a function.
11853  return isolate->factory()->undefined_value();
11854  }
11855 
11856  if (structure->IsDeclaredAccessorInfo()) {
11858  receiver, Handle<DeclaredAccessorInfo>::cast(structure), isolate);
11859  }
11860 
11861  UNREACHABLE();
11862  return MaybeHandle<Object>();
11863 }
11864 
11865 
11867  Handle<Object> structure,
11868  uint32_t index,
11869  Handle<Object> value,
11870  Handle<JSObject> holder,
11871  StrictMode strict_mode) {
11872  Isolate* isolate = object->GetIsolate();
11873 
11874  // We should never get here to initialize a const with the hole
11875  // value since a const declaration would conflict with the setter.
11876  DCHECK(!value->IsTheHole());
11877  DCHECK(!structure->IsForeign());
11878  if (structure->IsExecutableAccessorInfo()) {
11879  // api style callbacks
11882  Object* call_obj = data->setter();
11884  v8::ToCData<v8::AccessorNameSetterCallback>(call_obj);
11885  if (call_fun == NULL) return value;
11886  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
11887  Handle<String> key(isolate->factory()->NumberToString(number));
11888  LOG(isolate, ApiNamedPropertyAccess("store", *object, *key));
11890  args(isolate, data->data(), *object, *holder);
11891  args.Call(call_fun,
11892  v8::Utils::ToLocal(key),
11893  v8::Utils::ToLocal(value));
11895  return value;
11896  }
11897 
11898  if (structure->IsAccessorPair()) {
11899  Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
11900  if (setter->IsSpecFunction()) {
11901  // TODO(rossberg): nicer would be to cast to some JSCallable here...
11903  object, Handle<JSReceiver>::cast(setter), value);
11904  } else {
11905  if (strict_mode == SLOPPY) return value;
11906  Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
11907  Handle<Object> args[2] = { key, holder };
11909  isolate, NewTypeError("no_setter_in_callback", HandleVector(args, 2)),
11910  Object);
11911  }
11912  }
11913 
11914  // TODO(dcarney): Handle correctly.
11915  if (structure->IsDeclaredAccessorInfo()) return value;
11916 
11917  UNREACHABLE();
11918  return MaybeHandle<Object>();
11919 }
11920 
11921 
11923  Heap* heap = GetHeap();
11924  if (!elements()->IsFixedArray()) return false;
11925  FixedArray* elements = FixedArray::cast(this->elements());
11926  if (elements->map() != heap->sloppy_arguments_elements_map()) {
11927  return false;
11928  }
11929  FixedArray* arguments = FixedArray::cast(elements->get(1));
11930  return !arguments->IsDictionary();
11931 }
11932 
11933 
11935  Heap* heap = GetHeap();
11936  if (!elements()->IsFixedArray()) return false;
11937  FixedArray* elements = FixedArray::cast(this->elements());
11938  if (elements->map() != heap->sloppy_arguments_elements_map()) {
11939  return false;
11940  }
11941  FixedArray* arguments = FixedArray::cast(elements->get(1));
11942  return arguments->IsDictionary();
11943 }
11944 
11945 
11946 // Adding n elements in fast case is O(n*n).
11947 // Note: revisit design to have dual undefined values to capture absent
11948 // elements.
11950  uint32_t index,
11951  Handle<Object> value,
11952  StrictMode strict_mode,
11953  bool check_prototype) {
11954  DCHECK(object->HasFastSmiOrObjectElements() ||
11955  object->HasFastArgumentsElements());
11956 
11957  Isolate* isolate = object->GetIsolate();
11958 
11959  // Array optimizations rely on the prototype lookups of Array objects always
11960  // returning undefined. If there is a store to the initial prototype object,
11961  // make sure all of these optimizations are invalidated.
11962  if (isolate->is_initial_object_prototype(*object) ||
11963  isolate->is_initial_array_prototype(*object)) {
11964  object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate,
11966  }
11967 
11968  Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
11969  if (backing_store->map() ==
11970  isolate->heap()->sloppy_arguments_elements_map()) {
11971  backing_store = handle(FixedArray::cast(backing_store->get(1)));
11972  } else {
11973  backing_store = EnsureWritableFastElements(object);
11974  }
11975  uint32_t capacity = static_cast<uint32_t>(backing_store->length());
11976 
11977  if (check_prototype &&
11978  (index >= capacity || backing_store->get(index)->IsTheHole())) {
11979  bool found;
11980  MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
11981  object, index, value, &found, strict_mode);
11982  if (found) return result;
11983  }
11984 
11985  uint32_t new_capacity = capacity;
11986  // Check if the length property of this object needs to be updated.
11987  uint32_t array_length = 0;
11988  bool must_update_array_length = false;
11989  bool introduces_holes = true;
11990  if (object->IsJSArray()) {
11991  CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
11992  introduces_holes = index > array_length;
11993  if (index >= array_length) {
11994  must_update_array_length = true;
11995  array_length = index + 1;
11996  }
11997  } else {
11998  introduces_holes = index >= capacity;
11999  }
12000 
12001  // If the array is growing, and it's not growth by a single element at the
12002  // end, make sure that the ElementsKind is HOLEY.
12003  ElementsKind elements_kind = object->GetElementsKind();
12004  if (introduces_holes &&
12005  IsFastElementsKind(elements_kind) &&
12006  !IsFastHoleyElementsKind(elements_kind)) {
12007  ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12008  TransitionElementsKind(object, transitioned_kind);
12009  }
12010 
12011  // Check if the capacity of the backing store needs to be increased, or if
12012  // a transition to slow elements is necessary.
12013  if (index >= capacity) {
12014  bool convert_to_slow = true;
12015  if ((index - capacity) < kMaxGap) {
12016  new_capacity = NewElementsCapacity(index + 1);
12017  DCHECK(new_capacity > index);
12018  if (!object->ShouldConvertToSlowElements(new_capacity)) {
12019  convert_to_slow = false;
12020  }
12021  }
12022  if (convert_to_slow) {
12023  NormalizeElements(object);
12024  return SetDictionaryElement(object, index, value, NONE, strict_mode,
12025  check_prototype);
12026  }
12027  }
12028  // Convert to fast double elements if appropriate.
12029  if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12030  // Consider fixing the boilerplate as well if we have one.
12031  ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
12034 
12035  UpdateAllocationSite(object, to_kind);
12036 
12037  SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12038  FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12040  return value;
12041  }
12042  // Change elements kind from Smi-only to generic FAST if necessary.
12043  if (object->HasFastSmiElements() && !value->IsSmi()) {
12044  ElementsKind kind = object->HasFastHoleyElements()
12046  : FAST_ELEMENTS;
12047 
12048  UpdateAllocationSite(object, kind);
12049  Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12050  JSObject::MigrateToMap(object, new_map);
12051  DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12052  }
12053  // Increase backing store capacity if that's been decided previously.
12054  if (new_capacity != capacity) {
12056  value->IsSmi() && object->HasFastSmiElements()
12057  ? kAllowSmiElements
12058  : kDontAllowSmiElements;
12059  Handle<FixedArray> new_elements =
12060  SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12061  smi_mode);
12062  new_elements->set(index, *value);
12064  return value;
12065  }
12066 
12067  // Finally, set the new element and length.
12068  DCHECK(object->elements()->IsFixedArray());
12069  backing_store->set(index, *value);
12070  if (must_update_array_length) {
12071  Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12072  }
12073  return value;
12074 }
12075 
12076 
12078  Handle<JSObject> object,
12079  uint32_t index,
12080  Handle<Object> value,
12081  PropertyAttributes attributes,
12082  StrictMode strict_mode,
12083  bool check_prototype,
12084  SetPropertyMode set_mode) {
12085  DCHECK(object->HasDictionaryElements() ||
12086  object->HasDictionaryArgumentsElements());
12087  Isolate* isolate = object->GetIsolate();
12088 
12089  // Insert element in the dictionary.
12090  Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12091  bool is_arguments =
12092  (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12093  Handle<SeededNumberDictionary> dictionary(is_arguments
12094  ? SeededNumberDictionary::cast(elements->get(1))
12095  : SeededNumberDictionary::cast(*elements));
12096 
12097  int entry = dictionary->FindEntry(index);
12098  if (entry != SeededNumberDictionary::kNotFound) {
12099  Handle<Object> element(dictionary->ValueAt(entry), isolate);
12100  PropertyDetails details = dictionary->DetailsAt(entry);
12101  if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
12102  return SetElementWithCallback(object, element, index, value, object,
12103  strict_mode);
12104  } else {
12105  dictionary->UpdateMaxNumberKey(index);
12106  // If a value has not been initialized we allow writing to it even if it
12107  // is read-only (a declared const that has not been initialized). If a
12108  // value is being defined we skip attribute checks completely.
12109  if (set_mode == DEFINE_PROPERTY) {
12110  details = PropertyDetails(
12111  attributes, NORMAL, details.dictionary_index());
12112  dictionary->DetailsAtPut(entry, details);
12113  } else if (details.IsReadOnly() && !element->IsTheHole()) {
12114  if (strict_mode == SLOPPY) {
12115  return isolate->factory()->undefined_value();
12116  } else {
12117  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12118  Handle<Object> args[2] = { number, object };
12119  THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
12120  HandleVector(args, 2)),
12121  Object);
12122  }
12123  }
12124  // Elements of the arguments object in slow mode might be slow aliases.
12125  if (is_arguments && element->IsAliasedArgumentsEntry()) {
12128  Handle<Context> context(Context::cast(elements->get(0)));
12129  int context_index = entry->aliased_context_slot();
12130  DCHECK(!context->get(context_index)->IsTheHole());
12131  context->set(context_index, *value);
12132  // For elements that are still writable we keep slow aliasing.
12133  if (!details.IsReadOnly()) value = element;
12134  }
12135  dictionary->ValueAtPut(entry, *value);
12136  }
12137  } else {
12138  // Index not already used. Look for an accessor in the prototype chain.
12139  // Can cause GC!
12140  if (check_prototype) {
12141  bool found;
12142  MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12143  object, index, value, &found, strict_mode);
12144  if (found) return result;
12145  }
12146 
12147  // When we set the is_extensible flag to false we always force the
12148  // element into dictionary mode (and force them to stay there).
12149  if (!object->map()->is_extensible()) {
12150  if (strict_mode == SLOPPY) {
12151  return isolate->factory()->undefined_value();
12152  } else {
12153  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12154  Handle<String> name = isolate->factory()->NumberToString(number);
12155  Handle<Object> args[1] = { name };
12156  THROW_NEW_ERROR(isolate, NewTypeError("object_not_extensible",
12157  HandleVector(args, 1)),
12158  Object);
12159  }
12160  }
12161 
12162  PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
12163  Handle<SeededNumberDictionary> new_dictionary =
12164  SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
12165  details);
12166  if (*dictionary != *new_dictionary) {
12167  if (is_arguments) {
12168  elements->set(1, *new_dictionary);
12169  } else {
12170  object->set_elements(*new_dictionary);
12171  }
12172  dictionary = new_dictionary;
12173  }
12174  }
12175 
12176  // Update the array length if this JSObject is an array.
12177  if (object->IsJSArray()) {
12179  value);
12180  }
12181 
12182  // Attempt to put this object back in fast case.
12183  if (object->ShouldConvertToFastElements()) {
12184  uint32_t new_length = 0;
12185  if (object->IsJSArray()) {
12186  CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length));
12187  } else {
12188  new_length = dictionary->max_number_key() + 1;
12189  }
12190  bool has_smi_only_elements = false;
12191  bool should_convert_to_fast_double_elements =
12192  object->ShouldConvertToFastDoubleElements(&has_smi_only_elements);
12194  has_smi_only_elements ? kForceSmiElements : kAllowSmiElements;
12195 
12196  if (should_convert_to_fast_double_elements) {
12197  SetFastDoubleElementsCapacityAndLength(object, new_length, new_length);
12198  } else {
12199  SetFastElementsCapacityAndLength(object, new_length, new_length,
12200  smi_mode);
12201  }
12203 #ifdef DEBUG
12204  if (FLAG_trace_normalization) {
12205  OFStream os(stdout);
12206  os << "Object elements are fast case again:\n";
12207  object->Print(os);
12208  }
12209 #endif
12210  }
12211  return value;
12212 }
12213 
12215  Handle<JSObject> object,
12216  uint32_t index,
12217  Handle<Object> value,
12218  StrictMode strict_mode,
12219  bool check_prototype) {
12220  DCHECK(object->HasFastDoubleElements());
12221 
12222  Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12223  uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
12224 
12225  // If storing to an element that isn't in the array, pass the store request
12226  // up the prototype chain before storing in the receiver's elements.
12227  if (check_prototype &&
12228  (index >= elms_length ||
12229  Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) {
12230  bool found;
12231  MaybeHandle<Object> result = SetElementWithCallbackSetterInPrototypes(
12232  object, index, value, &found, strict_mode);
12233  if (found) return result;
12234  }
12235 
12236  // If the value object is not a heap number, switch to fast elements and try
12237  // again.
12238  bool value_is_smi = value->IsSmi();
12239  bool introduces_holes = true;
12240  uint32_t length = elms_length;
12241  if (object->IsJSArray()) {
12243  introduces_holes = index > length;
12244  } else {
12245  introduces_holes = index >= elms_length;
12246  }
12247 
12248  if (!value->IsNumber()) {
12249  SetFastElementsCapacityAndLength(object, elms_length, length,
12250  kDontAllowSmiElements);
12251  Handle<Object> result;
12253  object->GetIsolate(), result,
12254  SetFastElement(object, index, value, strict_mode, check_prototype),
12255  Object);
12257  return result;
12258  }
12259 
12260  double double_value = value_is_smi
12261  ? static_cast<double>(Handle<Smi>::cast(value)->value())
12262  : Handle<HeapNumber>::cast(value)->value();
12263 
12264  // If the array is growing, and it's not growth by a single element at the
12265  // end, make sure that the ElementsKind is HOLEY.
12266  ElementsKind elements_kind = object->GetElementsKind();
12267  if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
12268  ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12269  TransitionElementsKind(object, transitioned_kind);
12270  }
12271 
12272  // Check whether there is extra space in the fixed array.
12273  if (index < elms_length) {
12274  Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
12275  elms->set(index, double_value);
12276  if (object->IsJSArray()) {
12277  // Update the length of the array if needed.
12278  uint32_t array_length = 0;
12279  CHECK(
12280  Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length));
12281  if (index >= array_length) {
12282  Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12283  }
12284  }
12285  return value;
12286  }
12287 
12288  // Allow gap in fast case.
12289  if ((index - elms_length) < kMaxGap) {
12290  // Try allocating extra space.
12291  int new_capacity = NewElementsCapacity(index+1);
12292  if (!object->ShouldConvertToSlowElements(new_capacity)) {
12293  DCHECK(static_cast<uint32_t>(new_capacity) > index);
12294  SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
12295  FixedDoubleArray::cast(object->elements())->set(index, double_value);
12297  return value;
12298  }
12299  }
12300 
12301  // Otherwise default to slow case.
12302  DCHECK(object->HasFastDoubleElements());
12303  DCHECK(object->map()->has_fast_double_elements());
12304  DCHECK(object->elements()->IsFixedDoubleArray() ||
12305  object->elements()->length() == 0);
12306 
12307  NormalizeElements(object);
12308  DCHECK(object->HasDictionaryElements());
12309  return SetElement(object, index, value, NONE, strict_mode, check_prototype);
12310 }
12311 
12312 
12314  uint32_t index,
12315  Handle<Object> value,
12316  PropertyAttributes attributes,
12317  StrictMode strict_mode) {
12318  if (object->IsJSProxy()) {
12320  Handle<JSProxy>::cast(object), object, index, value, strict_mode);
12321  }
12322  return JSObject::SetElement(
12323  Handle<JSObject>::cast(object), index, value, attributes, strict_mode);
12324 }
12325 
12326 
12328  uint32_t index,
12329  Handle<Object> value,
12330  StrictMode strict_mode) {
12331  DCHECK(!object->HasExternalArrayElements());
12332  return JSObject::SetElement(object, index, value, NONE, strict_mode, false);
12333 }
12334 
12335 
12337  uint32_t index,
12338  Handle<Object> value,
12339  PropertyAttributes attributes,
12340  StrictMode strict_mode,
12341  bool check_prototype,
12342  SetPropertyMode set_mode) {
12343  Isolate* isolate = object->GetIsolate();
12344 
12345  if (object->HasExternalArrayElements() ||
12346  object->HasFixedTypedArrayElements()) {
12347  if (!value->IsNumber() && !value->IsUndefined()) {
12349  isolate, value,
12350  Execution::ToNumber(isolate, value), Object);
12351  }
12352  }
12353 
12354  // Check access rights if needed.
12355  if (object->IsAccessCheckNeeded()) {
12356  if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_SET)) {
12357  isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
12359  return value;
12360  }
12361  }
12362 
12363  if (object->IsJSGlobalProxy()) {
12364  PrototypeIterator iter(isolate, object);
12365  if (iter.IsAtEnd()) return value;
12366  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
12367  return SetElement(
12369  value, attributes, strict_mode, check_prototype, set_mode);
12370  }
12371 
12372  // Don't allow element properties to be redefined for external arrays.
12373  if ((object->HasExternalArrayElements() ||
12374  object->HasFixedTypedArrayElements()) &&
12375  set_mode == DEFINE_PROPERTY) {
12376  Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
12377  Handle<Object> args[] = { object, number };
12378  THROW_NEW_ERROR(isolate, NewTypeError("redef_external_array_element",
12379  HandleVector(args, arraysize(args))),
12380  Object);
12381  }
12382 
12383  // Normalize the elements to enable attributes on the property.
12384  if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
12385  Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
12386  // Make sure that we never go back to fast case.
12387  dictionary->set_requires_slow_elements();
12388  }
12389 
12390  if (!object->map()->is_observed()) {
12391  return object->HasIndexedInterceptor()
12392  ? SetElementWithInterceptor(object, index, value, attributes,
12393  strict_mode, check_prototype, set_mode)
12394  : SetElementWithoutInterceptor(object, index, value, attributes,
12395  strict_mode, check_prototype, set_mode);
12396  }
12397 
12399  JSReceiver::GetOwnElementAttribute(object, index);
12400  if (!maybe.has_value) return MaybeHandle<Object>();
12401  PropertyAttributes old_attributes = maybe.value;
12402 
12403  Handle<Object> old_value = isolate->factory()->the_hole_value();
12404  Handle<Object> old_length_handle;
12405  Handle<Object> new_length_handle;
12406 
12407  if (old_attributes != ABSENT) {
12408  if (GetOwnElementAccessorPair(object, index).is_null()) {
12409  old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
12410  }
12411  } else if (object->IsJSArray()) {
12412  // Store old array length in case adding an element grows the array.
12413  old_length_handle = handle(Handle<JSArray>::cast(object)->length(),
12414  isolate);
12415  }
12416 
12417  // Check for lookup interceptor
12418  Handle<Object> result;
12420  isolate, result,
12421  object->HasIndexedInterceptor()
12422  ? SetElementWithInterceptor(
12423  object, index, value, attributes,
12424  strict_mode, check_prototype, set_mode)
12425  : SetElementWithoutInterceptor(
12426  object, index, value, attributes,
12427  strict_mode, check_prototype, set_mode),
12428  Object);
12429 
12430  Handle<String> name = isolate->factory()->Uint32ToString(index);
12431  maybe = GetOwnElementAttribute(object, index);
12432  if (!maybe.has_value) return MaybeHandle<Object>();
12433  PropertyAttributes new_attributes = maybe.value;
12434 
12435  if (old_attributes == ABSENT) {
12436  if (object->IsJSArray() &&
12437  !old_length_handle->SameValue(
12438  Handle<JSArray>::cast(object)->length())) {
12439  new_length_handle = handle(Handle<JSArray>::cast(object)->length(),
12440  isolate);
12441  uint32_t old_length = 0;
12442  uint32_t new_length = 0;
12443  CHECK(old_length_handle->ToArrayIndex(&old_length));
12444  CHECK(new_length_handle->ToArrayIndex(&new_length));
12445 
12447  EnqueueChangeRecord(object, "add", name, old_value);
12448  EnqueueChangeRecord(object, "update", isolate->factory()->length_string(),
12449  old_length_handle);
12451  Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12452  EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length, deleted,
12453  new_length - old_length);
12454  } else {
12455  EnqueueChangeRecord(object, "add", name, old_value);
12456  }
12457  } else if (old_value->IsTheHole()) {
12458  EnqueueChangeRecord(object, "reconfigure", name, old_value);
12459  } else {
12460  Handle<Object> new_value =
12461  Object::GetElement(isolate, object, index).ToHandleChecked();
12462  bool value_changed = !old_value->SameValue(*new_value);
12463  if (old_attributes != new_attributes) {
12464  if (!value_changed) old_value = isolate->factory()->the_hole_value();
12465  EnqueueChangeRecord(object, "reconfigure", name, old_value);
12466  } else if (value_changed) {
12467  EnqueueChangeRecord(object, "update", name, old_value);
12468  }
12469  }
12470 
12471  return result;
12472 }
12473 
12474 
12476  Handle<JSObject> object,
12477  uint32_t index,
12478  Handle<Object> value,
12479  PropertyAttributes attributes,
12480  StrictMode strict_mode,
12481  bool check_prototype,
12482  SetPropertyMode set_mode) {
12483  DCHECK(object->HasDictionaryElements() ||
12484  object->HasDictionaryArgumentsElements() ||
12485  (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
12486  Isolate* isolate = object->GetIsolate();
12487  if (FLAG_trace_external_array_abuse &&
12488  IsExternalArrayElementsKind(object->GetElementsKind())) {
12489  CheckArrayAbuse(object, "external elements write", index);
12490  }
12491  if (FLAG_trace_js_array_abuse &&
12492  !IsExternalArrayElementsKind(object->GetElementsKind())) {
12493  if (object->IsJSArray()) {
12494  CheckArrayAbuse(object, "elements write", index, true);
12495  }
12496  }
12497  if (object->IsJSArray() && JSArray::WouldChangeReadOnlyLength(
12498  Handle<JSArray>::cast(object), index)) {
12499  if (strict_mode == SLOPPY) {
12500  return value;
12501  } else {
12503  }
12504  }
12505  switch (object->GetElementsKind()) {
12506  case FAST_SMI_ELEMENTS:
12507  case FAST_ELEMENTS:
12509  case FAST_HOLEY_ELEMENTS:
12510  return SetFastElement(object, index, value, strict_mode, check_prototype);
12511  case FAST_DOUBLE_ELEMENTS:
12513  return SetFastDoubleElement(object, index, value, strict_mode,
12514  check_prototype);
12515 
12516 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
12517  case EXTERNAL_##TYPE##_ELEMENTS: { \
12518  Handle<External##Type##Array> array( \
12519  External##Type##Array::cast(object->elements())); \
12520  return External##Type##Array::SetValue(array, index, value); \
12521  } \
12522  case TYPE##_ELEMENTS: { \
12523  Handle<Fixed##Type##Array> array( \
12524  Fixed##Type##Array::cast(object->elements())); \
12525  return Fixed##Type##Array::SetValue(array, index, value); \
12526  }
12527 
12529 
12530 #undef TYPED_ARRAY_CASE
12531 
12532  case DICTIONARY_ELEMENTS:
12533  return SetDictionaryElement(object, index, value, attributes, strict_mode,
12534  check_prototype,
12535  set_mode);
12537  Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
12538  uint32_t length = parameter_map->length();
12539  Handle<Object> probe = index < length - 2 ?
12540  Handle<Object>(parameter_map->get(index + 2), isolate) :
12541  Handle<Object>();
12542  if (!probe.is_null() && !probe->IsTheHole()) {
12543  Handle<Context> context(Context::cast(parameter_map->get(0)));
12544  int context_index = Handle<Smi>::cast(probe)->value();
12545  DCHECK(!context->get(context_index)->IsTheHole());
12546  context->set(context_index, *value);
12547  // Redefining attributes of an aliased element destroys fast aliasing.
12548  if (set_mode == SET_PROPERTY || attributes == NONE) return value;
12549  parameter_map->set_the_hole(index + 2);
12550  // For elements that are still writable we re-establish slow aliasing.
12551  if ((attributes & READ_ONLY) == 0) {
12552  value = Handle<Object>::cast(
12553  isolate->factory()->NewAliasedArgumentsEntry(context_index));
12554  }
12555  }
12556  Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
12557  if (arguments->IsDictionary()) {
12558  return SetDictionaryElement(object, index, value, attributes,
12559  strict_mode,
12560  check_prototype,
12561  set_mode);
12562  } else {
12563  return SetFastElement(object, index, value, strict_mode,
12564  check_prototype);
12565  }
12566  }
12567  }
12568  // All possible cases have been handled above. Add a return to avoid the
12569  // complaints from the compiler.
12570  UNREACHABLE();
12571  return isolate->factory()->null_value();
12572 }
12573 
12574 
12575 const double AllocationSite::kPretenureRatio = 0.85;
12576 
12577 
12579  set_pretenure_decision(kUndecided);
12580  set_memento_found_count(0);
12581  set_memento_create_count(0);
12582 }
12583 
12584 
12586  PretenureDecision mode = pretenure_decision();
12587  // Zombie objects "decide" to be untenured.
12588  return mode == kTenure ? TENURED : NOT_TENURED;
12589 }
12590 
12591 
12593  DCHECK(FLAG_trace_track_allocation_sites);
12594  Object* current = GetHeap()->allocation_sites_list();
12595  while (current->IsAllocationSite()) {
12596  AllocationSite* current_site = AllocationSite::cast(current);
12597  if (current_site->nested_site() == this) {
12598  return true;
12599  }
12600  current = current_site->weak_next();
12601  }
12602  return false;
12603 }
12604 
12605 
12607  ElementsKind to_kind) {
12608  Isolate* isolate = site->GetIsolate();
12609 
12610  if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
12611  Handle<JSArray> transition_info =
12612  handle(JSArray::cast(site->transition_info()));
12613  ElementsKind kind = transition_info->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 the array is huge, it's not likely to be defined in a local
12620  // function, so we shouldn't make new instances of it very often.
12621  uint32_t length = 0;
12622  CHECK(transition_info->length()->ToArrayIndex(&length));
12623  if (length <= kMaximumArrayBytesToPretransition) {
12624  if (FLAG_trace_track_allocation_sites) {
12625  bool is_nested = site->IsNestedSite();
12626  PrintF(
12627  "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
12628  reinterpret_cast<void*>(*site),
12629  is_nested ? "(nested)" : "",
12630  ElementsKindToString(kind),
12631  ElementsKindToString(to_kind));
12632  }
12633  JSObject::TransitionElementsKind(transition_info, to_kind);
12634  site->dependent_code()->DeoptimizeDependentCodeGroup(
12636  }
12637  }
12638  } else {
12639  ElementsKind kind = site->GetElementsKind();
12640  // if kind is holey ensure that to_kind is as well.
12641  if (IsHoleyElementsKind(kind)) {
12642  to_kind = GetHoleyElementsKind(to_kind);
12643  }
12644  if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
12645  if (FLAG_trace_track_allocation_sites) {
12646  PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
12647  reinterpret_cast<void*>(*site),
12648  ElementsKindToString(kind),
12649  ElementsKindToString(to_kind));
12650  }
12651  site->SetElementsKind(to_kind);
12652  site->dependent_code()->DeoptimizeDependentCodeGroup(
12654  }
12655  }
12656 }
12657 
12658 
12659 // static
12661  Reason reason,
12662  CompilationInfo* info) {
12663  DependentCode::DependencyGroup group = site->ToDependencyGroup(reason);
12664  Handle<DependentCode> dep(site->dependent_code());
12665  Handle<DependentCode> codes =
12666  DependentCode::Insert(dep, group, info->object_wrapper());
12667  if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
12668  info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
12669 }
12670 
12671 
12673  switch (decision) {
12674  case kUndecided: return "undecided";
12675  case kDontTenure: return "don't tenure";
12676  case kMaybeTenure: return "maybe tenure";
12677  case kTenure: return "tenure";
12678  case kZombie: return "zombie";
12679  default: UNREACHABLE();
12680  }
12681  return NULL;
12682 }
12683 
12684 
12686  ElementsKind to_kind) {
12687  if (!object->IsJSArray()) return;
12688 
12689  Heap* heap = object->GetHeap();
12690  if (!heap->InNewSpace(*object)) return;
12691 
12693  {
12694  DisallowHeapAllocation no_allocation;
12695 
12696  AllocationMemento* memento = heap->FindAllocationMemento(*object);
12697  if (memento == NULL) return;
12698 
12699  // Walk through to the Allocation Site
12700  site = handle(memento->GetAllocationSite());
12701  }
12703 }
12704 
12705 
12707  ElementsKind to_kind) {
12708  ElementsKind from_kind = object->map()->elements_kind();
12709 
12710  if (IsFastHoleyElementsKind(from_kind)) {
12711  to_kind = GetHoleyElementsKind(to_kind);
12712  }
12713 
12714  if (from_kind == to_kind) return;
12715  // Don't update the site if to_kind isn't fast
12716  if (IsFastElementsKind(to_kind)) {
12717  UpdateAllocationSite(object, to_kind);
12718  }
12719 
12720  Isolate* isolate = object->GetIsolate();
12721  if (object->elements() == isolate->heap()->empty_fixed_array() ||
12722  (IsFastSmiOrObjectElementsKind(from_kind) &&
12723  IsFastSmiOrObjectElementsKind(to_kind)) ||
12724  (from_kind == FAST_DOUBLE_ELEMENTS &&
12725  to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
12726  DCHECK(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
12727  // No change is needed to the elements() buffer, the transition
12728  // only requires a map change.
12729  Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
12730  MigrateToMap(object, new_map);
12731  if (FLAG_trace_elements_transitions) {
12732  Handle<FixedArrayBase> elms(object->elements());
12733  PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
12734  }
12735  return;
12736  }
12737 
12738  Handle<FixedArrayBase> elms(object->elements());
12739  uint32_t capacity = static_cast<uint32_t>(elms->length());
12740  uint32_t length = capacity;
12741 
12742  if (object->IsJSArray()) {
12743  Object* raw_length = Handle<JSArray>::cast(object)->length();
12744  if (raw_length->IsUndefined()) {
12745  // If length is undefined, then JSArray is being initialized and has no
12746  // elements, assume a length of zero.
12747  length = 0;
12748  } else {
12749  CHECK(raw_length->ToArrayIndex(&length));
12750  }
12751  }
12752 
12753  if (IsFastSmiElementsKind(from_kind) &&
12754  IsFastDoubleElementsKind(to_kind)) {
12755  SetFastDoubleElementsCapacityAndLength(object, capacity, length);
12757  return;
12758  }
12759 
12760  if (IsFastDoubleElementsKind(from_kind) &&
12761  IsFastObjectElementsKind(to_kind)) {
12762  SetFastElementsCapacityAndLength(object, capacity, length,
12763  kDontAllowSmiElements);
12765  return;
12766  }
12767 
12768  // This method should never be called for any other case than the ones
12769  // handled above.
12770  UNREACHABLE();
12771 }
12772 
12773 
12774 // static
12776  ElementsKind to_kind) {
12777  // Transitions can't go backwards.
12778  if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
12779  return false;
12780  }
12781 
12782  // Transitions from HOLEY -> PACKED are not allowed.
12783  return !IsFastHoleyElementsKind(from_kind) ||
12784  IsFastHoleyElementsKind(to_kind);
12785 }
12786 
12787 
12789  uint32_t index,
12790  Handle<Object> value) {
12791  uint32_t old_len = 0;
12792  CHECK(array->length()->ToArrayIndex(&old_len));
12793  // Check to see if we need to update the length. For now, we make
12794  // sure that the length stays within 32-bits (unsigned).
12795  if (index >= old_len && index != 0xffffffff) {
12796  Handle<Object> len = array->GetIsolate()->factory()->NewNumber(
12797  static_cast<double>(index) + 1);
12798  array->set_length(*len);
12799  }
12800 }
12801 
12802 
12804  Isolate* isolate = jsarray_map->GetIsolate();
12805  DCHECK(!jsarray_map->is_dictionary_map());
12806  LookupResult lookup(isolate);
12807  Handle<Name> length_string = isolate->factory()->length_string();
12808  jsarray_map->LookupDescriptor(NULL, *length_string, &lookup);
12809  return lookup.IsReadOnly();
12810 }
12811 
12812 
12814  uint32_t index) {
12815  uint32_t length = 0;
12816  CHECK(array->length()->ToArrayIndex(&length));
12817  if (length <= index) {
12818  LookupIterator it(array, array->GetIsolate()->factory()->length_string(),
12819  LookupIterator::OWN_SKIP_INTERCEPTOR);
12820  CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
12821  CHECK(it.IsFound());
12822  CHECK_EQ(LookupIterator::ACCESSOR, it.state());
12823  return it.IsReadOnly();
12824  }
12825  return false;
12826 }
12827 
12828 
12830  Isolate* isolate = array->GetIsolate();
12831  Handle<Name> length = isolate->factory()->length_string();
12832  Handle<Object> args[2] = { length, array };
12833  THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
12834  HandleVector(args, arraysize(args))),
12835  Object);
12836 }
12837 
12838 
12840  Handle<JSObject> object,
12841  Handle<Object> receiver,
12842  uint32_t index) {
12843  Isolate* isolate = object->GetIsolate();
12844 
12845  // Make sure that the top context does not change when doing
12846  // callbacks or interceptor calls.
12847  AssertNoContextChange ncc(isolate);
12848 
12849  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate);
12850  if (!interceptor->getter()->IsUndefined()) {
12852  v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
12853  LOG(isolate,
12854  ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index));
12856  args(isolate, interceptor->data(), *receiver, *object);
12857  v8::Handle<v8::Value> result = args.Call(getter, index);
12859  if (!result.IsEmpty()) {
12860  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
12861  result_internal->VerifyApiCallResultType();
12862  // Rebox handle before return.
12863  return handle(*result_internal, isolate);
12864  }
12865  }
12866 
12867  ElementsAccessor* handler = object->GetElementsAccessor();
12868  Handle<Object> result;
12870  isolate, result, handler->Get(receiver, object, index),
12871  Object);
12872  if (!result->IsTheHole()) return result;
12873 
12874  PrototypeIterator iter(isolate, object);
12875  if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
12877  isolate, PrototypeIterator::GetCurrent(iter), receiver, index);
12878 }
12879 
12880 
12882  int capacity = 0;
12883  int used = 0;
12884  GetElementsCapacityAndUsage(&capacity, &used);
12885  return (capacity == 0) || (used > (capacity / 2));
12886 }
12887 
12888 
12889 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
12890  *capacity = 0;
12891  *used = 0;
12892 
12893  FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
12894  FixedArray* backing_store = NULL;
12895  switch (GetElementsKind()) {
12897  backing_store_base =
12898  FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
12899  backing_store = FixedArray::cast(backing_store_base);
12900  if (backing_store->IsDictionary()) {
12901  SeededNumberDictionary* dictionary =
12902  SeededNumberDictionary::cast(backing_store);
12903  *capacity = dictionary->Capacity();
12904  *used = dictionary->NumberOfElements();
12905  break;
12906  }
12907  // Fall through.
12908  case FAST_SMI_ELEMENTS:
12909  case FAST_ELEMENTS:
12910  if (IsJSArray()) {
12911  *capacity = backing_store_base->length();
12912  *used = Smi::cast(JSArray::cast(this)->length())->value();
12913  break;
12914  }
12915  // Fall through if packing is not guaranteed.
12917  case FAST_HOLEY_ELEMENTS:
12918  backing_store = FixedArray::cast(backing_store_base);
12919  *capacity = backing_store->length();
12920  for (int i = 0; i < *capacity; ++i) {
12921  if (!backing_store->get(i)->IsTheHole()) ++(*used);
12922  }
12923  break;
12924  case DICTIONARY_ELEMENTS: {
12925  SeededNumberDictionary* dictionary = element_dictionary();
12926  *capacity = dictionary->Capacity();
12927  *used = dictionary->NumberOfElements();
12928  break;
12929  }
12930  case FAST_DOUBLE_ELEMENTS:
12931  if (IsJSArray()) {
12932  *capacity = backing_store_base->length();
12933  *used = Smi::cast(JSArray::cast(this)->length())->value();
12934  break;
12935  }
12936  // Fall through if packing is not guaranteed.
12938  *capacity = elements()->length();
12939  if (*capacity == 0) break;
12940  FixedDoubleArray * elms = FixedDoubleArray::cast(elements());
12941  for (int i = 0; i < *capacity; i++) {
12942  if (!elms->is_the_hole(i)) ++(*used);
12943  }
12944  break;
12945  }
12946 
12947 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
12948  case EXTERNAL_##TYPE##_ELEMENTS: \
12949  case TYPE##_ELEMENTS: \
12950 
12952 #undef TYPED_ARRAY_CASE
12953  {
12954  // External arrays are considered 100% used.
12955  FixedArrayBase* external_array = FixedArrayBase::cast(elements());
12956  *capacity = external_array->length();
12957  *used = external_array->length();
12958  break;
12959  }
12960  }
12961 }
12962 
12963 
12965  uint32_t index;
12966  if (HasFastElements() && key->ToArrayIndex(&index)) {
12967  Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
12968  uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12969  if (index >= capacity) {
12970  if ((index - capacity) >= kMaxGap) return true;
12971  uint32_t new_capacity = NewElementsCapacity(index + 1);
12972  return ShouldConvertToSlowElements(new_capacity);
12973  }
12974  }
12975  return false;
12976 }
12977 
12978 
12980  STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
12981  kMaxUncheckedFastElementsLength);
12982  if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
12983  (new_capacity <= kMaxUncheckedFastElementsLength &&
12984  GetHeap()->InNewSpace(this))) {
12985  return false;
12986  }
12987  // If the fast-case backing storage takes up roughly three times as
12988  // much space (in machine words) as a dictionary backing storage
12989  // would, the object should have slow elements.
12990  int old_capacity = 0;
12991  int used_elements = 0;
12992  GetElementsCapacityAndUsage(&old_capacity, &used_elements);
12993  int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
12995  return 3 * dictionary_size <= new_capacity;
12996 }
12997 
12998 
13000  DCHECK(HasDictionaryElements() || HasDictionaryArgumentsElements());
13001  // If the elements are sparse, we should not go back to fast case.
13002  if (!HasDenseElements()) return false;
13003  // An object requiring access checks is never allowed to have fast
13004  // elements. If it had fast elements we would skip security checks.
13005  if (IsAccessCheckNeeded()) return false;
13006  // Observed objects may not go to fast mode because they rely on map checks,
13007  // and for fast element accesses we sometimes check element kinds only.
13008  if (map()->is_observed()) return false;
13009 
13010  FixedArray* elements = FixedArray::cast(this->elements());
13011  SeededNumberDictionary* dictionary = NULL;
13012  if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) {
13013  dictionary = SeededNumberDictionary::cast(elements->get(1));
13014  } else {
13015  dictionary = SeededNumberDictionary::cast(elements);
13016  }
13017  // If an element has been added at a very high index in the elements
13018  // dictionary, we cannot go back to fast case.
13019  if (dictionary->requires_slow_elements()) return false;
13020  // If the dictionary backing storage takes up roughly half as much
13021  // space (in machine words) as a fast-case backing storage would,
13022  // the object should have fast elements.
13023  uint32_t array_size = 0;
13024  if (IsJSArray()) {
13025  CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
13026  } else {
13027  array_size = dictionary->max_number_key();
13028  }
13029  uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
13031  return 2 * dictionary_size >= array_size;
13032 }
13033 
13034 
13036  bool* has_smi_only_elements) {
13037  *has_smi_only_elements = false;
13038  if (HasSloppyArgumentsElements()) return false;
13039  if (FLAG_unbox_double_arrays) {
13040  DCHECK(HasDictionaryElements());
13041  SeededNumberDictionary* dictionary = element_dictionary();
13042  bool found_double = false;
13043  for (int i = 0; i < dictionary->Capacity(); i++) {
13044  Object* key = dictionary->KeyAt(i);
13045  if (key->IsNumber()) {
13046  Object* value = dictionary->ValueAt(i);
13047  if (!value->IsNumber()) return false;
13048  if (!value->IsSmi()) {
13049  found_double = true;
13050  }
13051  }
13052  }
13053  *has_smi_only_elements = !found_double;
13054  return found_double;
13055  } else {
13056  return false;
13057  }
13058 }
13059 
13060 
13061 // Certain compilers request function template instantiation when they
13062 // see the definition of the other template functions in the
13063 // class. This requires us to have the template functions put
13064 // together, so even though this function belongs in objects-debug.cc,
13065 // we keep it here instead to satisfy certain compilers.
13066 #ifdef OBJECT_PRINT
13067 template <typename Derived, typename Shape, typename Key>
13068 void Dictionary<Derived, Shape, Key>::Print(OStream& os) { // NOLINT
13069  int capacity = DerivedHashTable::Capacity();
13070  for (int i = 0; i < capacity; i++) {
13071  Object* k = DerivedHashTable::KeyAt(i);
13072  if (DerivedHashTable::IsKey(k)) {
13073  os << " ";
13074  if (k->IsString()) {
13075  String::cast(k)->StringPrint(os);
13076  } else {
13077  os << Brief(k);
13078  }
13079  os << ": " << Brief(ValueAt(i)) << "\n";
13080  }
13081  }
13082 }
13083 #endif
13084 
13085 
13086 template<typename Derived, typename Shape, typename Key>
13088  int pos = 0;
13089  int capacity = DerivedHashTable::Capacity();
13090  DisallowHeapAllocation no_gc;
13091  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
13092  for (int i = 0; i < capacity; i++) {
13093  Object* k = Dictionary::KeyAt(i);
13094  if (Dictionary::IsKey(k)) {
13095  elements->set(pos++, ValueAt(i), mode);
13096  }
13097  }
13098  DCHECK(pos == elements->length());
13099 }
13100 
13101 
13103  DCHECK(map()->has_named_interceptor());
13104  JSFunction* constructor = JSFunction::cast(map()->constructor());
13105  DCHECK(constructor->shared()->IsApiFunction());
13106  Object* result =
13107  constructor->shared()->get_api_func_data()->named_property_handler();
13108  return InterceptorInfo::cast(result);
13109 }
13110 
13111 
13113  DCHECK(map()->has_indexed_interceptor());
13114  JSFunction* constructor = JSFunction::cast(map()->constructor());
13115  DCHECK(constructor->shared()->IsApiFunction());
13116  Object* result =
13117  constructor->shared()->get_api_func_data()->indexed_property_handler();
13118  return InterceptorInfo::cast(result);
13119 }
13120 
13121 
13123  Handle<JSObject> holder,
13124  Handle<Object> receiver,
13125  Handle<Name> name) {
13126  Isolate* isolate = holder->GetIsolate();
13127 
13128  // TODO(rossberg): Support symbols in the API.
13129  if (name->IsSymbol()) return isolate->factory()->undefined_value();
13130 
13131  Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor(), isolate);
13132  Handle<String> name_string = Handle<String>::cast(name);
13133 
13134  if (interceptor->getter()->IsUndefined()) return MaybeHandle<Object>();
13135 
13137  v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
13138  LOG(isolate,
13139  ApiNamedPropertyAccess("interceptor-named-get", *holder, *name));
13141  args(isolate, interceptor->data(), *receiver, *holder);
13142  v8::Handle<v8::Value> result =
13143  args.Call(getter, v8::Utils::ToLocal(name_string));
13145  if (result.IsEmpty()) return MaybeHandle<Object>();
13146 
13147  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
13148  result_internal->VerifyApiCallResultType();
13149  // Rebox handle before return
13150  return handle(*result_internal, isolate);
13151 }
13152 
13153 
13154 // Compute the property keys from the interceptor.
13155 // TODO(rossberg): support symbols in API, and filter here if needed.
13157  Handle<JSObject> object, Handle<JSReceiver> receiver) {
13158  Isolate* isolate = receiver->GetIsolate();
13159  Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
13161  args(isolate, interceptor->data(), *receiver, *object);
13162  v8::Handle<v8::Object> result;
13163  if (!interceptor->enumerator()->IsUndefined()) {
13165  v8::ToCData<v8::NamedPropertyEnumeratorCallback>(
13166  interceptor->enumerator());
13167  LOG(isolate, ApiObjectAccess("interceptor-named-enum", *object));
13168  result = args.Call(enum_fun);
13169  }
13170  if (result.IsEmpty()) return MaybeHandle<JSObject>();
13171 #if ENABLE_EXTRA_CHECKS
13172  CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13173  v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13174 #endif
13175  // Rebox before returning.
13176  return handle(*v8::Utils::OpenHandle(*result), isolate);
13177 }
13178 
13179 
13180 // Compute the element keys from the interceptor.
13182  Handle<JSObject> object, Handle<JSReceiver> receiver) {
13183  Isolate* isolate = receiver->GetIsolate();
13184  Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
13186  args(isolate, interceptor->data(), *receiver, *object);
13187  v8::Handle<v8::Object> result;
13188  if (!interceptor->enumerator()->IsUndefined()) {
13190  v8::ToCData<v8::IndexedPropertyEnumeratorCallback>(
13191  interceptor->enumerator());
13192  LOG(isolate, ApiObjectAccess("interceptor-indexed-enum", *object));
13193  result = args.Call(enum_fun);
13194  }
13195  if (result.IsEmpty()) return MaybeHandle<JSObject>();
13196 #if ENABLE_EXTRA_CHECKS
13197  CHECK(v8::Utils::OpenHandle(*result)->IsJSArray() ||
13198  v8::Utils::OpenHandle(*result)->HasSloppyArgumentsElements());
13199 #endif
13200  // Rebox before returning.
13201  return handle(*v8::Utils::OpenHandle(*result), isolate);
13202 }
13203 
13204 
13206  Handle<Name> key) {
13207  LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
13208  Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
13209  if (!maybe_result.has_value) return Maybe<bool>();
13210  return maybe(it.IsFound());
13211 }
13212 
13213 
13215  uint32_t index) {
13216  Isolate* isolate = object->GetIsolate();
13217  HandleScope scope(isolate);
13218  // Check access rights if needed.
13219  if (object->IsAccessCheckNeeded()) {
13220  if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
13221  isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
13223  return maybe(false);
13224  }
13225  }
13226 
13227  if (object->IsJSGlobalProxy()) {
13228  HandleScope scope(isolate);
13229  PrototypeIterator iter(isolate, object);
13230  if (iter.IsAtEnd()) return maybe(false);
13231  DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
13232  return HasRealElementProperty(
13234  }
13235 
13236  Maybe<PropertyAttributes> result =
13237  GetElementAttributeWithoutInterceptor(object, object, index, false);
13238  if (!result.has_value) return Maybe<bool>();
13239  return maybe(result.value != ABSENT);
13240 }
13241 
13242 
13244  Handle<Name> key) {
13245  LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
13246  Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
13247  if (!maybe_result.has_value) return Maybe<bool>();
13248  return maybe(it.state() == LookupIterator::ACCESSOR);
13249 }
13250 
13251 
13253  if (HasFastProperties()) {
13254  Map* map = this->map();
13255  if (filter == NONE) return map->NumberOfOwnDescriptors();
13256  if (filter & DONT_ENUM) {
13257  int result = map->EnumLength();
13258  if (result != kInvalidEnumCacheSentinel) return result;
13259  }
13261  }
13262  return property_dictionary()->NumberOfElementsFilterAttributes(filter);
13263 }
13264 
13265 
13266 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
13267  Object* temp = get(i);
13268  set(i, get(j));
13269  set(j, temp);
13270  if (this != numbers) {
13271  temp = numbers->get(i);
13272  numbers->set(i, Smi::cast(numbers->get(j)));
13273  numbers->set(j, Smi::cast(temp));
13274  }
13275 }
13276 
13277 
13278 static void InsertionSortPairs(FixedArray* content,
13279  FixedArray* numbers,
13280  int len) {
13281  for (int i = 1; i < len; i++) {
13282  int j = i;
13283  while (j > 0 &&
13284  (NumberToUint32(numbers->get(j - 1)) >
13285  NumberToUint32(numbers->get(j)))) {
13286  content->SwapPairs(numbers, j - 1, j);
13287  j--;
13288  }
13289  }
13290 }
13291 
13292 
13293 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
13294  // In-place heap sort.
13295  DCHECK(content->length() == numbers->length());
13296 
13297  // Bottom-up max-heap construction.
13298  for (int i = 1; i < len; ++i) {
13299  int child_index = i;
13300  while (child_index > 0) {
13301  int parent_index = ((child_index + 1) >> 1) - 1;
13302  uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13303  uint32_t child_value = NumberToUint32(numbers->get(child_index));
13304  if (parent_value < child_value) {
13305  content->SwapPairs(numbers, parent_index, child_index);
13306  } else {
13307  break;
13308  }
13309  child_index = parent_index;
13310  }
13311  }
13312 
13313  // Extract elements and create sorted array.
13314  for (int i = len - 1; i > 0; --i) {
13315  // Put max element at the back of the array.
13316  content->SwapPairs(numbers, 0, i);
13317  // Sift down the new top element.
13318  int parent_index = 0;
13319  while (true) {
13320  int child_index = ((parent_index + 1) << 1) - 1;
13321  if (child_index >= i) break;
13322  uint32_t child1_value = NumberToUint32(numbers->get(child_index));
13323  uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
13324  uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
13325  if (child_index + 1 >= i || child1_value > child2_value) {
13326  if (parent_value > child1_value) break;
13327  content->SwapPairs(numbers, parent_index, child_index);
13328  parent_index = child_index;
13329  } else {
13330  if (parent_value > child2_value) break;
13331  content->SwapPairs(numbers, parent_index, child_index + 1);
13332  parent_index = child_index + 1;
13333  }
13334  }
13335  }
13336 }
13337 
13338 
13339 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
13341  DCHECK(this->length() == numbers->length());
13342  // For small arrays, simply use insertion sort.
13343  if (len <= 10) {
13344  InsertionSortPairs(this, numbers, len);
13345  return;
13346  }
13347  // Check the range of indices.
13348  uint32_t min_index = NumberToUint32(numbers->get(0));
13349  uint32_t max_index = min_index;
13350  uint32_t i;
13351  for (i = 1; i < len; i++) {
13352  if (NumberToUint32(numbers->get(i)) < min_index) {
13353  min_index = NumberToUint32(numbers->get(i));
13354  } else if (NumberToUint32(numbers->get(i)) > max_index) {
13355  max_index = NumberToUint32(numbers->get(i));
13356  }
13357  }
13358  if (max_index - min_index + 1 == len) {
13359  // Indices form a contiguous range, unless there are duplicates.
13360  // Do an in-place linear time sort assuming distinct numbers, but
13361  // avoid hanging in case they are not.
13362  for (i = 0; i < len; i++) {
13363  uint32_t p;
13364  uint32_t j = 0;
13365  // While the current element at i is not at its correct position p,
13366  // swap the elements at these two positions.
13367  while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
13368  j++ < len) {
13369  SwapPairs(numbers, i, p);
13370  }
13371  }
13372  } else {
13373  HeapSortPairs(this, numbers, len);
13374  return;
13375  }
13376 }
13377 
13378 
13379 // Fill in the names of own properties into the supplied storage. The main
13380 // purpose of this function is to provide reflection information for the object
13381 // mirrors.
13383  FixedArray* storage, int index, PropertyAttributes filter) {
13384  DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index));
13385  if (HasFastProperties()) {
13386  int real_size = map()->NumberOfOwnDescriptors();
13387  DescriptorArray* descs = map()->instance_descriptors();
13388  for (int i = 0; i < real_size; i++) {
13389  if ((descs->GetDetails(i).attributes() & filter) == 0 &&
13390  !FilterKey(descs->GetKey(i), filter)) {
13391  storage->set(index++, descs->GetKey(i));
13392  }
13393  }
13394  } else {
13395  property_dictionary()->CopyKeysTo(storage,
13396  index,
13397  filter,
13399  }
13400 }
13401 
13402 
13404  return GetOwnElementKeys(NULL, filter);
13405 }
13406 
13407 
13409  // Fast case for objects with no elements.
13410  if (!IsJSValue() && HasFastObjectElements()) {
13411  uint32_t length = IsJSArray() ?
13412  static_cast<uint32_t>(
13413  Smi::cast(JSArray::cast(this)->length())->value()) :
13414  static_cast<uint32_t>(FixedArray::cast(elements())->length());
13415  if (length == 0) return 0;
13416  }
13417  // Compute the number of enumerable elements.
13418  return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
13419 }
13420 
13421 
13423  PropertyAttributes filter) {
13424  int counter = 0;
13425  switch (GetElementsKind()) {
13426  case FAST_SMI_ELEMENTS:
13427  case FAST_ELEMENTS:
13429  case FAST_HOLEY_ELEMENTS: {
13430  int length = IsJSArray() ?
13431  Smi::cast(JSArray::cast(this)->length())->value() :
13432  FixedArray::cast(elements())->length();
13433  for (int i = 0; i < length; i++) {
13434  if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
13435  if (storage != NULL) {
13436  storage->set(counter, Smi::FromInt(i));
13437  }
13438  counter++;
13439  }
13440  }
13441  DCHECK(!storage || storage->length() >= counter);
13442  break;
13443  }
13444  case FAST_DOUBLE_ELEMENTS:
13446  int length = IsJSArray() ?
13447  Smi::cast(JSArray::cast(this)->length())->value() :
13448  FixedArrayBase::cast(elements())->length();
13449  for (int i = 0; i < length; i++) {
13450  if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
13451  if (storage != NULL) {
13452  storage->set(counter, Smi::FromInt(i));
13453  }
13454  counter++;
13455  }
13456  }
13457  DCHECK(!storage || storage->length() >= counter);
13458  break;
13459  }
13460 
13461 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
13462  case EXTERNAL_##TYPE##_ELEMENTS: \
13463  case TYPE##_ELEMENTS: \
13464 
13466 #undef TYPED_ARRAY_CASE
13467  {
13468  int length = FixedArrayBase::cast(elements())->length();
13469  while (counter < length) {
13470  if (storage != NULL) {
13471  storage->set(counter, Smi::FromInt(counter));
13472  }
13473  counter++;
13474  }
13475  DCHECK(!storage || storage->length() >= counter);
13476  break;
13477  }
13478 
13479  case DICTIONARY_ELEMENTS: {
13480  if (storage != NULL) {
13481  element_dictionary()->CopyKeysTo(storage,
13482  filter,
13484  }
13485  counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
13486  break;
13487  }
13489  FixedArray* parameter_map = FixedArray::cast(elements());
13490  int mapped_length = parameter_map->length() - 2;
13491  FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
13492  if (arguments->IsDictionary()) {
13493  // Copy the keys from arguments first, because Dictionary::CopyKeysTo
13494  // will insert in storage starting at index 0.
13495  SeededNumberDictionary* dictionary =
13496  SeededNumberDictionary::cast(arguments);
13497  if (storage != NULL) {
13498  dictionary->CopyKeysTo(
13499  storage, filter, SeededNumberDictionary::UNSORTED);
13500  }
13501  counter += dictionary->NumberOfElementsFilterAttributes(filter);
13502  for (int i = 0; i < mapped_length; ++i) {
13503  if (!parameter_map->get(i + 2)->IsTheHole()) {
13504  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13505  ++counter;
13506  }
13507  }
13508  if (storage != NULL) storage->SortPairs(storage, counter);
13509 
13510  } else {
13511  int backing_length = arguments->length();
13512  int i = 0;
13513  for (; i < mapped_length; ++i) {
13514  if (!parameter_map->get(i + 2)->IsTheHole()) {
13515  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13516  ++counter;
13517  } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
13518  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13519  ++counter;
13520  }
13521  }
13522  for (; i < backing_length; ++i) {
13523  if (storage != NULL) storage->set(counter, Smi::FromInt(i));
13524  ++counter;
13525  }
13526  }
13527  break;
13528  }
13529  }
13530 
13531  if (this->IsJSValue()) {
13532  Object* val = JSValue::cast(this)->value();
13533  if (val->IsString()) {
13534  String* str = String::cast(val);
13535  if (storage) {
13536  for (int i = 0; i < str->length(); i++) {
13537  storage->set(counter + i, Smi::FromInt(i));
13538  }
13539  }
13540  counter += str->length();
13541  }
13542  }
13543  DCHECK(!storage || storage->length() == counter);
13544  return counter;
13545 }
13546 
13547 
13549  return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
13550 }
13551 
13552 
13553 // StringSharedKeys are used as keys in the eval cache.
13555  public:
13558  StrictMode strict_mode,
13559  int scope_position)
13560  : source_(source),
13561  shared_(shared),
13562  strict_mode_(strict_mode),
13563  scope_position_(scope_position) { }
13564 
13565  bool IsMatch(Object* other) OVERRIDE {
13566  DisallowHeapAllocation no_allocation;
13567  if (!other->IsFixedArray()) return false;
13568  FixedArray* other_array = FixedArray::cast(other);
13569  SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13570  if (shared != *shared_) return false;
13571  int strict_unchecked = Smi::cast(other_array->get(2))->value();
13572  DCHECK(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
13573  StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
13574  if (strict_mode != strict_mode_) return false;
13575  int scope_position = Smi::cast(other_array->get(3))->value();
13576  if (scope_position != scope_position_) return false;
13577  String* source = String::cast(other_array->get(1));
13578  return source->Equals(*source_);
13579  }
13580 
13582  SharedFunctionInfo* shared,
13583  StrictMode strict_mode,
13584  int scope_position) {
13585  uint32_t hash = source->Hash();
13586  if (shared->HasSourceCode()) {
13587  // Instead of using the SharedFunctionInfo pointer in the hash
13588  // code computation, we use a combination of the hash of the
13589  // script source code and the start position of the calling scope.
13590  // We do this to ensure that the cache entries can survive garbage
13591  // collection.
13592  Script* script(Script::cast(shared->script()));
13593  hash ^= String::cast(script->source())->Hash();
13594  if (strict_mode == STRICT) hash ^= 0x8000;
13595  hash += scope_position;
13596  }
13597  return hash;
13598  }
13599 
13601  return StringSharedHashHelper(*source_, *shared_, strict_mode_,
13602  scope_position_);
13603  }
13604 
13606  DisallowHeapAllocation no_allocation;
13607  FixedArray* other_array = FixedArray::cast(obj);
13608  SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
13609  String* source = String::cast(other_array->get(1));
13610  int strict_unchecked = Smi::cast(other_array->get(2))->value();
13611  DCHECK(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
13612  StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
13613  int scope_position = Smi::cast(other_array->get(3))->value();
13614  return StringSharedHashHelper(
13615  source, shared, strict_mode, scope_position);
13616  }
13617 
13618 
13620  Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
13621  array->set(0, *shared_);
13622  array->set(1, *source_);
13623  array->set(2, Smi::FromInt(strict_mode_));
13624  array->set(3, Smi::FromInt(scope_position_));
13625  return array;
13626  }
13627 
13628  private:
13633 };
13634 
13635 
13636 // RegExpKey carries the source and flags of a regular expression as key.
13637 class RegExpKey : public HashTableKey {
13638  public:
13640  : string_(string),
13641  flags_(Smi::FromInt(flags.value())) { }
13642 
13643  // Rather than storing the key in the hash table, a pointer to the
13644  // stored value is stored where the key should be. IsMatch then
13645  // compares the search key to the found object, rather than comparing
13646  // a key to a key.
13647  bool IsMatch(Object* obj) OVERRIDE {
13648  FixedArray* val = FixedArray::cast(obj);
13649  return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
13650  && (flags_ == val->get(JSRegExp::kFlagsIndex));
13651  }
13652 
13653  uint32_t Hash() OVERRIDE { return RegExpHash(*string_, flags_); }
13654 
13656  // Plain hash maps, which is where regexp keys are used, don't
13657  // use this function.
13658  UNREACHABLE();
13659  return MaybeHandle<Object>().ToHandleChecked();
13660  }
13661 
13663  FixedArray* val = FixedArray::cast(obj);
13664  return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
13665  Smi::cast(val->get(JSRegExp::kFlagsIndex)));
13666  }
13667 
13668  static uint32_t RegExpHash(String* string, Smi* flags) {
13669  return string->Hash() + flags->value();
13670  }
13671 
13674 };
13675 
13676 
13678  if (hash_field_ == 0) Hash();
13679  return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
13680 }
13681 
13682 
13684  if (hash_field_ == 0) Hash();
13685  return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
13686 }
13687 
13688 
13690  if (hash_field_ == 0) Hash();
13691  return isolate->factory()->NewOneByteInternalizedSubString(
13692  string_, from_, length_, hash_field_);
13693 }
13694 
13695 
13697  Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
13698  return String::cast(string)->IsOneByteEqualTo(chars);
13699 }
13700 
13701 
13702 // InternalizedStringKey carries a string/internalized-string object as key.
13704  public:
13706  : string_(string) { }
13707 
13708  virtual bool IsMatch(Object* string) OVERRIDE {
13709  return String::cast(string)->Equals(*string_);
13710  }
13711 
13712  virtual uint32_t Hash() OVERRIDE { return string_->Hash(); }
13713 
13715  return String::cast(other)->Hash();
13716  }
13717 
13719  // Internalize the string if possible.
13720  MaybeHandle<Map> maybe_map =
13721  isolate->factory()->InternalizedStringMapForString(string_);
13722  Handle<Map> map;
13723  if (maybe_map.ToHandle(&map)) {
13724  string_->set_map_no_write_barrier(*map);
13725  DCHECK(string_->IsInternalizedString());
13726  return string_;
13727  }
13728  // Otherwise allocate a new internalized string.
13729  return isolate->factory()->NewInternalizedStringImpl(
13730  string_, string_->length(), string_->hash_field());
13731  }
13732 
13733  static uint32_t StringHash(Object* obj) {
13734  return String::cast(obj)->Hash();
13735  }
13736 
13738 };
13739 
13740 
13741 template<typename Derived, typename Shape, typename Key>
13743  IteratePointers(v, 0, kElementsStartOffset);
13744 }
13745 
13746 
13747 template<typename Derived, typename Shape, typename Key>
13749  IteratePointers(v,
13750  kElementsStartOffset,
13752 }
13753 
13754 
13755 template<typename Derived, typename Shape, typename Key>
13757  Isolate* isolate,
13758  int at_least_space_for,
13759  MinimumCapacity capacity_option,
13760  PretenureFlag pretenure) {
13761  DCHECK(0 <= at_least_space_for);
13762  DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
13763  int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
13764  ? at_least_space_for
13765  : ComputeCapacity(at_least_space_for);
13766  if (capacity > HashTable::kMaxCapacity) {
13767  v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
13768  }
13769 
13770  Factory* factory = isolate->factory();
13771  int length = EntryToIndex(capacity);
13772  Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
13773  array->set_map_no_write_barrier(*factory->hash_table_map());
13774  Handle<Derived> table = Handle<Derived>::cast(array);
13775 
13776  table->SetNumberOfElements(0);
13777  table->SetNumberOfDeletedElements(0);
13778  table->SetCapacity(capacity);
13779  return table;
13780 }
13781 
13782 
13783 // Find entry for key otherwise return kNotFound.
13785  if (!key->IsUniqueName()) {
13786  return DerivedHashTable::FindEntry(key);
13787  }
13788 
13789  // Optimized for unique names. Knowledge of the key type allows:
13790  // 1. Move the check if the key is unique out of the loop.
13791  // 2. Avoid comparing hash codes in unique-to-unique comparison.
13792  // 3. Detect a case when a dictionary key is not unique but the key is.
13793  // In case of positive result the dictionary key may be replaced by the
13794  // internalized string with minimal performance penalty. It gives a chance
13795  // to perform further lookups in code stubs (and significant performance
13796  // boost a certain style of code).
13797 
13798  // EnsureCapacity will guarantee the hash table is never full.
13799  uint32_t capacity = Capacity();
13800  uint32_t entry = FirstProbe(key->Hash(), capacity);
13801  uint32_t count = 1;
13802 
13803  while (true) {
13804  int index = EntryToIndex(entry);
13805  Object* element = get(index);
13806  if (element->IsUndefined()) break; // Empty entry.
13807  if (*key == element) return entry;
13808  if (!element->IsUniqueName() &&
13809  !element->IsTheHole() &&
13810  Name::cast(element)->Equals(*key)) {
13811  // Replace a key that is a non-internalized string by the equivalent
13812  // internalized string for faster further lookups.
13813  set(index, *key);
13814  return entry;
13815  }
13816  DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
13817  entry = NextProbe(entry, count++, capacity);
13818  }
13819  return kNotFound;
13820 }
13821 
13822 
13823 template<typename Derived, typename Shape, typename Key>
13825  Handle<Derived> new_table,
13826  Key key) {
13827  DCHECK(NumberOfElements() < new_table->Capacity());
13828 
13829  DisallowHeapAllocation no_gc;
13830  WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
13831 
13832  // Copy prefix to new array.
13833  for (int i = kPrefixStartIndex;
13834  i < kPrefixStartIndex + Shape::kPrefixSize;
13835  i++) {
13836  new_table->set(i, get(i), mode);
13837  }
13838 
13839  // Rehash the elements.
13840  int capacity = Capacity();
13841  for (int i = 0; i < capacity; i++) {
13842  uint32_t from_index = EntryToIndex(i);
13843  Object* k = get(from_index);
13844  if (IsKey(k)) {
13845  uint32_t hash = HashTable::HashForObject(key, k);
13846  uint32_t insertion_index =
13847  EntryToIndex(new_table->FindInsertionEntry(hash));
13848  for (int j = 0; j < Shape::kEntrySize; j++) {
13849  new_table->set(insertion_index + j, get(from_index + j), mode);
13850  }
13851  }
13852  }
13853  new_table->SetNumberOfElements(NumberOfElements());
13854  new_table->SetNumberOfDeletedElements(0);
13855 }
13856 
13857 
13858 template<typename Derived, typename Shape, typename Key>
13860  Key key,
13861  Object* k,
13862  int probe,
13863  uint32_t expected) {
13864  uint32_t hash = HashTable::HashForObject(key, k);
13865  uint32_t capacity = Capacity();
13866  uint32_t entry = FirstProbe(hash, capacity);
13867  for (int i = 1; i < probe; i++) {
13868  if (entry == expected) return expected;
13869  entry = NextProbe(entry, i, capacity);
13870  }
13871  return entry;
13872 }
13873 
13874 
13875 template<typename Derived, typename Shape, typename Key>
13877  uint32_t entry2,
13879  int index1 = EntryToIndex(entry1);
13880  int index2 = EntryToIndex(entry2);
13881  Object* temp[Shape::kEntrySize];
13882  for (int j = 0; j < Shape::kEntrySize; j++) {
13883  temp[j] = get(index1 + j);
13884  }
13885  for (int j = 0; j < Shape::kEntrySize; j++) {
13886  set(index1 + j, get(index2 + j), mode);
13887  }
13888  for (int j = 0; j < Shape::kEntrySize; j++) {
13889  set(index2 + j, temp[j], mode);
13890  }
13891 }
13892 
13893 
13894 template<typename Derived, typename Shape, typename Key>
13896  DisallowHeapAllocation no_gc;
13898  uint32_t capacity = Capacity();
13899  bool done = false;
13900  for (int probe = 1; !done; probe++) {
13901  // All elements at entries given by one of the first _probe_ probes
13902  // are placed correctly. Other elements might need to be moved.
13903  done = true;
13904  for (uint32_t current = 0; current < capacity; current++) {
13905  Object* current_key = get(EntryToIndex(current));
13906  if (IsKey(current_key)) {
13907  uint32_t target = EntryForProbe(key, current_key, probe, current);
13908  if (current == target) continue;
13909  Object* target_key = get(EntryToIndex(target));
13910  if (!IsKey(target_key) ||
13911  EntryForProbe(key, target_key, probe, target) != target) {
13912  // Put the current element into the correct position.
13913  Swap(current, target, mode);
13914  // The other element will be processed on the next iteration.
13915  current--;
13916  } else {
13917  // The place for the current element is occupied. Leave the element
13918  // for the next probe.
13919  done = false;
13920  }
13921  }
13922  }
13923  }
13924 }
13925 
13926 
13927 template<typename Derived, typename Shape, typename Key>
13929  Handle<Derived> table,
13930  int n,
13931  Key key,
13932  PretenureFlag pretenure) {
13933  Isolate* isolate = table->GetIsolate();
13934  int capacity = table->Capacity();
13935  int nof = table->NumberOfElements() + n;
13936  int nod = table->NumberOfDeletedElements();
13937  // Return if:
13938  // 50% is still free after adding n elements and
13939  // at most 50% of the free elements are deleted elements.
13940  if (nod <= (capacity - nof) >> 1) {
13941  int needed_free = nof >> 1;
13942  if (nof + needed_free <= capacity) return table;
13943  }
13944 
13945  const int kMinCapacityForPretenure = 256;
13946  bool should_pretenure = pretenure == TENURED ||
13947  ((capacity > kMinCapacityForPretenure) &&
13948  !isolate->heap()->InNewSpace(*table));
13949  Handle<Derived> new_table = HashTable::New(
13950  isolate,
13951  nof * 2,
13953  should_pretenure ? TENURED : NOT_TENURED);
13954 
13955  table->Rehash(new_table, key);
13956  return new_table;
13957 }
13958 
13959 
13960 template<typename Derived, typename Shape, typename Key>
13962  Key key) {
13963  int capacity = table->Capacity();
13964  int nof = table->NumberOfElements();
13965 
13966  // Shrink to fit the number of elements if only a quarter of the
13967  // capacity is filled with elements.
13968  if (nof > (capacity >> 2)) return table;
13969  // Allocate a new dictionary with room for at least the current
13970  // number of elements. The allocation method will make sure that
13971  // there is extra room in the dictionary for additions. Don't go
13972  // lower than room for 16 elements.
13973  int at_least_room_for = nof;
13974  if (at_least_room_for < 16) return table;
13975 
13976  Isolate* isolate = table->GetIsolate();
13977  const int kMinCapacityForPretenure = 256;
13978  bool pretenure =
13979  (at_least_room_for > kMinCapacityForPretenure) &&
13980  !isolate->heap()->InNewSpace(*table);
13981  Handle<Derived> new_table = HashTable::New(
13982  isolate,
13983  at_least_room_for,
13985  pretenure ? TENURED : NOT_TENURED);
13986 
13987  table->Rehash(new_table, key);
13988  return new_table;
13989 }
13990 
13991 
13992 template<typename Derived, typename Shape, typename Key>
13994  uint32_t capacity = Capacity();
13995  uint32_t entry = FirstProbe(hash, capacity);
13996  uint32_t count = 1;
13997  // EnsureCapacity will guarantee the hash table is never full.
13998  while (true) {
13999  Object* element = KeyAt(entry);
14000  if (element->IsUndefined() || element->IsTheHole()) break;
14001  entry = NextProbe(entry, count++, capacity);
14002  }
14003  return entry;
14004 }
14005 
14006 
14007 // Force instantiation of template instances class.
14008 // Please note this list is compiler dependent.
14009 
14011 
14012 template class HashTable<CompilationCacheTable,
14014  HashTableKey*>;
14015 
14017 
14018 template class HashTable<ObjectHashTable,
14020  Handle<Object> >;
14021 
14023 
14025 
14026 template class Dictionary<SeededNumberDictionary,
14028  uint32_t>;
14029 
14030 template class Dictionary<UnseededNumberDictionary,
14032  uint32_t>;
14033 
14036  New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14037 
14040  New(Isolate*, int at_least_space_for, PretenureFlag pretenure);
14041 
14042 template Handle<NameDictionary>
14044  New(Isolate*, int n, PretenureFlag pretenure);
14045 
14049 
14053 
14054 template Object*
14056  SlowReverseLookup(Object* value);
14057 
14058 template Object*
14060  SlowReverseLookup(Object* value);
14061 
14062 template void
14064  CopyKeysTo(
14065  FixedArray*,
14069  uint32_t>::SortMode);
14070 
14071 template Handle<Object>
14074 
14075 template Handle<Object>
14078 
14079 template Handle<NameDictionary>
14081  New(Isolate*, int, MinimumCapacity, PretenureFlag);
14082 
14083 template Handle<NameDictionary>
14086 
14090 
14092  CopyKeysTo(
14093  FixedArray*,
14094  int,
14096  Dictionary<
14098 
14099 template int
14101  NumberOfElementsFilterAttributes(PropertyAttributes);
14102 
14103 template Handle<NameDictionary>
14106 
14107 template void
14109  GenerateNewEnumerationIndices(Handle<NameDictionary>);
14110 
14111 template int
14114 
14118  uint32_t,
14120  PropertyDetails);
14121 
14125  uint32_t,
14127  PropertyDetails);
14128 
14132 
14136 
14137 template Handle<NameDictionary>
14139  EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
14140 
14141 template
14144 
14145 template
14147  NumberOfEnumElements();
14148 
14149 template
14152 
14153 
14155  Handle<JSObject> object, uint32_t limit) {
14156  DCHECK(object->HasDictionaryElements());
14157  Isolate* isolate = object->GetIsolate();
14158  // Must stay in dictionary mode, either because of requires_slow_elements,
14159  // or because we are not going to sort (and therefore compact) all of the
14160  // elements.
14161  Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
14163  SeededNumberDictionary::New(isolate, dict->NumberOfElements());
14164 
14165  uint32_t pos = 0;
14166  uint32_t undefs = 0;
14167  int capacity = dict->Capacity();
14168  Handle<Smi> bailout(Smi::FromInt(-1), isolate);
14169  // Entry to the new dictionary does not cause it to grow, as we have
14170  // allocated one that is large enough for all entries.
14171  DisallowHeapAllocation no_gc;
14172  for (int i = 0; i < capacity; i++) {
14173  Object* k = dict->KeyAt(i);
14174  if (!dict->IsKey(k)) continue;
14175 
14176  DCHECK(k->IsNumber());
14177  DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
14178  DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
14179  DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
14180 
14181  HandleScope scope(isolate);
14182  Handle<Object> value(dict->ValueAt(i), isolate);
14183  PropertyDetails details = dict->DetailsAt(i);
14184  if (details.type() == CALLBACKS || details.IsReadOnly()) {
14185  // Bail out and do the sorting of undefineds and array holes in JS.
14186  // Also bail out if the element is not supposed to be moved.
14187  return bailout;
14188  }
14189 
14190  uint32_t key = NumberToUint32(k);
14191  if (key < limit) {
14192  if (value->IsUndefined()) {
14193  undefs++;
14194  } else 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  } else {
14200  new_dict, pos, value, details);
14201  DCHECK(result.is_identical_to(new_dict));
14202  USE(result);
14203  pos++;
14204  }
14205  } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
14206  // Adding an entry with the key beyond smi-range requires
14207  // allocation. Bailout.
14208  return bailout;
14209  } else {
14211  new_dict, key, value, details);
14212  DCHECK(result.is_identical_to(new_dict));
14213  USE(result);
14214  }
14215  }
14216 
14217  uint32_t result = pos;
14218  PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0);
14219  while (undefs > 0) {
14220  if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
14221  // Adding an entry with the key beyond smi-range requires
14222  // allocation. Bailout.
14223  return bailout;
14224  }
14225  HandleScope scope(isolate);
14227  new_dict, pos, isolate->factory()->undefined_value(), no_details);
14228  DCHECK(result.is_identical_to(new_dict));
14229  USE(result);
14230  pos++;
14231  undefs--;
14232  }
14233 
14234  object->set_elements(*new_dict);
14235 
14236  AllowHeapAllocation allocate_return_value;
14237  return isolate->factory()->NewNumberFromUint(result);
14238 }
14239 
14240 
14241 // Collects all defined (non-hole) and non-undefined (array) elements at
14242 // the start of the elements array.
14243 // If the object is in dictionary mode, it is converted to fast elements
14244 // mode.
14246  uint32_t limit) {
14247  Isolate* isolate = object->GetIsolate();
14248  if (object->HasSloppyArgumentsElements() ||
14249  object->map()->is_observed()) {
14250  return handle(Smi::FromInt(-1), isolate);
14251  }
14252 
14253  if (object->HasDictionaryElements()) {
14254  // Convert to fast elements containing only the existing properties.
14255  // Ordering is irrelevant, since we are going to sort anyway.
14256  Handle<SeededNumberDictionary> dict(object->element_dictionary());
14257  if (object->IsJSArray() || dict->requires_slow_elements() ||
14258  dict->max_number_key() >= limit) {
14259  return JSObject::PrepareSlowElementsForSort(object, limit);
14260  }
14261  // Convert to fast elements.
14262 
14263  Handle<Map> new_map =
14265 
14266  PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
14268  Handle<FixedArray> fast_elements =
14269  isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
14270  dict->CopyValuesTo(*fast_elements);
14272 
14273  JSObject::SetMapAndElements(object, new_map, fast_elements);
14274  } else if (object->HasExternalArrayElements() ||
14275  object->HasFixedTypedArrayElements()) {
14276  // Typed arrays cannot have holes or undefined elements.
14277  return handle(Smi::FromInt(
14278  FixedArrayBase::cast(object->elements())->length()), isolate);
14279  } else if (!object->HasFastDoubleElements()) {
14280  EnsureWritableFastElements(object);
14281  }
14282  DCHECK(object->HasFastSmiOrObjectElements() ||
14283  object->HasFastDoubleElements());
14284 
14285  // Collect holes at the end, undefined before that and the rest at the
14286  // start, and return the number of non-hole, non-undefined values.
14287 
14288  Handle<FixedArrayBase> elements_base(object->elements());
14289  uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
14290  if (limit > elements_length) {
14291  limit = elements_length ;
14292  }
14293  if (limit == 0) {
14294  return handle(Smi::FromInt(0), isolate);
14295  }
14296 
14297  uint32_t result = 0;
14298  if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
14299  FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
14300  // Split elements into defined and the_hole, in that order.
14301  unsigned int holes = limit;
14302  // Assume most arrays contain no holes and undefined values, so minimize the
14303  // number of stores of non-undefined, non-the-hole values.
14304  for (unsigned int i = 0; i < holes; i++) {
14305  if (elements->is_the_hole(i)) {
14306  holes--;
14307  } else {
14308  continue;
14309  }
14310  // Position i needs to be filled.
14311  while (holes > i) {
14312  if (elements->is_the_hole(holes)) {
14313  holes--;
14314  } else {
14315  elements->set(i, elements->get_scalar(holes));
14316  break;
14317  }
14318  }
14319  }
14320  result = holes;
14321  while (holes < limit) {
14322  elements->set_the_hole(holes);
14323  holes++;
14324  }
14325  } else {
14326  FixedArray* elements = FixedArray::cast(*elements_base);
14327  DisallowHeapAllocation no_gc;
14328 
14329  // Split elements into defined, undefined and the_hole, in that order. Only
14330  // count locations for undefined and the hole, and fill them afterwards.
14331  WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
14332  unsigned int undefs = limit;
14333  unsigned int holes = limit;
14334  // Assume most arrays contain no holes and undefined values, so minimize the
14335  // number of stores of non-undefined, non-the-hole values.
14336  for (unsigned int i = 0; i < undefs; i++) {
14337  Object* current = elements->get(i);
14338  if (current->IsTheHole()) {
14339  holes--;
14340  undefs--;
14341  } else if (current->IsUndefined()) {
14342  undefs--;
14343  } else {
14344  continue;
14345  }
14346  // Position i needs to be filled.
14347  while (undefs > i) {
14348  current = elements->get(undefs);
14349  if (current->IsTheHole()) {
14350  holes--;
14351  undefs--;
14352  } else if (current->IsUndefined()) {
14353  undefs--;
14354  } else {
14355  elements->set(i, current, write_barrier);
14356  break;
14357  }
14358  }
14359  }
14360  result = undefs;
14361  while (undefs < holes) {
14362  elements->set_undefined(undefs);
14363  undefs++;
14364  }
14365  while (holes < limit) {
14366  elements->set_the_hole(holes);
14367  holes++;
14368  }
14369  }
14370 
14371  return isolate->factory()->NewNumberFromUint(result);
14372 }
14373 
14374 
14376  switch (elements()->map()->instance_type()) {
14377 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size) \
14378  case EXTERNAL_##TYPE##_ARRAY_TYPE: \
14379  case FIXED_##TYPE##_ARRAY_TYPE: \
14380  return kExternal##Type##Array;
14381 
14383 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
14384 
14385  default:
14386  UNREACHABLE();
14387  return static_cast<ExternalArrayType>(-1);
14388  }
14389 }
14390 
14391 
14393  switch (elements()->map()->instance_type()) {
14394 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size) \
14395  case EXTERNAL_##TYPE##_ARRAY_TYPE: \
14396  return size;
14397 
14399 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
14400 
14401  default:
14402  UNREACHABLE();
14403  return 0;
14404  }
14405 }
14406 
14407 
14410  uint32_t index,
14411  Handle<Object> value) {
14412  uint8_t clamped_value = 0;
14413  if (index < static_cast<uint32_t>(array->length())) {
14414  if (value->IsSmi()) {
14415  int int_value = Handle<Smi>::cast(value)->value();
14416  if (int_value < 0) {
14417  clamped_value = 0;
14418  } else if (int_value > 255) {
14419  clamped_value = 255;
14420  } else {
14421  clamped_value = static_cast<uint8_t>(int_value);
14422  }
14423  } else if (value->IsHeapNumber()) {
14424  double double_value = Handle<HeapNumber>::cast(value)->value();
14425  if (!(double_value > 0)) {
14426  // NaN and less than zero clamp to zero.
14427  clamped_value = 0;
14428  } else if (double_value > 255) {
14429  // Greater than 255 clamp to 255.
14430  clamped_value = 255;
14431  } else {
14432  // Other doubles are rounded to the nearest integer.
14433  clamped_value = static_cast<uint8_t>(lrint(double_value));
14434  }
14435  } else {
14436  // Clamp undefined to zero (default). All other types have been
14437  // converted to a number type further up in the call chain.
14438  DCHECK(value->IsUndefined());
14439  }
14440  array->set(index, clamped_value);
14441  }
14442  return handle(Smi::FromInt(clamped_value), array->GetIsolate());
14443 }
14444 
14445 
14446 template<typename ExternalArrayClass, typename ValueType>
14448  Isolate* isolate,
14449  Handle<ExternalArrayClass> receiver,
14450  uint32_t index,
14451  Handle<Object> value) {
14452  ValueType cast_value = 0;
14453  if (index < static_cast<uint32_t>(receiver->length())) {
14454  if (value->IsSmi()) {
14455  int int_value = Handle<Smi>::cast(value)->value();
14456  cast_value = static_cast<ValueType>(int_value);
14457  } else if (value->IsHeapNumber()) {
14458  double double_value = Handle<HeapNumber>::cast(value)->value();
14459  cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
14460  } else {
14461  // Clamp undefined to zero (default). All other types have been
14462  // converted to a number type further up in the call chain.
14463  DCHECK(value->IsUndefined());
14464  }
14465  receiver->set(index, cast_value);
14466  }
14467  return isolate->factory()->NewNumberFromInt(cast_value);
14468 }
14469 
14470 
14472  uint32_t index,
14473  Handle<Object> value) {
14474  return ExternalArrayIntSetter<ExternalInt8Array, int8_t>(
14475  array->GetIsolate(), array, index, value);
14476 }
14477 
14478 
14480  uint32_t index,
14481  Handle<Object> value) {
14482  return ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(
14483  array->GetIsolate(), array, index, value);
14484 }
14485 
14486 
14488  uint32_t index,
14489  Handle<Object> value) {
14490  return ExternalArrayIntSetter<ExternalInt16Array, int16_t>(
14491  array->GetIsolate(), array, index, value);
14492 }
14493 
14494 
14496  uint32_t index,
14497  Handle<Object> value) {
14498  return ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(
14499  array->GetIsolate(), array, index, value);
14500 }
14501 
14502 
14504  uint32_t index,
14505  Handle<Object> value) {
14506  return ExternalArrayIntSetter<ExternalInt32Array, int32_t>(
14507  array->GetIsolate(), array, index, value);
14508 }
14509 
14510 
14513  uint32_t index,
14514  Handle<Object> value) {
14515  uint32_t cast_value = 0;
14516  if (index < static_cast<uint32_t>(array->length())) {
14517  if (value->IsSmi()) {
14518  int int_value = Handle<Smi>::cast(value)->value();
14519  cast_value = static_cast<uint32_t>(int_value);
14520  } else if (value->IsHeapNumber()) {
14521  double double_value = Handle<HeapNumber>::cast(value)->value();
14522  cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
14523  } else {
14524  // Clamp undefined to zero (default). All other types have been
14525  // converted to a number type further up in the call chain.
14526  DCHECK(value->IsUndefined());
14527  }
14528  array->set(index, cast_value);
14529  }
14530  return array->GetIsolate()->factory()->NewNumberFromUint(cast_value);
14531 }
14532 
14533 
14536  uint32_t index,
14537  Handle<Object> value) {
14538  float cast_value = static_cast<float>(base::OS::nan_value());
14539  if (index < static_cast<uint32_t>(array->length())) {
14540  if (value->IsSmi()) {
14541  int int_value = Handle<Smi>::cast(value)->value();
14542  cast_value = static_cast<float>(int_value);
14543  } else if (value->IsHeapNumber()) {
14544  double double_value = Handle<HeapNumber>::cast(value)->value();
14545  cast_value = static_cast<float>(double_value);
14546  } else {
14547  // Clamp undefined to NaN (default). All other types have been
14548  // converted to a number type further up in the call chain.
14549  DCHECK(value->IsUndefined());
14550  }
14551  array->set(index, cast_value);
14552  }
14553  return array->GetIsolate()->factory()->NewNumber(cast_value);
14554 }
14555 
14556 
14559  uint32_t index,
14560  Handle<Object> value) {
14561  double double_value = base::OS::nan_value();
14562  if (index < static_cast<uint32_t>(array->length())) {
14563  if (value->IsNumber()) {
14564  double_value = value->Number();
14565  } else {
14566  // Clamp undefined to NaN (default). All other types have been
14567  // converted to a number type further up in the call chain.
14568  DCHECK(value->IsUndefined());
14569  }
14570  array->set(index, double_value);
14571  }
14572  return array->GetIsolate()->factory()->NewNumber(double_value);
14573 }
14574 
14575 
14577  Handle<JSGlobalObject> global,
14578  Handle<Name> name) {
14579  DCHECK(!global->HasFastProperties());
14580  int entry = global->property_dictionary()->FindEntry(name);
14581  if (entry == NameDictionary::kNotFound) {
14582  Isolate* isolate = global->GetIsolate();
14583  Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(
14584  isolate->factory()->the_hole_value());
14585  PropertyDetails details(NONE, NORMAL, 0);
14586  details = details.AsDeleted();
14588  handle(global->property_dictionary()), name, cell, details);
14589  global->set_properties(*dictionary);
14590  return cell;
14591  } else {
14592  Object* value = global->property_dictionary()->ValueAt(entry);
14593  DCHECK(value->IsPropertyCell());
14594  return handle(PropertyCell::cast(value));
14595  }
14596 }
14597 
14598 
14599 // This class is used for looking up two character strings in the string table.
14600 // If we don't have a hit we don't want to waste much time so we unroll the
14601 // string hash calculation loop here for speed. Doesn't work if the two
14602 // characters form a decimal integer, since such strings have a different hash
14603 // algorithm.
14605  public:
14607  : c1_(c1), c2_(c2) {
14608  // Char 1.
14609  uint32_t hash = seed;
14610  hash += c1;
14611  hash += hash << 10;
14612  hash ^= hash >> 6;
14613  // Char 2.
14614  hash += c2;
14615  hash += hash << 10;
14616  hash ^= hash >> 6;
14617  // GetHash.
14618  hash += hash << 3;
14619  hash ^= hash >> 11;
14620  hash += hash << 15;
14621  if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
14622  hash_ = hash;
14623 #ifdef DEBUG
14624  // If this assert fails then we failed to reproduce the two-character
14625  // version of the string hashing algorithm above. One reason could be
14626  // that we were passed two digits as characters, since the hash
14627  // algorithm is different in that case.
14628  uint16_t chars[2] = {c1, c2};
14629  uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
14631  DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
14632 #endif
14633  }
14634 
14636  if (!o->IsString()) return false;
14637  String* other = String::cast(o);
14638  if (other->length() != 2) return false;
14639  if (other->Get(0) != c1_) return false;
14640  return other->Get(1) == c2_;
14641  }
14642 
14643  uint32_t Hash() OVERRIDE { return hash_; }
14645  if (!key->IsString()) return 0;
14646  return String::cast(key)->Hash();
14647  }
14648 
14650  // The TwoCharHashTableKey is only used for looking in the string
14651  // table, not for adding to it.
14652  UNREACHABLE();
14653  return MaybeHandle<Object>().ToHandleChecked();
14654  }
14655 
14656  private:
14660 };
14661 
14662 
14664  Isolate* isolate,
14665  Handle<String> string) {
14666  if (string->IsInternalizedString()) {
14667  return string;
14668  }
14669  return LookupStringIfExists(isolate, string);
14670 }
14671 
14672 
14674  Isolate* isolate,
14675  Handle<String> string) {
14676  Handle<StringTable> string_table = isolate->factory()->string_table();
14677  InternalizedStringKey key(string);
14678  int entry = string_table->FindEntry(&key);
14679  if (entry == kNotFound) {
14680  return MaybeHandle<String>();
14681  } else {
14682  Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14683  DCHECK(StringShape(*result).IsInternalized());
14684  return result;
14685  }
14686 }
14687 
14688 
14690  Isolate* isolate,
14691  uint16_t c1,
14692  uint16_t c2) {
14693  Handle<StringTable> string_table = isolate->factory()->string_table();
14694  TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
14695  int entry = string_table->FindEntry(&key);
14696  if (entry == kNotFound) {
14697  return MaybeHandle<String>();
14698  } else {
14699  Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
14700  DCHECK(StringShape(*result).IsInternalized());
14701  return result;
14702  }
14703 }
14704 
14705 
14707  Handle<String> string) {
14708  InternalizedStringKey key(string);
14709  return LookupKey(isolate, &key);
14710 }
14711 
14712 
14714  Handle<StringTable> table = isolate->factory()->string_table();
14715  int entry = table->FindEntry(key);
14716 
14717  // String already in table.
14718  if (entry != kNotFound) {
14719  return handle(String::cast(table->KeyAt(entry)), isolate);
14720  }
14721 
14722  // Adding new string. Grow table if needed.
14723  table = StringTable::EnsureCapacity(table, 1, key);
14724 
14725  // Create string object.
14726  Handle<Object> string = key->AsHandle(isolate);
14727  // There must be no attempts to internalize strings that could throw
14728  // InvalidStringLength error.
14729  CHECK(!string.is_null());
14730 
14731  // Add the new string and return it along with the string table.
14732  entry = table->FindInsertionEntry(key->Hash());
14733  table->set(EntryToIndex(entry), *string);
14734  table->ElementAdded();
14735 
14736  isolate->factory()->set_string_table(table);
14737  return Handle<String>::cast(string);
14738 }
14739 
14740 
14742  Handle<Context> context) {
14743  Isolate* isolate = GetIsolate();
14744  Handle<SharedFunctionInfo> shared(context->closure()->shared());
14745  StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
14747  int entry = FindEntry(&key);
14748  if (entry == kNotFound) return isolate->factory()->undefined_value();
14749  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14750 }
14751 
14752 
14754  Handle<Context> context,
14755  StrictMode strict_mode,
14756  int scope_position) {
14757  Isolate* isolate = GetIsolate();
14758  Handle<SharedFunctionInfo> shared(context->closure()->shared());
14759  StringSharedKey key(src, shared, strict_mode, scope_position);
14760  int entry = FindEntry(&key);
14761  if (entry == kNotFound) return isolate->factory()->undefined_value();
14762  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14763 }
14764 
14765 
14768  Isolate* isolate = GetIsolate();
14769  DisallowHeapAllocation no_allocation;
14770  RegExpKey key(src, flags);
14771  int entry = FindEntry(&key);
14772  if (entry == kNotFound) return isolate->factory()->undefined_value();
14773  return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
14774 }
14775 
14776 
14779  Handle<Context> context, Handle<Object> value) {
14780  Isolate* isolate = cache->GetIsolate();
14781  Handle<SharedFunctionInfo> shared(context->closure()->shared());
14782  StringSharedKey key(src, shared, FLAG_use_strict ? STRICT : SLOPPY,
14784  cache = EnsureCapacity(cache, 1, &key);
14785  Handle<Object> k = key.AsHandle(isolate);
14786  int entry = cache->FindInsertionEntry(key.Hash());
14787  cache->set(EntryToIndex(entry), *k);
14788  cache->set(EntryToIndex(entry) + 1, *value);
14789  cache->ElementAdded();
14790  return cache;
14791 }
14792 
14793 
14797  int scope_position) {
14798  Isolate* isolate = cache->GetIsolate();
14799  Handle<SharedFunctionInfo> shared(context->closure()->shared());
14800  StringSharedKey key(src, shared, value->strict_mode(), scope_position);
14801  cache = EnsureCapacity(cache, 1, &key);
14802  Handle<Object> k = key.AsHandle(isolate);
14803  int entry = cache->FindInsertionEntry(key.Hash());
14804  cache->set(EntryToIndex(entry), *k);
14805  cache->set(EntryToIndex(entry) + 1, *value);
14806  cache->ElementAdded();
14807  return cache;
14808 }
14809 
14810 
14814  RegExpKey key(src, flags);
14815  cache = EnsureCapacity(cache, 1, &key);
14816  int entry = cache->FindInsertionEntry(key.Hash());
14817  // We store the value in the key slot, and compare the search key
14818  // to the stored value with a custon IsMatch function during lookups.
14819  cache->set(EntryToIndex(entry), *value);
14820  cache->set(EntryToIndex(entry) + 1, *value);
14821  cache->ElementAdded();
14822  return cache;
14823 }
14824 
14825 
14827  DisallowHeapAllocation no_allocation;
14828  Object* the_hole_value = GetHeap()->the_hole_value();
14829  for (int entry = 0, size = Capacity(); entry < size; entry++) {
14830  int entry_index = EntryToIndex(entry);
14831  int value_index = entry_index + 1;
14832  if (get(value_index) == value) {
14833  NoWriteBarrierSet(this, entry_index, the_hole_value);
14834  NoWriteBarrierSet(this, value_index, the_hole_value);
14835  ElementRemoved();
14836  }
14837  }
14838  return;
14839 }
14840 
14841 
14842 // StringsKey used for HashTable where key is array of internalized strings.
14843 class StringsKey : public HashTableKey {
14844  public:
14845  explicit StringsKey(Handle<FixedArray> strings) : strings_(strings) { }
14846 
14847  bool IsMatch(Object* strings) OVERRIDE {
14848  FixedArray* o = FixedArray::cast(strings);
14849  int len = strings_->length();
14850  if (o->length() != len) return false;
14851  for (int i = 0; i < len; i++) {
14852  if (o->get(i) != strings_->get(i)) return false;
14853  }
14854  return true;
14855  }
14856 
14857  uint32_t Hash() OVERRIDE { return HashForObject(*strings_); }
14858 
14860  FixedArray* strings = FixedArray::cast(obj);
14861  int len = strings->length();
14862  uint32_t hash = 0;
14863  for (int i = 0; i < len; i++) {
14864  hash ^= String::cast(strings->get(i))->Hash();
14865  }
14866  return hash;
14867  }
14868 
14869  Handle<Object> AsHandle(Isolate* isolate) OVERRIDE { return strings_; }
14870 
14871  private:
14873 };
14874 
14875 
14877  DisallowHeapAllocation no_alloc;
14878  StringsKey key(handle(array));
14879  int entry = FindEntry(&key);
14880  if (entry == kNotFound) return GetHeap()->undefined_value();
14881  return get(EntryToIndex(entry) + 1);
14882 }
14883 
14884 
14886  Handle<MapCache> map_cache, Handle<FixedArray> array, Handle<Map> value) {
14887  StringsKey key(array);
14888 
14889  Handle<MapCache> new_cache = EnsureCapacity(map_cache, 1, &key);
14890  int entry = new_cache->FindInsertionEntry(key.Hash());
14891  new_cache->set(EntryToIndex(entry), *array);
14892  new_cache->set(EntryToIndex(entry) + 1, *value);
14893  new_cache->ElementAdded();
14894  return new_cache;
14895 }
14896 
14897 
14898 template<typename Derived, typename Shape, typename Key>
14900  Isolate* isolate,
14901  int at_least_space_for,
14902  PretenureFlag pretenure) {
14903  DCHECK(0 <= at_least_space_for);
14904  Handle<Derived> dict = DerivedHashTable::New(isolate,
14905  at_least_space_for,
14907  pretenure);
14908 
14909  // Initialize the next enumeration index.
14910  dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
14911  return dict;
14912 }
14913 
14914 
14915 template<typename Derived, typename Shape, typename Key>
14917  Handle<Derived> dictionary) {
14918  Factory* factory = dictionary->GetIsolate()->factory();
14919  int length = dictionary->NumberOfElements();
14920 
14921  // Allocate and initialize iteration order array.
14922  Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
14923  for (int i = 0; i < length; i++) {
14924  iteration_order->set(i, Smi::FromInt(i));
14925  }
14926 
14927  // Allocate array with enumeration order.
14928  Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
14929 
14930  // Fill the enumeration order array with property details.
14931  int capacity = dictionary->Capacity();
14932  int pos = 0;
14933  for (int i = 0; i < capacity; i++) {
14934  if (dictionary->IsKey(dictionary->KeyAt(i))) {
14935  int index = dictionary->DetailsAt(i).dictionary_index();
14936  enumeration_order->set(pos++, Smi::FromInt(index));
14937  }
14938  }
14939 
14940  // Sort the arrays wrt. enumeration order.
14941  iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
14942 
14943  // Overwrite the enumeration_order with the enumeration indices.
14944  for (int i = 0; i < length; i++) {
14945  int index = Smi::cast(iteration_order->get(i))->value();
14946  int enum_index = PropertyDetails::kInitialIndex + i;
14947  enumeration_order->set(index, Smi::FromInt(enum_index));
14948  }
14949 
14950  // Update the dictionary with new indices.
14951  capacity = dictionary->Capacity();
14952  pos = 0;
14953  for (int i = 0; i < capacity; i++) {
14954  if (dictionary->IsKey(dictionary->KeyAt(i))) {
14955  int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
14956  PropertyDetails details = dictionary->DetailsAt(i);
14957  PropertyDetails new_details = PropertyDetails(
14958  details.attributes(), details.type(), enum_index);
14959  dictionary->DetailsAtPut(i, new_details);
14960  }
14961  }
14962 
14963  // Set the next enumeration index.
14964  dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
14965 }
14966 
14967 
14968 template<typename Derived, typename Shape, typename Key>
14970  Handle<Derived> dictionary, int n, Key key) {
14971  // Check whether there are enough enumeration indices to add n elements.
14972  if (Shape::kIsEnumerable &&
14973  !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
14974  // If not, we generate new indices for the properties.
14975  GenerateNewEnumerationIndices(dictionary);
14976  }
14977  return DerivedHashTable::EnsureCapacity(dictionary, n, key);
14978 }
14979 
14980 
14981 template<typename Derived, typename Shape, typename Key>
14983  Handle<Derived> dictionary,
14984  int entry,
14986  Factory* factory = dictionary->GetIsolate()->factory();
14987  PropertyDetails details = dictionary->DetailsAt(entry);
14988  // Ignore attributes if forcing a deletion.
14989  if (!details.IsConfigurable() && mode != JSReceiver::FORCE_DELETION) {
14990  return factory->false_value();
14991  }
14992 
14993  dictionary->SetEntry(
14994  entry, factory->the_hole_value(), factory->the_hole_value());
14995  dictionary->ElementRemoved();
14996  return factory->true_value();
14997 }
14998 
14999 
15000 template<typename Derived, typename Shape, typename Key>
15002  Handle<Derived> dictionary, Key key, Handle<Object> value) {
15003  int entry = dictionary->FindEntry(key);
15004 
15005  // If the entry is present set the value;
15006  if (entry != Dictionary::kNotFound) {
15007  dictionary->ValueAtPut(entry, *value);
15008  return dictionary;
15009  }
15010 
15011  // Check whether the dictionary should be extended.
15012  dictionary = EnsureCapacity(dictionary, 1, key);
15013 #ifdef DEBUG
15014  USE(Shape::AsHandle(dictionary->GetIsolate(), key));
15015 #endif
15016  PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
15017 
15018  AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15019  return dictionary;
15020 }
15021 
15022 
15023 template<typename Derived, typename Shape, typename Key>
15025  Handle<Derived> dictionary,
15026  Key key,
15027  Handle<Object> value,
15028  PropertyDetails details) {
15029  // Valdate key is absent.
15030  SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
15031  // Check whether the dictionary should be extended.
15032  dictionary = EnsureCapacity(dictionary, 1, key);
15033 
15034  AddEntry(dictionary, key, value, details, dictionary->Hash(key));
15035  return dictionary;
15036 }
15037 
15038 
15039 // Add a key, value pair to the dictionary.
15040 template<typename Derived, typename Shape, typename Key>
15042  Handle<Derived> dictionary,
15043  Key key,
15044  Handle<Object> value,
15045  PropertyDetails details,
15046  uint32_t hash) {
15047  // Compute the key object.
15048  Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
15049 
15050  uint32_t entry = dictionary->FindInsertionEntry(hash);
15051  // Insert element at empty or deleted entry
15052  if (!details.IsDeleted() &&
15053  details.dictionary_index() == 0 &&
15054  Shape::kIsEnumerable) {
15055  // Assign an enumeration index to the property and update
15056  // SetNextEnumerationIndex.
15057  int index = dictionary->NextEnumerationIndex();
15058  details = PropertyDetails(details.attributes(), details.type(), index);
15059  dictionary->SetNextEnumerationIndex(index + 1);
15060  }
15061  dictionary->SetEntry(entry, k, value, details);
15062  DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
15063  dictionary->KeyAt(entry)->IsName()));
15064  dictionary->ElementAdded();
15065 }
15066 
15067 
15069  DisallowHeapAllocation no_allocation;
15070  // If the dictionary requires slow elements an element has already
15071  // been added at a high index.
15072  if (requires_slow_elements()) return;
15073  // Check if this index is high enough that we should require slow
15074  // elements.
15075  if (key > kRequiresSlowElementsLimit) {
15076  set_requires_slow_elements();
15077  return;
15078  }
15079  // Update max key value.
15080  Object* max_index_object = get(kMaxNumberKeyIndex);
15081  if (!max_index_object->IsSmi() || max_number_key() < key) {
15082  FixedArray::set(kMaxNumberKeyIndex,
15083  Smi::FromInt(key << kRequiresSlowElementsTagSize));
15084  }
15085 }
15086 
15087 
15089  Handle<SeededNumberDictionary> dictionary,
15090  uint32_t key,
15091  Handle<Object> value,
15092  PropertyDetails details) {
15093  dictionary->UpdateMaxNumberKey(key);
15094  SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
15095  return Add(dictionary, key, value, details);
15096 }
15097 
15098 
15101  uint32_t key,
15102  Handle<Object> value) {
15103  SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
15104  return Add(dictionary, key, value, PropertyDetails(NONE, NORMAL, 0));
15105 }
15106 
15107 
15109  Handle<SeededNumberDictionary> dictionary,
15110  uint32_t key,
15111  Handle<Object> value) {
15112  dictionary->UpdateMaxNumberKey(key);
15113  return AtPut(dictionary, key, value);
15114 }
15115 
15116 
15119  uint32_t key,
15120  Handle<Object> value) {
15121  return AtPut(dictionary, key, value);
15122 }
15123 
15124 
15126  Handle<SeededNumberDictionary> dictionary,
15127  uint32_t key,
15128  Handle<Object> value,
15129  PropertyDetails details) {
15130  int entry = dictionary->FindEntry(key);
15131  if (entry == kNotFound) {
15132  return AddNumberEntry(dictionary, key, value, details);
15133  }
15134  // Preserve enumeration index.
15135  details = PropertyDetails(details.attributes(),
15136  details.type(),
15137  dictionary->DetailsAt(entry).dictionary_index());
15138  Handle<Object> object_key =
15139  SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15140  dictionary->SetEntry(entry, object_key, value, details);
15141  return dictionary;
15142 }
15143 
15144 
15147  uint32_t key,
15148  Handle<Object> value) {
15149  int entry = dictionary->FindEntry(key);
15150  if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
15151  Handle<Object> object_key =
15152  UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
15153  dictionary->SetEntry(entry, object_key, value);
15154  return dictionary;
15155 }
15156 
15157 
15158 
15159 template<typename Derived, typename Shape, typename Key>
15161  PropertyAttributes filter) {
15162  int capacity = DerivedHashTable::Capacity();
15163  int result = 0;
15164  for (int i = 0; i < capacity; i++) {
15165  Object* k = DerivedHashTable::KeyAt(i);
15166  if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15167  PropertyDetails details = DetailsAt(i);
15168  if (details.IsDeleted()) continue;
15169  PropertyAttributes attr = details.attributes();
15170  if ((attr & filter) == 0) result++;
15171  }
15172  }
15173  return result;
15174 }
15175 
15176 
15177 template<typename Derived, typename Shape, typename Key>
15179  return NumberOfElementsFilterAttributes(
15180  static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC));
15181 }
15182 
15183 
15184 template<typename Derived, typename Shape, typename Key>
15186  FixedArray* storage,
15187  PropertyAttributes filter,
15188  typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
15189  DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
15190  int capacity = DerivedHashTable::Capacity();
15191  int index = 0;
15192  for (int i = 0; i < capacity; i++) {
15193  Object* k = DerivedHashTable::KeyAt(i);
15194  if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15195  PropertyDetails details = DetailsAt(i);
15196  if (details.IsDeleted()) continue;
15197  PropertyAttributes attr = details.attributes();
15198  if ((attr & filter) == 0) storage->set(index++, k);
15199  }
15200  }
15201  if (sort_mode == Dictionary::SORTED) {
15202  storage->SortPairs(storage, index);
15203  }
15204  DCHECK(storage->length() >= index);
15205 }
15206 
15207 
15209  explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { }
15210  bool operator() (Smi* a, Smi* b) {
15211  PropertyDetails da(dict->DetailsAt(a->value()));
15212  PropertyDetails db(dict->DetailsAt(b->value()));
15213  return da.dictionary_index() < db.dictionary_index();
15214  }
15216 };
15217 
15218 
15220  int length = storage->length();
15221  int capacity = Capacity();
15222  int properties = 0;
15223  for (int i = 0; i < capacity; i++) {
15224  Object* k = KeyAt(i);
15225  if (IsKey(k) && !k->IsSymbol()) {
15226  PropertyDetails details = DetailsAt(i);
15227  if (details.IsDeleted() || details.IsDontEnum()) continue;
15228  storage->set(properties, Smi::FromInt(i));
15229  properties++;
15230  if (properties == length) break;
15231  }
15232  }
15233  CHECK_EQ(length, properties);
15234  EnumIndexComparator cmp(this);
15235  Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
15236  std::sort(start, start + length, cmp);
15237  for (int i = 0; i < length; i++) {
15238  int index = Smi::cast(storage->get(i))->value();
15239  storage->set(i, KeyAt(index));
15240  }
15241 }
15242 
15243 
15244 template<typename Derived, typename Shape, typename Key>
15246  FixedArray* storage,
15247  int index,
15248  PropertyAttributes filter,
15249  typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
15250  DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
15251  int capacity = DerivedHashTable::Capacity();
15252  for (int i = 0; i < capacity; i++) {
15253  Object* k = DerivedHashTable::KeyAt(i);
15254  if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) {
15255  PropertyDetails details = DetailsAt(i);
15256  if (details.IsDeleted()) continue;
15257  PropertyAttributes attr = details.attributes();
15258  if ((attr & filter) == 0) storage->set(index++, k);
15259  }
15260  }
15261  if (sort_mode == Dictionary::SORTED) {
15262  storage->SortPairs(storage, index);
15263  }
15264  DCHECK(storage->length() >= index);
15265 }
15266 
15267 
15268 // Backwards lookup (slow).
15269 template<typename Derived, typename Shape, typename Key>
15271  int capacity = DerivedHashTable::Capacity();
15272  for (int i = 0; i < capacity; i++) {
15273  Object* k = DerivedHashTable::KeyAt(i);
15274  if (Dictionary::IsKey(k)) {
15275  Object* e = ValueAt(i);
15276  if (e->IsPropertyCell()) {
15277  e = PropertyCell::cast(e)->value();
15278  }
15279  if (e == value) return k;
15280  }
15281  }
15282  Heap* heap = Dictionary::GetHeap();
15283  return heap->undefined_value();
15284 }
15285 
15286 
15288  DisallowHeapAllocation no_gc;
15289  DCHECK(IsKey(*key));
15290 
15291  // If the object does not have an identity hash, it was never used as a key.
15292  Object* hash = key->GetHash();
15293  if (hash->IsUndefined()) {
15294  return GetHeap()->the_hole_value();
15295  }
15296  int entry = FindEntry(key);
15297  if (entry == kNotFound) return GetHeap()->the_hole_value();
15298  return get(EntryToIndex(entry) + 1);
15299 }
15300 
15301 
15303  Handle<Object> key,
15304  Handle<Object> value) {
15305  DCHECK(table->IsKey(*key));
15306  DCHECK(!value->IsTheHole());
15307 
15308  Isolate* isolate = table->GetIsolate();
15309 
15310  // Make sure the key object has an identity hash code.
15311  Handle<Smi> hash = Object::GetOrCreateHash(isolate, key);
15312 
15313  int entry = table->FindEntry(key);
15314 
15315  // Key is already in table, just overwrite value.
15316  if (entry != kNotFound) {
15317  table->set(EntryToIndex(entry) + 1, *value);
15318  return table;
15319  }
15320 
15321  // Check whether the hash table should be extended.
15322  table = EnsureCapacity(table, 1, key);
15323  table->AddEntry(table->FindInsertionEntry(hash->value()),
15324  *key,
15325  *value);
15326  return table;
15327 }
15328 
15329 
15331  Handle<Object> key,
15332  bool* was_present) {
15333  DCHECK(table->IsKey(*key));
15334 
15335  Object* hash = key->GetHash();
15336  if (hash->IsUndefined()) {
15337  *was_present = false;
15338  return table;
15339  }
15340 
15341  int entry = table->FindEntry(key);
15342  if (entry == kNotFound) {
15343  *was_present = false;
15344  return table;
15345  }
15346 
15347  *was_present = true;
15348  table->RemoveEntry(entry);
15349  return Shrink(table, key);
15350 }
15351 
15352 
15353 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
15354  set(EntryToIndex(entry), key);
15355  set(EntryToIndex(entry) + 1, value);
15356  ElementAdded();
15357 }
15358 
15359 
15361  set_the_hole(EntryToIndex(entry));
15362  set_the_hole(EntryToIndex(entry) + 1);
15363  ElementRemoved();
15364 }
15365 
15366 
15368  DisallowHeapAllocation no_gc;
15369  DCHECK(IsKey(*key));
15370  int entry = FindEntry(key);
15371  if (entry == kNotFound) return GetHeap()->the_hole_value();
15372  return get(EntryToValueIndex(entry));
15373 }
15374 
15375 
15377  Handle<Object> key,
15378  Handle<Object> value) {
15379  DCHECK(table->IsKey(*key));
15380  int entry = table->FindEntry(key);
15381  // Key is already in table, just overwrite value.
15382  if (entry != kNotFound) {
15383  // TODO(ulan): Skipping write barrier is a temporary solution to avoid
15384  // memory leaks. Remove this once we have special visitor for weak fixed
15385  // arrays.
15386  table->set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
15387  return table;
15388  }
15389 
15390  // Check whether the hash table should be extended.
15391  table = EnsureCapacity(table, 1, key, TENURED);
15392 
15393  table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key, value);
15394  return table;
15395 }
15396 
15397 
15399  Handle<Object> key,
15400  Handle<Object> value) {
15401  DisallowHeapAllocation no_allocation;
15402  // TODO(ulan): Skipping write barrier is a temporary solution to avoid
15403  // memory leaks. Remove this once we have special visitor for weak fixed
15404  // arrays.
15405  set(EntryToIndex(entry), *key, SKIP_WRITE_BARRIER);
15406  set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
15407  ElementAdded();
15408 }
15409 
15410 
15411 template<class Derived, class Iterator, int entrysize>
15413  Isolate* isolate, int capacity, PretenureFlag pretenure) {
15414  // Capacity must be a power of two, since we depend on being able
15415  // to divide and multiple by 2 (kLoadFactor) to derive capacity
15416  // from number of buckets. If we decide to change kLoadFactor
15417  // to something other than 2, capacity should be stored as another
15418  // field of this object.
15419  capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
15420  if (capacity > kMaxCapacity) {
15421  v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
15422  }
15423  int num_buckets = capacity / kLoadFactor;
15424  Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
15425  kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
15426  backing_store->set_map_no_write_barrier(
15427  isolate->heap()->ordered_hash_table_map());
15428  Handle<Derived> table = Handle<Derived>::cast(backing_store);
15429  for (int i = 0; i < num_buckets; ++i) {
15430  table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
15431  }
15432  table->SetNumberOfBuckets(num_buckets);
15433  table->SetNumberOfElements(0);
15434  table->SetNumberOfDeletedElements(0);
15435  return table;
15436 }
15437 
15438 
15439 template<class Derived, class Iterator, int entrysize>
15441  Handle<Derived> table) {
15442  DCHECK(!table->IsObsolete());
15443 
15444  int nof = table->NumberOfElements();
15445  int nod = table->NumberOfDeletedElements();
15446  int capacity = table->Capacity();
15447  if ((nof + nod) < capacity) return table;
15448  // Don't need to grow if we can simply clear out deleted entries instead.
15449  // Note that we can't compact in place, though, so we always allocate
15450  // a new table.
15451  return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
15452 }
15453 
15454 
15455 template<class Derived, class Iterator, int entrysize>
15457  Handle<Derived> table) {
15458  DCHECK(!table->IsObsolete());
15459 
15460  int nof = table->NumberOfElements();
15461  int capacity = table->Capacity();
15462  if (nof >= (capacity >> 2)) return table;
15463  return Rehash(table, capacity / 2);
15464 }
15465 
15466 
15467 template<class Derived, class Iterator, int entrysize>
15469  Handle<Derived> table) {
15470  DCHECK(!table->IsObsolete());
15471 
15472  Handle<Derived> new_table =
15473  Allocate(table->GetIsolate(),
15474  kMinCapacity,
15475  table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15476 
15477  table->SetNextTable(*new_table);
15478  table->SetNumberOfDeletedElements(-1);
15479 
15480  return new_table;
15481 }
15482 
15483 
15484 template<class Derived, class Iterator, int entrysize>
15486  Handle<Derived> table, Handle<Object> key, bool* was_present) {
15487  int entry = table->FindEntry(key);
15488  if (entry == kNotFound) {
15489  *was_present = false;
15490  return table;
15491  }
15492  *was_present = true;
15493  table->RemoveEntry(entry);
15494  return Shrink(table);
15495 }
15496 
15497 
15498 template<class Derived, class Iterator, int entrysize>
15500  Handle<Derived> table, int new_capacity) {
15501  DCHECK(!table->IsObsolete());
15502 
15503  Handle<Derived> new_table =
15504  Allocate(table->GetIsolate(),
15505  new_capacity,
15506  table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
15507  int nof = table->NumberOfElements();
15508  int nod = table->NumberOfDeletedElements();
15509  int new_buckets = new_table->NumberOfBuckets();
15510  int new_entry = 0;
15511  int removed_holes_index = 0;
15512 
15513  for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
15514  Object* key = table->KeyAt(old_entry);
15515  if (key->IsTheHole()) {
15516  table->SetRemovedIndexAt(removed_holes_index++, old_entry);
15517  continue;
15518  }
15519 
15520  Object* hash = key->GetHash();
15521  int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
15522  Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
15523  new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
15524  int new_index = new_table->EntryToIndex(new_entry);
15525  int old_index = table->EntryToIndex(old_entry);
15526  for (int i = 0; i < entrysize; ++i) {
15527  Object* value = table->get(old_index + i);
15528  new_table->set(new_index + i, value);
15529  }
15530  new_table->set(new_index + kChainOffset, chain_entry);
15531  ++new_entry;
15532  }
15533 
15534  DCHECK_EQ(nod, removed_holes_index);
15535 
15536  new_table->SetNumberOfElements(nof);
15537  table->SetNextTable(*new_table);
15538 
15539  return new_table;
15540 }
15541 
15542 
15543 template <class Derived, class Iterator, int entrysize>
15545  Handle<Object> key, int hash) {
15546  DCHECK(!IsObsolete());
15547 
15548  DisallowHeapAllocation no_gc;
15549  DCHECK(!key->IsTheHole());
15550  for (int entry = HashToEntry(hash); entry != kNotFound;
15551  entry = ChainAt(entry)) {
15552  Object* candidate = KeyAt(entry);
15553  if (candidate->SameValueZero(*key))
15554  return entry;
15555  }
15556  return kNotFound;
15557 }
15558 
15559 
15560 template <class Derived, class Iterator, int entrysize>
15562  Handle<Object> key) {
15563  DisallowHeapAllocation no_gc;
15564  Object* hash = key->GetHash();
15565  if (!hash->IsSmi()) return kNotFound;
15566  return FindEntry(key, Smi::cast(hash)->value());
15567 }
15568 
15569 
15570 template <class Derived, class Iterator, int entrysize>
15572  DCHECK(!IsObsolete());
15573 
15574  int entry = UsedCapacity();
15575  int bucket = HashToBucket(hash);
15576  int index = EntryToIndex(entry);
15577  Object* chain_entry = get(kHashTableStartIndex + bucket);
15578  set(kHashTableStartIndex + bucket, Smi::FromInt(entry));
15579  set(index + kChainOffset, chain_entry);
15580  SetNumberOfElements(NumberOfElements() + 1);
15581  return index;
15582 }
15583 
15584 
15585 template<class Derived, class Iterator, int entrysize>
15587  DCHECK(!IsObsolete());
15588 
15589  int index = EntryToIndex(entry);
15590  for (int i = 0; i < entrysize; ++i) {
15591  set_the_hole(index + i);
15592  }
15593  SetNumberOfElements(NumberOfElements() - 1);
15594  SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
15595 }
15596 
15597 
15598 template Handle<OrderedHashSet>
15600  Isolate* isolate, int capacity, PretenureFlag pretenure);
15601 
15602 template Handle<OrderedHashSet>
15604  Handle<OrderedHashSet> table);
15605 
15606 template Handle<OrderedHashSet>
15608  Handle<OrderedHashSet> table);
15609 
15610 template Handle<OrderedHashSet>
15612  Handle<OrderedHashSet> table);
15613 
15614 template Handle<OrderedHashSet>
15616  Handle<OrderedHashSet> table, Handle<Object> key, bool* was_present);
15617 
15619  Handle<Object> key, int hash);
15621  Handle<Object> key);
15622 
15623 template int
15625 
15626 template void
15628 
15629 
15630 template Handle<OrderedHashMap>
15632  Isolate* isolate, int capacity, PretenureFlag pretenure);
15633 
15634 template Handle<OrderedHashMap>
15636  Handle<OrderedHashMap> table);
15637 
15638 template Handle<OrderedHashMap>
15640  Handle<OrderedHashMap> table);
15641 
15642 template Handle<OrderedHashMap>
15644  Handle<OrderedHashMap> table);
15645 
15646 template Handle<OrderedHashMap>
15648  Handle<OrderedHashMap> table, Handle<Object> key, bool* was_present);
15649 
15651  Handle<Object> key, int hash);
15653  Handle<Object> key);
15654 
15655 template int
15657 
15658 template void
15660 
15661 
15663  return FindEntry(key) != kNotFound;
15664 }
15665 
15666 
15668  Handle<Object> key) {
15669  int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
15670  if (table->FindEntry(key, hash) != kNotFound) return table;
15671 
15672  table = EnsureGrowable(table);
15673 
15674  int index = table->AddEntry(hash);
15675  table->set(index, *key);
15676  return table;
15677 }
15678 
15679 
15681  DisallowHeapAllocation no_gc;
15682  int entry = FindEntry(key);
15683  if (entry == kNotFound) return GetHeap()->the_hole_value();
15684  return ValueAt(entry);
15685 }
15686 
15687 
15689  Handle<Object> key,
15690  Handle<Object> value) {
15691  DCHECK(!key->IsTheHole());
15692 
15693  int hash = GetOrCreateHash(table->GetIsolate(), key)->value();
15694  int entry = table->FindEntry(key, hash);
15695 
15696  if (entry != kNotFound) {
15697  table->set(table->EntryToIndex(entry) + kValueOffset, *value);
15698  return table;
15699  }
15700 
15701  table = EnsureGrowable(table);
15702 
15703  int index = table->AddEntry(hash);
15704  table->set(index, *key);
15705  table->set(index + kValueOffset, *value);
15706  return table;
15707 }
15708 
15709 
15710 template<class Derived, class TableType>
15712  DisallowHeapAllocation no_allocation;
15713  TableType* table = TableType::cast(this->table());
15714  if (!table->IsObsolete()) return;
15715 
15716  int index = Smi::cast(this->index())->value();
15717  while (table->IsObsolete()) {
15718  TableType* next_table = table->NextTable();
15719 
15720  if (index > 0) {
15721  int nod = table->NumberOfDeletedElements();
15722 
15723  // When we clear the table we set the number of deleted elements to -1.
15724  if (nod == -1) {
15725  index = 0;
15726  } else {
15727  int old_index = index;
15728  for (int i = 0; i < nod; ++i) {
15729  int removed_index = table->RemovedIndexAt(i);
15730  if (removed_index >= old_index) break;
15731  --index;
15732  }
15733  }
15734  }
15735 
15736  table = next_table;
15737  }
15738 
15739  set_table(table);
15740  set_index(Smi::FromInt(index));
15741 }
15742 
15743 
15744 template<class Derived, class TableType>
15746  DisallowHeapAllocation no_allocation;
15747  if (this->table()->IsUndefined()) return false;
15748 
15749  Transition();
15750 
15751  TableType* table = TableType::cast(this->table());
15752  int index = Smi::cast(this->index())->value();
15753  int used_capacity = table->UsedCapacity();
15754 
15755  while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
15756  index++;
15757  }
15758 
15759  set_index(Smi::FromInt(index));
15760 
15761  if (index < used_capacity) return true;
15762 
15763  set_table(GetHeap()->undefined_value());
15764  return false;
15765 }
15766 
15767 
15768 template<class Derived, class TableType>
15770  DisallowHeapAllocation no_allocation;
15771  if (HasMore()) {
15772  FixedArray* array = FixedArray::cast(value_array->elements());
15773  static_cast<Derived*>(this)->PopulateValueArray(array);
15774  MoveNext();
15775  return Smi::cast(kind());
15776  }
15777  return Smi::FromInt(0);
15778 }
15779 
15780 
15781 template Smi*
15783  JSArray* value_array);
15784 
15785 template bool
15787 
15788 template void
15790 
15791 template Object*
15793 
15794 template void
15796 
15797 
15798 template Smi*
15800  JSArray* value_array);
15801 
15802 template bool
15804 
15805 template void
15807 
15808 template Object*
15810 
15811 template void
15813 
15814 
15816  DeclaredAccessorDescriptor* descriptor)
15817  : array_(descriptor->serialized_data()->GetDataStartAddress()),
15818  length_(descriptor->serialized_data()->length()),
15819  offset_(0) {
15820 }
15821 
15822 
15825  DCHECK(offset_ < length_);
15826  uint8_t* ptr = &array_[offset_];
15827  DCHECK(reinterpret_cast<uintptr_t>(ptr) % sizeof(uintptr_t) == 0);
15828  const DeclaredAccessorDescriptorData* data =
15829  reinterpret_cast<const DeclaredAccessorDescriptorData*>(ptr);
15830  offset_ += sizeof(*data);
15831  DCHECK(offset_ <= length_);
15832  return data;
15833 }
15834 
15835 
15837  Isolate* isolate,
15838  const DeclaredAccessorDescriptorData& descriptor,
15840  int previous_length =
15841  previous.is_null() ? 0 : previous->serialized_data()->length();
15842  int length = sizeof(descriptor) + previous_length;
15843  Handle<ByteArray> serialized_descriptor =
15844  isolate->factory()->NewByteArray(length);
15846  isolate->factory()->NewDeclaredAccessorDescriptor();
15847  value->set_serialized_data(*serialized_descriptor);
15848  // Copy in the data.
15849  {
15850  DisallowHeapAllocation no_allocation;
15851  uint8_t* array = serialized_descriptor->GetDataStartAddress();
15852  if (previous_length != 0) {
15853  uint8_t* previous_array =
15854  previous->serialized_data()->GetDataStartAddress();
15855  MemCopy(array, previous_array, previous_length);
15856  array += previous_length;
15857  }
15858  DCHECK(reinterpret_cast<uintptr_t>(array) % sizeof(uintptr_t) == 0);
15860  reinterpret_cast<DeclaredAccessorDescriptorData*>(array);
15861  *data = descriptor;
15862  }
15863  return value;
15864 }
15865 
15866 
15867 // Check if there is a break point at this code position.
15868 bool DebugInfo::HasBreakPoint(int code_position) {
15869  // Get the break point info object for this code position.
15870  Object* break_point_info = GetBreakPointInfo(code_position);
15871 
15872  // If there is no break point info object or no break points in the break
15873  // point info object there is no break point at this code position.
15874  if (break_point_info->IsUndefined()) return false;
15875  return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
15876 }
15877 
15878 
15879 // Get the break point info object for this code position.
15881  // Find the index of the break point info object for this code position.
15882  int index = GetBreakPointInfoIndex(code_position);
15883 
15884  // Return the break point info object if any.
15885  if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
15886  return BreakPointInfo::cast(break_points()->get(index));
15887 }
15888 
15889 
15890 // Clear a break point at the specified code position.
15892  int code_position,
15893  Handle<Object> break_point_object) {
15894  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15895  debug_info->GetIsolate());
15896  if (break_point_info->IsUndefined()) return;
15898  Handle<BreakPointInfo>::cast(break_point_info),
15899  break_point_object);
15900 }
15901 
15902 
15904  int code_position,
15905  int source_position,
15906  int statement_position,
15907  Handle<Object> break_point_object) {
15908  Isolate* isolate = debug_info->GetIsolate();
15909  Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
15910  isolate);
15911  if (!break_point_info->IsUndefined()) {
15913  Handle<BreakPointInfo>::cast(break_point_info),
15914  break_point_object);
15915  return;
15916  }
15917 
15918  // Adding a new break point for a code position which did not have any
15919  // break points before. Try to find a free slot.
15920  int index = kNoBreakPointInfo;
15921  for (int i = 0; i < debug_info->break_points()->length(); i++) {
15922  if (debug_info->break_points()->get(i)->IsUndefined()) {
15923  index = i;
15924  break;
15925  }
15926  }
15927  if (index == kNoBreakPointInfo) {
15928  // No free slot - extend break point info array.
15929  Handle<FixedArray> old_break_points =
15930  Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
15931  Handle<FixedArray> new_break_points =
15932  isolate->factory()->NewFixedArray(
15933  old_break_points->length() +
15935 
15936  debug_info->set_break_points(*new_break_points);
15937  for (int i = 0; i < old_break_points->length(); i++) {
15938  new_break_points->set(i, old_break_points->get(i));
15939  }
15940  index = old_break_points->length();
15941  }
15942  DCHECK(index != kNoBreakPointInfo);
15943 
15944  // Allocate new BreakPointInfo object and set the break point.
15946  isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
15947  new_break_point_info->set_code_position(Smi::FromInt(code_position));
15948  new_break_point_info->set_source_position(Smi::FromInt(source_position));
15949  new_break_point_info->
15950  set_statement_position(Smi::FromInt(statement_position));
15951  new_break_point_info->set_break_point_objects(
15952  isolate->heap()->undefined_value());
15953  BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
15954  debug_info->break_points()->set(index, *new_break_point_info);
15955 }
15956 
15957 
15958 // Get the break point objects for a code position.
15960  Object* break_point_info = GetBreakPointInfo(code_position);
15961  if (break_point_info->IsUndefined()) {
15962  return GetHeap()->undefined_value();
15963  }
15964  return BreakPointInfo::cast(break_point_info)->break_point_objects();
15965 }
15966 
15967 
15968 // Get the total number of break points.
15970  if (break_points()->IsUndefined()) return 0;
15971  int count = 0;
15972  for (int i = 0; i < break_points()->length(); i++) {
15973  if (!break_points()->get(i)->IsUndefined()) {
15974  BreakPointInfo* break_point_info =
15975  BreakPointInfo::cast(break_points()->get(i));
15976  count += break_point_info->GetBreakPointCount();
15977  }
15978  }
15979  return count;
15980 }
15981 
15982 
15984  Handle<Object> break_point_object) {
15985  Heap* heap = debug_info->GetHeap();
15986  if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
15987  for (int i = 0; i < debug_info->break_points()->length(); i++) {
15988  if (!debug_info->break_points()->get(i)->IsUndefined()) {
15989  Handle<BreakPointInfo> break_point_info =
15990  Handle<BreakPointInfo>(BreakPointInfo::cast(
15991  debug_info->break_points()->get(i)));
15992  if (BreakPointInfo::HasBreakPointObject(break_point_info,
15993  break_point_object)) {
15994  return *break_point_info;
15995  }
15996  }
15997  }
15998  return heap->undefined_value();
15999 }
16000 
16001 
16002 // Find the index of the break point info object for the specified code
16003 // position.
16004 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
16005  if (break_points()->IsUndefined()) return kNoBreakPointInfo;
16006  for (int i = 0; i < break_points()->length(); i++) {
16007  if (!break_points()->get(i)->IsUndefined()) {
16008  BreakPointInfo* break_point_info =
16009  BreakPointInfo::cast(break_points()->get(i));
16010  if (break_point_info->code_position()->value() == code_position) {
16011  return i;
16012  }
16013  }
16014  }
16015  return kNoBreakPointInfo;
16016 }
16017 
16018 
16019 // Remove the specified break point object.
16021  Handle<Object> break_point_object) {
16022  Isolate* isolate = break_point_info->GetIsolate();
16023  // If there are no break points just ignore.
16024  if (break_point_info->break_point_objects()->IsUndefined()) return;
16025  // If there is a single break point clear it if it is the same.
16026  if (!break_point_info->break_point_objects()->IsFixedArray()) {
16027  if (break_point_info->break_point_objects() == *break_point_object) {
16028  break_point_info->set_break_point_objects(
16029  isolate->heap()->undefined_value());
16030  }
16031  return;
16032  }
16033  // If there are multiple break points shrink the array
16034  DCHECK(break_point_info->break_point_objects()->IsFixedArray());
16035  Handle<FixedArray> old_array =
16037  FixedArray::cast(break_point_info->break_point_objects()));
16038  Handle<FixedArray> new_array =
16039  isolate->factory()->NewFixedArray(old_array->length() - 1);
16040  int found_count = 0;
16041  for (int i = 0; i < old_array->length(); i++) {
16042  if (old_array->get(i) == *break_point_object) {
16043  DCHECK(found_count == 0);
16044  found_count++;
16045  } else {
16046  new_array->set(i - found_count, old_array->get(i));
16047  }
16048  }
16049  // If the break point was found in the list change it.
16050  if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
16051 }
16052 
16053 
16054 // Add the specified break point object.
16056  Handle<Object> break_point_object) {
16057  Isolate* isolate = break_point_info->GetIsolate();
16058 
16059  // If there was no break point objects before just set it.
16060  if (break_point_info->break_point_objects()->IsUndefined()) {
16061  break_point_info->set_break_point_objects(*break_point_object);
16062  return;
16063  }
16064  // If the break point object is the same as before just ignore.
16065  if (break_point_info->break_point_objects() == *break_point_object) return;
16066  // If there was one break point object before replace with array.
16067  if (!break_point_info->break_point_objects()->IsFixedArray()) {
16068  Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
16069  array->set(0, break_point_info->break_point_objects());
16070  array->set(1, *break_point_object);
16071  break_point_info->set_break_point_objects(*array);
16072  return;
16073  }
16074  // If there was more than one break point before extend array.
16075  Handle<FixedArray> old_array =
16077  FixedArray::cast(break_point_info->break_point_objects()));
16078  Handle<FixedArray> new_array =
16079  isolate->factory()->NewFixedArray(old_array->length() + 1);
16080  for (int i = 0; i < old_array->length(); i++) {
16081  // If the break point was there before just ignore.
16082  if (old_array->get(i) == *break_point_object) return;
16083  new_array->set(i, old_array->get(i));
16084  }
16085  // Add the new break point.
16086  new_array->set(old_array->length(), *break_point_object);
16087  break_point_info->set_break_point_objects(*new_array);
16088 }
16089 
16090 
16092  Handle<BreakPointInfo> break_point_info,
16093  Handle<Object> break_point_object) {
16094  // No break point.
16095  if (break_point_info->break_point_objects()->IsUndefined()) return false;
16096  // Single break point.
16097  if (!break_point_info->break_point_objects()->IsFixedArray()) {
16098  return break_point_info->break_point_objects() == *break_point_object;
16099  }
16100  // Multiple break points.
16101  FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
16102  for (int i = 0; i < array->length(); i++) {
16103  if (array->get(i) == *break_point_object) {
16104  return true;
16105  }
16106  }
16107  return false;
16108 }
16109 
16110 
16111 // Get the number of break points.
16113  // No break point.
16114  if (break_point_objects()->IsUndefined()) return 0;
16115  // Single break point.
16116  if (!break_point_objects()->IsFixedArray()) return 1;
16117  // Multiple break points.
16118  return FixedArray::cast(break_point_objects())->length();
16119 }
16120 
16121 
16122 Object* JSDate::GetField(Object* object, Smi* index) {
16123  return JSDate::cast(object)->DoGetField(
16124  static_cast<FieldIndex>(index->value()));
16125 }
16126 
16127 
16129  DCHECK(index != kDateValue);
16130 
16131  DateCache* date_cache = GetIsolate()->date_cache();
16132 
16133  if (index < kFirstUncachedField) {
16134  Object* stamp = cache_stamp();
16135  if (stamp != date_cache->stamp() && stamp->IsSmi()) {
16136  // Since the stamp is not NaN, the value is also not NaN.
16137  int64_t local_time_ms =
16138  date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
16139  SetCachedFields(local_time_ms, date_cache);
16140  }
16141  switch (index) {
16142  case kYear: return year();
16143  case kMonth: return month();
16144  case kDay: return day();
16145  case kWeekday: return weekday();
16146  case kHour: return hour();
16147  case kMinute: return min();
16148  case kSecond: return sec();
16149  default: UNREACHABLE();
16150  }
16151  }
16152 
16153  if (index >= kFirstUTCField) {
16154  return GetUTCField(index, value()->Number(), date_cache);
16155  }
16156 
16157  double time = value()->Number();
16158  if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
16159 
16160  int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
16161  int days = DateCache::DaysFromTime(local_time_ms);
16162 
16163  if (index == kDays) return Smi::FromInt(days);
16164 
16165  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16166  if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
16167  DCHECK(index == kTimeInDay);
16168  return Smi::FromInt(time_in_day_ms);
16169 }
16170 
16171 
16173  double value,
16174  DateCache* date_cache) {
16175  DCHECK(index >= kFirstUTCField);
16176 
16177  if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
16178 
16179  int64_t time_ms = static_cast<int64_t>(value);
16180 
16181  if (index == kTimezoneOffset) {
16182  return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
16183  }
16184 
16185  int days = DateCache::DaysFromTime(time_ms);
16186 
16187  if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
16188 
16189  if (index <= kDayUTC) {
16190  int year, month, day;
16191  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16192  if (index == kYearUTC) return Smi::FromInt(year);
16193  if (index == kMonthUTC) return Smi::FromInt(month);
16194  DCHECK(index == kDayUTC);
16195  return Smi::FromInt(day);
16196  }
16197 
16198  int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
16199  switch (index) {
16200  case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
16201  case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
16202  case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
16203  case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
16204  case kDaysUTC: return Smi::FromInt(days);
16205  case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
16206  default: UNREACHABLE();
16207  }
16208 
16209  UNREACHABLE();
16210  return NULL;
16211 }
16212 
16213 
16214 void JSDate::SetValue(Object* value, bool is_value_nan) {
16215  set_value(value);
16216  if (is_value_nan) {
16217  HeapNumber* nan = GetIsolate()->heap()->nan_value();
16218  set_cache_stamp(nan, SKIP_WRITE_BARRIER);
16219  set_year(nan, SKIP_WRITE_BARRIER);
16220  set_month(nan, SKIP_WRITE_BARRIER);
16221  set_day(nan, SKIP_WRITE_BARRIER);
16222  set_hour(nan, SKIP_WRITE_BARRIER);
16223  set_min(nan, SKIP_WRITE_BARRIER);
16224  set_sec(nan, SKIP_WRITE_BARRIER);
16225  set_weekday(nan, SKIP_WRITE_BARRIER);
16226  } else {
16228  }
16229 }
16230 
16231 
16232 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
16233  int days = DateCache::DaysFromTime(local_time_ms);
16234  int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
16235  int year, month, day;
16236  date_cache->YearMonthDayFromDays(days, &year, &month, &day);
16237  int weekday = date_cache->Weekday(days);
16238  int hour = time_in_day_ms / (60 * 60 * 1000);
16239  int min = (time_in_day_ms / (60 * 1000)) % 60;
16240  int sec = (time_in_day_ms / 1000) % 60;
16241  set_cache_stamp(date_cache->stamp());
16242  set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
16243  set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
16244  set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
16245  set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
16246  set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
16247  set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
16248  set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
16249 }
16250 
16251 
16253  DCHECK(is_external());
16254  set_backing_store(NULL);
16255  set_byte_length(Smi::FromInt(0));
16256 }
16257 
16258 
16260  set_byte_offset(Smi::FromInt(0));
16261  set_byte_length(Smi::FromInt(0));
16262 }
16263 
16264 
16266  NeuterView();
16267 }
16268 
16269 
16271  NeuterView();
16272  set_length(Smi::FromInt(0));
16273  set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
16274 }
16275 
16276 
16278  switch (elements_kind) {
16279 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
16280  case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
16281 
16283 #undef TYPED_ARRAY_CASE
16284 
16285  default:
16286  UNREACHABLE();
16288  }
16289 }
16290 
16291 
16293  Handle<JSTypedArray> typed_array) {
16294 
16295  Handle<Map> map(typed_array->map());
16296  Isolate* isolate = typed_array->GetIsolate();
16297 
16299 
16301  map,
16303 
16304  Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
16305  Handle<FixedTypedArrayBase> fixed_typed_array(
16306  FixedTypedArrayBase::cast(typed_array->elements()));
16308  fixed_typed_array->DataSize(), false);
16309  memcpy(buffer->backing_store(),
16310  fixed_typed_array->DataPtr(),
16311  fixed_typed_array->DataSize());
16312  Handle<ExternalArray> new_elements =
16313  isolate->factory()->NewExternalArray(
16314  fixed_typed_array->length(), typed_array->type(),
16315  static_cast<uint8_t*>(buffer->backing_store()));
16316 
16317  buffer->set_weak_first_view(*typed_array);
16318  DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value());
16319  typed_array->set_buffer(*buffer);
16320  JSObject::SetMapAndElements(typed_array, new_map, new_elements);
16321 
16322  return buffer;
16323 }
16324 
16325 
16327  Handle<Object> result(buffer(), GetIsolate());
16328  if (*result != Smi::FromInt(0)) {
16329  DCHECK(IsExternalArrayElementsKind(map()->elements_kind()));
16330  return Handle<JSArrayBuffer>::cast(result);
16331  }
16332  Handle<JSTypedArray> self(this);
16333  return MaterializeArrayBuffer(self);
16334 }
16335 
16336 
16338  return static_cast<HeapType*>(type_raw());
16339 }
16340 
16341 
16343  DCHECK(IsPropertyCell());
16344  set_type_raw(type, ignored);
16345 }
16346 
16347 
16349  Handle<Object> value) {
16350  Isolate* isolate = cell->GetIsolate();
16351  Handle<HeapType> old_type(cell->type(), isolate);
16352  Handle<HeapType> new_type = HeapType::Constant(value, isolate);
16353 
16354  if (new_type->Is(old_type)) return old_type;
16355 
16356  cell->dependent_code()->DeoptimizeDependentCodeGroup(
16358 
16359  if (old_type->Is(HeapType::None()) || old_type->Is(HeapType::Undefined())) {
16360  return new_type;
16361  }
16362 
16363  return HeapType::Any(isolate);
16364 }
16365 
16366 
16368  Handle<Object> value) {
16369  cell->set_value(*value);
16370  if (!HeapType::Any()->Is(cell->type())) {
16371  Handle<HeapType> new_type = UpdatedType(cell, value);
16372  cell->set_type(*new_type);
16373  }
16374 }
16375 
16376 
16377 // static
16379  CompilationInfo* info) {
16380  Handle<DependentCode> codes =
16381  DependentCode::Insert(handle(cell->dependent_code(), info->isolate()),
16383  info->object_wrapper());
16384  if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
16386  cell, info->zone());
16387 }
16388 
16389 } } // namespace v8::internal
#define REGISTER(N, C)
const int kPageSizeBits
Definition: build_config.h:159
#define BUILTIN(name)
Definition: builtins.cc:122
#define CODE_AGE_LIST(V)
Definition: builtins.h:27
#define SLOW_DCHECK(condition)
Definition: checks.h:30
virtual const char * NameOfCPURegister(int reg) const
static uint16_t LeadSurrogate(uint32_t char_code)
Definition: unicode.h:108
static const int kNoPreviousCharacter
Definition: unicode.h:97
static const uchar kMaxNonSurrogateCharCode
Definition: unicode.h:98
static uint16_t TrailSurrogate(uint32_t char_code)
Definition: unicode.h:111
static const unsigned kMaxOneByteChar
Definition: unicode.h:141
static uchar ValueOf(const byte *str, unsigned length, unsigned *cursor)
Definition: unicode-inl.h:129
static uchar Length(uchar chr, int previous)
Definition: unicode-inl.h:140
static const unsigned kMaxEncodedSize
Definition: unicode.h:140
static unsigned Encode(char *out, uchar c, int previous, bool replace_invalid=false)
Definition: unicode-inl.h:91
bool IsEmpty() const
Returns true if the handle is empty.
Definition: v8.h:228
int length()
Definition: api.cc:736
v8::internal::Object * get(int index)
Definition: api.cc:741
A JavaScript object (ECMA-262, 4.3.3)
Definition: v8.h:2283
An ExternalOneByteStringResource is a wrapper around an one-byte string buffer that resides outside V...
Definition: v8.h:1918
virtual const char * data() const =0
The string data from the underlying buffer.
virtual size_t length() const =0
The number of Latin-1 characters in the string.
An ExternalStringResource is a wrapper around a two-byte string buffer that resides outside V8's heap...
Definition: v8.h:1885
virtual const uint16_t * data() const =0
The string data from the underlying buffer.
virtual size_t length() const =0
The length of the string.
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:288
bool IsBoolean() const
Returns true if this value is boolean.
Definition: api.cc:2500
int32_t Int32Value() const
Definition: api.cc:3004
bool IsInt32() const
Returns true if this value is a 32-bit signed integer.
Definition: api.cc:2510
P * GetParameter() const
Definition: v8.h:423
static double nan_value()
static int AppendUnique(Handle< Object > descriptors, Handle< FixedArray > array, int valid_descriptors)
Definition: objects.cc:3185
static bool IsCompatibleReceiverType(Isolate *isolate, Handle< AccessorInfo > info, Handle< HeapType > type)
Definition: objects.cc:467
bool IsCompatibleReceiver(Object *receiver)
Definition: objects-inl.h:6784
Object * GetComponent(AccessorComponent component)
Definition: objects.cc:7912
static Handle< AccessorPair > Copy(Handle< AccessorPair > pair)
Definition: objects.cc:7904
static Handle< ExecutableAccessorInfo > CloneAccessor(Isolate *isolate, Handle< ExecutableAccessorInfo > accessor)
Definition: accessors.cc:44
AllocationSite * GetAllocationSite()
Definition: objects.h:8295
const char * PretenureDecisionName(PretenureDecision decision)
Definition: objects.cc:12672
PretenureFlag GetPretenureMode()
Definition: objects.cc:12585
static void DigestTransitionFeedback(Handle< AllocationSite > site, ElementsKind to_kind)
Definition: objects.cc:12606
static const double kPretenureRatio
Definition: objects.h:8093
static void AddDependentCompilationInfo(Handle< AllocationSite > site, Reason reason, CompilationInfo *info)
Definition: objects.cc:12660
uint32_t pc_offset(uint32_t index)
Definition: full-codegen.h:898
BailoutId ast_id(uint32_t index)
Definition: full-codegen.h:889
bool IsNone() const
Definition: utils.h:966
int ToInt() const
Definition: utils.h:958
static BailoutId None()
Definition: utils.h:960
static const U kShift
Definition: utils.h:204
static T decode(U value)
Definition: utils.h:228
static bool HasBreakPointObject(Handle< BreakPointInfo > info, Handle< Object > break_point_object)
Definition: objects.cc:16091
static void ClearBreakPoint(Handle< BreakPointInfo > info, Handle< Object > break_point_object)
Definition: objects.cc:16020
static void SetBreakPoint(Handle< BreakPointInfo > info, Handle< Object > break_point_object)
Definition: objects.cc:16055
Code * builtin(Name name)
Definition: builtins.h:254
static uint32_t NameFlagsHashHelper(Name *name, Code::Flags flags)
Definition: objects.cc:7467
uint32_t HashForObject(Object *obj) OVERRIDE
Definition: objects.cc:7473
CodeCacheHashTableKey(Handle< Name > name, Code::Flags flags)
Definition: objects.cc:7450
MUST_USE_RESULT Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:7480
CodeCacheHashTableKey(Handle< Name > name, Handle< Code > code)
Definition: objects.cc:7453
bool IsMatch(Object *other) OVERRIDE
Definition: objects.cc:7456
int GetIndex(Name *name, Code::Flags flags)
Definition: objects.cc:7521
static const int kInitialSize
Definition: objects.h:7979
static Handle< CodeCacheHashTable > Put(Handle< CodeCacheHashTable > table, Handle< Name > name, Handle< Code > code)
Definition: objects.cc:7505
Object * Lookup(Name *name, Code::Flags flags)
Definition: objects.cc:7496
Object * LookupNormalTypeCache(Name *name, Code::Flags flags)
Definition: objects.cc:7399
Object * Lookup(Name *name, Code::Flags flags)
Definition: objects.cc:7370
static void UpdateNormalTypeCache(Handle< CodeCache > code_cache, Handle< Name > name, Handle< Code > code)
Definition: objects.cc:7360
Object * LookupDefaultCache(Name *name, Code::Flags flags)
Definition: objects.cc:7380
static void UpdateDefaultCache(Handle< CodeCache > code_cache, Handle< Name > name, Handle< Code > code)
Definition: objects.cc:7301
int GetIndex(Object *name, Code *code)
Definition: objects.cc:7409
static void Update(Handle< CodeCache > cache, Handle< Name > name, Handle< Code > code)
Definition: objects.cc:7280
void RemoveByIndex(Object *name, Code *code, int index)
Definition: objects.cc:7425
void EvictOptimizedCodeMap(SharedFunctionInfo *code_map_holder)
Handle< Object > replace_[kMaxCount]
Definition: objects-inl.h:5062
unsigned stack_slots()
Definition: objects-inl.h:4801
void CopyFrom(const CodeDesc &desc)
Definition: objects.cc:10134
AllocationSite * FindFirstAllocationSite()
Definition: objects.cc:10267
ConstantPoolArray * constant_pool()
Definition: objects-inl.h:4942
uint32_t TranslateAstIdToPcOffset(BailoutId ast_id)
Definition: objects.cc:10440
void set_has_deoptimization_support(bool value)
Definition: objects-inl.h:4721
unsigned safepoint_table_offset()
Definition: objects-inl.h:4817
void Relocate(intptr_t delta)
Definition: objects.cc:10126
Map * FindFirstMap()
Definition: objects.cc:10273
static Code * GetCodeAgeStub(Isolate *isolate, Age age, MarkingParity parity)
Definition: objects.cc:10561
void InvalidateRelocation()
Definition: objects.cc:10104
bool is_compare_ic_stub()
Definition: objects.h:5055
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:5018
BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset)
Definition: objects.cc:10429
ExtraICState extra_ic_state()
Definition: objects-inl.h:4647
static void PatchPlatformCodeAge(Isolate *isolate, byte *sequence, Age age, MarkingParity parity)
static const char * Kind2String(Kind kind)
Definition: objects.cc:10627
static void GetCodeAgeAndParity(Code *code, Age *age, MarkingParity *parity)
Definition: objects.cc:10525
static void MarkCodeAsExecuted(byte *sequence, Isolate *isolate)
Definition: objects.cc:10457
bool is_inline_cache_stub()
Definition: objects-inl.h:4921
bool marked_for_deoptimization()
Definition: objects-inl.h:4877
Object * FindNthObject(int n, Map *match_map)
Definition: objects.cc:10250
void FindAllMaps(MapHandleList *maps)
Definition: objects.cc:10300
void PrintDeoptLocation(FILE *out, int bailout_id)
Definition: objects.cc:10589
byte * relocation_start()
Definition: objects-inl.h:6196
int SourceStatementPosition(Address pc)
Definition: objects.cc:10224
Code * FindFirstHandler()
Definition: objects.cc:10312
bool FindHandlers(CodeHandleList *code_list, int length=-1)
Definition: objects.cc:10325
static void MakeCodeAgeSequenceYoung(byte *sequence, Isolate *isolate)
Definition: objects.cc:10452
STATIC_ASSERT(NUMBER_OF_KINDS<=16)
int instruction_size() const
SafepointEntry GetSafepointEntry(Address pc)
Definition: objects.cc:10244
bool CanDeoptAt(Address pc)
Definition: objects.cc:10613
friend class RelocIterator
Definition: objects.h:5452
void ClearInlineCaches()
Definition: objects.cc:10377
void set_marked_for_deoptimization(bool flag)
Definition: objects-inl.h:4884
byte * instruction_start()
Definition: objects-inl.h:6176
static Object * GetObjectFromEntryAddress(Address location_of_address)
Definition: objects-inl.h:5029
InlineCacheState ic_state()
Definition: objects-inl.h:4635
void FindAndReplace(const FindAndReplacePattern &pattern)
Definition: objects.cc:10279
MaybeHandle< Code > FindHandlerForMap(Map *map)
Definition: objects.cc:10344
int SourcePosition(Address pc)
Definition: objects.cc:10192
uint32_t stub_key()
Definition: objects-inl.h:6159
void MakeOlder(MarkingParity)
Definition: objects.cc:10475
unsigned back_edge_table_offset()
Definition: objects-inl.h:4834
Object * type_feedback_info()
Definition: objects-inl.h:6145
bool has_debug_break_slots()
Definition: objects-inl.h:4729
Name * FindFirstName()
Definition: objects.cc:10364
static Flags RemoveTypeFromFlags(Flags flags)
Definition: objects-inl.h:5006
static const int kPrologueOffsetNotSet
Definition: objects.h:4973
byte * FindCodeAgeSequence()
Definition: objects.cc:10498
int prologue_offset() const
void InvalidateEmbeddedObjects()
Definition: objects.cc:10110
static const char * GetStateName(CompareICState::State state)
Definition: ic-state.cc:457
static Handle< CompilationCacheTable > PutRegExp(Handle< CompilationCacheTable > cache, Handle< String > src, JSRegExp::Flags flags, Handle< FixedArray > value)
Definition: objects.cc:14811
Handle< Object > LookupRegExp(Handle< String > source, JSRegExp::Flags flags)
Definition: objects.cc:14766
static Handle< CompilationCacheTable > PutEval(Handle< CompilationCacheTable > cache, Handle< String > src, Handle< Context > context, Handle< SharedFunctionInfo > value, int scope_position)
Definition: objects.cc:14794
static Handle< CompilationCacheTable > Put(Handle< CompilationCacheTable > cache, Handle< String > src, Handle< Context > context, Handle< Object > value)
Definition: objects.cc:14777
Handle< Object > LookupEval(Handle< String > src, Handle< Context > context, StrictMode strict_mode, int scope_position)
Definition: objects.cc:14753
Handle< Object > Lookup(Handle< String > src, Handle< Context > context)
Definition: objects.cc:14741
ZoneList< Handle< HeapObject > > * dependencies(DependentCode::DependencyGroup group)
Definition: compiler.h:310
Handle< Foreign > object_wrapper()
Definition: compiler.h:364
Isolate * isolate() const
Definition: compiler.h:96
void Reset(ConsString *cons_string, int offset=0)
Definition: objects.h:9293
String * Continue(int *offset_out)
Definition: objects.cc:8206
void PushRight(ConsString *string)
Definition: objects-inl.h:3658
static int OffsetForDepth(int depth)
Definition: objects-inl.h:3648
String * Next(int *offset_out)
Definition: objects.h:9300
String * NextLeaf(bool *blew_stack)
Definition: objects.cc:8285
String * Search(int *offset_out)
Definition: objects.cc:8224
ConsString * frames_[kStackSize]
Definition: objects.h:9325
void PushLeft(ConsString *string)
Definition: objects-inl.h:3653
void Initialize(ConsString *cons_string, int offset)
Definition: objects.cc:8195
uint16_t ConsStringGet(int index)
Definition: objects.cc:8333
void ClearPtrEntries(Isolate *isolate)
Definition: objects.cc:9084
Object ** RawFieldOfElementAt(int index)
Definition: objects.h:2819
int OffsetOfElementAt(int index)
Definition: objects.h:2792
void ConstantPoolIterateBody(ObjectVisitor *v)
Definition: objects.cc:9062
int first_index(Type type, LayoutSection layout_section)
Definition: objects-inl.h:2394
int number_of_entries(Type type, LayoutSection layout_section)
Definition: objects-inl.h:2415
static Context * cast(Object *context)
Definition: contexts.h:255
Object * extension()
Definition: contexts.h:427
Context * native_context()
Definition: contexts.cc:44
static void FlushICache(void *start, size_t size)
static int TimeInDay(int64_t time_ms, int days)
Definition: date.h:65
void YearMonthDayFromDays(int days, int *year, int *month, int *day)
Definition: date.cc:55
static const int kInvalidStamp
Definition: date.h:40
int64_t ToLocal(int64_t time_ms)
Definition: date.h:110
int Weekday(int days)
Definition: date.h:72
static int DaysFromTime(int64_t time_ms)
Definition: date.h:57
int TimezoneOffset(int64_t time_ms)
Definition: date.h:100
static const int kEstimatedNofBreakPointsInFunction
Definition: objects.h:10621
static Object * FindBreakPointInfo(Handle< DebugInfo > debug_info, Handle< Object > break_point_object)
Definition: objects.cc:15983
static void ClearBreakPoint(Handle< DebugInfo > debug_info, int code_position, Handle< Object > break_point_object)
Definition: objects.cc:15891
static const int kNoBreakPointInfo
Definition: objects.h:10624
int GetBreakPointInfoIndex(int code_position)
Definition: objects.cc:16004
static void SetBreakPoint(Handle< DebugInfo > debug_info, int code_position, int source_position, int statement_position, Handle< Object > break_point_object)
Definition: objects.cc:15903
Object * GetBreakPointInfo(int code_position)
Definition: objects.cc:15880
Object * GetBreakPointObjects(int code_position)
Definition: objects.cc:15959
bool HasBreakPoint(int code_position)
Definition: objects.cc:15868
bool StepInActive()
Definition: debug.h:402
void HandleStepIn(Handle< JSFunction > function, Handle< Object > holder, Address fp, bool is_constructor)
Definition: debug.cc:1593
DeclaredAccessorDescriptorIterator(DeclaredAccessorDescriptor *descriptor)
Definition: objects.cc:15815
const DeclaredAccessorDescriptorData * Next()
Definition: objects.cc:15824
static Handle< DeclaredAccessorDescriptor > Create(Isolate *isolate, const DeclaredAccessorDescriptorData &data, Handle< DeclaredAccessorDescriptor > previous)
Definition: objects.cc:15836
static Handle< DeoptimizationInputData > New(Isolate *isolate, int deopt_entry_count, PretenureFlag pretenure)
Definition: objects.cc:7918
static Handle< DeoptimizationOutputData > New(Isolate *isolate, int number_of_deopt_points, PretenureFlag pretenure)
Definition: objects.cc:7927
static void DeoptimizeGlobalObject(JSObject *object)
Definition: deoptimizer.cc:470
static void DeoptimizeMarkedCode(Isolate *isolate)
Definition: deoptimizer.cc:454
static int GetOutputInfo(DeoptimizationOutputData *data, BailoutId node_id, SharedFunctionInfo *shared)
Definition: deoptimizer.cc:707
static int GetDeoptimizationId(Isolate *isolate, Address addr, BailoutType type)
Definition: deoptimizer.cc:690
void Recompute(DependentCode *entries)
Definition: objects.cc:11388
static Handle< DependentCode > Insert(Handle< DependentCode > entries, DependencyGroup group, Handle< Object > object)
Definition: objects.cc:11410
bool MarkCodeForDeoptimization(Isolate *isolate, DependentCode::DependencyGroup group)
Definition: objects.cc:11535
int number_of_entries(DependencyGroup group)
Definition: objects-inl.h:4554
void UpdateToFinishedCode(DependencyGroup group, CompilationInfo *info, Code *code)
Definition: objects.cc:11450
void DeoptimizeDependentCodeGroup(Isolate *isolate, DependentCode::DependencyGroup group)
Definition: objects.cc:11573
static const int kCodesStartIndex
Definition: objects.h:5589
static const char * DependencyGroupName(DependencyGroup group)
Definition: objects.cc:11618
static void SetMarkedForDeoptimization(Code *code, DependencyGroup group)
Definition: objects.cc:11602
static const int kGroupCount
Definition: objects.h:5534
void set_number_of_entries(DependencyGroup group, int value)
Definition: objects-inl.h:4560
static DependentCode * ForObject(Handle< HeapObject > object, DependencyGroup group)
Definition: objects.cc:11397
void set_object_at(int i, Object *object)
Definition: objects-inl.h:4580
void RemoveCompilationInfo(DependentCode::DependencyGroup group, CompilationInfo *info)
Definition: objects.cc:11474
void AddToDependentICList(Handle< Code > stub)
Definition: objects.cc:11584
CompilationInfo * compilation_info_at(int i)
Definition: objects-inl.h:4574
void copy(int from, int to)
Definition: objects-inl.h:4600
bool Contains(DependencyGroup group, Code *code)
Definition: objects.cc:11521
void Replace(int descriptor_number, Descriptor *descriptor)
Definition: objects.cc:7812
void SetEnumCache(FixedArray *bridge_storage, FixedArray *new_cache, Object *new_index_cache)
Definition: objects.cc:7818
void SetValue(int descriptor_number, Object *value)
Definition: objects-inl.h:2976
int GetSortedKeyIndex(int descriptor_number)
Definition: objects-inl.h:2934
void SetRepresentation(int descriptor_number, Representation representation)
Definition: objects-inl.h:2950
static Handle< DescriptorArray > CopyUpTo(Handle< DescriptorArray > desc, int enumeration_index, int slack=0)
Definition: objects.cc:6951
static Handle< DescriptorArray > Allocate(Isolate *isolate, int number_of_descriptors, int slack=0)
Definition: objects.cc:7790
Name * GetKey(int descriptor_number)
Definition: objects-inl.h:2928
static const int kNotFound
Definition: objects.h:3015
PropertyDetails GetDetails(int descriptor_number)
Definition: objects-inl.h:2981
FixedArray * GetEnumCache()
Definition: objects.h:2917
bool CanHoldValue(int descriptor, Object *value)
Definition: objects.cc:6713
Object * GetValue(int descriptor_number)
Definition: objects-inl.h:2970
int GetFieldIndex(int descriptor_number)
Definition: objects-inl.h:2993
PropertyType GetType(int descriptor_number)
Definition: objects-inl.h:2988
Object * GetConstant(int descriptor_number)
Definition: objects-inl.h:3005
static const int kEnumCacheBridgeLength
Definition: objects.h:3022
static Handle< DescriptorArray > CopyUpToAddAttributes(Handle< DescriptorArray > desc, int enumeration_index, PropertyAttributes attributes, int slack=0)
Definition: objects.cc:6960
void CopyFrom(int index, DescriptorArray *src, const WhitenessWitness &)
Definition: objects.cc:7833
HeapType * GetFieldType(int descriptor_number)
Definition: objects-inl.h:2999
static MUST_USE_RESULT Handle< NameDictionary > New(Isolate *isolate, int at_least_space_for, PretenureFlag pretenure=NOT_TENURED)
Definition: objects.cc:14899
static Handle< Derived > EnsureCapacity(Handle< Derived > obj, int n, Key key)
Definition: objects.cc:14969
void CopyKeysTo(FixedArray *storage, PropertyAttributes filter, SortMode sort_mode)
Object * ValueAt(int entry)
Definition: objects.h:3491
static void GenerateNewEnumerationIndices(Handle< Derived > dictionary)
Definition: objects.cc:14916
static MUST_USE_RESULT Handle< Derived > AtPut(Handle< Derived > dictionary, Key key, Handle< Object > value)
Definition: objects.cc:15001
static MUST_USE_RESULT Handle< NameDictionary > Add(Handle< NameDictionary > dictionary, Handle< Name > key, Handle< Object > value, PropertyDetails details)
Definition: objects.cc:15024
static Handle< Object > DeleteProperty(Handle< NameDictionary > dictionary, int entry, JSObject::DeleteMode mode)
Definition: objects.cc:14982
void SetNextEnumerationIndex(int index)
Definition: objects.h:3547
void SetEntry(int entry, Handle< Object > key, Handle< Object > value)
Definition: objects-inl.h:6798
static MUST_USE_RESULT Handle< NameDictionary > Shrink(Handle< NameDictionary > dictionary, Handle< Name > key)
Definition: objects.h:3522
PropertyDetails DetailsAt(int entry)
Definition: objects.h:3501
Object * SlowReverseLookup(Object *value)
Definition: objects.cc:15270
void DetailsAtPut(int entry, PropertyDetails value)
Definition: objects.h:3508
static void AddEntry(Handle< Derived > dictionary, Key key, Handle< Object > value, PropertyDetails details, uint32_t hash)
Definition: objects.cc:15041
int NumberOfElementsFilterAttributes(PropertyAttributes filter)
Definition: objects.cc:15160
void CopyValuesTo(FixedArray *elements)
Definition: objects.cc:13087
static int Decode(Isolate *isolate, OStream *os, byte *begin, byte *end, Code *code=NULL)
virtual void CopyElements(Handle< FixedArrayBase > source, uint32_t source_start, ElementsKind source_kind, Handle< FixedArrayBase > destination, uint32_t destination_start, int copy_size)=0
virtual void SetCapacityAndLength(Handle< JSArray > array, int capacity, int length)=0
virtual MUST_USE_RESULT MaybeHandle< FixedArray > AddElementsToFixedArray(Handle< Object > receiver, Handle< JSObject > holder, Handle< FixedArray > to, Handle< FixedArrayBase > from)=0
virtual MUST_USE_RESULT MaybeHandle< Object > Get(Handle< Object > receiver, Handle< JSObject > holder, uint32_t key, Handle< FixedArrayBase > backing_store)=0
static ElementsAccessor * ForArray(Handle< FixedArrayBase > array)
Definition: elements.cc:1731
static ElementsAccessor * ForKind(ElementsKind elements_kind)
Definition: elements.h:184
static Handle< Object > SetValue(Handle< ExternalFloat32Array > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:14534
static Handle< Object > SetValue(Handle< ExternalFloat64Array > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:14557
static Handle< Object > SetValue(Handle< ExternalInt16Array > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:14487
static Handle< Object > SetValue(Handle< ExternalInt32Array > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:14503
static Handle< Object > SetValue(Handle< ExternalInt8Array > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:14471
static const int kSize
Definition: objects.h:9139
static const int kShortSize
Definition: objects.h:9137
static Handle< Object > SetValue(Handle< ExternalUint16Array > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:14495
static Handle< Object > SetValue(Handle< ExternalUint32Array > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:14511
static Handle< Object > SetValue(Handle< ExternalUint8Array > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:14479
static Handle< Object > SetValue(Handle< ExternalUint8ClampedArray > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:14408
static const int kHeaderSize
Definition: objects.h:2393
void Shrink(int length)
Definition: objects.cc:7690
void SwapPairs(FixedArray *numbers, int i, int j)
Definition: objects.cc:13266
void set_null(int index)
Definition: objects-inl.h:2714
void SortPairs(FixedArray *numbers, uint32_t len)
Definition: objects.cc:13340
static Handle< FixedArray > CopySize(Handle< FixedArray > array, int new_length, PretenureFlag pretenure=NOT_TENURED)
Definition: objects.cc:7749
Object * get(int index)
Definition: objects-inl.h:2165
static MUST_USE_RESULT MaybeHandle< FixedArray > AddKeysFromArrayLike(Handle< FixedArray > content, Handle< JSObject > array)
Definition: objects.cc:7699
static void NoWriteBarrierSet(FixedArray *array, int index, Object *value)
Definition: objects-inl.h:2694
Object ** GetFirstElementAddress()
Definition: objects-inl.h:1539
bool is_the_hole(int index)
Definition: objects-inl.h:2176
void CopyTo(int pos, FixedArray *dest, int dest_pos, int len)
Definition: objects.cc:7770
void set(int index, Object *value)
Definition: objects-inl.h:2190
STATIC_ASSERT(kHeaderSize==Internals::kFixedArrayHeaderSize)
static MUST_USE_RESULT MaybeHandle< FixedArray > UnionOfKeys(Handle< FixedArray > first, Handle< FixedArray > second)
Definition: objects.cc:7723
void set_undefined(int index)
Definition: objects-inl.h:2704
void set_the_hole(int index)
Definition: objects-inl.h:2723
void set(int index, double value)
Definition: objects-inl.h:2244
double get_scalar(int index)
Definition: objects-inl.h:2217
FlatStringReader(Isolate *isolate, Handle< String > str)
Definition: objects.cc:8162
void set_foreign_address(Address value)
Definition: objects-inl.h:6060
static const char * State2String(State state)
Definition: full-codegen.h:90
bool IsTemplateFor(Object *object)
Definition: objects.cc:210
static void MakeWeak(Object **location, void *parameter, WeakCallback weak_callback)
static void Destroy(Object **location)
Handle< Object > Create(Object *value)
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116
bool is_null() const
Definition: handles.h:124
static Handle< T > null()
Definition: handles.h:123
virtual uint32_t Hash()=0
virtual MUST_USE_RESULT Handle< Object > AsHandle(Isolate *isolate)=0
static int ComputeCapacity(int at_least_space_for)
Definition: objects-inl.h:3099
static MUST_USE_RESULT Handle< Derived > EnsureCapacity(Handle< Derived > table, int n, Key key, PretenureFlag pretenure=NOT_TENURED)
Definition: objects.cc:13928
bool IsKey(Object *k)
Definition: objects.h:3255
Object * KeyAt(int entry)
Definition: objects.h:3251
static const int kNotFound
Definition: objects.h:3283
static MUST_USE_RESULT Handle< ObjectHashTable > New(Isolate *isolate, int at_least_space_for, MinimumCapacity capacity_option=USE_DEFAULT_MINIMUM_CAPACITY, PretenureFlag pretenure=NOT_TENURED)
Definition: objects.cc:13756
uint32_t HashForObject(Key key, Object *object)
Definition: objects.h:3201
void IteratePrefix(ObjectVisitor *visitor)
Definition: objects.cc:13742
void Rehash(Key key)
Definition: objects.cc:13895
uint32_t EntryForProbe(Key key, Object *k, int probe, uint32_t expected)
Definition: objects.cc:13859
void Swap(uint32_t entry1, uint32_t entry2, WriteBarrierMode mode)
Definition: objects.cc:13876
uint32_t FindInsertionEntry(uint32_t hash)
Definition: objects.cc:13993
static const int kEntrySize
Definition: objects.h:3276
static const int kMaxCapacity
Definition: objects.h:3288
void IterateElements(ObjectVisitor *visitor)
Definition: objects.cc:13748
static MUST_USE_RESULT Handle< Derived > Shrink(Handle< Derived > table, Key key)
Definition: objects.cc:13961
void set_value(double value)
Definition: objects-inl.h:1520
void set_map_no_write_barrier(Map *value)
Definition: objects-inl.h:1435
STATIC_ASSERT(kMapOffset==Internals::kHeapObjectMapOffset)
void set_map(Map *value)
Definition: objects-inl.h:1404
Heap * GetHeap() const
Definition: objects-inl.h:1379
static Object ** RawField(HeapObject *obj, int offset)
Definition: objects-inl.h:1311
static void UpdateMapCodeCache(Handle< HeapObject > object, Handle< Name > name, Handle< Code > code)
Definition: objects.cc:4158
Isolate * GetIsolate() const
Definition: objects-inl.h:1387
static const int kHeaderSize
Definition: objects.h:1428
void synchronized_set_map(Map *value)
Definition: objects-inl.h:1419
WriteBarrierMode GetWriteBarrierMode(const DisallowHeapAllocation &promise)
Definition: objects-inl.h:2660
void Iterate(ObjectVisitor *v)
Definition: objects.cc:1529
void IteratePointers(ObjectVisitor *v, int start, int end)
Definition: objects-inl.h:1499
void HeapObjectShortPrint(OStream &os)
Definition: objects.cc:1374
int SizeFromMap(Map *map)
Definition: objects-inl.h:4259
bool Contains(Address addr)
Definition: heap.cc:4447
void ClearInstanceofCache()
Definition: heap-inl.h:701
Object * allocation_sites_list()
Definition: heap.h:801
bool InNewSpace(Object *object)
Definition: heap-inl.h:322
void CreateFillerObjectAt(Address addr, int size)
Definition: heap.cc:3221
Isolate * isolate()
Definition: heap-inl.h:589
void ClearAllICsByKind(Code::Kind kind)
Definition: heap.cc:470
uint32_t HashSeed()
Definition: heap.h:1237
void AdjustLiveBytes(Address address, int by, InvocationMode mode)
Definition: heap.cc:3254
IncrementalMarking * incremental_marking()
Definition: heap.h:1205
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
Definition: heap.cc:5376
static bool ShouldZapGarbage()
Definition: heap.h:926
NewSpace * new_space()
Definition: heap.h:593
void RightTrimFixedArray(FixedArrayBase *obj, int elements_to_trim)
Definition: heap.cc:3322
AllocationMemento * FindAllocationMemento(HeapObject *object)
Definition: heap-inl.h:497
String * hidden_string()
Definition: heap.h:788
MarkCompactCollector * mark_compact_collector()
Definition: heap.h:1197
static Handle< Map > TypeToMap(HeapType *type, Isolate *isolate)
Definition: ic.cc:719
static void Clear(Isolate *isolate, Address address, ConstantPoolArray *constant_pool)
Definition: ic.cc:478
virtual Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:13718
static uint32_t StringHash(Object *obj)
Definition: objects.cc:13733
virtual uint32_t Hash() OVERRIDE
Definition: objects.cc:13712
virtual uint32_t HashForObject(Object *other) OVERRIDE
Definition: objects.cc:13714
InternalizedStringKey(Handle< String > string)
Definition: objects.cc:13705
virtual bool IsMatch(Object *string) OVERRIDE
Definition: objects.cc:13708
IntrusiveMapTransitionIterator(Map *map, TransitionArray *transition_array, Object *constructor)
Definition: objects.cc:7080
IntrusivePrototypeTransitionIterator(Map *map, HeapObject *proto_trans, Object *constructor)
Definition: objects.cc:7130
StaticResource< ConsStringIteratorOp > * objects_string_iterator()
Definition: isolate.h:941
bool serializer_enabled() const
Definition: isolate.h:1007
void ReportFailedAccessCheck(Handle< JSObject > receiver, v8::AccessType type)
Definition: isolate.cc:634
ConsStringIteratorOp * objects_string_compare_iterator_b()
Definition: isolate.h:937
bool MayIndexedAccess(Handle< JSObject > receiver, uint32_t index, v8::AccessType type)
Definition: isolate.cc:736
Handle< Context > native_context()
Definition: isolate.cc:1339
DateCache * date_cache()
Definition: isolate.h:1020
Builtins * builtins()
Definition: isolate.h:947
Object * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:832
Context * context()
Definition: isolate.h:548
Counters * counters()
Definition: isolate.h:857
CodeTracer * GetCodeTracer()
Definition: isolate.cc:2154
base::RandomNumberGenerator * random_number_generator()
Definition: isolate-inl.h:33
ConsStringIteratorOp * objects_string_compare_iterator_a()
Definition: isolate.h:933
bool MayNamedAccess(Handle< JSObject > receiver, Handle< Object > key, v8::AccessType type)
Definition: isolate.cc:697
Object * StackOverflow()
Definition: isolate.cc:773
Factory * factory()
Definition: isolate.h:982
GlobalHandles * global_handles()
Definition: isolate.h:917
Bootstrapper * bootstrapper()
Definition: isolate.h:856
static uint32_t Hash(String *string, uint32_t seed)
Definition: objects-inl.h:6572
static MUST_USE_RESULT MaybeHandle< Object > SetElementsLength(Handle< JSArray > array, Handle< Object > length)
Definition: objects.cc:11167
static void JSArrayUpdateLengthFromIndex(Handle< JSArray > array, uint32_t index, Handle< Object > value)
Definition: objects.cc:12788
static bool IsReadOnlyLengthDescriptor(Handle< Map > jsarray_map)
Definition: objects.cc:12803
static void Expand(Handle< JSArray > array, int minimum_size_of_backing_fixed_array)
Definition: objects.cc:11090
static MaybeHandle< Object > ReadOnlyLengthError(Handle< JSArray > array)
Definition: objects.cc:12829
static bool WouldChangeReadOnlyLength(Handle< JSArray > array, uint32_t index)
Definition: objects.cc:12813
static void Initialize(Handle< JSArray > array, int capacity, int length=0)
Definition: objects.cc:11083
void SetValue(Object *value, bool is_value_nan)
Definition: objects.cc:16214
Object * GetUTCField(FieldIndex index, double value, DateCache *date_cache)
Definition: objects.cc:16172
Object * DoGetField(FieldIndex index)
Definition: objects.cc:16128
static Object * GetField(Object *date, Smi *index)
Definition: objects.cc:16122
void SetCachedFields(int64_t local_time_ms, DateCache *date_cache)
Definition: objects.cc:16232
void JSFunctionIterateBody(int object_size, ObjectVisitor *v)
Definition: objects.cc:9105
static const int kLiteralNativeContextIndex
Definition: objects.h:7389
void CompleteInobjectSlackTracking()
Definition: objects.cc:9982
void set_code_no_write_barrier(Code *code)
Definition: objects-inl.h:5855
static void SetInitialMap(Handle< JSFunction > function, Handle< Map > map, Handle< Object > prototype)
Definition: objects.cc:9491
static void SetInstancePrototype(Handle< JSFunction > function, Handle< Object > value)
Definition: objects.cc:9386
void StartInobjectSlackTracking()
Definition: objects.cc:9923
bool IsInobjectSlackTrackingInProgress()
Definition: objects-inl.h:5832
static void EnsureHasInitialMap(Handle< JSFunction > function)
Definition: objects.cc:9503
void SetInstanceClassName(String *name)
Definition: objects.cc:9543
static void SetPrototype(Handle< JSFunction > function, Handle< Object > value)
Definition: objects.cc:9439
static Handle< JSFunction > CloneClosure(Handle< JSFunction > function)
Definition: objects.cc:9160
static const int kGenerousAllocationCount
Definition: objects.h:7261
void MarkForConcurrentOptimization()
Definition: objects.cc:9125
FixedArray * literals()
Definition: objects-inl.h:5953
bool PassesFilter(const char *raw_filter)
Definition: objects.cc:9567
static const int kNoSlackTracking
Definition: objects.h:7263
bool IsMarkedForConcurrentOptimization()
Definition: objects-inl.h:5820
static Context * NativeContextFromLiterals(FixedArray *literals)
Definition: objects.cc:9554
void PrintName(FILE *out=stdout)
Definition: objects.cc:9548
static const int kCodeEntryOffset
Definition: objects.h:7376
static Handle< PropertyCell > EnsurePropertyCell(Handle< JSGlobalObject > global, Handle< Name > name)
Definition: objects.cc:14576
MUST_USE_RESULT MaybeHandle< JSObject > StructureWalk(Handle< JSObject > object)
Definition: objects.cc:5405
JSObjectWalkVisitor(ContextObject *site_context, bool copying, JSObject::DeepCopyHints hints)
Definition: objects.cc:5374
ContextObject * site_context()
Definition: objects.cc:5392
MUST_USE_RESULT MaybeHandle< JSObject > VisitElementOrProperty(Handle< JSObject > object, Handle< JSObject > value)
Definition: objects.cc:5383
const JSObject::DeepCopyHints hints_
Definition: objects.cc:5400
bool HasFastArgumentsElements()
Definition: objects.cc:11922
static void AllocateStorageForMap(Handle< JSObject > object, Handle< Map > map)
Definition: objects.cc:3707
static void GeneralizeFieldRepresentation(Handle< JSObject > object, int modify_index, Representation new_representation, Handle< HeapType > new_field_type)
Definition: objects.cc:2084
static void SetMapAndElements(Handle< JSObject > object, Handle< Map > map, Handle< FixedArrayBase > elements)
Definition: objects-inl.h:1814
static void ResetElements(Handle< JSObject > object)
Definition: objects.cc:4416
static MUST_USE_RESULT MaybeHandle< Object > GetElementWithCallback(Handle< JSObject > object, Handle< Object > receiver, Handle< Object > structure, uint32_t index, Handle< Object > holder)
Definition: objects.cc:11812
static MUST_USE_RESULT MaybeHandle< Object > SetElementWithCallback(Handle< JSObject > object, Handle< Object > structure, uint32_t index, Handle< Object > value, Handle< JSObject > holder, StrictMode strict_mode)
Definition: objects.cc:11866
static MUST_USE_RESULT MaybeHandle< AccessorPair > GetOwnElementAccessorPair(Handle< JSObject > object, uint32_t index)
Definition: objects.cc:11759
MUST_USE_RESULT Object * GetIdentityHash()
Definition: objects.cc:4554
int GetEnumElementKeys(FixedArray *storage)
Definition: objects.cc:13548
bool HasDictionaryArgumentsElements()
Definition: objects.cc:11934
static MUST_USE_RESULT MaybeHandle< Object > DeleteElement(Handle< JSObject > object, uint32_t index, DeleteMode mode)
Definition: objects.cc:4838
static void MigrateSlowToFast(Handle< JSObject > object, int unused_property_fields)
Definition: objects.cc:4279
static MUST_USE_RESULT MaybeHandle< Object > SetAccessor(Handle< JSObject > object, Handle< AccessorInfo > info)
Definition: objects.cc:6188
static void DeleteHiddenProperty(Handle< JSObject > object, Handle< Name > key)
Definition: objects.cc:4673
static MUST_USE_RESULT MaybeHandle< Object > GetElementWithInterceptor(Handle< JSObject > object, Handle< Object > receiver, uint32_t index)
Definition: objects.cc:12839
static void SetObserved(Handle< JSObject > object)
Definition: objects.cc:5340
static const int kFieldsAdded
Definition: objects.h:2190
static MUST_USE_RESULT MaybeHandle< Object > Freeze(Handle< JSObject > object)
Definition: objects.cc:5239
static MUST_USE_RESULT Maybe< bool > HasRealNamedCallbackProperty(Handle< JSObject > object, Handle< Name > key)
Definition: objects.cc:13243
static void MigrateToNewProperty(Handle< JSObject > object, Handle< Map > transition, Handle< Object > value)
Definition: objects.cc:3756
static void NormalizeProperties(Handle< JSObject > object, PropertyNormalizationMode mode, int expected_additional_properties)
Definition: objects.cc:4166
static void ReoptimizeIfPrototype(Handle< JSObject > object)
Definition: objects.cc:9349
static void MigrateFastToSlow(Handle< JSObject > object, Handle< Map > new_map, int expected_additional_properties)
Definition: objects.cc:4178
static MUST_USE_RESULT MaybeHandle< Object > DeleteProperty(Handle< JSObject > object, Handle< Name > name, DeleteMode mode)
Definition: objects.cc:4912
static const int kMaxInstanceSize
Definition: objects.h:2186
void PrintInstanceMigration(FILE *file, Map *original_map, Map *new_map)
Definition: objects.cc:1345
static Handle< FixedArray > SetFastElementsCapacityAndLength(Handle< JSObject > object, int capacity, int length, SetFastElementsCapacitySmiMode smi_mode)
Definition: objects.cc:10982
static Handle< ObjectHashTable > GetOrCreateHiddenPropertiesHashtable(Handle< JSObject > object)
Definition: objects.cc:4740
static MUST_USE_RESULT MaybeHandle< Object > GetAccessor(Handle< JSObject > object, Handle< Name > name, AccessorComponent component)
Definition: objects.cc:6268
static void UpdateAllocationSite(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:12685
static void SetFastDoubleElementsCapacityAndLength(Handle< JSObject > object, int capacity, int length)
Definition: objects.cc:11044
void JSObjectShortPrint(StringStream *accumulator)
Definition: objects.cc:1185
SeededNumberDictionary * element_dictionary()
Definition: objects-inl.h:6449
static MUST_USE_RESULT MaybeHandle< Object > SetFastElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictMode strict_mode, bool check_prototype)
Definition: objects.cc:11949
Object * GetHiddenProperty(Handle< Name > key)
Definition: objects.cc:4594
static void AddSlowProperty(Handle< JSObject > object, Handle< Name > name, Handle< Object > value, PropertyAttributes attributes)
Definition: objects.cc:1762
static MUST_USE_RESULT Maybe< PropertyAttributes > GetElementAttributeWithReceiver(Handle< JSObject > object, Handle< JSReceiver > receiver, uint32_t index, bool check_prototype)
Definition: objects.cc:4025
static const int kHeaderSize
Definition: objects.h:2195
int NumberOfOwnElements(PropertyAttributes filter)
Definition: objects.cc:13403
static void TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:12706
static MUST_USE_RESULT MaybeHandle< Object > DeletePropertyWithInterceptor(Handle< JSObject > holder, Handle< JSObject > receiver, Handle< Name > name)
Definition: objects.cc:4776
static MUST_USE_RESULT Maybe< bool > HasRealNamedProperty(Handle< JSObject > object, Handle< Name > key)
Definition: objects.cc:13205
static MUST_USE_RESULT MaybeHandle< Object > SetOwnElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictMode strict_mode)
Definition: objects.cc:12327
static Handle< Object > FastPropertyAt(Handle< JSObject > object, Representation representation, FieldIndex index)
Definition: objects.cc:5362
static Handle< Object > SetHiddenPropertiesHashTable(Handle< JSObject > object, Handle< Object > value)
Definition: objects.cc:4766
bool ReferencesObject(Object *obj)
Definition: objects.cc:5047
static Handle< Object > PrepareSlowElementsForSort(Handle< JSObject > object, uint32_t limit)
Definition: objects.cc:14154
static void SetPropertyCallback(Handle< JSObject > object, Handle< Name > name, Handle< Object > structure, PropertyAttributes attributes)
Definition: objects.cc:6064
static MUST_USE_RESULT MaybeHandle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, bool check_prototype=true, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:12336
static MUST_USE_RESULT MaybeHandle< Object > GetPropertyWithInterceptor(Handle< JSObject > object, Handle< Object > receiver, Handle< Name > name)
Definition: objects.cc:13122
void GetElementsCapacityAndUsage(int *capacity, int *used)
Definition: objects.cc:12889
static void MigrateToMap(Handle< JSObject > object, Handle< Map > new_map)
Definition: objects.cc:1886
static void SetElementCallback(Handle< JSObject > object, uint32_t index, Handle< Object > structure, PropertyAttributes attributes)
Definition: objects.cc:6024
static void OptimizeAsPrototype(Handle< JSObject > object, PrototypeOptimizationMode mode)
Definition: objects.cc:9329
static MUST_USE_RESULT Maybe< bool > HasRealElementProperty(Handle< JSObject > object, uint32_t index)
Definition: objects.cc:13214
static Handle< Object > DeleteNormalizedProperty(Handle< JSObject > object, Handle< Name > name, DeleteMode mode)
Definition: objects.cc:692
static MUST_USE_RESULT MaybeHandle< Object > SetElementWithoutInterceptor(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, bool check_prototype, SetPropertyMode set_mode)
Definition: objects.cc:12475
void GetOwnPropertyNames(FixedArray *storage, int index, PropertyAttributes filter=NONE)
Definition: objects.cc:13382
static MUST_USE_RESULT MaybeHandle< JSObject > GetKeysForIndexedInterceptor(Handle< JSObject > object, Handle< JSReceiver > receiver)
Definition: objects.cc:13181
static Handle< Object > GetDataProperty(Handle< JSObject > object, Handle< Name > key)
Definition: objects.cc:140
static MUST_USE_RESULT Maybe< PropertyAttributes > GetElementAttributeWithoutInterceptor(Handle< JSObject > object, Handle< JSReceiver > receiver, uint32_t index, bool continue_search)
Definition: objects.cc:4095
static MUST_USE_RESULT MaybeHandle< Object > SetDictionaryElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, bool check_prototype, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:12077
static bool TryMigrateInstance(Handle< JSObject > instance)
Definition: objects.cc:3740
bool ReferencesObjectFromElements(FixedArray *elements, ElementsKind kind, Object *object)
Definition: objects.cc:5024
static Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:3385
static MUST_USE_RESULT MaybeHandle< Object > SetElementWithInterceptor(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, bool check_prototype, SetPropertyMode set_mode)
Definition: objects.cc:11777
static MUST_USE_RESULT Maybe< PropertyAttributes > GetElementAttributeWithInterceptor(Handle< JSObject > object, Handle< JSReceiver > receiver, uint32_t index, bool continue_search)
Definition: objects.cc:4059
static MUST_USE_RESULT MaybeHandle< Object > GetPropertyWithFailedAccessCheck(LookupIterator *it)
Definition: objects.cc:587
static MUST_USE_RESULT MaybeHandle< Object > SetPrototype(Handle< JSObject > object, Handle< Object > value, bool from_javascript)
Definition: objects.cc:11658
static MUST_USE_RESULT MaybeHandle< Object > PreventExtensions(Handle< JSObject > object)
Definition: objects.cc:5159
static void SetIdentityHash(Handle< JSObject > object, Handle< Smi > hash)
Definition: objects.cc:4534
static Handle< Object > SetHiddenProperty(Handle< JSObject > object, Handle< Name > key, Handle< Object > value)
Definition: objects.cc:4627
static const int kPropertiesOffset
Definition: objects.h:2193
static MUST_USE_RESULT MaybeHandle< JSObject > DeepWalk(Handle< JSObject > object, AllocationSiteCreationContext *site_context)
Definition: objects.cc:5581
static void AddProperty(Handle< JSObject > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes)
Definition: objects.cc:3786
int NumberOfOwnProperties(PropertyAttributes filter=NONE)
Definition: objects.cc:13252
static MUST_USE_RESULT MaybeHandle< Object > SetPropertyWithInterceptor(LookupIterator *it, Handle< Object > value)
Definition: objects.cc:2773
static Handle< FixedArray > EnsureWritableFastElements(Handle< JSObject > object)
Definition: objects.cc:383
Object * SlowReverseLookup(Object *value)
Definition: objects.cc:6346
static void EnqueueChangeRecord(Handle< JSObject > object, const char *type, Handle< Name > name, Handle< Object > old_value)
Definition: objects.cc:1809
static void ValidateElements(Handle< JSObject > object)
Definition: objects-inl.h:1561
static void EnsureCanContainElements(Handle< JSObject > object, Object **elements, uint32_t count, EnsureElementsMode mode)
Definition: objects-inl.h:1738
InterceptorInfo * GetNamedInterceptor()
Definition: objects.cc:13102
static MaybeHandle< Object > DefineAccessor(Handle< JSObject > object, Handle< Name > name, Handle< Object > getter, Handle< Object > setter, PropertyAttributes attributes)
Definition: objects.cc:6095
static MUST_USE_RESULT MaybeHandle< JSObject > DeepCopy(Handle< JSObject > object, AllocationSiteUsageContext *site_context, DeepCopyHints hints=kNoHints)
Definition: objects.cc:5593
bool WouldConvertToSlowElements(Handle< Object > key)
Definition: objects.cc:12964
static MUST_USE_RESULT Maybe< PropertyAttributes > GetPropertyAttributesWithInterceptor(Handle< JSObject > holder, Handle< Object > receiver, Handle< Name > name)
Definition: objects.cc:3940
static bool HasHiddenProperties(Handle< JSObject > object)
Definition: objects.cc:4697
MUST_USE_RESULT Object * GetHiddenPropertiesHashTable()
Definition: objects.cc:4707
static MUST_USE_RESULT MaybeHandle< Object > SetElementWithCallbackSetterInPrototypes(Handle< JSObject > object, uint32_t index, Handle< Object > value, bool *found, StrictMode strict_mode)
Definition: objects.cc:3020
static MUST_USE_RESULT MaybeHandle< JSObject > GetKeysForNamedInterceptor(Handle< JSObject > object, Handle< JSReceiver > receiver)
Definition: objects.cc:13156
int GetOwnElementKeys(FixedArray *storage, PropertyAttributes filter)
Definition: objects.cc:13422
InterceptorInfo * GetIndexedInterceptor()
Definition: objects.cc:13112
static Handle< SeededNumberDictionary > NormalizeElements(Handle< JSObject > object)
Definition: objects.cc:4459
static void PrintElementsTransition(FILE *file, Handle< JSObject > object, ElementsKind from_kind, Handle< FixedArrayBase > from_elements, ElementsKind to_kind, Handle< FixedArrayBase > to_elements)
Definition: objects.cc:1283
static MUST_USE_RESULT MaybeHandle< Object > SetPropertyWithFailedAccessCheck(LookupIterator *it, Handle< Object > value, StrictMode strict_mode)
Definition: objects.cc:626
static MUST_USE_RESULT MaybeHandle< Object > SetOwnPropertyIgnoreAttributes(Handle< JSObject > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, ExecutableAccessorInfoHandling handling=DEFAULT_HANDLING)
Definition: objects.cc:3808
void WriteToField(int descriptor, Object *value)
Definition: objects.cc:3765
bool ShouldConvertToFastDoubleElements(bool *has_smi_only_elements)
Definition: objects.cc:13035
static MUST_USE_RESULT MaybeHandle< Object > DeleteElementWithInterceptor(Handle< JSObject > object, uint32_t index)
Definition: objects.cc:4805
static Handle< Smi > GetOrCreateIdentityHash(Handle< JSObject > object)
Definition: objects.cc:4568
static void MigrateInstance(Handle< JSObject > instance)
Definition: objects.cc:3728
bool ShouldConvertToSlowElements(int new_capacity)
Definition: objects.cc:12979
static void DefineElementAccessor(Handle< JSObject > object, uint32_t index, Handle< Object > getter, Handle< Object > setter, PropertyAttributes attributes)
Definition: objects.cc:5937
static Handle< Object > PrepareElementsForSort(Handle< JSObject > object, uint32_t limit)
Definition: objects.cc:14245
static MUST_USE_RESULT MaybeHandle< Object > SetFastDoubleElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictMode strict_mode, bool check_prototype=true)
Definition: objects.cc:12214
NameDictionary * property_dictionary()
Definition: objects-inl.h:6443
bool ShouldConvertToFastElements()
Definition: objects.cc:12999
static void SetNormalizedProperty(Handle< JSObject > object, Handle< Name > key, Handle< Object > value, PropertyDetails details)
Definition: objects.cc:641
static MUST_USE_RESULT Maybe< PropertyAttributes > GetPropertyAttributesWithFailedAccessCheck(LookupIterator *it)
Definition: objects.cc:601
static MUST_USE_RESULT MaybeHandle< Object > GetPropertyWithHandler(Handle< JSProxy > proxy, Handle< Object > receiver, Handle< Name > name)
Definition: objects.cc:397
static MUST_USE_RESULT MaybeHandle< Object > GetElementWithHandler(Handle< JSProxy > proxy, Handle< Object > receiver, uint32_t index)
Definition: objects-inl.h:1146
static MUST_USE_RESULT MaybeHandle< Object > DeleteElementWithHandler(Handle< JSProxy > proxy, uint32_t index, DeleteMode mode)
Definition: objects.cc:3564
static MUST_USE_RESULT Maybe< bool > HasPropertyWithHandler(Handle< JSProxy > proxy, Handle< Name > name)
Definition: objects.cc:3392
static Handle< Smi > GetOrCreateIdentityHash(Handle< JSProxy > proxy)
Definition: objects.cc:4589
static MUST_USE_RESULT MaybeHandle< Object > SetPropertyViaPrototypesWithHandler(Handle< JSProxy > proxy, Handle< Object > receiver, Handle< Name > name, Handle< Object > value, StrictMode strict_mode, bool *done)
Definition: objects.cc:3434
MUST_USE_RESULT Object * GetIdentityHash()
Definition: objects.cc:4584
static MUST_USE_RESULT Maybe< PropertyAttributes > GetPropertyAttributesWithHandler(Handle< JSProxy > proxy, Handle< Object > receiver, Handle< Name > name)
Definition: objects.cc:3572
static MUST_USE_RESULT Maybe< PropertyAttributes > GetElementAttributeWithHandler(Handle< JSProxy > proxy, Handle< JSReceiver > receiver, uint32_t index)
Definition: objects.cc:3647
static MUST_USE_RESULT MaybeHandle< Object > SetElementWithHandler(Handle< JSProxy > proxy, Handle< JSReceiver > receiver, uint32_t index, Handle< Object > value, StrictMode strict_mode)
Definition: objects-inl.h:1154
static MUST_USE_RESULT MaybeHandle< Object > CallTrap(Handle< JSProxy > proxy, const char *name, Handle< Object > derived_trap, int argc, Handle< Object > args[])
Definition: objects.cc:3677
static MUST_USE_RESULT MaybeHandle< Object > DeletePropertyWithHandler(Handle< JSProxy > proxy, Handle< Name > name, DeleteMode mode)
Definition: objects.cc:3532
static MUST_USE_RESULT MaybeHandle< Object > SetPropertyWithHandler(Handle< JSProxy > proxy, Handle< Object > receiver, Handle< Name > name, Handle< Object > value, StrictMode strict_mode)
Definition: objects.cc:3410
static void Fix(Handle< JSProxy > proxy)
Definition: objects.cc:3655
static MUST_USE_RESULT MaybeHandle< Object > SetElement(Handle< JSReceiver > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode)
Definition: objects.cc:12313
String * constructor_name()
Definition: objects.cc:1705
static MUST_USE_RESULT Maybe< PropertyAttributes > GetPropertyAttributes(Handle< JSReceiver > object, Handle< Name > name)
Definition: objects-inl.h:6670
static MUST_USE_RESULT Maybe< PropertyAttributes > GetOwnPropertyAttributes(Handle< JSReceiver > object, Handle< Name > name)
Definition: objects.cc:3983
static Handle< Smi > GetOrCreateIdentityHash(Handle< JSReceiver > object)
Definition: objects-inl.h:6704
static MUST_USE_RESULT MaybeHandle< Object > DeleteElement(Handle< JSReceiver > object, uint32_t index, DeleteMode mode=NORMAL_DELETION)
Definition: objects.cc:5002
static MUST_USE_RESULT MaybeHandle< FixedArray > GetKeys(Handle< JSReceiver > object, KeyCollectionType type)
Definition: objects.cc:5797
static MUST_USE_RESULT Maybe< PropertyAttributes > GetOwnElementAttribute(Handle< JSReceiver > object, uint32_t index)
Definition: objects-inl.h:6743
static MUST_USE_RESULT MaybeHandle< Object > DeleteProperty(Handle< JSReceiver > object, Handle< Name > name, DeleteMode mode=NORMAL_DELETION)
Definition: objects.cc:5013
static const int kFlagsIndex
Definition: objects.h:7777
static const int kSourceIndex
Definition: objects.h:7776
static Handle< JSArrayBuffer > MaterializeArrayBuffer(Handle< JSTypedArray > typed_array)
Definition: objects.cc:16292
Handle< JSArrayBuffer > GetBuffer()
Definition: objects.cc:16326
ExternalArrayType type()
Definition: objects.cc:14375
static void PrintTop(Isolate *isolate, FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:811
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:17
T & at(int i) const
Definition: list.h:69
Object * Lookup(FixedArray *key)
Definition: objects.cc:14876
static Handle< MapCache > Put(Handle< MapCache > map_cache, Handle< FixedArray > key, Handle< Map > value)
Definition: objects.cc:14885
void DeprecateTarget(Name *key, DescriptorArray *new_descriptors)
Definition: objects.cc:2187
static Handle< Map > Create(Isolate *isolate, int inobject_properties)
Definition: objects.cc:6674
static Handle< Map > TransitionToAccessorProperty(Handle< Map > map, Handle< Name > name, AccessorComponent component, Handle< Object > accessor, PropertyAttributes attributes)
Definition: objects.cc:6816
uint32_t bit_field3()
Definition: objects-inl.h:5120
ElementsKind elements_kind()
Definition: objects.h:5730
void SetEnumLength(int length)
Definition: objects.h:5959
static void UpdateCodeCache(Handle< Map > map, Handle< Name > name, Handle< Code > code)
Definition: objects.cc:7030
int NumberOfOwnDescriptors()
Definition: objects.h:5944
void set_migration_target(bool value)
Definition: objects-inl.h:4470
int unused_property_fields()
Definition: objects-inl.h:4333
FixedArray * GetPrototypeTransitions()
Definition: objects-inl.h:5181
static MUST_USE_RESULT Handle< HeapType > GeneralizeFieldType(Handle< HeapType > type1, Handle< HeapType > type2, Isolate *isolate)
Definition: objects.cc:2297
static Handle< Map > AsElementsKind(Handle< Map > map, ElementsKind kind)
Definition: objects.cc:3374
String * constructor_name()
Definition: objects.cc:1689
int pre_allocated_property_fields()
Definition: objects-inl.h:4246
Object * GetBackPointer()
Definition: objects-inl.h:5134
Map * LookupElementsTransitionMap(ElementsKind elements_kind)
Definition: objects.cc:3273
Map * elements_transition_map()
Definition: objects-inl.h:5156
static Handle< Map > CopyAsElementsKind(Handle< Map > map, ElementsKind kind, TransitionFlag flag)
Definition: objects.cc:6592
bool HasElementsTransition()
Definition: objects-inl.h:5145
static const int kProtoTransitionMapOffset
Definition: objects.h:5905
static Handle< Map > CopyReplaceDescriptors(Handle< Map > map, Handle< DescriptorArray > descriptors, TransitionFlag flag, MaybeHandle< Name > maybe_name, SimpleTransitionFlag simple_flag=FULL_TRANSITION)
Definition: objects.cc:6533
static Handle< Map > GeneralizeRepresentation(Handle< Map > map, int modify_index, Representation new_representation, Handle< HeapType > new_field_type, StoreMode store_mode)
Definition: objects.cc:2378
void set_unused_property_fields(int value)
Definition: objects-inl.h:4338
Map * GetTransition(int transition_index)
Definition: objects-inl.h:5170
void set_construction_count(int value)
Definition: objects-inl.h:4490
static Handle< Map > TransitionElementsTo(Handle< Map > map, ElementsKind to_kind)
Definition: objects.cc:3321
static Handle< Map > Update(Handle< Map > map)
Definition: objects.cc:2705
void SetNumberOfProtoTransitions(int value)
Definition: objects.h:5914
static Handle< Map > CopyInstallDescriptors(Handle< Map > map, int new_descriptor, Handle< DescriptorArray > descriptors)
Definition: objects.cc:6565
static void AddDependentCompilationInfo(Handle< Map > map, DependentCode::DependencyGroup group, CompilationInfo *info)
Definition: objects.cc:11345
void NotifyLeafMapLayoutChange()
Definition: objects-inl.h:4539
static Handle< Map > CopyInsertDescriptor(Handle< Map > map, Descriptor *descriptor, TransitionFlag flag)
Definition: objects.cc:6934
int IndexInCodeCache(Object *name, Code *code)
Definition: objects.cc:7057
void PrintGeneralization(FILE *file, const char *reason, int modify_index, int split, int descriptors, bool constant_to_field, Representation old_representation, Representation new_representation, HeapType *old_field_type, HeapType *new_field_type)
Definition: objects.cc:1303
int NumberOfFields()
Definition: objects.cc:2095
void RemoveFromCodeCache(Name *name, Code *code, int index)
Definition: objects.cc:7066
static Handle< Map > CopyGeneralizeAllRepresentations(Handle< Map > map, int modify_index, StoreMode store_mode, PropertyAttributes attributes, const char *reason)
Definition: objects.cc:2105
bool IsMapInArrayPrototypeChain()
Definition: objects.cc:3280
static void EnsureDescriptorSlack(Handle< Map > map, int slack)
Definition: objects.cc:3057
static Handle< Map > CopyNormalized(Handle< Map > map, PropertyNormalizationMode mode)
Definition: objects.cc:6444
static MaybeHandle< Map > TryUpdate(Handle< Map > map) WARN_UNUSED_RESULT
Definition: objects.cc:2691
void UpdateFieldType(int descriptor_number, Handle< Name > name, Handle< HeapType > new_type)
Definition: objects.cc:2277
bool EquivalentToForNormalization(Map *other, PropertyNormalizationMode mode)
Definition: objects.cc:9054
bool done_inobject_slack_tracking()
Definition: objects-inl.h:4485
static Handle< Map > GetPrototypeTransition(Handle< Map > map, Handle< Object > prototype)
Definition: objects.cc:11267
int NextFreePropertyIndex()
Definition: objects.cc:5663
bool CanHaveMoreTransitions()
Definition: objects-inl.h:5162
PropertyDetails GetLastDescriptorDetails()
Definition: objects-inl.h:2867
static Handle< Map > CopyReplaceDescriptor(Handle< Map > map, Handle< DescriptorArray > descriptors, Descriptor *descriptor, int index, TransitionFlag flag)
Definition: objects.cc:7006
bool has_instance_call_handler()
Definition: objects-inl.h:4455
void SetNumberOfOwnDescriptors(int number)
Definition: objects.h:5948
bool is_dictionary_map()
Definition: objects-inl.h:4430
static const int kMaxCachedPrototypeTransitions
Definition: objects.h:6180
void DeprecateTransitionTree()
Definition: objects.cc:2169
static Handle< Map > PrepareForDataProperty(Handle< Map > old_map, int descriptor_number, Handle< Object > value)
Definition: objects.cc:6738
bool IsJSObjectMap()
Definition: objects.h:6125
static Handle< Map > CopyDropDescriptors(Handle< Map > map)
Definition: objects.cc:6468
static Handle< Map > Normalize(Handle< Map > map, PropertyNormalizationMode mode)
Definition: objects.cc:6398
static void AddDependentCode(Handle< Map > map, DependentCode::DependencyGroup group, Handle< Code > code)
Definition: objects.cc:11357
void ZapPrototypeTransitions()
Definition: objects.cc:11336
void ZapTransitions()
Definition: objects.cc:11323
static Handle< Map > GeneralizeAllFieldRepresentations(Handle< Map > map)
Definition: objects.cc:2676
static Handle< Map > ReconfigureDataProperty(Handle< Map > map, int descriptor, PropertyAttributes attributes)
Definition: objects.cc:6804
static Handle< Map > PutPrototypeTransition(Handle< Map > map, Handle< Object > prototype, Handle< Map > target_map)
Definition: objects.cc:11285
static const int kDependentCodeOffset
Definition: objects.h:6201
int NumberOfDescribedProperties(DescriptorFlag which=OWN_DESCRIPTORS, PropertyAttributes filter=NONE)
Definition: objects.cc:5646
static const int kProtoTransitionNumberOfEntriesOffset
Definition: objects.h:5902
static bool IsValidElementsTransition(ElementsKind from_kind, ElementsKind to_kind)
Definition: objects.cc:12775
static void ConnectTransition(Handle< Map > parent, Handle< Map > child, Handle< Name > name, SimpleTransitionFlag flag)
Definition: objects.cc:6519
static Handle< Map > RawCopy(Handle< Map > map, int instance_size)
Definition: objects.cc:6375
InstanceType instance_type()
Definition: objects-inl.h:4323
bool IsGlobalObjectMap()
Definition: objects.h:6138
static const int kProtoTransitionElementsPerEntry
Definition: objects.h:5903
static MaybeHandle< Map > TryUpdateInternal(Handle< Map > map) WARN_UNUSED_RESULT
Definition: objects.cc:2714
static const int kSize
Definition: objects.h:6202
void set_done_inobject_slack_tracking(bool value)
Definition: objects-inl.h:4480
Handle< Map > FindTransitionedMap(MapHandleList *candidates)
Definition: objects.cc:3212
Map * FindRootMap()
Definition: objects.cc:2214
Map * FindLastMatchMap(int verbatim, int length, DescriptorArray *descriptors)
Definition: objects.cc:2224
static const int kProtoTransitionPrototypeOffset
Definition: objects.h:5904
static Handle< Map > TransitionElementsToSlow(Handle< Map > object, ElementsKind to_kind)
Definition: objects.cc:3344
static void SetPrototypeTransitions(Handle< Map > map, Handle< FixedArray > prototype_transitions)
Definition: objects-inl.h:5190
void TraverseTransitionTree(TraverseCallback callback, void *data)
Definition: objects.cc:7257
static MUST_USE_RESULT MaybeHandle< Map > CopyWithConstant(Handle< Map > map, Handle< Name > name, Handle< Object > constant, PropertyAttributes attributes, TransitionFlag flag)
Definition: objects.cc:1746
static Handle< Map > CopyAddDescriptor(Handle< Map > map, Descriptor *descriptor, TransitionFlag flag)
Definition: objects.cc:6911
static const int kCodeCacheOffset
Definition: objects.h:6200
static void AppendCallbackDescriptors(Handle< Map > map, Handle< Object > descriptors)
Definition: objects.cc:3174
bool has_fast_object_elements()
Definition: objects.h:5740
static Handle< Map > TransitionToDataProperty(Handle< Map > map, Handle< Name > name, Handle< Object > value, PropertyAttributes attributes, StoreFromKeyed store_mode)
Definition: objects.cc:6759
bool is_observed()
Definition: objects.h:5714
static Handle< Map > TransitionToPrototype(Handle< Map > map, Handle< Object > prototype)
Definition: objects.cc:11646
void set_inobject_properties(int value)
Definition: objects-inl.h:4309
int NumberOfProtoTransitions()
Definition: objects.h:5907
static const int kConstructorOffset
Definition: objects.h:6191
Object * FindInCodeCache(Name *name, Code::Flags flags)
Definition: objects.cc:7047
Map * FindFieldOwner(int descriptor)
Definition: objects.cc:2262
static MUST_USE_RESULT MaybeHandle< Map > CopyWithField(Handle< Map > map, Handle< Name > name, Handle< HeapType > type, PropertyAttributes attributes, Representation representation, TransitionFlag flag)
Definition: objects.cc:1710
bool EquivalentToForTransition(Map *other)
Definition: objects.cc:9049
static Handle< Map > CopyForObserved(Handle< Map > map)
Definition: objects.cc:6637
bool HasTransitionArray() const
Definition: objects-inl.h:5150
static void AddDependentIC(Handle< Map > map, Handle< Code > stub)
Definition: objects.cc:11367
bool DictionaryElementsInPrototypeChainOnly()
Definition: objects.cc:6003
int SearchTransition(Name *name)
Definition: objects-inl.h:5175
static Handle< Map > Copy(Handle< Map > map)
Definition: objects.cc:6664
static const int kProtoTransitionHeaderSize
Definition: objects.h:5901
static Handle< Map > CopyForFreeze(Handle< Map > map)
Definition: objects.cc:6699
bool TooManyFastProperties(StoreFromKeyed store_mode)
Definition: objects-inl.h:2098
static Handle< Map > ShareDescriptor(Handle< Map > map, Handle< DescriptorArray > descriptors, Descriptor *descriptor)
Definition: objects.cc:6483
bool is_null() const
Definition: handles.h:66
static const intptr_t kAlignmentMask
Definition: spaces.h:526
static Address & Address_at(Address addr)
Definition: v8memory.h:56
static void DoGenerateNewEnumerationIndices(Handle< NameDictionary > dictionary)
Definition: objects-inl.h:6883
int FindEntry(Handle< Name > key)
Definition: objects.cc:13784
void CopyEnumKeysTo(FixedArray *storage)
Definition: objects.cc:15219
static const int kHashShift
Definition: objects.h:8499
void set_hash_field(uint32_t value)
Definition: objects-inl.h:3301
static const uint32_t kHashBitMask
Definition: objects.h:8503
static const int kIsNotArrayIndexMask
Definition: objects.h:8495
bool Equals(Name *other)
Definition: objects-inl.h:3309
uint32_t hash_field()
Definition: objects-inl.h:3296
void set_top(Address top)
Definition: spaces.h:2424
bool Contains(Address a)
Definition: spaces.h:2349
static Handle< NormalizedMapCache > New(Isolate *isolate)
Definition: objects.cc:4123
MUST_USE_RESULT MaybeHandle< Map > Get(Handle< Map > fast_map, PropertyNormalizationMode mode)
Definition: objects.cc:4130
void Set(Handle< Map > fast_map, Handle< Map > normalized_map)
Definition: objects.cc:4142
static Handle< Object > AsHandle(Isolate *isolate, uint32_t key)
Definition: objects-inl.h:6853
const char * c_str() const
Definition: ostreams.h:84
void AddEntry(int entry, Object *key, Object *value)
Definition: objects.cc:15353
static Handle< ObjectHashTable > Remove(Handle< ObjectHashTable > table, Handle< Object > key, bool *was_present)
Definition: objects.cc:15330
Object * Lookup(Handle< Object > key)
Definition: objects.cc:15287
static Handle< ObjectHashTable > Put(Handle< ObjectHashTable > table, Handle< Object > key, Handle< Object > value)
Definition: objects.cc:15302
void RemoveEntry(int entry)
Definition: objects.cc:15360
Handle< HeapType > OptimalType(Isolate *isolate, Representation representation)
Definition: objects.cc:47
static MUST_USE_RESULT MaybeHandle< Object > AddDataProperty(LookupIterator *it, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode)
Definition: objects.cc:2968
static MUST_USE_RESULT MaybeHandle< Object > GetPropertyOrElement(Handle< Object > object, Handle< Name > key)
Definition: objects-inl.h:1124
Object * GetHash()
Definition: objects.cc:835
static MUST_USE_RESULT MaybeHandle< Object > SetPropertyWithDefinedSetter(Handle< Object > receiver, Handle< JSReceiver > setter, Handle< Object > value)
Definition: objects.cc:552
static MUST_USE_RESULT MaybeHandle< Object > SetPropertyWithAccessor(Handle< Object > receiver, Handle< Name > name, Handle< Object > value, Handle< JSObject > holder, Handle< Object > structure, StrictMode strict_mode)
Definition: objects.cc:478
bool ToUint32(uint32_t *value)
Definition: objects.cc:191
static MaybeHandle< JSReceiver > ToObject(Isolate *isolate, Handle< Object > object)
Definition: objects-inl.h:1094
static MUST_USE_RESULT MaybeHandle< Object > GetElement(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: objects-inl.h:1113
bool SameValue(Object *other)
Definition: objects.cc:865
friend class LookupIterator
Definition: objects.h:1226
static MUST_USE_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it)
Definition: objects.cc:109
@ CERTAINLY_NOT_STORE_FROM_KEYED
Definition: objects.h:1007
Map * GetRootMap(Isolate *isolate)
Definition: objects.cc:803
bool SameValueZero(Object *other)
Definition: objects.cc:886
static Handle< Object > NewStorageFor(Isolate *isolate, Handle< Object > object, Representation representation)
Definition: objects-inl.h:277
bool IsCallable() const
Definition: objects.cc:98
static MUST_USE_RESULT MaybeHandle< Object > WriteToReadOnlyProperty(LookupIterator *it, Handle< Object > value, StrictMode strict_mode)
Definition: objects.cc:2920
void ShortPrint(FILE *out=stdout)
Definition: objects.cc:905
static MUST_USE_RESULT MaybeHandle< Object > GetPropertyWithDefinedGetter(Handle< Object > receiver, Handle< JSReceiver > getter)
Definition: objects.cc:536
bool FitsRepresentation(Representation representation)
Definition: objects.h:1068
static Handle< Object > SetDataProperty(LookupIterator *it, Handle< Object > value)
Definition: objects.cc:2933
bool ToInt32(int32_t *value)
Definition: objects.cc:175
bool ToArrayIndex(uint32_t *index)
Definition: objects-inl.h:2116
static Handle< Smi > GetOrCreateHash(Isolate *isolate, Handle< Object > object)
Definition: objects.cc:856
static Handle< Object > WrapForRead(Isolate *isolate, Handle< Object > object, Representation representation)
Definition: objects-inl.h:296
static MUST_USE_RESULT MaybeHandle< Object > GetElementWithReceiver(Isolate *isolate, Handle< Object > object, Handle< Object > receiver, uint32_t index)
Definition: objects.cc:747
static MUST_USE_RESULT MaybeHandle< Object > GetPropertyWithAccessor(Handle< Object > receiver, Handle< Name > name, Handle< JSObject > holder, Handle< Object > structure)
Definition: objects.cc:411
static MUST_USE_RESULT MaybeHandle< Object > SetProperty(Handle< Object > object, Handle< Name > key, Handle< Object > value, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:2798
static void Initialize(Isolate *isolate, Handle< Oddball > oddball, const char *to_string, Handle< Object > to_number, byte kind)
Definition: objects.cc:9596
virtual Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:13677
Object * Lookup(Handle< Object > key)
Definition: objects.cc:15680
static Handle< OrderedHashMap > Put(Handle< OrderedHashMap > table, Handle< Object > key, Handle< Object > value)
Definition: objects.cc:15688
bool Contains(Handle< Object > key)
Definition: objects.cc:15662
static Handle< OrderedHashSet > Add(Handle< OrderedHashSet > table, Handle< Object > key)
Definition: objects.cc:15667
Smi * Next(JSArray *value_array)
Definition: objects.cc:15769
static Handle< Derived > Allocate(Isolate *isolate, int capacity, PretenureFlag pretenure=NOT_TENURED)
Definition: objects.cc:15412
int FindEntry(Handle< Object > key, int hash)
Definition: objects.cc:15544
static Handle< Derived > Remove(Handle< Derived > table, Handle< Object > key, bool *was_present)
Definition: objects.cc:15485
static Handle< Derived > Shrink(Handle< Derived > table)
Definition: objects.cc:15456
static Handle< Derived > EnsureGrowable(Handle< Derived > table)
Definition: objects.cc:15440
static Handle< Derived > Rehash(Handle< Derived > table, int new_capacity)
Definition: objects.cc:15499
static Handle< Derived > Clear(Handle< Derived > table)
Definition: objects.cc:15468
uint32_t HashForObject(Object *obj) OVERRIDE
Definition: objects.cc:7623
MUST_USE_RESULT Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:7630
bool IsMatch(Object *other) OVERRIDE
Definition: objects.cc:7584
PolymorphicCodeCacheHashTableKey(MapHandleList *maps, int code_flags)
Definition: objects.cc:7580
static MapHandleList * FromObject(Object *obj, int *code_flags, MapHandleList *maps)
Definition: objects.cc:7644
static uint32_t MapsHashHelper(MapHandleList *maps, int code_flags)
Definition: objects.cc:7611
Object * Lookup(MapHandleList *maps, int code_kind)
Definition: objects.cc:7662
static Handle< PolymorphicCodeCacheHashTable > Put(Handle< PolymorphicCodeCacheHashTable > hash_table, MapHandleList *maps, int code_kind, Handle< Code > code)
Definition: objects.cc:7672
Handle< Object > Lookup(MapHandleList *maps, Code::Flags flags)
Definition: objects.cc:7562
static void Update(Handle< PolymorphicCodeCache > cache, MapHandleList *maps, Code::Flags flags, Handle< Code > code)
Definition: objects.cc:7538
static Handle< HeapType > UpdatedType(Handle< PropertyCell > cell, Handle< Object > value)
Definition: objects.cc:16348
void set_type(HeapType *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects.cc:16342
static void SetValueInferType(Handle< PropertyCell > cell, Handle< Object > value)
Definition: objects.cc:16367
static void AddDependentCompilationInfo(Handle< PropertyCell > cell, CompilationInfo *info)
Definition: objects.cc:16378
A class to uniformly access the prototype of any Object and walk its prototype chain.
Definition: prototype.h:25
bool IsAtEnd(WhereToEnd where_to_end=END_AT_NULL) const
Definition: prototype.h:99
Object * GetCurrent() const
Definition: prototype.h:62
static bool compare(const uint16_t *a, const uint16_t *b, int len)
Definition: objects.cc:8544
static bool compare(const uint8_t *a, const uint8_t *b, int len)
Definition: objects.cc:8553
static bool compare(const Chars1 *a, const Chars2 *b, int len)
Definition: objects.cc:8529
bool IsMatch(Object *obj) OVERRIDE
Definition: objects.cc:13647
RegExpKey(Handle< String > string, JSRegExp::Flags flags)
Definition: objects.cc:13639
static uint32_t RegExpHash(String *string, Smi *flags)
Definition: objects.cc:13668
uint32_t Hash() OVERRIDE
Definition: objects.cc:13653
Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:13655
Handle< String > string_
Definition: objects.cc:13672
uint32_t HashForObject(Object *obj) OVERRIDE
Definition: objects.cc:13662
static int ModeMask(Mode mode)
Definition: assembler.h:445
static const int kCodeTargetMask
Definition: assembler.h:587
static bool IsDebugBreakSlot(Mode mode)
Definition: assembler.h:436
static const int kPositionMask
Definition: assembler.h:588
static bool IsJSReturn(Mode mode)
Definition: assembler.h:412
static bool IsRuntimeEntry(Mode mode)
Definition: assembler.h:405
static const int kApplyMask
Definition: assembler.h:591
static bool IsCodeTarget(Mode mode)
Definition: assembler.h:399
byte * pc() const
Definition: assembler.h:457
Code * host() const
Definition: assembler.h:463
intptr_t data() const
Definition: assembler.h:460
static bool IsStatementPosition(Mode mode)
Definition: assembler.h:427
Mode rmode() const
Definition: assembler.h:459
static bool IsCodeAgeSequence(Mode mode)
Definition: assembler.h:442
static const int kNoPosition
Definition: assembler.h:317
const char * Mnemonic() const
Definition: objects.cc:1828
bool fits_into(const Representation &other) const
Representation generalize(Representation other)
bool Equals(const Representation &other) const
static Representation Tagged()
static Representation None()
static bool SetupArrayBufferAllocatingData(Isolate *isolate, Handle< JSArrayBuffer > array_buffer, size_t allocated_length, bool initialize=true)
static Handle< Object > GetNameOrSourceURL(Handle< Script > script)
Definition: objects.cc:9697
static int GetColumnNumber(Handle< Script > script, int code_pos)
Definition: objects.cc:9635
int GetLineNumberWithArray(int code_pos)
Definition: objects.cc:9649
void ClearWrapperCache()
Definition: objects.cc:9731
static void InitLineEnds(Handle< Script > script)
Definition: objects.cc:9609
static Handle< JSObject > GetWrapper(Handle< Script > script)
Definition: objects.cc:9741
static int GetLineNumber(Handle< Script > script, int code_pos)
Definition: objects.cc:9673
static MUST_USE_RESULT Handle< SeededNumberDictionary > AtNumberPut(Handle< SeededNumberDictionary > dictionary, uint32_t key, Handle< Object > value)
Definition: objects.cc:15108
static MUST_USE_RESULT Handle< SeededNumberDictionary > Set(Handle< SeededNumberDictionary > dictionary, uint32_t key, Handle< Object > value, PropertyDetails details)
Definition: objects.cc:15125
void UpdateMaxNumberKey(uint32_t key)
Definition: objects.cc:15068
static MUST_USE_RESULT Handle< SeededNumberDictionary > AddNumberEntry(Handle< SeededNumberDictionary > dictionary, uint32_t key, Handle< Object > value, PropertyDetails details)
Definition: objects.cc:15088
static int SizeFor(int length)
Definition: objects.h:8976
virtual Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:13689
virtual bool IsMatch(Object *string) OVERRIDE
Definition: objects.cc:13696
static MUST_USE_RESULT Handle< String > Truncate(Handle< SeqString > string, int new_length)
Definition: objects.cc:8883
const uint16_t * SeqTwoByteStringGetData(unsigned start)
Definition: objects.cc:8105
static int SizeFor(int length)
Definition: objects.h:9015
static const int kCachedCodeOffset
Definition: objects.h:6626
bool VerifyBailoutId(BailoutId id)
Definition: objects.cc:9912
void ResetForNewContext(int new_ic_age)
Definition: objects.cc:9943
static void AddToOptimizedCodeMap(Handle< SharedFunctionInfo > shared, Handle< Context > native_context, Handle< Code > code, Handle< FixedArray > literals, BailoutId osr_ast_id)
Definition: objects.cc:9184
void set_opt_count(int opt_count)
Definition: objects-inl.h:5744
void EnableDeoptimizationSupport(Code *recompiled)
Definition: objects.cc:9868
static const int kNextMapIndex
Definition: objects.h:6623
static const int kEntriesStart
Definition: objects.h:6624
static const int kOsrAstIdOffset
Definition: objects.h:6628
void set_bailout_reason(BailoutReason reason)
Definition: objects.h:6861
STATIC_ASSERT(SharedFunctionInfo::kCompilerHintsCount<=SharedFunctionInfo::kCompilerHintsSize *kBitsPerByte)
static const int kLiteralsOffset
Definition: objects.h:6627
void DisableOptimization(BailoutReason reason)
Definition: objects.cc:9887
static const int kInitialLength
Definition: objects.h:6630
void TrimOptimizedCodeMap(int shrink_by)
Definition: objects.cc:9317
Code * GetCodeFromOptimizedCodeMap(int index)
Definition: objects.cc:9248
int SearchOptimizedCodeMap(Context *native_context, BailoutId osr_ast_id)
Definition: objects.cc:9998
void EvictFromOptimizedCodeMap(Code *optimized_code, const char *reason)
Definition: objects.cc:9272
Handle< Object > GetSourceCode()
Definition: objects.cc:9782
static const int kContextOffset
Definition: objects.h:6625
static const int kEntryLength
Definition: objects.h:6629
FixedArray * GetLiteralsFromOptimizedCodeMap(int index)
Definition: objects.cc:9236
uint16_t SlicedStringGet(int index)
Definition: objects.cc:8364
void SmiPrint(OStream &os) const
Definition: objects.cc:930
static const int kMaxValue
Definition: objects.h:1272
int value() const
Definition: objects-inl.h:1316
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
static VisitorId GetVisitorId(int instance_type, int instance_size)
void Reset(String *string, int offset=0)
Definition: objects-inl.h:3694
void VisitOneByteString(const uint8_t *chars, int length)
Definition: objects.cc:8575
State(ConsStringIteratorOp *op)
Definition: objects.cc:8562
ConsStringIteratorOp *const op_
Definition: objects.cc:8607
void VisitTwoByteString(const uint16_t *chars, int length)
Definition: objects.cc:8581
static bool Equals(State *state_1, State *state_2, int to_check)
Definition: objects.cc:8627
bool Equals(String *string_1, String *string_2)
Definition: objects.cc:8633
StringComparator(ConsStringIteratorOp *op_1, ConsStringIteratorOp *op_2)
Definition: objects.cc:8620
DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator)
void AddCharacter(uint16_t c)
Definition: objects-inl.h:6512
static uint32_t ComputeUtf8Hash(Vector< const char > chars, uint32_t seed, int *utf16_length_out)
Definition: objects.cc:8956
static uint32_t MakeArrayIndexHash(uint32_t value, int length)
Definition: objects.cc:8925
bool UpdateIndex(uint16_t c)
Definition: objects-inl.h:6519
static const int kZeroHash
Definition: objects.h:8363
static uint32_t HashSequentialString(const schar *chars, int length, uint32_t seed)
Definition: objects-inl.h:6563
int Search(Vector< const SubjectChar > subject, int index)
Definition: string-search.h:78
bool IsMatch(Object *other) OVERRIDE
Definition: objects.cc:13565
static uint32_t StringSharedHashHelper(String *source, SharedFunctionInfo *shared, StrictMode strict_mode, int scope_position)
Definition: objects.cc:13581
Handle< String > source_
Definition: objects.cc:13629
Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:13619
StringSharedKey(Handle< String > source, Handle< SharedFunctionInfo > shared, StrictMode strict_mode, int scope_position)
Definition: objects.cc:13556
uint32_t HashForObject(Object *obj) OVERRIDE
Definition: objects.cc:13605
Handle< SharedFunctionInfo > shared_
Definition: objects.cc:13630
uint32_t Hash() OVERRIDE
Definition: objects.cc:13600
static Handle< String > LookupString(Isolate *isolate, Handle< String > key)
Definition: objects.cc:14706
static MUST_USE_RESULT MaybeHandle< String > InternalizeStringIfExists(Isolate *isolate, Handle< String > string)
Definition: objects.cc:14663
static Handle< String > LookupKey(Isolate *isolate, HashTableKey *key)
Definition: objects.cc:14713
static MUST_USE_RESULT MaybeHandle< String > LookupStringIfExists(Isolate *isolate, Handle< String > str)
Definition: objects.cc:14673
static MUST_USE_RESULT MaybeHandle< String > LookupTwoCharsStringIfExists(Isolate *isolate, uint16_t c1, uint16_t c2)
Definition: objects.cc:14689
Vector< const uint8_t > ToOneByteVector()
Definition: objects.h:8639
Vector< const uc16 > ToUC16Vector()
Definition: objects.h:8645
void StringShortPrint(StringStream *accumulator)
Definition: objects.cc:1111
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:8370
static const unsigned int kContainsCachedArrayIndexMask
Definition: objects.h:8618
const uc16 * GetTwoByteData(unsigned start)
Definition: objects.cc:8062
void PrintOn(FILE *out)
Definition: objects.cc:9005
bool MarkAsUndetectable()
Definition: objects.cc:8766
FlatContent GetFlatContent()
Definition: objects.cc:7961
static Handle< String > SlowFlatten(Handle< ConsString > cons, PretenureFlag tenure)
Definition: objects.cc:959
bool IsTwoByteRepresentation() const
Definition: objects-inl.h:343
bool IsOneByteEqualTo(Vector< const uint8_t > str)
Definition: objects.cc:8813
static const int kArrayIndexValueBits
Definition: objects.h:8601
bool ComputeArrayIndex(uint32_t *index)
Definition: objects.cc:8860
SmartArrayPointer< uc16 > ToWideCString(RobustnessFlag robustness_flag=FAST_STRING_TRAVERSAL)
Definition: objects.cc:8083
static const int kMaxHashCalcLength
Definition: objects.h:8824
bool SlowAsArrayIndex(uint32_t *index)
Definition: objects.cc:8869
uint32_t ComputeAndSetHash()
Definition: objects.cc:8844
static const int kMaxShortPrintLength
Definition: objects.h:8827
bool SlowEquals(String *other)
Definition: objects.cc:8671
bool IsUtf8EqualTo(Vector< const char > str, bool allow_prefix_match=false)
Definition: objects.cc:8783
bool MakeExternal(v8::String::ExternalStringResource *resource)
Definition: objects.cc:989
bool IsTwoByteEqualTo(Vector< const uc16 > str)
Definition: objects.cc:8829
void PrintUC16(OStream &os, int start=0, int end=-1)
Definition: objects.cc:1175
static ConsString * VisitFlat(Visitor *visitor, String *string, int offset=0)
Definition: objects-inl.h:3416
bool IsOneByteRepresentation() const
Definition: objects-inl.h:337
static const int kMaxArrayIndexSize
Definition: objects.h:8807
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
Definition: objects.cc:8004
static Handle< String > Flatten(Handle< String > string, PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:3354
static Handle< FixedArray > CalculateLineEnds(Handle< String > string, bool include_ending_line)
Definition: objects.cc:8483
static bool IsOneByte(const uc16 *chars, int length)
Definition: objects.h:8895
static const int kMaxCachedArrayIndexLength
Definition: objects.h:8596
bool Equals(String *other)
Definition: objects-inl.h:3336
bool IsMatch(Object *strings) OVERRIDE
Definition: objects.cc:14847
Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:14869
uint32_t HashForObject(Object *obj) OVERRIDE
Definition: objects.cc:14859
StringsKey(Handle< FixedArray > strings)
Definition: objects.cc:14845
Handle< FixedArray > strings_
Definition: objects.cc:14872
uint32_t Hash() OVERRIDE
Definition: objects.cc:14857
static const char * Name(Value tok)
Definition: token.h:180
static const int kNotFound
Definition: transitions.h:116
Map * GetTarget(int transition_number)
static Handle< TransitionArray > CopyInsert(Handle< Map > map, Handle< Name > name, Handle< Map > target, SimpleTransitionFlag flag)
Definition: transitions.cc:88
FixedArray * GetPrototypeTransitions()
TraversableMap * ChildIteratorNext(Object *constructor)
Definition: objects.cc:7224
void SetParent(TraversableMap *parent)
Definition: objects.cc:7213
TraversableMap * GetAndResetParent()
Definition: objects.cc:7216
virtual Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:13683
bool IsMatch(Object *o) OVERRIDE
Definition: objects.cc:14635
Handle< Object > AsHandle(Isolate *isolate) OVERRIDE
Definition: objects.cc:14649
TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
Definition: objects.cc:14606
uint32_t HashForObject(Object *key) OVERRIDE
Definition: objects.cc:14644
static Object * RawUninitializedSentinel(Heap *heap)
bool NowIs(TypeImpl *that)
Definition: types.cc:472
static TypeHandle Constant(i::Handle< i::Object > value, Region *region)
Definition: types.h:330
static TypeImpl * cast(typename Config::Base *object)
Definition: types-inl.h:20
void PrintTo(OStream &os, PrintDimension dim=BOTH_DIMS)
Definition: types.cc:1034
static TypeHandle Class(i::Handle< i::Map > map, Region *region)
Definition: types.h:327
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region *reg)
Definition: types.cc:737
static MUST_USE_RESULT Handle< UnseededNumberDictionary > Set(Handle< UnseededNumberDictionary > dictionary, uint32_t key, Handle< Object > value)
Definition: objects.cc:15145
static MUST_USE_RESULT Handle< UnseededNumberDictionary > AtNumberPut(Handle< UnseededNumberDictionary > dictionary, uint32_t key, Handle< Object > value)
Definition: objects.cc:15117
static MUST_USE_RESULT Handle< UnseededNumberDictionary > AddNumberEntry(Handle< UnseededNumberDictionary > dictionary, uint32_t key, Handle< Object > value)
Definition: objects.cc:15099
Vector< T > SubVector(int from, int to)
Definition: vector.h:33
T * start() const
Definition: vector.h:47
int length() const
Definition: vector.h:41
static Vector< T > New(int length)
Definition: vector.h:27
static const char *const kTagNames[kNumberOfSyncTags]
Definition: objects.h:10712
static const char *const kTags[kNumberOfSyncTags]
Definition: objects.h:10711
void AddEntry(int entry, Handle< Object > key, Handle< Object > value)
Definition: objects.cc:15398
Object * Lookup(Handle< Object > key)
Definition: objects.cc:15367
static MUST_USE_RESULT Handle< WeakHashTable > Put(Handle< WeakHashTable > table, Handle< Object > key, Handle< Object > value)
Definition: objects.cc:15376
#define OVERRIDE
#define PROFILE(IsolateGetter, Call)
Definition: cpu-profiler.h:181
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions true
enable harmony numeric literals(0o77, 0b11)") DEFINE_BOOL(harmony_object_literals
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_BOOL(profile_deserialization
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes A file to write the raw context snapshot bytes Write V8 startup blob file(mksnapshot only)") DEFINE_BOOL(profile_hydrogen_code_stub_compilation
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
Definition: isolate.h:123
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T)
Definition: isolate.h:135
#define RETURN_ON_EXCEPTION(isolate, call, T)
Definition: isolate.h:165
#define THROW_NEW_ERROR(isolate, call, T)
Definition: isolate.h:138
#define RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, T)
Definition: isolate.h:120
#define RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, value)
Definition: isolate.h:111
#define LOG(isolate, Call)
Definition: log.h:69
#define UNREACHABLE()
Definition: logging.h:30
#define CHECK_EQ(expected, value)
Definition: logging.h:169
#define DCHECK_LE(v1, v2)
Definition: logging.h:210
#define CHECK(condition)
Definition: logging.h:36
#define CHECK_NE(unexpected, value)
Definition: logging.h:173
#define DCHECK_NE(v1, v2)
Definition: logging.h:207
#define UNIMPLEMENTED()
Definition: logging.h:28
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
void USE(T)
Definition: macros.h:322
#define arraysize(array)
Definition: macros.h:86
#define V8PRIxPTR
Definition: macros.h:363
#define MUST_USE_RESULT
Definition: macros.h:266
unsigned short uint16_t
Definition: unicode.cc:23
int int32_t
Definition: unicode.cc:24
uint32_t RoundUpToPowerOfTwo32(uint32_t value)
Definition: bits.cc:12
bool IsPowerOfTwo32(uint32_t value)
Definition: bits.h:77
static int comparator(const HeapObjectInfo *a, const HeapObjectInfo *b)
Vector< const char > CStrVector(const char *data)
Definition: vector.h:158
const int kPointerSize
Definition: globals.h:129
void CopyChars(sinkchar *dest, const sourcechar *src, int chars)
Definition: utils.h:1258
bool IsFastHoleyElementsKind(ElementsKind kind)
uint32_t DoubleToUint32(double x)
Definition: conversions.h:93
bool Is(Object *obj)
static void ShrinkInstanceSize(Map *map, void *data)
Definition: objects.cc:9971
static bool FilterKey(Object *key, PropertyAttributes filter)
Definition: objects.cc:5628
static Handle< Object > ExternalArrayIntSetter(Isolate *isolate, Handle< ExternalArrayClass > receiver, uint32_t index, Handle< Object > value)
Definition: objects.cc:14447
ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number)
@ kSeqStringTag
Definition: objects.h:563
@ kConsStringTag
Definition: objects.h:564
@ kSlicedStringTag
Definition: objects.h:566
@ kExternalStringTag
Definition: objects.h:565
bool IsExternalArrayElementsKind(ElementsKind kind)
Definition: elements-kind.h:95
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
Definition: assert-scope.h:110
@ SKIP_WRITE_BARRIER
Definition: objects.h:235
@ UPDATE_WRITE_BARRIER
Definition: objects.h:235
uint32_t ComputeLongHash(uint64_t key)
Definition: utils.h:262
bool CanTransitionToMoreGeneralFastElementsKind(ElementsKind elements_kind, bool allow_only_packed)
PrototypeOptimizationMode
Definition: objects.h:258
@ FAST_PROTOTYPE
Definition: objects.h:258
@ REGULAR_PROTOTYPE
Definition: objects.h:258
static Map * FindClosestElementsTransition(Map *map, ElementsKind to_kind)
Definition: objects.cc:3235
static int min(int a, int b)
Definition: liveedit.cc:273
static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind)
Definition: objects.cc:16277
static LifetimePosition Min(LifetimePosition a, LifetimePosition b)
@ DEFINE_PROPERTY
Definition: objects.h:1552
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
const uint32_t kTwoByteStringTag
Definition: objects.h:556
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
int CompareChars(const lchar *lhs, const rchar *rhs, int chars)
Definition: utils.h:705
bool IsTransitionElementsKind(ElementsKind kind)
static Handle< Object > GetPrimitiveValue(const PrimitiveValueDescriptor &descriptor, char *ptr, Isolate *isolate)
Definition: objects.cc:282
Handle< Object > CacheInitialJSArrayMaps(Handle< Context > native_context, Handle< Map > initial_map)
Definition: objects.cc:9355
void CheckArrayAbuse(Handle< JSObject > obj, const char *op, uint32_t key, bool allow_appending)
Definition: elements.cc:496
@ INSERT_TRANSITION
Definition: objects.h:263
@ OMIT_TRANSITION
Definition: objects.h:264
static void CalculateLineEndsImpl(Isolate *isolate, List< int > *line_ends, Vector< const SourceChar > src, bool include_ending_line)
Definition: objects.cc:8460
@ ALLOW_AS_CONSTANT
Definition: objects.h:240
unsigned int FastD2UI(double x)
static void ClearWrapperCacheWeakCallback(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: objects.cc:9723
@ USE_DEFAULT_MINIMUM_CAPACITY
Definition: globals.h:385
@ USE_CUSTOM_MINIMUM_CAPACITY
Definition: globals.h:386
const int kDoubleSize
Definition: globals.h:127
static Handle< Map > AddMissingElementsTransitions(Handle< Map > map, ElementsKind to_kind)
Definition: objects.cc:3294
@ DISALLOW_NULLS
Definition: objects.h:8337
SimpleTransitionFlag
Definition: objects.h:277
@ FULL_TRANSITION
Definition: objects.h:279
@ SIMPLE_TRANSITION
Definition: objects.h:278
ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind, bool allow_only_packed)
static bool CheckEquivalent(Map *first, Map *second)
Definition: objects.cc:9037
static Handle< Object > GetDeclaredAccessorProperty(Handle< Object > receiver, Handle< DeclaredAccessorInfo > info, Isolate *isolate)
Definition: objects.cc:329
static Handle< Object > PerformCompare(const BitmaskCompareDescriptor &descriptor, char *ptr, Isolate *isolate)
Definition: objects.cc:243
void MemsetPointer(T **dest, U *value, int counter)
Definition: utils.h:1183
bool IsHoleyElementsKind(ElementsKind kind)
int SNPrintF(Vector< char > str, const char *format,...)
Definition: utils.cc:105
int ExtraICState
Definition: objects.h:305
const int kElementsKindCount
Definition: elements-kind.h:66
int ToNumber(Register reg)
kSerializedDataOffset Object
Definition: objects-inl.h:5322
const int kMaxInt
Definition: globals.h:109
static bool CodeListContains(Object *head, Code *code)
Definition: objects.cc:11512
static void InsertionSortPairs(FixedArray *content, FixedArray *numbers, int len)
Definition: objects.cc:13278
const int kPointerSizeLog2
Definition: globals.h:147
double FastI2D(int x)
Definition: conversions.h:64
@ LAST_NONCALLABLE_SPEC_OBJECT_TYPE
Definition: objects.h:785
@ JS_REGEXP_TYPE
Definition: objects.h:748
@ FIRST_NONCALLABLE_SPEC_OBJECT_TYPE
Definition: objects.h:784
@ FIXED_DOUBLE_ARRAY_TYPE
Definition: objects.h:692
@ JS_ARRAY_TYPE
Definition: objects.h:738
@ FIXED_ARRAY_TYPE
Definition: objects.h:717
@ JS_MODULE_TYPE
Definition: objects.h:734
@ JS_OBJECT_TYPE
Definition: objects.h:731
@ FREE_SPACE_TYPE
Definition: objects.h:673
@ JS_GENERATOR_OBJECT_TYPE
Definition: objects.h:733
@ BYTE_ARRAY_TYPE
Definition: objects.h:672
@ JS_WEAK_SET_TYPE
Definition: objects.h:747
@ ODDBALL_TYPE
Definition: objects.h:663
@ ALLOCATION_SITE_TYPE
Definition: objects.h:707
@ MUTABLE_HEAP_NUMBER_TYPE
Definition: objects.h:670
@ HEAP_NUMBER_TYPE
Definition: objects.h:669
@ JS_MESSAGE_OBJECT_TYPE
Definition: objects.h:729
@ JS_FUNCTION_TYPE
Definition: objects.h:749
@ SHARED_FUNCTION_INFO_TYPE
Definition: objects.h:719
@ BREAK_POINT_INFO_TYPE
Definition: objects.h:716
@ JS_WEAK_MAP_TYPE
Definition: objects.h:746
@ FAST_HOLEY_DOUBLE_ELEMENTS
Definition: elements-kind.h:27
@ SLOPPY_ARGUMENTS_ELEMENTS
Definition: elements-kind.h:31
@ TERMINAL_FAST_ELEMENTS_KIND
Definition: elements-kind.h:63
@ FAST_HOLEY_SMI_ELEMENTS
Definition: elements-kind.h:17
@ FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
Definition: elements-kind.h:59
static void FreezeDictionary(Dictionary *dictionary)
Definition: objects.cc:5215
const char * ElementsKindToString(ElementsKind kind)
bool IsFastDoubleElementsKind(ElementsKind kind)
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
const uint32_t kOneByteStringTag
Definition: objects.h:557
static uint32_t ObjectAddressForHashing(Object *object)
Definition: objects.cc:9013
@ ROBUST_STRING_TRAVERSAL
Definition: objects.h:8338
static bool AnWord(String *str)
Definition: objects.cc:940
static To * CheckedCast(void *from)
Definition: objects.cc:236
int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind)
@ NO_MARKING_PARITY
Definition: objects.h:298
bool IsFastPackedElementsKind(ElementsKind kind)
const Register pc
const bool FLAG_enable_slow_asserts
Definition: checks.h:31
OStream & operator<<(OStream &os, const BasicBlockProfiler &p)
static void EndPerformSplice(Handle< JSArray > object)
Definition: objects.cc:11154
static const int kInvalidEnumCacheSentinel
static Handle< FixedArray > GetEnumPropertyKeys(Handle< JSObject > object, bool cache_result)
Definition: objects.cc:5699
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
static bool ContainsMap(MapHandleList *maps, Handle< Map > map)
Definition: objects.cc:3196
const int kFastElementsKindCount
Definition: elements-kind.h:67
static bool FindAllCanWriteHolder(LookupIterator *it)
Definition: objects.cc:613
const char * GetBailoutReason(BailoutReason reason)
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
ElementsKind GetNextTransitionElementsKind(ElementsKind kind)
static void GetMinInobjectSlack(Map *map, void *data)
Definition: objects.cc:9963
const uint32_t kStringRepresentationMask
Definition: objects.h:561
static Handle< FixedArray > ReduceFixedArrayTo(Handle< FixedArray > array, int length)
Definition: objects.cc:5687
static bool IsCodeEquivalent(Code *code, Code *recompiled)
Definition: objects.cc:9855
bool IsTerminalElementsKind(ElementsKind kind)
static int AppendUniqueCallbacks(NeanderArray *callbacks, Handle< typename T::Array > array, int valid_descriptors)
Definition: objects.cc:3099
int32_t NumberToInt32(Object *number)
Definition: conversions.h:189
byte * Address
Definition: globals.h:101
bool IsFastElementsKind(ElementsKind kind)
static bool CompareRawStringContents(const Char *const a, const Char *const b, int length)
Definition: objects.cc:8519
kSerializedDataOffset kPrototypeTemplateOffset kIndexedPropertyHandlerOffset kInstanceCallHandlerOffset kInternalFieldCountOffset dependent_code
Definition: objects-inl.h:5353
static uint32_t Hash(RegisteredExtension *extension)
static const int kMaxNumberOfDescriptors
void PrintF(const char *format,...)
Definition: utils.cc:80
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: utils.h:1100
int32_t DoubleToInt32(double x)
bool IsDictionaryElementsKind(ElementsKind kind)
Definition: elements-kind.h:85
const int kHeapObjectTag
Definition: v8.h:5737
uint32_t NumberToUint32(Object *number)
Definition: conversions.h:195
int FastD2I(double x)
Definition: conversions.h:57
static Smi * GenerateIdentityHash(Isolate *isolate)
Definition: objects.cc:4519
static Code::Age EffectiveAge(Code::Age age)
Definition: objects.cc:10463
int TenToThe(int exponent)
Definition: utils.h:733
kFeedbackVectorOffset flag
Definition: objects-inl.h:5418
static int ArchiveSpacePerThread()
Definition: v8threads.cc:171
static bool GetOldValue(Isolate *isolate, Handle< JSObject > object, uint32_t index, List< Handle< Object > > *old_values, List< uint32_t > *indices)
Definition: objects.cc:11099
const int kMaxKeyedPolymorphism
Definition: ic-state.h:14
static Handle< SeededNumberDictionary > CopyFastElementsToDictionary(Handle< FixedArrayBase > array, int length, Handle< SeededNumberDictionary > dictionary)
Definition: objects.cc:4429
@ kDescriptorBitmaskCompare
Definition: objects.h:10155
@ kDescriptorPointerDereference
Definition: objects.h:10159
@ kDescriptorPointerShift
Definition: objects.h:10160
@ kDescriptorObjectDereference
Definition: objects.h:10158
@ kDescriptorPrimitiveValue
Definition: objects.h:10157
@ kDescriptorReturnObject
Definition: objects.h:10161
@ kDescriptorPointerCompare
Definition: objects.h:10156
@ SKIP_ICACHE_FLUSH
Definition: assembler.h:293
bool IsFixedTypedArrayElementsKind(ElementsKind kind)
double FastUI2D(unsigned x)
Definition: conversions.h:72
uint16_t uc16
Definition: globals.h:184
static void BeginPerformSplice(Handle< JSArray > object)
Definition: objects.cc:11141
static bool ContainsOnlyValidKeys(Handle< FixedArray > array)
Definition: objects.cc:5677
const uint32_t kMaxUInt32
Definition: globals.h:120
bool IsFastSmiElementsKind(ElementsKind kind)
bool StringToArrayIndex(Stream *stream, uint32_t *index)
Definition: utils.h:1431
static bool UpdateGetterSetterInDictionary(SeededNumberDictionary *dictionary, uint32_t index, Object *getter, Object *setter, PropertyAttributes attributes)
Definition: objects.cc:5912
@ ACCESSOR_GETTER
Definition: objects.h:1558
@ ACCESSOR_SETTER
Definition: objects.h:1559
bool IsTransitionableFastElementsKind(ElementsKind from_kind)
void MemCopy(void *dest, const void *src, size_t size)
Definition: utils.h:350
ElementsKind GetInitialFastElementsKind()
Definition: elements-kind.h:78
uint64_t double_to_uint64(double d)
Definition: double.h:14
static bool FindAllCanReadHolder(LookupIterator *it)
Definition: objects.cc:574
static Handle< Smi > GetOrCreateIdentityHashHelper(Handle< ProxyType > proxy)
Definition: objects.cc:4542
@ OWN_DESCRIPTORS
Definition: objects.h:287
@ ALL_DESCRIPTORS
Definition: objects.h:286
static void EnqueueSpliceRecord(Handle< JSArray > object, uint32_t index, Handle< JSArray > deleted, uint32_t add_count)
Definition: objects.cc:11120
void CopyBytes(uint8_t *target, uint8_t *source)
@ UNINITIALIZED
Definition: globals.h:446
@ PROTOTYPE_FAILURE
Definition: globals.h:452
@ PREMONOMORPHIC
Definition: globals.h:448
static Handle< T > MaybeNull(T *p)
Definition: objects.cc:3206
@ INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE
Definition: heap.h:513
bool IsFastObjectElementsKind(ElementsKind kind)
void HeapSortPairs(FixedArray *content, FixedArray *numbers, int len)
Definition: objects.cc:13293
PropertyNormalizationMode
Definition: objects.h:247
@ KEEP_INOBJECT_PROPERTIES
Definition: objects.h:249
@ CLEAR_INOBJECT_PROPERTIES
Definition: objects.h:248
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ None
Definition: v8.h:2211
@ kDescriptorInt8Type
Definition: v8.h:3939
@ kDescriptorUint16Type
Definition: v8.h:3940
@ kDescriptorDoubleType
Definition: v8.h:3942
@ kDescriptorFloatType
Definition: v8.h:3942
@ kDescriptorInt16Type
Definition: v8.h:3940
@ kDescriptorUint8Type
Definition: v8.h:3939
@ kDescriptorUint32Type
Definition: v8.h:3941
@ kDescriptorInt32Type
Definition: v8.h:3941
@ kDescriptorBoolType
Definition: v8.h:3938
void(* AccessorNameSetterCallback)(Local< Name > property, Local< Value > value, const PropertyCallbackInfo< void > &info)
Definition: v8.h:2257
void(* IndexedPropertyGetterCallback)(uint32_t index, const PropertyCallbackInfo< Value > &info)
Returns the value of the property if the getter intercepts the request.
Definition: v8.h:3474
void(* IndexedPropertySetterCallback)(uint32_t index, Local< Value > value, const PropertyCallbackInfo< Value > &info)
Returns the value if the setter intercepts the request.
Definition: v8.h:3483
void(* NamedPropertyGetterCallback)(Local< String > property, const PropertyCallbackInfo< Value > &info)
NamedProperty[Getter|Setter] are used as interceptors on object.
Definition: v8.h:3427
void(* IndexedPropertyDeleterCallback)(uint32_t index, const PropertyCallbackInfo< Boolean > &info)
Returns a non-empty handle if the deleter intercepts the request.
Definition: v8.h:3503
void(* NamedPropertyEnumeratorCallback)(const PropertyCallbackInfo< Array > &info)
Returns an array containing the names of the properties the named property getter intercepts.
Definition: v8.h:3466
Maybe< T > maybe(T t)
Definition: v8.h:902
void(* AccessorNameGetterCallback)(Local< Name > property, const PropertyCallbackInfo< Value > &info)
Definition: v8.h:2248
void(* NamedPropertySetterCallback)(Local< String > property, Local< Value > value, const PropertyCallbackInfo< Value > &info)
Returns the value if the setter intercepts the request.
Definition: v8.h:3436
void(* IndexedPropertyQueryCallback)(uint32_t index, const PropertyCallbackInfo< Integer > &info)
Returns a non-empty handle if the interceptor intercepts the request.
Definition: v8.h:3493
void(* NamedPropertyDeleterCallback)(Local< String > property, const PropertyCallbackInfo< Boolean > &info)
Returns a non-empty handle if the deleter intercepts the request.
Definition: v8.h:3457
ExternalArrayType
Definition: v8.h:2217
void(* NamedPropertyQueryCallback)(Local< String > property, const PropertyCallbackInfo< Integer > &info)
Returns a non-empty handle if the interceptor intercepts the request.
Definition: v8.h:3447
void(* IndexedPropertyEnumeratorCallback)(const PropertyCallbackInfo< Array > &info)
Returns an array containing the indices of the properties the indexed property getter intercepts.
Definition: v8.h:3512
@ ACCESS_SET
Definition: v8.h:3521
@ ACCESS_HAS
Definition: v8.h:3522
@ ACCESS_KEYS
Definition: v8.h:3524
@ ACCESS_GET
Definition: v8.h:3520
@ ACCESS_DELETE
Definition: v8.h:3523
Handle< Primitive > Undefined(Isolate *isolate)
Definition: v8.h:6836
#define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)
#define DECLARE_TAG(ignore1, name, ignore2)
Definition: objects.cc:10032
#define HANDLE_CODE_AGE(AGE)
#define CASE(name)
#define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)
#define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)
#define MAKE_STRUCT_CASE(NAME, Name, name)
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)
#define STRUCT_LIST(V)
Definition: objects.h:515
#define CODE_KIND_LIST(V)
Definition: objects.h:4950
#define TYPED_ARRAYS(V)
Definition: objects.h:4433
#define VISITOR_SYNCHRONIZATION_TAGS_LIST(V)
Definition: objects.h:10684
PropertyAttributes
@ DONT_ENUM
@ SYMBOLIC
@ DONT_DELETE
@ ABSENT
@ NONE
@ PRIVATE_SYMBOL
@ DONT_SHOW
@ FROZEN
@ READ_ONLY
@ STRING
#define DCHECK_OBJECT_ALIGNED(address)
Definition: spaces.h:81
A simple Maybe type, representing an object which may or may not have a value.
Definition: v8.h:890
T value
Definition: v8.h:896
bool has_value
Definition: v8.h:895
const Object * value
Definition: objects.h:1238
Assembler * origin
Definition: globals.h:423
struct BitmaskCompareDescriptor bitmask_compare_descriptor
Definition: objects.h:10196
struct PrimitiveValueDescriptor primitive_value_descriptor
Definition: objects.h:10198
struct PointerCompareDescriptor pointer_compare_descriptor
Definition: objects.h:10197
struct PointerShiftDescriptor pointer_shift_descriptor
Definition: objects.h:10200
struct ObjectDerefenceDescriptor object_dereference_descriptor
Definition: objects.h:10199
static void Insert(Handle< Name > key, Handle< AccessorInfo > entry, int valid_descriptors, Handle< DescriptorArray > array)
Definition: objects.cc:3142
static bool Contains(Handle< Name > key, Handle< AccessorInfo > entry, int valid_descriptors, Handle< DescriptorArray > array)
Definition: objects.cc:3135
static const char * AllocationIndexToString(int index)
EnumIndexComparator(NameDictionary *dict)
Definition: objects.cc:15209
static bool Contains(Handle< Name > key, Handle< AccessorInfo > entry, int valid_descriptors, Handle< FixedArray > array)
Definition: objects.cc:3155
static void Insert(Handle< Name > key, Handle< AccessorInfo > entry, int valid_descriptors, Handle< FixedArray > array)
Definition: objects.cc:3164
v8::DeclaredAccessorDescriptorDataType data_type
Definition: objects.h:10178
const SharedFunctionInfo * value
Definition: objects.h:7074
#define T(name, string, precedence)
Definition: token.cc:25
#define STATIC_CHAR_VECTOR(x)
Definition: vector.h:154