objects-inl.h 115 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7 8 9 10
//
// Review notes:
//
// - The use of macros in these inline functions may seem superfluous
// but it is absolutely needed to make sure gcc generates optimal
// code. gcc is not happy when attempting to inline too deep.
//
11 12 13 14

#ifndef V8_OBJECTS_INL_H_
#define V8_OBJECTS_INL_H_

15
#include "src/base/atomicops.h"
16
#include "src/base/bits.h"
17
#include "src/base/tsan.h"
18
#include "src/builtins/builtins.h"
19
#include "src/contexts-inl.h"
20
#include "src/conversions-inl.h"
21
#include "src/factory.h"
22
#include "src/feedback-vector-inl.h"
23
#include "src/field-index-inl.h"
24
#include "src/field-type.h"
25
#include "src/handles-inl.h"
26 27
#include "src/heap/heap-inl.h"
#include "src/heap/heap.h"
28
#include "src/isolate-inl.h"
29 30
#include "src/isolate.h"
#include "src/keys.h"
31
#include "src/layout-descriptor-inl.h"
32 33
#include "src/lookup-cache-inl.h"
#include "src/lookup.h"
34
#include "src/objects.h"
35
#include "src/objects/arguments-inl.h"
36
#include "src/objects/bigint.h"
37
#include "src/objects/data-handler-inl.h"
38
#include "src/objects/fixed-array-inl.h"
39
#include "src/objects/hash-table-inl.h"
40
#include "src/objects/hash-table.h"
41
#include "src/objects/js-array-inl.h"
42
#include "src/objects/js-collection-inl.h"
43
#include "src/objects/js-regexp-inl.h"
44
#include "src/objects/literal-objects.h"
45
#include "src/objects/module-inl.h"
46
#include "src/objects/regexp-match-info.h"
47
#include "src/objects/scope-info.h"
48
#include "src/objects/template-objects.h"
49
#include "src/property.h"
50
#include "src/prototype.h"
51
#include "src/transitions-inl.h"
52
#include "src/v8memory.h"
53

54 55 56
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

57 58
namespace v8 {
namespace internal {
59 60 61 62 63 64

PropertyDetails::PropertyDetails(Smi* smi) {
  value_ = smi->value();
}


65
Smi* PropertyDetails::AsSmi() const {
66 67 68 69
  // Ensure the upper 2 bits have the same value by sign extending it. This is
  // necessary to be able to use the 31st bit of the property details.
  int value = value_ << 1;
  return Smi::FromInt(value >> 1);
70 71 72
}


73
int PropertyDetails::field_width_in_words() const {
74
  DCHECK_EQ(location(), kField);
75 76 77 78 79
  if (!FLAG_unbox_double_fields) return 1;
  if (kDoubleSize == kPointerSize) return 1;
  return representation().IsDouble() ? kDoubleSize / kPointerSize : 1;
}

80
TYPE_CHECKER(BigInt, BIGINT_TYPE)
81
TYPE_CHECKER(BreakPoint, TUPLE2_TYPE)
82
TYPE_CHECKER(BreakPointInfo, TUPLE2_TYPE)
83
TYPE_CHECKER(CallHandlerInfo, TUPLE3_TYPE)
84
TYPE_CHECKER(Cell, CELL_TYPE)
85
TYPE_CHECKER(ConstantElementsPair, TUPLE2_TYPE)
86
TYPE_CHECKER(CoverageInfo, FIXED_ARRAY_TYPE)
87
TYPE_CHECKER(DescriptorArray, DESCRIPTOR_ARRAY_TYPE)
88
TYPE_CHECKER(FeedbackVector, FEEDBACK_VECTOR_TYPE)
89 90
TYPE_CHECKER(Foreign, FOREIGN_TYPE)
TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
91
TYPE_CHECKER(HashTable, HASH_TABLE_TYPE)
92
TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
93
TYPE_CHECKER(JSAsyncFromSyncIterator, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE)
94
TYPE_CHECKER(JSAsyncGeneratorObject, JS_ASYNC_GENERATOR_OBJECT_TYPE)
95 96 97 98 99 100 101 102 103 104 105 106 107
TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE)
TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
TYPE_CHECKER(JSDate, JS_DATE_TYPE)
TYPE_CHECKER(JSError, JS_ERROR_TYPE)
TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE)
TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE)
TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
TYPE_CHECKER(Oddball, ODDBALL_TYPE)
108 109
TYPE_CHECKER(PreParsedScopeData, TUPLE2_TYPE)
TYPE_CHECKER(PropertyArray, PROPERTY_ARRAY_TYPE)
110
TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
111
TYPE_CHECKER(PropertyDescriptorObject, FIXED_ARRAY_TYPE)
112 113
TYPE_CHECKER(SmallOrderedHashMap, SMALL_ORDERED_HASH_MAP_TYPE)
TYPE_CHECKER(SmallOrderedHashSet, SMALL_ORDERED_HASH_SET_TYPE)
114
TYPE_CHECKER(SourcePositionTableWithFrameCache, TUPLE2_TYPE)
115 116
TYPE_CHECKER(TemplateMap, HASH_TABLE_TYPE)
TYPE_CHECKER(TemplateObjectDescription, TUPLE3_TYPE)
117
TYPE_CHECKER(TransitionArray, TRANSITION_ARRAY_TYPE)
118 119 120 121
TYPE_CHECKER(WasmInstanceObject, WASM_INSTANCE_TYPE)
TYPE_CHECKER(WasmMemoryObject, WASM_MEMORY_TYPE)
TYPE_CHECKER(WasmModuleObject, WASM_MODULE_TYPE)
TYPE_CHECKER(WasmTableObject, WASM_TABLE_TYPE)
122 123 124 125 126 127 128 129
TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE)

#define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \
  TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
#undef TYPED_ARRAY_TYPE_CHECKER


130
bool HeapObject::IsFixedArrayBase() const {
131
  return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
132 133
}

134 135
bool HeapObject::IsFixedArray() const {
  InstanceType instance_type = map()->instance_type();
136 137
  return instance_type >= FIRST_FIXED_ARRAY_TYPE &&
         instance_type <= LAST_FIXED_ARRAY_TYPE;
138 139
}

140 141 142
bool HeapObject::IsSloppyArgumentsElements() const {
  return IsFixedArrayExact();
}
143

144 145 146 147
bool HeapObject::IsJSSloppyArgumentsObject() const {
  return IsJSArgumentsObject();
}

148 149 150 151 152
bool HeapObject::IsJSGeneratorObject() const {
  return map()->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
         IsJSAsyncGeneratorObject();
}

153 154 155
bool HeapObject::IsBoilerplateDescription() const {
  return IsFixedArrayExact();
}
156

157
bool HeapObject::IsClassBoilerplate() const { return IsFixedArrayExact(); }
158

159
bool HeapObject::IsExternal() const {
160
  return map()->FindRootMap() == GetHeap()->external_map();
161 162
}

163 164 165 166 167
#define IS_TYPE_FUNCTION_DEF(type_)                               \
  bool Object::Is##type_() const {                                \
    return IsHeapObject() && HeapObject::cast(this)->Is##type_(); \
  }
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF)
168
#undef IS_TYPE_FUNCTION_DEF
169

170 171 172 173 174 175 176 177 178
#define IS_TYPE_FUNCTION_DEF(Type, Value)             \
  bool Object::Is##Type(Isolate* isolate) const {     \
    return this == isolate->heap()->Value();          \
  }                                                   \
  bool HeapObject::Is##Type(Isolate* isolate) const { \
    return this == isolate->heap()->Value();          \
  }
ODDBALL_LIST(IS_TYPE_FUNCTION_DEF)
#undef IS_TYPE_FUNCTION_DEF
179

180 181 182 183 184 185 186 187 188 189
bool Object::IsNullOrUndefined(Isolate* isolate) const {
  Heap* heap = isolate->heap();
  return this == heap->null_value() || this == heap->undefined_value();
}

bool HeapObject::IsNullOrUndefined(Isolate* isolate) const {
  Heap* heap = isolate->heap();
  return this == heap->null_value() || this == heap->undefined_value();
}

190 191
bool HeapObject::IsString() const {
  return map()->instance_type() < FIRST_NONSTRING_TYPE;
192
}
193

194 195
bool HeapObject::IsName() const {
  return map()->instance_type() <= LAST_NAME_TYPE;
196 197
}

198
bool HeapObject::IsUniqueName() const {
199
  return IsInternalizedString() || IsSymbol();
200 201
}

202
bool HeapObject::IsFunction() const {
203
  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
204
  return map()->instance_type() >= FIRST_FUNCTION_TYPE;
205 206
}

207
bool HeapObject::IsCallable() const { return map()->is_callable(); }
208

209
bool HeapObject::IsConstructor() const { return map()->is_constructor(); }
210

211
bool HeapObject::IsTemplateInfo() const {
212 213 214
  return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
}

215 216
bool HeapObject::IsInternalizedString() const {
  uint32_t type = map()->instance_type();
217 218 219
  STATIC_ASSERT(kNotInternalizedTag != 0);
  return (type & (kIsNotStringMask | kIsNotInternalizedMask)) ==
      (kStringTag | kInternalizedTag);
220 221
}

222
bool HeapObject::IsConsString() const {
223 224 225 226
  if (!IsString()) return false;
  return StringShape(String::cast(this)).IsCons();
}

227 228 229 230 231
bool HeapObject::IsThinString() const {
  if (!IsString()) return false;
  return StringShape(String::cast(this)).IsThin();
}

232
bool HeapObject::IsSlicedString() const {
233 234
  if (!IsString()) return false;
  return StringShape(String::cast(this)).IsSliced();
235 236
}

237
bool HeapObject::IsSeqString() const {
238 239
  if (!IsString()) return false;
  return StringShape(String::cast(this)).IsSequential();
240 241
}

242
bool HeapObject::IsSeqOneByteString() const {
243
  if (!IsString()) return false;
244
  return StringShape(String::cast(this)).IsSequential() &&
245
         String::cast(this)->IsOneByteRepresentation();
246 247
}

248
bool HeapObject::IsSeqTwoByteString() const {
249
  if (!IsString()) return false;
250
  return StringShape(String::cast(this)).IsSequential() &&
251
         String::cast(this)->IsTwoByteRepresentation();
252 253
}

254
bool HeapObject::IsExternalString() const {
255 256
  if (!IsString()) return false;
  return StringShape(String::cast(this)).IsExternal();
257 258
}

259
bool HeapObject::IsExternalOneByteString() const {
260
  if (!IsString()) return false;
261
  return StringShape(String::cast(this)).IsExternal() &&
262
         String::cast(this)->IsOneByteRepresentation();
263 264
}

265
bool HeapObject::IsExternalTwoByteString() const {
266
  if (!IsString()) return false;
267
  return StringShape(String::cast(this)).IsExternal() &&
268
         String::cast(this)->IsTwoByteRepresentation();
269 270
}

271
bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); }
272

273 274
bool Object::IsNumeric() const { return IsNumber() || IsBigInt(); }

275 276 277
bool HeapObject::IsFiller() const {
  InstanceType instance_type = map()->instance_type();
  return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
278 279
}

280 281 282 283
bool HeapObject::IsFixedTypedArrayBase() const {
  InstanceType instance_type = map()->instance_type();
  return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
          instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
284 285
}

286 287 288
bool HeapObject::IsJSReceiver() const {
  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
  return map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
289 290
}

291 292 293
bool HeapObject::IsJSObject() const {
  STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
  return map()->IsJSObjectMap();
294 295
}

296
bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); }
297

298 299 300 301 302 303 304 305 306 307 308 309
bool HeapObject::IsJSMapIterator() const {
  InstanceType instance_type = map()->instance_type();
  return (instance_type >= JS_MAP_KEY_ITERATOR_TYPE &&
          instance_type <= JS_MAP_VALUE_ITERATOR_TYPE);
}

bool HeapObject::IsJSSetIterator() const {
  InstanceType instance_type = map()->instance_type();
  return (instance_type == JS_SET_VALUE_ITERATOR_TYPE ||
          instance_type == JS_SET_KEY_VALUE_ITERATOR_TYPE);
}

310 311 312 313
bool HeapObject::IsJSArrayIterator() const {
  InstanceType instance_type = map()->instance_type();
  return (instance_type >= FIRST_ARRAY_ITERATOR_TYPE &&
          instance_type <= LAST_ARRAY_ITERATOR_TYPE);
314 315
}

316 317
bool HeapObject::IsJSWeakCollection() const {
  return IsJSWeakMap() || IsJSWeakSet();
318 319
}

320
bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
321

322 323
bool HeapObject::IsPromiseCapability() const { return IsTuple3(); }

324 325
bool HeapObject::IsEnumCache() const { return IsTuple2(); }

326
bool HeapObject::IsFrameArray() const { return IsFixedArrayExact(); }
327

328
bool HeapObject::IsArrayList() const { return IsFixedArrayExact(); }
329

330
bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArrayExact(); }
331

332
bool Object::IsLayoutDescriptor() const { return IsSmi() || IsByteArray(); }
333

334
bool HeapObject::IsFeedbackMetadata() const { return IsFixedArrayExact(); }
335

336
bool HeapObject::IsDeoptimizationData() const {
337
  // Must be a fixed array.
338
  if (!IsFixedArrayExact()) return false;
339

340 341 342 343 344 345
  // There's no sure way to detect the difference between a fixed array and
  // a deoptimization data array.  Since this is used for asserts we can
  // check that the length is zero or else the fixed size plus a multiple of
  // the entry size.
  int length = FixedArray::cast(this)->length();
  if (length == 0) return true;
346

347 348
  length -= DeoptimizationData::kFirstDeoptEntryIndex;
  return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0;
349 350
}

351
bool HeapObject::IsHandlerTable() const {
352
  if (!IsFixedArrayExact()) return false;
353 354 355
  // There's actually no way to see the difference between a fixed array and
  // a handler table array.
  return true;
356 357
}

358
bool HeapObject::IsTemplateList() const {
359
  if (!IsFixedArrayExact()) return false;
360 361 362 363
  // There's actually no way to see the difference between a fixed array and
  // a template list.
  if (FixedArray::cast(this)->length() < 1) return false;
  return true;
364 365
}

366
bool HeapObject::IsDependentCode() const {
367
  if (!IsFixedArrayExact()) return false;
368 369 370
  // There's actually no way to see the difference between a fixed array and
  // a dependent codes array.
  return true;
371 372
}

373 374 375 376 377 378 379
bool HeapObject::IsContext() const {
  Map* map = this->map();
  Heap* heap = GetHeap();
  return (
      map == heap->function_context_map() || map == heap->catch_context_map() ||
      map == heap->with_context_map() || map == heap->native_context_map() ||
      map == heap->block_context_map() || map == heap->module_context_map() ||
380
      map == heap->eval_context_map() || map == heap->script_context_map() ||
381
      map == heap->debug_evaluate_context_map());
382 383
}

384 385
bool HeapObject::IsNativeContext() const {
  return map() == GetHeap()->native_context_map();
386 387
}

388 389
bool HeapObject::IsScriptContextTable() const {
  return map() == GetHeap()->script_context_table_map();
390 391
}

392 393
bool HeapObject::IsScopeInfo() const {
  return map() == GetHeap()->scope_info_map();
394 395
}

396 397 398
template <>
inline bool Is<JSFunction>(Object* obj) {
  return obj->IsJSFunction();
399 400
}

401 402
bool HeapObject::IsAbstractCode() const {
  return IsBytecodeArray() || IsCode();
403 404
}

405 406 407
bool HeapObject::IsStringWrapper() const {
  return IsJSValue() && JSValue::cast(this)->value()->IsString();
}
408

409 410 411
bool HeapObject::IsBoolean() const {
  return IsOddball() &&
         ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
412 413
}

414 415 416
bool HeapObject::IsJSArrayBufferView() const {
  return IsJSDataView() || IsJSTypedArray();
}
417

418 419 420
bool HeapObject::IsWeakHashTable() const {
  return map() == GetHeap()->weak_hash_table_map();
}
421

422 423
bool HeapObject::IsDictionary() const {
  return IsHashTable() && this != GetHeap()->string_table();
424 425
}

426 427 428
bool HeapObject::IsGlobalDictionary() const {
  return map() == GetHeap()->global_dictionary_map();
}
429

430 431 432
bool HeapObject::IsNameDictionary() const {
  return map() == GetHeap()->name_dictionary_map();
}
433

434
bool HeapObject::IsNumberDictionary() const {
435
  return map() == GetHeap()->number_dictionary_map();
436
}
437

438 439 440
bool HeapObject::IsStringTable() const {
  return map() == GetHeap()->string_table_map();
}
441

442
bool HeapObject::IsStringSet() const { return IsHashTable(); }
443

444
bool HeapObject::IsObjectHashSet() const { return IsHashTable(); }
445

446 447
bool HeapObject::IsNormalizedMapCache() const {
  return NormalizedMapCache::IsNormalizedMapCache(this);
448 449
}

450
bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); }
451

452
bool HeapObject::IsMapCache() const { return IsHashTable(); }
453

454
bool HeapObject::IsObjectHashTable() const { return IsHashTable(); }
455

456 457
bool HeapObject::IsOrderedHashSet() const {
  return map() == GetHeap()->ordered_hash_set_map();
458
}
459

460 461 462
bool HeapObject::IsOrderedHashMap() const {
  return map() == GetHeap()->ordered_hash_map_map();
}
463

464 465 466 467
bool Object::IsSmallOrderedHashTable() const {
  return IsSmallOrderedHashSet() || IsSmallOrderedHashMap();
}

468 469 470
bool Object::IsPrimitive() const {
  return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap();
}
471

472 473 474 475 476 477 478 479 480
// static
Maybe<bool> Object::IsArray(Handle<Object> object) {
  if (object->IsSmi()) return Just(false);
  Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
  if (heap_object->IsJSArray()) return Just(true);
  if (!heap_object->IsJSProxy()) return Just(false);
  return JSProxy::IsArray(Handle<JSProxy>::cast(object));
}

481 482 483 484 485
bool HeapObject::IsJSGlobalProxy() const {
  bool result = map()->instance_type() == JS_GLOBAL_PROXY_TYPE;
  DCHECK(!result || map()->is_access_check_needed());
  return result;
}
486

487
bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); }
488

489 490 491 492 493
bool HeapObject::IsAccessCheckNeeded() const {
  if (IsJSGlobalProxy()) {
    const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
    JSGlobalObject* global = proxy->GetIsolate()->context()->global_object();
    return proxy->IsDetachedFrom(global);
494
  }
495 496
  return map()->is_access_check_needed();
}
497

498 499 500 501 502 503 504 505 506
bool HeapObject::IsStruct() const {
  switch (map()->instance_type()) {
#define MAKE_STRUCT_CASE(NAME, Name, name) \
  case NAME##_TYPE:                        \
    return true;
    STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
    default:
      return false;
507
  }
508
}
509

510 511 512 513 514 515
#define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
  bool Object::Is##Name() const {                                \
    return IsHeapObject() && HeapObject::cast(this)->Is##Name(); \
  }                                                              \
  bool HeapObject::Is##Name() const {                            \
    return map()->instance_type() == NAME##_TYPE;                \
516
  }
517 518
STRUCT_LIST(MAKE_STRUCT_PREDICATE)
#undef MAKE_STRUCT_PREDICATE
519

520 521 522 523 524 525
double Object::Number() const {
  DCHECK(IsNumber());
  return IsSmi()
             ? static_cast<double>(reinterpret_cast<const Smi*>(this)->value())
             : reinterpret_cast<const HeapNumber*>(this)->value();
}
526

527 528 529
bool Object::IsNaN() const {
  return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
}
530

531 532 533 534
bool Object::IsMinusZero() const {
  return this->IsHeapNumber() &&
         i::IsMinusZero(HeapNumber::cast(this)->value());
}
535

536 537
// ------------------------------------
// Cast operations
538

539 540 541 542 543 544
CAST_ACCESSOR(AccessCheckInfo)
CAST_ACCESSOR(AccessorInfo)
CAST_ACCESSOR(AccessorPair)
CAST_ACCESSOR(AllocationMemento)
CAST_ACCESSOR(AllocationSite)
CAST_ACCESSOR(AsyncGeneratorRequest)
545
CAST_ACCESSOR(BigInt)
546
CAST_ACCESSOR(BoilerplateDescription)
547
CAST_ACCESSOR(CallHandlerInfo)
548
CAST_ACCESSOR(Cell)
549
CAST_ACCESSOR(ConstantElementsPair)
550
CAST_ACCESSOR(ContextExtension)
551
CAST_ACCESSOR(DescriptorArray)
552
CAST_ACCESSOR(EnumCache)
553
CAST_ACCESSOR(Foreign)
554
CAST_ACCESSOR(FunctionTemplateInfo)
555 556
CAST_ACCESSOR(GlobalDictionary)
CAST_ACCESSOR(HeapObject)
557 558 559
CAST_ACCESSOR(InterceptorInfo)
CAST_ACCESSOR(JSAsyncFromSyncIterator)
CAST_ACCESSOR(JSAsyncGeneratorObject)
560 561 562 563 564 565 566 567 568
CAST_ACCESSOR(JSBoundFunction)
CAST_ACCESSOR(JSDataView)
CAST_ACCESSOR(JSDate)
CAST_ACCESSOR(JSFunction)
CAST_ACCESSOR(JSGeneratorObject)
CAST_ACCESSOR(JSGlobalObject)
CAST_ACCESSOR(JSGlobalProxy)
CAST_ACCESSOR(JSMessageObject)
CAST_ACCESSOR(JSObject)
569
CAST_ACCESSOR(JSPromise)
570 571 572 573 574 575 576 577 578
CAST_ACCESSOR(JSProxy)
CAST_ACCESSOR(JSReceiver)
CAST_ACCESSOR(JSStringIterator)
CAST_ACCESSOR(JSValue)
CAST_ACCESSOR(LayoutDescriptor)
CAST_ACCESSOR(NameDictionary)
CAST_ACCESSOR(NormalizedMapCache)
CAST_ACCESSOR(Object)
CAST_ACCESSOR(ObjectHashSet)
579 580
CAST_ACCESSOR(ObjectHashTable)
CAST_ACCESSOR(ObjectTemplateInfo)
581 582 583
CAST_ACCESSOR(Oddball)
CAST_ACCESSOR(OrderedHashMap)
CAST_ACCESSOR(OrderedHashSet)
584
CAST_ACCESSOR(PromiseCapability)
585 586
CAST_ACCESSOR(PromiseReactionJobInfo)
CAST_ACCESSOR(PromiseResolveThenableJobInfo)
587
CAST_ACCESSOR(PropertyArray)
588
CAST_ACCESSOR(PropertyCell)
589
CAST_ACCESSOR(PrototypeInfo)
590 591
CAST_ACCESSOR(RegExpMatchInfo)
CAST_ACCESSOR(ScopeInfo)
592
CAST_ACCESSOR(NumberDictionary)
593 594
CAST_ACCESSOR(SmallOrderedHashMap)
CAST_ACCESSOR(SmallOrderedHashSet)
595
CAST_ACCESSOR(Smi)
596 597
CAST_ACCESSOR(SourcePositionTableWithFrameCache)
CAST_ACCESSOR(StackFrameInfo)
598 599 600 601
CAST_ACCESSOR(StringSet)
CAST_ACCESSOR(StringTable)
CAST_ACCESSOR(Struct)
CAST_ACCESSOR(TemplateInfo)
602 603
CAST_ACCESSOR(TemplateMap)
CAST_ACCESSOR(TemplateObjectDescription)
604 605
CAST_ACCESSOR(Tuple2)
CAST_ACCESSOR(Tuple3)
606 607
CAST_ACCESSOR(WeakCell)
CAST_ACCESSOR(WeakHashTable)
608

609 610 611
bool Object::HasValidElements() {
  // Dictionary is covered under FixedArray.
  return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
612 613
}

614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
bool Object::KeyEquals(Object* second) {
  Object* first = this;
  if (second->IsNumber()) {
    if (first->IsNumber()) return first->Number() == second->Number();
    Object* temp = first;
    first = second;
    second = temp;
  }
  if (first->IsNumber()) {
    DCHECK_LE(0, first->Number());
    uint32_t expected = static_cast<uint32_t>(first->Number());
    uint32_t index;
    return Name::cast(second)->AsArrayIndex(&index) && index == expected;
  }
  return Name::cast(first)->Equals(Name::cast(second));
629 630
}

631
bool Object::FilterKey(PropertyFilter filter) {
632
  DCHECK(!IsPropertyCell());
633 634 635 636 637 638 639
  if (IsSymbol()) {
    if (filter & SKIP_SYMBOLS) return true;
    if (Symbol::cast(this)->is_private()) return true;
  } else {
    if (filter & SKIP_STRINGS) return true;
  }
  return false;
640 641
}

642 643 644
Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object,
                                     Representation representation) {
  if (!representation.IsDouble()) return object;
645
  Handle<HeapNumber> result = isolate->factory()->NewHeapNumber(MUTABLE);
646
  if (object->IsUninitialized(isolate)) {
647
    result->set_value_as_bits(kHoleNanInt64);
648
  } else if (object->IsMutableHeapNumber()) {
649 650
    // Ensure that all bits of the double value are preserved.
    result->set_value_as_bits(HeapNumber::cast(*object)->value_as_bits());
651
  } else {
652
    result->set_value(object->Number());
653
  }
654
  return result;
655 656
}

657 658 659 660 661 662 663 664
Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object,
                                   Representation representation) {
  DCHECK(!object->IsUninitialized(isolate));
  if (!representation.IsDouble()) {
    DCHECK(object->FitsRepresentation(representation));
    return object;
  }
  return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value());
665 666
}

667 668 669 670 671 672
Representation Object::OptimalRepresentation() {
  if (!FLAG_track_fields) return Representation::Tagged();
  if (IsSmi()) {
    return Representation::Smi();
  } else if (FLAG_track_double_fields && IsHeapNumber()) {
    return Representation::Double();
673 674
  } else if (FLAG_track_computed_fields &&
             IsUninitialized(HeapObject::cast(this)->GetIsolate())) {
675 676 677 678 679 680 681 682 683 684 685
    return Representation::None();
  } else if (FLAG_track_heap_object_fields) {
    DCHECK(IsHeapObject());
    return Representation::HeapObject();
  } else {
    return Representation::Tagged();
  }
}


ElementsKind Object::OptimalElementsKind() {
686 687 688
  if (IsSmi()) return PACKED_SMI_ELEMENTS;
  if (IsNumber()) return PACKED_DOUBLE_ELEMENTS;
  return PACKED_ELEMENTS;
689 690 691 692
}


bool Object::FitsRepresentation(Representation representation) {
693
  if (FLAG_track_fields && representation.IsSmi()) {
694 695 696 697 698
    return IsSmi();
  } else if (FLAG_track_double_fields && representation.IsDouble()) {
    return IsMutableHeapNumber() || IsNumber();
  } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
    return IsHeapObject();
699 700
  } else if (FLAG_track_fields && representation.IsNone()) {
    return false;
701 702 703 704
  }
  return true;
}

705
bool Object::ToUint32(uint32_t* value) const {
706
  if (IsSmi()) {
jgruber's avatar
jgruber committed
707
    int num = Smi::ToInt(this);
708 709 710 711 712 713
    if (num < 0) return false;
    *value = static_cast<uint32_t>(num);
    return true;
  }
  if (IsHeapNumber()) {
    double num = HeapNumber::cast(this)->value();
714
    return DoubleToUint32IfEqualToSelf(num, value);
715 716 717
  }
  return false;
}
718

719
// static
720
MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
721 722
                                         Handle<Object> object,
                                         const char* method_name) {
723
  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
724
  return ToObject(isolate, object, isolate->native_context(), method_name);
725 726 727
}


728 729 730 731 732 733
// static
MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) {
  if (input->IsName()) return Handle<Name>::cast(input);
  return ConvertToName(isolate, input);
}

734 735 736 737 738 739 740
// static
MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
                                          Handle<Object> value) {
  if (value->IsSmi() || HeapObject::cast(*value)->IsName()) return value;
  return ConvertToPropertyKey(isolate, value);
}

741 742 743 744 745 746 747
// static
MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input,
                                        ToPrimitiveHint hint) {
  if (input->IsPrimitive()) return input;
  return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint);
}

748 749
// static
MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
750 751 752 753 754 755 756 757 758 759
  if (input->IsNumber()) return input;  // Shortcut.
  return ConvertToNumberOrNumeric(HeapObject::cast(*input)->GetIsolate(), input,
                                  Conversion::kToNumber);
}

// static
MaybeHandle<Object> Object::ToNumeric(Handle<Object> input) {
  if (input->IsNumber() || input->IsBigInt()) return input;  // Shortcut.
  return ConvertToNumberOrNumeric(HeapObject::cast(*input)->GetIsolate(), input,
                                  Conversion::kToNumeric);
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
}

// static
MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
  if (input->IsSmi()) return input;
  return ConvertToInteger(isolate, input);
}

// static
MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
  if (input->IsSmi()) return input;
  return ConvertToInt32(isolate, input);
}

// static
MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
  if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
  return ConvertToUint32(isolate, input);
}

// static
MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
  if (input->IsString()) return Handle<String>::cast(input);
  return ConvertToString(isolate, input);
}
785

786 787 788
// static
MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
  if (input->IsSmi()) {
jgruber's avatar
jgruber committed
789
    int value = std::max(Smi::ToInt(*input), 0);
790 791 792 793 794 795 796 797
    return handle(Smi::FromInt(value), isolate);
  }
  return ConvertToLength(isolate, input);
}

// static
MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input,
                                    MessageTemplate::Template error_index) {
jgruber's avatar
jgruber committed
798
  if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
799 800 801
  return ConvertToIndex(isolate, input, error_index);
}

802 803 804 805
bool Object::HasSpecificClassOf(String* name) {
  return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
}

806
MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
807
                                        Handle<Name> name) {
808
  LookupIterator it(object, name);
809
  if (!it.IsFound()) return it.factory()->undefined_value();
810
  return GetProperty(&it);
811 812
}

813 814 815 816 817 818 819
MaybeHandle<Object> JSReceiver::GetProperty(Handle<JSReceiver> receiver,
                                            Handle<Name> name) {
  LookupIterator it(receiver, name, receiver);
  if (!it.IsFound()) return it.factory()->undefined_value();
  return Object::GetProperty(&it);
}

820
MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
821
                                       uint32_t index) {
822
  LookupIterator it(isolate, object, index);
823
  if (!it.IsFound()) return it.factory()->undefined_value();
824
  return GetProperty(&it);
825 826
}

827 828 829 830 831 832 833 834
MaybeHandle<Object> JSReceiver::GetElement(Isolate* isolate,
                                           Handle<JSReceiver> receiver,
                                           uint32_t index) {
  LookupIterator it(isolate, receiver, index, receiver);
  if (!it.IsFound()) return it.factory()->undefined_value();
  return Object::GetProperty(&it);
}

835 836
Handle<Object> JSReceiver::GetDataProperty(Handle<JSReceiver> object,
                                           Handle<Name> name) {
837
  LookupIterator it(object, name, object,
838 839 840 841
                    LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
  if (!it.IsFound()) return it.factory()->undefined_value();
  return GetDataProperty(&it);
}
842

843 844 845 846
MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object,
                                       uint32_t index, Handle<Object> value,
                                       LanguageMode language_mode) {
  LookupIterator it(isolate, object, index);
847 848 849
  MAYBE_RETURN_NULL(
      SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED));
  return value;
850 851
}

852 853
MaybeHandle<Object> JSReceiver::GetPrototype(Isolate* isolate,
                                             Handle<JSReceiver> receiver) {
854
  // We don't expect access checks to be needed on JSProxy objects.
855
  DCHECK(!receiver->IsAccessCheckNeeded() || receiver->IsJSObject());
856
  PrototypeIterator iter(isolate, receiver, kStartAtReceiver,
857
                         PrototypeIterator::END_AT_NON_HIDDEN);
858
  do {
859
    if (!iter.AdvanceFollowingProxies()) return MaybeHandle<Object>();
860
  } while (!iter.IsAtEnd());
861 862 863
  return PrototypeIterator::GetCurrent(iter);
}

864 865 866
MaybeHandle<Object> JSReceiver::GetProperty(Isolate* isolate,
                                            Handle<JSReceiver> receiver,
                                            const char* name) {
867
  Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
868
  return GetProperty(receiver, str);
869 870
}

871 872 873
// static
MUST_USE_RESULT MaybeHandle<FixedArray> JSReceiver::OwnPropertyKeys(
    Handle<JSReceiver> object) {
874 875 876
  return KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
                                 ALL_PROPERTIES,
                                 GetKeysConversion::kConvertToString);
877
}
878

879 880 881 882
bool JSObject::PrototypeHasNoElements(Isolate* isolate, JSObject* object) {
  DisallowHeapAllocation no_gc;
  HeapObject* prototype = HeapObject::cast(object->map()->prototype());
  HeapObject* null = isolate->heap()->null_value();
883 884 885
  HeapObject* empty_fixed_array = isolate->heap()->empty_fixed_array();
  HeapObject* empty_slow_element_dictionary =
      isolate->heap()->empty_slow_element_dictionary();
886 887 888
  while (prototype != null) {
    Map* map = prototype->map();
    if (map->instance_type() <= LAST_CUSTOM_ELEMENTS_RECEIVER) return false;
889 890 891 892 893
    HeapObject* elements = JSObject::cast(prototype)->elements();
    if (elements != empty_fixed_array &&
        elements != empty_slow_element_dictionary) {
      return false;
    }
894 895 896 897 898
    prototype = HeapObject::cast(map->prototype());
  }
  return true;
}

899
Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
900
  return reinterpret_cast<Object**>(FIELD_ADDR(obj, byte_offset));
901 902
}

jgruber's avatar
jgruber committed
903
int Smi::ToInt(const Object* object) { return Smi::cast(object)->value(); }
904

905
MapWord MapWord::FromMap(const Map* map) {
906 907 908
  return MapWord(reinterpret_cast<uintptr_t>(map));
}

909
Map* MapWord::ToMap() const { return reinterpret_cast<Map*>(value_); }
910

911
bool MapWord::IsForwardingAddress() const {
912
  return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
913 914 915 916
}


MapWord MapWord::FromForwardingAddress(HeapObject* object) {
917 918
  Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
  return MapWord(reinterpret_cast<uintptr_t>(raw));
919 920 921 922
}


HeapObject* MapWord::ToForwardingAddress() {
923
  DCHECK(IsForwardingAddress());
924
  return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
925 926 927
}


928
#ifdef VERIFY_HEAP
929 930 931
void HeapObject::VerifyObjectField(int offset) {
  VerifyPointer(READ_FIELD(this, offset));
}
932 933

void HeapObject::VerifySmiField(int offset) {
934
  CHECK(READ_FIELD(this, offset)->IsSmi());
935
}
936 937 938
#endif


939
Heap* HeapObject::GetHeap() const {
940 941 942
  Heap* heap = MemoryChunk::FromAddress(
                   reinterpret_cast<Address>(const_cast<HeapObject*>(this)))
                   ->heap();
943
  SLOW_DCHECK(heap != nullptr);
944
  return heap;
945 946 947
}


948
Isolate* HeapObject::GetIsolate() const {
949
  return GetHeap()->isolate();
950 951
}

952
Map* HeapObject::map() const {
953
  return map_word().ToMap();
954 955 956 957
}


void HeapObject::set_map(Map* value) {
958 959 960 961 962
  if (value != nullptr) {
#ifdef VERIFY_HEAP
    value->GetHeap()->VerifyObjectLayoutChange(this, value);
#endif
  }
963
  set_map_word(MapWord::FromMap(value));
964
  if (value != nullptr) {
965
    // TODO(1600) We are passing nullptr as a slot because maps can never be on
966
    // evacuation candidate.
967
    value->GetHeap()->incremental_marking()->RecordWrite(this, nullptr, value);
968
  }
969 970
}

971
Map* HeapObject::synchronized_map() const {
972 973 974 975 976
  return synchronized_map_word().ToMap();
}


void HeapObject::synchronized_set_map(Map* value) {
977 978 979 980
  if (value != nullptr) {
#ifdef VERIFY_HEAP
    value->GetHeap()->VerifyObjectLayoutChange(this, value);
#endif
981
  }
982
  synchronized_set_map_word(MapWord::FromMap(value));
983
  if (value != nullptr) {
984
    // TODO(1600) We are passing nullptr as a slot because maps can never be on
985 986 987
    // evacuation candidate.
    value->GetHeap()->incremental_marking()->RecordWrite(this, nullptr, value);
  }
988 989 990
}


991
// Unsafe accessor omitting write barrier.
992
void HeapObject::set_map_no_write_barrier(Map* value) {
993 994 995 996 997 998 999 1000 1001
  if (value != nullptr) {
#ifdef VERIFY_HEAP
    value->GetHeap()->VerifyObjectLayoutChange(this, value);
#endif
  }
  set_map_word(MapWord::FromMap(value));
}

void HeapObject::set_map_after_allocation(Map* value, WriteBarrierMode mode) {
1002
  set_map_word(MapWord::FromMap(value));
1003
  if (mode != SKIP_WRITE_BARRIER) {
1004
    DCHECK_NOT_NULL(value);
1005
    // TODO(1600) We are passing nullptr as a slot because maps can never be on
1006 1007 1008
    // evacuation candidate.
    value->GetHeap()->incremental_marking()->RecordWrite(this, nullptr, value);
  }
1009 1010
}

1011 1012 1013
HeapObject** HeapObject::map_slot() {
  return reinterpret_cast<HeapObject**>(FIELD_ADDR(this, kMapOffset));
}
1014

1015
MapWord HeapObject::map_word() const {
1016
  return MapWord(
1017
      reinterpret_cast<uintptr_t>(RELAXED_READ_FIELD(this, kMapOffset)));
1018 1019 1020
}


1021
void HeapObject::set_map_word(MapWord map_word) {
1022 1023
  RELAXED_WRITE_FIELD(this, kMapOffset,
                      reinterpret_cast<Object*>(map_word.value_));
1024 1025 1026
}


1027
MapWord HeapObject::synchronized_map_word() const {
1028 1029 1030 1031 1032 1033 1034 1035
  return MapWord(
      reinterpret_cast<uintptr_t>(ACQUIRE_READ_FIELD(this, kMapOffset)));
}


void HeapObject::synchronized_set_map_word(MapWord map_word) {
  RELEASE_WRITE_FIELD(
      this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1036
}
1037

1038
int HeapObject::Size() const { return SizeFromMap(map()); }
1039

1040
double HeapNumber::value() const {
1041 1042 1043 1044 1045 1046 1047 1048
  return READ_DOUBLE_FIELD(this, kValueOffset);
}


void HeapNumber::set_value(double value) {
  WRITE_DOUBLE_FIELD(this, kValueOffset, value);
}

1049 1050 1051 1052 1053 1054 1055
uint64_t HeapNumber::value_as_bits() const {
  return READ_UINT64_FIELD(this, kValueOffset);
}

void HeapNumber::set_value_as_bits(uint64_t bits) {
  WRITE_UINT64_FIELD(this, kValueOffset, bits);
}
1056

1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
int HeapNumber::get_exponent() {
  return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
          kExponentShift) - kExponentBias;
}


int HeapNumber::get_sign() {
  return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
}

1067
ACCESSORS(JSReceiver, raw_properties_or_hash, Object, kPropertiesOrHashOffset)
1068

1069
FixedArrayBase* JSObject::elements() const {
1070
  Object* array = READ_FIELD(this, kElementsOffset);
1071
  return static_cast<FixedArrayBase*>(array);
1072 1073
}

1074
void AllocationSite::Initialize() {
1075
  set_transition_info_or_boilerplate(Smi::kZero);
1076
  SetElementsKind(GetInitialFastElementsKind());
1077
  set_nested_site(Smi::kZero);
1078 1079
  set_pretenure_data(0);
  set_pretenure_create_count(0);
1080 1081 1082 1083
  set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
                     SKIP_WRITE_BARRIER);
}

1084 1085 1086
bool AllocationSite::IsZombie() const {
  return pretenure_decision() == kZombie;
}
1087

1088
bool AllocationSite::IsMaybeTenure() const {
1089 1090 1091
  return pretenure_decision() == kMaybeTenure;
}

1092
bool AllocationSite::PretenuringDecisionMade() const {
1093 1094 1095 1096
  return pretenure_decision() != kUndecided;
}


1097
void AllocationSite::MarkZombie() {
1098
  DCHECK(!IsZombie());
1099
  Initialize();
1100
  set_pretenure_decision(kZombie);
1101 1102
}

1103 1104
ElementsKind AllocationSite::GetElementsKind() const {
  return ElementsKindBits::decode(transition_info());
1105 1106 1107 1108
}


void AllocationSite::SetElementsKind(ElementsKind kind) {
1109
  set_transition_info(ElementsKindBits::update(transition_info(), kind));
1110 1111
}

1112 1113
bool AllocationSite::CanInlineCall() const {
  return DoNotInlineBit::decode(transition_info()) == 0;
1114 1115 1116 1117
}


void AllocationSite::SetDoNotInlineCall() {
1118
  set_transition_info(DoNotInlineBit::update(transition_info(), true));
1119 1120
}

1121 1122 1123 1124 1125
bool AllocationSite::PointsToLiteral() const {
  Object* raw_value = transition_info_or_boilerplate();
  DCHECK_EQ(!raw_value->IsSmi(),
            raw_value->IsJSArray() || raw_value->IsJSObject());
  return !raw_value->IsSmi();
1126 1127 1128
}


1129 1130
// Heuristic: We only need to create allocation site info if the boilerplate
// elements kind is the initial elements kind.
1131
bool AllocationSite::ShouldTrack(ElementsKind boilerplate_elements_kind) {
1132
  return IsSmiElementsKind(boilerplate_elements_kind);
1133 1134
}

1135
inline bool AllocationSite::CanTrack(InstanceType type) {
1136
  if (FLAG_allocation_site_pretenuring) {
1137 1138 1139 1140
    // TurboFan doesn't care at all about String pretenuring feedback,
    // so don't bother even trying to track that.
    return type == JS_ARRAY_TYPE || type == JS_OBJECT_TYPE;
  }
1141 1142 1143
  return type == JS_ARRAY_TYPE;
}

1144 1145
AllocationSite::PretenureDecision AllocationSite::pretenure_decision() const {
  return PretenureDecisionBits::decode(pretenure_data());
1146 1147 1148
}

void AllocationSite::set_pretenure_decision(PretenureDecision decision) {
1149 1150
  int value = pretenure_data();
  set_pretenure_data(PretenureDecisionBits::update(value, decision));
1151 1152
}

1153 1154
bool AllocationSite::deopt_dependent_code() const {
  return DeoptDependentCodeBit::decode(pretenure_data());
1155 1156 1157
}

void AllocationSite::set_deopt_dependent_code(bool deopt) {
1158 1159
  int value = pretenure_data();
  set_pretenure_data(DeoptDependentCodeBit::update(value, deopt));
1160 1161
}

1162 1163
int AllocationSite::memento_found_count() const {
  return MementoFoundCountBits::decode(pretenure_data());
1164 1165
}

1166
inline void AllocationSite::set_memento_found_count(int count) {
1167
  int value = pretenure_data();
1168 1169
  // Verify that we can count more mementos than we can possibly find in one
  // new space collection.
1170
  DCHECK((GetHeap()->MaxSemiSpaceSize() /
1171
          (Heap::kMinObjectSizeInWords * kPointerSize +
1172
           AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
1173
  DCHECK_LT(count, MementoFoundCountBits::kMax);
1174
  set_pretenure_data(MementoFoundCountBits::update(value, count));
1175 1176
}

1177 1178 1179
int AllocationSite::memento_create_count() const {
  return pretenure_create_count();
}
1180 1181

void AllocationSite::set_memento_create_count(int count) {
1182
  set_pretenure_create_count(count);
1183 1184
}

1185
bool AllocationSite::IncrementMementoFoundCount(int increment) {
1186 1187
  if (IsZombie()) return false;

1188
  int value = memento_found_count();
1189 1190
  set_memento_found_count(value + increment);
  return memento_found_count() >= kPretenureMinimumCreated;
1191 1192 1193 1194
}


inline void AllocationSite::IncrementMementoCreateCount() {
1195
  DCHECK(FLAG_allocation_site_pretenuring);
1196 1197
  int value = memento_create_count();
  set_memento_create_count(value + 1);
1198 1199
}

1200
bool AllocationMemento::IsValid() const {
1201 1202 1203 1204
  return allocation_site()->IsAllocationSite() &&
         !AllocationSite::cast(allocation_site())->IsZombie();
}

1205
AllocationSite* AllocationMemento::GetAllocationSite() const {
1206 1207 1208 1209
  DCHECK(IsValid());
  return AllocationSite::cast(allocation_site());
}

1210
Address AllocationMemento::GetAllocationSiteUnchecked() const {
1211 1212
  return reinterpret_cast<Address>(allocation_site());
}
1213

1214
void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) {
1215
  JSObject::ValidateElements(*object);
1216
  ElementsKind elements_kind = object->map()->elements_kind();
1217 1218
  if (!IsObjectElementsKind(elements_kind)) {
    if (IsHoleyElementsKind(elements_kind)) {
1219
      TransitionElementsKind(object, HOLEY_ELEMENTS);
1220
    } else {
1221
      TransitionElementsKind(object, PACKED_ELEMENTS);
1222
    }
1223 1224 1225 1226
  }
}


1227 1228 1229 1230
void JSObject::EnsureCanContainElements(Handle<JSObject> object,
                                        Object** objects,
                                        uint32_t count,
                                        EnsureElementsMode mode) {
1231
  ElementsKind current_kind = object->GetElementsKind();
1232
  ElementsKind target_kind = current_kind;
1233 1234
  {
    DisallowHeapAllocation no_allocation;
1235
    DCHECK(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1236
    bool is_holey = IsHoleyElementsKind(current_kind);
1237
    if (current_kind == HOLEY_ELEMENTS) return;
1238
    Object* the_hole = object->GetHeap()->the_hole_value();
1239 1240 1241 1242 1243 1244 1245
    for (uint32_t i = 0; i < count; ++i) {
      Object* current = *objects++;
      if (current == the_hole) {
        is_holey = true;
        target_kind = GetHoleyElementsKind(target_kind);
      } else if (!current->IsSmi()) {
        if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) {
1246
          if (IsSmiElementsKind(target_kind)) {
1247
            if (is_holey) {
1248
              target_kind = HOLEY_DOUBLE_ELEMENTS;
1249
            } else {
1250
              target_kind = PACKED_DOUBLE_ELEMENTS;
1251
            }
1252
          }
1253
        } else if (is_holey) {
1254
          target_kind = HOLEY_ELEMENTS;
1255 1256
          break;
        } else {
1257
          target_kind = PACKED_ELEMENTS;
1258
        }
1259 1260 1261
      }
    }
  }
1262
  if (target_kind != current_kind) {
1263
    TransitionElementsKind(object, target_kind);
1264
  }
1265 1266 1267
}


1268 1269 1270 1271
void JSObject::EnsureCanContainElements(Handle<JSObject> object,
                                        Handle<FixedArrayBase> elements,
                                        uint32_t length,
                                        EnsureElementsMode mode) {
1272 1273
  Heap* heap = object->GetHeap();
  if (elements->map() != heap->fixed_double_array_map()) {
1274
    DCHECK(elements->map() == heap->fixed_array_map() ||
1275
           elements->map() == heap->fixed_cow_array_map());
1276 1277 1278
    if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
      mode = DONT_ALLOW_DOUBLE_ELEMENTS;
    }
1279 1280 1281 1282
    Object** objects =
        Handle<FixedArray>::cast(elements)->GetFirstElementAddress();
    EnsureCanContainElements(object, objects, length, mode);
    return;
1283 1284
  }

1285
  DCHECK(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1286 1287 1288
  if (object->GetElementsKind() == HOLEY_SMI_ELEMENTS) {
    TransitionElementsKind(object, HOLEY_DOUBLE_ELEMENTS);
  } else if (object->GetElementsKind() == PACKED_SMI_ELEMENTS) {
1289 1290
    Handle<FixedDoubleArray> double_array =
        Handle<FixedDoubleArray>::cast(elements);
1291 1292
    for (uint32_t i = 0; i < length; ++i) {
      if (double_array->is_the_hole(i)) {
1293
        TransitionElementsKind(object, HOLEY_DOUBLE_ELEMENTS);
1294
        return;
1295 1296
      }
    }
1297
    TransitionElementsKind(object, PACKED_DOUBLE_ELEMENTS);
1298
  }
1299 1300
}

1301

1302 1303 1304 1305
void JSObject::SetMapAndElements(Handle<JSObject> object,
                                 Handle<Map> new_map,
                                 Handle<FixedArrayBase> value) {
  JSObject::MigrateToMap(object, new_map);
1306
  DCHECK((object->map()->has_fast_smi_or_object_elements() ||
1307 1308
          (*value == object->GetHeap()->empty_fixed_array()) ||
          object->map()->has_fast_string_wrapper_elements()) ==
1309 1310
         (value->map() == object->GetHeap()->fixed_array_map() ||
          value->map() == object->GetHeap()->fixed_cow_array_map()));
1311
  DCHECK((*value == object->GetHeap()->empty_fixed_array()) ||
1312 1313 1314
         (object->map()->has_fast_double_elements() ==
          value->IsFixedDoubleArray()));
  object->set_elements(*value);
1315
}
1316 1317


1318
void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
1319 1320
  WRITE_FIELD(this, kElementsOffset, value);
  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1321 1322 1323
}


1324
void JSObject::initialize_elements() {
1325 1326
  FixedArrayBase* elements = map()->GetInitialElements();
  WRITE_FIELD(this, kElementsOffset, elements);
1327 1328 1329
}


1330
InterceptorInfo* JSObject::GetIndexedInterceptor() {
1331 1332 1333 1334 1335 1336 1337
  return map()->GetIndexedInterceptor();
}

InterceptorInfo* JSObject::GetNamedInterceptor() {
  return map()->GetNamedInterceptor();
}

1338 1339 1340 1341 1342 1343 1344
double Oddball::to_number_raw() const {
  return READ_DOUBLE_FIELD(this, kToNumberRawOffset);
}

void Oddball::set_to_number_raw(double value) {
  WRITE_DOUBLE_FIELD(this, kToNumberRawOffset, value);
}
1345

1346 1347 1348 1349
void Oddball::set_to_number_raw_as_bits(uint64_t bits) {
  WRITE_UINT64_FIELD(this, kToNumberRawOffset, bits);
}

1350 1351
ACCESSORS(Oddball, to_string, String, kToStringOffset)
ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1352
ACCESSORS(Oddball, type_of, String, kTypeOfOffset)
1353

jgruber's avatar
jgruber committed
1354
byte Oddball::kind() const { return Smi::ToInt(READ_FIELD(this, kKindOffset)); }
1355 1356

void Oddball::set_kind(byte value) {
1357
  WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
1358 1359 1360
}


1361 1362 1363 1364 1365 1366
// static
Handle<Object> Oddball::ToNumber(Handle<Oddball> input) {
  return handle(input->to_number(), input->GetIsolate());
}


1367
ACCESSORS(Cell, value, Object, kValueOffset)
1368
ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
1369
ACCESSORS(PropertyCell, name, Name, kNameOffset)
verwaest's avatar
verwaest committed
1370
ACCESSORS(PropertyCell, value, Object, kValueOffset)
1371
ACCESSORS(PropertyCell, property_details_raw, Object, kDetailsOffset)
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382

PropertyDetails PropertyCell::property_details() {
  return PropertyDetails(Smi::cast(property_details_raw()));
}


void PropertyCell::set_property_details(PropertyDetails details) {
  set_property_details_raw(details.AsSmi());
}


1383
Object* WeakCell::value() const { return READ_FIELD(this, kValueOffset); }
ulan@chromium.org's avatar
ulan@chromium.org committed
1384 1385


1386
void WeakCell::clear() {
1387 1388 1389 1390
  // Either the garbage collector is clearing the cell or we are simply
  // initializing the root empty weak cell.
  DCHECK(GetHeap()->gc_state() == Heap::MARK_COMPACT ||
         this == GetHeap()->empty_weak_cell());
1391
  WRITE_FIELD(this, kValueOffset, Smi::kZero);
ulan@chromium.org's avatar
ulan@chromium.org committed
1392 1393 1394 1395 1396
}


void WeakCell::initialize(HeapObject* val) {
  WRITE_FIELD(this, kValueOffset, val);
1397 1398 1399
  // We just have to execute the generational barrier here because we never
  // mark through a weak cell and collect evacuation candidates when we process
  // all weak cells.
1400
  Heap* heap = val->GetHeap();
1401
  WriteBarrierMode mode =
1402
      heap->incremental_marking()->marking_state()->IsBlack(this)
1403 1404
          ? UPDATE_WRITE_BARRIER
          : UPDATE_WEAK_WRITE_BARRIER;
1405
  CONDITIONAL_WRITE_BARRIER(heap, this, kValueOffset, val, mode);
ulan@chromium.org's avatar
ulan@chromium.org committed
1406 1407
}

1408
bool WeakCell::cleared() const { return value() == Smi::kZero; }
1409

1410 1411 1412
int JSObject::GetHeaderSize() const { return GetHeaderSize(map()); }

int JSObject::GetHeaderSize(const Map* map) {
1413 1414 1415
  // Check for the most common kind of JavaScript object before
  // falling into the generic switch. This speeds up the internal
  // field operations considerably on average.
1416 1417 1418 1419
  InstanceType instance_type = map->instance_type();
  return instance_type == JS_OBJECT_TYPE
             ? JSObject::kHeaderSize
             : GetHeaderSize(instance_type, map->has_prototype_slot());
1420 1421
}

1422 1423 1424
inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
  return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
}
1425

1426 1427 1428 1429 1430 1431 1432 1433 1434
// This should be in objects/map-inl.h, but can't, because of a cyclic
// dependency.
bool Map::IsSpecialReceiverMap() const {
  bool result = IsSpecialReceiverInstanceType(instance_type());
  DCHECK_IMPLIES(!result,
                 !has_named_interceptor() && !is_access_check_needed());
  return result;
}

1435 1436
// static
int JSObject::GetEmbedderFieldCount(const Map* map) {
1437 1438
  int instance_size = map->instance_size();
  if (instance_size == kVariableSizeSentinel) return 0;
1439
  return ((instance_size - GetHeaderSize(map)) >> kPointerSizeLog2) -
1440
         map->GetInObjectProperties();
1441 1442
}

1443 1444 1445
int JSObject::GetEmbedderFieldCount() const {
  return GetEmbedderFieldCount(map());
}
1446

1447 1448
int JSObject::GetEmbedderFieldOffset(int index) {
  DCHECK(index < GetEmbedderFieldCount() && index >= 0);
1449 1450 1451
  return GetHeaderSize() + (kPointerSize * index);
}

1452 1453
Object* JSObject::GetEmbedderField(int index) {
  DCHECK(index < GetEmbedderFieldCount() && index >= 0);
1454 1455 1456
  // Internal objects do follow immediately after the header, whereas in-object
  // properties are at the end of the object. Therefore there is no need
  // to adjust the index here.
1457 1458 1459
  return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
}

1460 1461
void JSObject::SetEmbedderField(int index, Object* value) {
  DCHECK(index < GetEmbedderFieldCount() && index >= 0);
1462 1463 1464
  // Internal objects do follow immediately after the header, whereas in-object
  // properties are at the end of the object. Therefore there is no need
  // to adjust the index here.
1465 1466
  int offset = GetHeaderSize() + (kPointerSize * index);
  WRITE_FIELD(this, offset, value);
1467
  WRITE_BARRIER(GetHeap(), this, offset, value);
1468 1469
}

1470 1471
void JSObject::SetEmbedderField(int index, Smi* value) {
  DCHECK(index < GetEmbedderFieldCount() && index >= 0);
1472 1473 1474 1475 1476 1477 1478 1479
  // Internal objects do follow immediately after the header, whereas in-object
  // properties are at the end of the object. Therefore there is no need
  // to adjust the index here.
  int offset = GetHeaderSize() + (kPointerSize * index);
  WRITE_FIELD(this, offset, value);
}


1480 1481 1482 1483 1484
bool JSObject::IsUnboxedDoubleField(FieldIndex index) {
  if (!FLAG_unbox_double_fields) return false;
  return map()->IsUnboxedDoubleField(index);
}

1485 1486 1487
// Access fast-case object properties at index. The use of these routines
// is needed to correctly distinguish between properties stored in-object and
// properties stored in the properties array.
1488
Object* JSObject::RawFastPropertyAt(FieldIndex index) {
1489
  DCHECK(!IsUnboxedDoubleField(index));
1490 1491
  if (index.is_inobject()) {
    return READ_FIELD(this, index.offset());
1492
  } else {
1493
    return property_array()->get(index.outobject_array_index());
1494 1495 1496 1497
  }
}


1498 1499 1500 1501 1502
double JSObject::RawFastDoublePropertyAt(FieldIndex index) {
  DCHECK(IsUnboxedDoubleField(index));
  return READ_DOUBLE_FIELD(this, index.offset());
}

1503 1504 1505 1506
uint64_t JSObject::RawFastDoublePropertyAsBitsAt(FieldIndex index) {
  DCHECK(IsUnboxedDoubleField(index));
  return READ_UINT64_FIELD(this, index.offset());
}
1507 1508

void JSObject::RawFastPropertyAtPut(FieldIndex index, Object* value) {
1509 1510
  if (index.is_inobject()) {
    int offset = index.offset();
1511
    WRITE_FIELD(this, offset, value);
1512
    WRITE_BARRIER(GetHeap(), this, offset, value);
1513
  } else {
1514
    property_array()->set(index.outobject_array_index(), value);
1515 1516 1517
  }
}

1518 1519
void JSObject::RawFastDoublePropertyAsBitsAtPut(FieldIndex index,
                                                uint64_t bits) {
1520 1521 1522 1523 1524
  // Double unboxing is enabled only on 64-bit platforms.
  DCHECK_EQ(kDoubleSize, kPointerSize);
  Address field_addr = FIELD_ADDR(this, index.offset());
  base::Relaxed_Store(reinterpret_cast<base::AtomicWord*>(field_addr),
                      static_cast<base::AtomicWord>(bits));
1525 1526 1527 1528 1529
}

void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) {
  if (IsUnboxedDoubleField(index)) {
    DCHECK(value->IsMutableHeapNumber());
1530 1531 1532
    // Ensure that all bits of the double value are preserved.
    RawFastDoublePropertyAsBitsAtPut(index,
                                     HeapNumber::cast(value)->value_as_bits());
1533 1534 1535 1536 1537
  } else {
    RawFastPropertyAtPut(index, value);
  }
}

1538 1539
void JSObject::WriteToField(int descriptor, PropertyDetails details,
                            Object* value) {
1540 1541
  DCHECK_EQ(kField, details.location());
  DCHECK_EQ(kData, details.kind());
1542
  DisallowHeapAllocation no_gc;
1543 1544 1545
  FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
  if (details.representation().IsDouble()) {
    // Nothing more to be done.
1546 1547 1548
    if (value->IsUninitialized(this->GetIsolate())) {
      return;
    }
1549 1550 1551 1552 1553 1554
    // Manipulating the signaling NaN used for the hole and uninitialized
    // double field sentinel in C++, e.g. with bit_cast or value()/set_value(),
    // will change its value on ia32 (the x87 stack is used to return values
    // and stores to the stack silently clear the signalling bit).
    uint64_t bits;
    if (value->IsSmi()) {
jgruber's avatar
jgruber committed
1555
      bits = bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(value)));
1556 1557 1558 1559
    } else {
      DCHECK(value->IsHeapNumber());
      bits = HeapNumber::cast(value)->value_as_bits();
    }
1560
    if (IsUnboxedDoubleField(index)) {
1561
      RawFastDoublePropertyAsBitsAtPut(index, bits);
1562 1563 1564
    } else {
      HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
      DCHECK(box->IsMutableHeapNumber());
1565
      box->set_value_as_bits(bits);
1566 1567 1568 1569 1570 1571
    }
  } else {
    RawFastPropertyAtPut(index, value);
  }
}

1572
int JSObject::GetInObjectPropertyOffset(int index) {
1573
  return map()->GetInObjectPropertyOffset(index);
1574 1575 1576
}


1577
Object* JSObject::InObjectPropertyAt(int index) {
1578
  int offset = GetInObjectPropertyOffset(index);
1579 1580 1581 1582
  return READ_FIELD(this, offset);
}


1583 1584 1585 1586
Object* JSObject::InObjectPropertyAtPut(int index,
                                        Object* value,
                                        WriteBarrierMode mode) {
  // Adjust for the number of properties stored in the object.
1587
  int offset = GetInObjectPropertyOffset(index);
1588
  WRITE_FIELD(this, offset, value);
1589
  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1590 1591 1592 1593
  return value;
}


1594
void JSObject::InitializeBody(Map* map, int start_offset,
1595 1596
                              Object* pre_allocated_value,
                              Object* filler_value) {
1597
  DCHECK(!filler_value->IsHeapObject() ||
1598
         !GetHeap()->InNewSpace(filler_value));
1599
  DCHECK(!pre_allocated_value->IsHeapObject() ||
1600 1601
         !GetHeap()->InNewSpace(pre_allocated_value));
  int size = map->instance_size();
1602
  int offset = start_offset;
1603
  if (filler_value != pre_allocated_value) {
1604
    int end_of_pre_allocated_offset =
1605
        size - (map->UnusedPropertyFields() * kPointerSize);
1606 1607
    DCHECK_LE(kHeaderSize, end_of_pre_allocated_offset);
    while (offset < end_of_pre_allocated_offset) {
1608 1609 1610 1611 1612 1613 1614
      WRITE_FIELD(this, offset, pre_allocated_value);
      offset += kPointerSize;
    }
  }
  while (offset < size) {
    WRITE_FIELD(this, offset, filler_value);
    offset += kPointerSize;
1615 1616 1617 1618
  }
}

void Struct::InitializeBody(int object_size) {
1619
  Object* value = GetHeap()->undefined_value();
1620
  for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1621
    WRITE_FIELD(this, offset, value);
1622 1623 1624
  }
}

1625 1626 1627
bool Object::ToArrayLength(uint32_t* index) const {
  return Object::ToUint32(index);
}
1628

1629
bool Object::ToArrayIndex(uint32_t* index) const {
1630
  return Object::ToUint32(index) && *index != kMaxUInt32;
1631 1632 1633
}


1634
void Object::VerifyApiCallResultType() {
jochen's avatar
jochen committed
1635
#if DEBUG
1636 1637 1638 1639
  if (IsSmi()) return;
  DCHECK(IsHeapObject());
  Isolate* isolate = HeapObject::cast(this)->GetIsolate();
  if (!(IsString() || IsSymbol() || IsJSReceiver() || IsHeapNumber() ||
bbudge's avatar
bbudge committed
1640 1641
        IsUndefined(isolate) || IsTrue(isolate) || IsFalse(isolate) ||
        IsNull(isolate))) {
1642 1643
    FATAL("API call returned invalid object");
  }
jochen's avatar
jochen committed
1644
#endif  // DEBUG
1645 1646
}

1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
Object* PropertyArray::get(int index) const {
  DCHECK_GE(index, 0);
  DCHECK_LE(index, this->length());
  return RELAXED_READ_FIELD(this, kHeaderSize + index * kPointerSize);
}

void PropertyArray::set(int index, Object* value) {
  DCHECK(IsPropertyArray());
  DCHECK_GE(index, 0);
  DCHECK_LT(index, this->length());
  int offset = kHeaderSize + index * kPointerSize;
  RELAXED_WRITE_FIELD(this, offset, value);
  WRITE_BARRIER(GetHeap(), this, offset, value);
}
1661

1662 1663 1664
int RegExpMatchInfo::NumberOfCaptureRegisters() {
  DCHECK_GE(length(), kLastMatchOverhead);
  Object* obj = get(kNumberOfCapturesIndex);
jgruber's avatar
jgruber committed
1665
  return Smi::ToInt(obj);
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696
}

void RegExpMatchInfo::SetNumberOfCaptureRegisters(int value) {
  DCHECK_GE(length(), kLastMatchOverhead);
  set(kNumberOfCapturesIndex, Smi::FromInt(value));
}

String* RegExpMatchInfo::LastSubject() {
  DCHECK_GE(length(), kLastMatchOverhead);
  Object* obj = get(kLastSubjectIndex);
  return String::cast(obj);
}

void RegExpMatchInfo::SetLastSubject(String* value) {
  DCHECK_GE(length(), kLastMatchOverhead);
  set(kLastSubjectIndex, value);
}

Object* RegExpMatchInfo::LastInput() {
  DCHECK_GE(length(), kLastMatchOverhead);
  return get(kLastInputIndex);
}

void RegExpMatchInfo::SetLastInput(Object* value) {
  DCHECK_GE(length(), kLastMatchOverhead);
  set(kLastInputIndex, value);
}

int RegExpMatchInfo::Capture(int i) {
  DCHECK_LT(i, NumberOfCaptureRegisters());
  Object* obj = get(kFirstCaptureIndex + i);
jgruber's avatar
jgruber committed
1697
  return Smi::ToInt(obj);
1698 1699 1700 1701 1702 1703
}

void RegExpMatchInfo::SetCapture(int i, int value) {
  DCHECK_LT(i, NumberOfCaptureRegisters());
  set(kFirstCaptureIndex + i, Smi::FromInt(value));
}
1704

1705 1706
WriteBarrierMode HeapObject::GetWriteBarrierMode(
    const DisallowHeapAllocation& promise) {
1707 1708 1709
  Heap* heap = GetHeap();
  if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
  if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
1710 1711 1712
  return UPDATE_WRITE_BARRIER;
}

1713
AllocationAlignment HeapObject::RequiredAlignment() const {
1714
#ifdef V8_HOST_ARCH_32_BIT
1715
  if ((IsFixedFloat64Array() || IsFixedDoubleArray()) &&
1716 1717 1718 1719
      FixedArrayBase::cast(this)->length() != 0) {
    return kDoubleAligned;
  }
  if (IsHeapNumber()) return kDoubleUnaligned;
1720
#endif  // V8_HOST_ARCH_32_BIT
1721
  return kWordAligned;
1722 1723
}

1724 1725
bool HeapObject::NeedsRehashing() const {
  switch (map()->instance_type()) {
1726 1727
    case DESCRIPTOR_ARRAY_TYPE:
      return DescriptorArray::cast(this)->number_of_descriptors() > 1;
1728 1729
    case TRANSITION_ARRAY_TYPE:
      return TransitionArray::cast(this)->number_of_entries() > 1;
1730
    case HASH_TABLE_TYPE:
1731 1732 1733 1734 1735 1736
      if (IsOrderedHashMap()) {
        return OrderedHashMap::cast(this)->NumberOfElements() > 0;
      } else if (IsOrderedHashSet()) {
        return OrderedHashSet::cast(this)->NumberOfElements() > 0;
      }
      return true;
1737 1738 1739 1740 1741 1742 1743
    case SMALL_ORDERED_HASH_MAP_TYPE:
    case SMALL_ORDERED_HASH_SET_TYPE:
      return true;
    default:
      return false;
  }
}
1744

1745 1746 1747 1748 1749 1750 1751
void PropertyArray::set(int index, Object* value, WriteBarrierMode mode) {
  DCHECK_GE(index, 0);
  DCHECK_LT(index, this->length());
  int offset = kHeaderSize + index * kPointerSize;
  RELAXED_WRITE_FIELD(this, offset, value);
  CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
}
1752

1753 1754 1755
Object** PropertyArray::data_start() {
  return HeapObject::RawField(this, kHeaderSize);
}
1756

1757 1758
ACCESSORS(EnumCache, keys, FixedArray, kKeysOffset)
ACCESSORS(EnumCache, indices, FixedArray, kIndicesOffset)
1759

1760
int DescriptorArray::number_of_descriptors() const {
1761
  return Smi::ToInt(get(kDescriptorLengthIndex));
1762 1763
}

1764
int DescriptorArray::number_of_descriptors_storage() const {
1765
  return (length() - kFirstIndex) / kEntrySize;
1766 1767
}

1768
int DescriptorArray::NumberOfSlackDescriptors() const {
1769 1770 1771 1772
  return number_of_descriptors_storage() - number_of_descriptors();
}


1773
void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
1774
  set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
1775 1776
}

1777
inline int DescriptorArray::number_of_entries() const {
1778 1779 1780 1781
  return number_of_descriptors();
}

void DescriptorArray::CopyEnumCacheFrom(DescriptorArray* array) {
1782
  set(kEnumCacheIndex, array->get(kEnumCacheIndex));
1783 1784
}

1785 1786
EnumCache* DescriptorArray::GetEnumCache() {
  return EnumCache::cast(get(kEnumCacheIndex));
1787 1788
}

1789
// Perform a binary search in a fixed array.
1790
template <SearchMode search_mode, typename T>
1791
int BinarySearch(T* array, Name* name, int valid_entries,
1792
                 int* out_insertion_index) {
1793
  DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr);
1794 1795 1796
  int low = 0;
  int high = array->number_of_entries() - 1;
  uint32_t hash = name->hash_field();
1797 1798
  int limit = high;

1799
  DCHECK(low <= high);
1800 1801

  while (low != high) {
1802
    int mid = low + (high - low) / 2;
1803
    Name* mid_name = array->GetSortedKey(mid);
1804
    uint32_t mid_hash = mid_name->hash_field();
1805 1806 1807 1808 1809 1810 1811 1812

    if (mid_hash >= hash) {
      high = mid;
    } else {
      low = mid + 1;
    }
  }

1813 1814
  for (; low <= limit; ++low) {
    int sort_index = array->GetSortedKeyIndex(low);
1815
    Name* entry = array->GetKey(sort_index);
1816
    uint32_t current_hash = entry->hash_field();
1817
    if (current_hash != hash) {
1818
      if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
1819 1820 1821 1822
        *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
      }
      return T::kNotFound;
    }
1823
    if (entry == name) {
1824 1825 1826 1827 1828
      if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
        return sort_index;
      }
      return T::kNotFound;
    }
1829 1830
  }

1831 1832 1833
  if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
    *out_insertion_index = limit + 1;
  }
1834 1835 1836
  return T::kNotFound;
}

1837

1838 1839
// Perform a linear search in this fixed array. len is the number of entry
// indices that are valid.
1840
template <SearchMode search_mode, typename T>
1841
int LinearSearch(T* array, Name* name, int valid_entries,
1842
                 int* out_insertion_index) {
1843 1844 1845
  if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
    uint32_t hash = name->hash_field();
    int len = array->number_of_entries();
1846 1847
    for (int number = 0; number < len; number++) {
      int sorted_index = array->GetSortedKeyIndex(number);
1848
      Name* entry = array->GetKey(sorted_index);
1849
      uint32_t current_hash = entry->hash_field();
1850
      if (current_hash > hash) {
1851
        *out_insertion_index = sorted_index;
1852 1853
        return T::kNotFound;
      }
1854
      if (entry == name) return sorted_index;
1855
    }
1856
    *out_insertion_index = len;
1857
    return T::kNotFound;
1858
  } else {
1859
    DCHECK_LE(valid_entries, array->number_of_entries());
1860
    DCHECK_NULL(out_insertion_index);  // Not supported here.
1861
    for (int number = 0; number < valid_entries; number++) {
1862
      if (array->GetKey(number) == name) return number;
1863
    }
1864
    return T::kNotFound;
1865 1866 1867 1868
  }
}


1869 1870
template <SearchMode search_mode, typename T>
int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) {
1871
  SLOW_DCHECK(array->IsSortedNoDuplicates());
1872

1873 1874 1875 1876
  if (valid_entries == 0) {
    if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
      *out_insertion_index = 0;
    }
1877 1878
    return T::kNotFound;
  }
1879 1880 1881

  // Fast case: do linear search for small arrays.
  const int kMaxElementsForLinearSearch = 8;
1882 1883
  if (valid_entries <= kMaxElementsForLinearSearch) {
    return LinearSearch<search_mode>(array, name, valid_entries,
1884
                                     out_insertion_index);
1885 1886 1887
  }

  // Slow case: perform binary search.
1888
  return BinarySearch<search_mode>(array, name, valid_entries,
1889
                                   out_insertion_index);
1890 1891 1892
}


1893
int DescriptorArray::Search(Name* name, int valid_descriptors) {
1894
  DCHECK(name->IsUniqueName());
1895 1896
  return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors,
                                         nullptr);
1897 1898
}

1899
int DescriptorArray::SearchWithCache(Isolate* isolate, Name* name, Map* map) {
1900
  DCHECK(name->IsUniqueName());
1901 1902
  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
  if (number_of_own_descriptors == 0) return kNotFound;
1903

1904
  DescriptorLookupCache* cache = isolate->descriptor_lookup_cache();
1905
  int number = cache->Lookup(map, name);
1906

1907
  if (number == DescriptorLookupCache::kAbsent) {
1908 1909
    number = Search(name, number_of_own_descriptors);
    cache->Update(map, name, number);
1910
  }
1911

1912 1913 1914
  return number;
}

1915

1916
Object** DescriptorArray::GetKeySlot(int descriptor_number) {
1917
  DCHECK(descriptor_number < number_of_descriptors());
1918
  return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
1919 1920 1921
}


1922 1923 1924 1925 1926 1927 1928 1929 1930 1931
Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) {
  return GetKeySlot(descriptor_number);
}


Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) {
  return GetValueSlot(descriptor_number - 1) + 1;
}


1932
Name* DescriptorArray::GetKey(int descriptor_number) {
1933
  DCHECK(descriptor_number < number_of_descriptors());
1934
  return Name::cast(get(ToKeyIndex(descriptor_number)));
1935 1936 1937
}


1938 1939 1940 1941 1942
int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
  return GetDetails(descriptor_number).pointer();
}


1943
Name* DescriptorArray::GetSortedKey(int descriptor_number) {
1944 1945 1946 1947
  return GetKey(GetSortedKeyIndex(descriptor_number));
}


1948 1949 1950
void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
  PropertyDetails details = GetDetails(descriptor_index);
  set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi());
1951 1952 1953
}


1954
Object** DescriptorArray::GetValueSlot(int descriptor_number) {
1955
  DCHECK(descriptor_number < number_of_descriptors());
1956
  return RawFieldOfElementAt(ToValueIndex(descriptor_number));
1957 1958 1959
}


1960 1961 1962 1963 1964
int DescriptorArray::GetValueOffset(int descriptor_number) {
  return OffsetOfElementAt(ToValueIndex(descriptor_number));
}


1965
Object* DescriptorArray::GetValue(int descriptor_number) {
1966
  DCHECK(descriptor_number < number_of_descriptors());
1967
  return get(ToValueIndex(descriptor_number));
1968 1969 1970
}


1971 1972 1973 1974 1975
void DescriptorArray::SetValue(int descriptor_index, Object* value) {
  set(ToValueIndex(descriptor_index), value);
}


1976
PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
1977
  DCHECK(descriptor_number < number_of_descriptors());
1978
  Object* details = get(ToDetailsIndex(descriptor_number));
1979
  return PropertyDetails(Smi::cast(details));
1980 1981
}

1982
int DescriptorArray::GetFieldIndex(int descriptor_number) {
1983
  DCHECK_EQ(GetDetails(descriptor_number).location(), kField);
1984
  return GetDetails(descriptor_number).field_index();
1985 1986
}

1987
FieldType* DescriptorArray::GetFieldType(int descriptor_number) {
1988
  DCHECK_EQ(GetDetails(descriptor_number).location(), kField);
1989 1990 1991 1992
  Object* wrapped_type = GetValue(descriptor_number);
  return Map::UnwrapFieldType(wrapped_type);
}

1993
void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1994 1995
  desc->Init(handle(GetKey(descriptor_number), GetIsolate()),
             handle(GetValue(descriptor_number), GetIsolate()),
1996
             GetDetails(descriptor_number));
1997 1998
}

1999 2000
void DescriptorArray::Set(int descriptor_number, Name* key, Object* value,
                          PropertyDetails details) {
2001
  // Range check.
2002
  DCHECK(descriptor_number < number_of_descriptors());
2003 2004 2005
  set(ToKeyIndex(descriptor_number), key);
  set(ToValueIndex(descriptor_number), value);
  set(ToDetailsIndex(descriptor_number), details.AsSmi());
2006 2007
}

2008
void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
2009 2010 2011
  Name* key = *desc->GetKey();
  Object* value = *desc->GetValue();
  Set(descriptor_number, key, value, desc->GetDetails());
2012 2013 2014 2015
}


void DescriptorArray::Append(Descriptor* desc) {
2016
  DisallowHeapAllocation no_gc;
2017 2018 2019 2020 2021 2022 2023 2024 2025
  int descriptor_number = number_of_descriptors();
  SetNumberOfDescriptors(descriptor_number + 1);
  Set(descriptor_number, desc);

  uint32_t hash = desc->GetKey()->Hash();

  int insertion;

  for (insertion = descriptor_number; insertion > 0; --insertion) {
2026
    Name* key = GetSortedKey(insertion - 1);
2027 2028 2029 2030 2031 2032 2033 2034
    if (key->Hash() <= hash) break;
    SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
  }

  SetSortedKey(insertion, descriptor_number);
}


2035 2036 2037 2038
void DescriptorArray::SwapSortedKeys(int first, int second) {
  int first_key = GetSortedKeyIndex(first);
  SetSortedKey(first, GetSortedKeyIndex(second));
  SetSortedKey(second, first_key);
2039 2040
}

2041
bool StringSetShape::IsMatch(String* key, Object* value) {
2042 2043
  DCHECK(value->IsString());
  return key->Equals(String::cast(value));
2044 2045
}

2046 2047 2048
uint32_t StringSetShape::Hash(Isolate* isolate, String* key) {
  return key->Hash();
}
2049

2050
uint32_t StringSetShape::HashForObject(Isolate* isolate, Object* object) {
2051
  return String::cast(object)->Hash();
2052
}
2053

2054 2055 2056 2057 2058 2059
StringTableKey::StringTableKey(uint32_t hash_field)
    : HashTableKey(hash_field >> Name::kHashShift), hash_field_(hash_field) {}

void StringTableKey::set_hash_field(uint32_t hash_field) {
  hash_field_ = hash_field;
  set_hash(hash_field >> Name::kHashShift);
2060
}
2061

2062 2063
Handle<Object> StringTableShape::AsHandle(Isolate* isolate,
                                          StringTableKey* key) {
2064 2065 2066
  return key->AsHandle(isolate);
}

2067
uint32_t StringTableShape::HashForObject(Isolate* isolate, Object* object) {
2068 2069 2070
  return String::cast(object)->Hash();
}

2071 2072
int StringTableShape::GetMapRootIndex() {
  return Heap::kStringTableMapRootIndex;
2073 2074
}

2075
bool NumberDictionary::requires_slow_elements() {
2076
  Object* max_index_object = get(kMaxNumberKeyIndex);
2077
  if (!max_index_object->IsSmi()) return false;
jgruber's avatar
jgruber committed
2078
  return 0 != (Smi::ToInt(max_index_object) & kRequiresSlowElementsMask);
2079 2080
}

2081
uint32_t NumberDictionary::max_number_key() {
2082
  DCHECK(!requires_slow_elements());
2083
  Object* max_index_object = get(kMaxNumberKeyIndex);
2084
  if (!max_index_object->IsSmi()) return 0;
jgruber's avatar
jgruber committed
2085
  uint32_t value = static_cast<uint32_t>(Smi::ToInt(max_index_object));
2086 2087 2088
  return value >> kRequiresSlowElementsTagSize;
}

2089
void NumberDictionary::set_requires_slow_elements() {
2090
  set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
2091 2092
}

2093 2094 2095
DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
DEFINE_DEOPT_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
DEFINE_DEOPT_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
2096
DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrBytecodeOffset, Smi)
2097 2098 2099
DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi)
DEFINE_DEOPT_ELEMENT_ACCESSORS(WeakCellCache, Object)
2100
DEFINE_DEOPT_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
2101

2102
DEFINE_DEOPT_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
2103 2104 2105
DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi)
DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi)

2106
int PropertyArray::length() const {
2107
  Object* value_obj = READ_FIELD(this, kLengthAndHashOffset);
2108
  int value = Smi::ToInt(value_obj);
2109
  return LengthField::decode(value);
2110 2111 2112 2113
}

void PropertyArray::initialize_length(int len) {
  SLOW_DCHECK(len >= 0);
2114
  SLOW_DCHECK(len < LengthField::kMax);
2115
  WRITE_FIELD(this, kLengthAndHashOffset, Smi::FromInt(len));
2116 2117 2118
}

int PropertyArray::synchronized_length() const {
2119
  Object* value_obj = ACQUIRE_READ_FIELD(this, kLengthAndHashOffset);
2120
  int value = Smi::ToInt(value_obj);
2121
  return LengthField::decode(value);
2122 2123 2124
}

int PropertyArray::Hash() const {
2125
  Object* value_obj = READ_FIELD(this, kLengthAndHashOffset);
2126
  int value = Smi::ToInt(value_obj);
2127
  return HashField::decode(value);
2128 2129
}

2130
void PropertyArray::SetHash(int hash) {
2131
  Object* value_obj = READ_FIELD(this, kLengthAndHashOffset);
2132
  int value = Smi::ToInt(value_obj);
2133
  value = HashField::update(value, hash);
2134
  WRITE_FIELD(this, kLengthAndHashOffset, Smi::FromInt(value));
2135
}
2136

2137
SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2138
RELAXED_SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2139

2140

2141 2142 2143
int FreeSpace::Size() { return size(); }


2144
FreeSpace* FreeSpace::next() {
2145
  DCHECK(map() == GetHeap()->root(Heap::kFreeSpaceMapRootIndex) ||
2146
         (!GetHeap()->deserialization_complete() && map() == nullptr));
2147
  DCHECK_LE(kNextOffset + kPointerSize, relaxed_read_size());
2148 2149 2150 2151 2152 2153
  return reinterpret_cast<FreeSpace*>(
      Memory::Address_at(address() + kNextOffset));
}


void FreeSpace::set_next(FreeSpace* next) {
2154
  DCHECK(map() == GetHeap()->root(Heap::kFreeSpaceMapRootIndex) ||
2155
         (!GetHeap()->deserialization_complete() && map() == nullptr));
2156 2157
  DCHECK_LE(kNextOffset + kPointerSize, relaxed_read_size());
  base::Relaxed_Store(
2158 2159 2160 2161 2162 2163 2164 2165 2166 2167
      reinterpret_cast<base::AtomicWord*>(address() + kNextOffset),
      reinterpret_cast<base::AtomicWord>(next));
}


FreeSpace* FreeSpace::cast(HeapObject* o) {
  SLOW_DCHECK(!o->GetHeap()->deserialization_complete() || o->IsFreeSpace());
  return reinterpret_cast<FreeSpace*>(o);
}

2168
int HeapObject::SizeFromMap(Map* map) const {
2169 2170
  int instance_size = map->instance_size();
  if (instance_size != kVariableSizeSentinel) return instance_size;
2171
  // Only inline the most frequent cases.
yangguo@chromium.org's avatar
yangguo@chromium.org committed
2172
  InstanceType instance_type = map->instance_type();
2173 2174
  if (instance_type >= FIRST_FIXED_ARRAY_TYPE &&
      instance_type <= LAST_FIXED_ARRAY_TYPE) {
2175
    return FixedArray::SizeFor(
2176
        reinterpret_cast<const FixedArray*>(this)->synchronized_length());
2177
  }
2178 2179
  if (instance_type == ONE_BYTE_STRING_TYPE ||
      instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) {
2180 2181
    // Strings may get concurrently truncated, hence we have to access its
    // length synchronized.
2182
    return SeqOneByteString::SizeFor(
2183
        reinterpret_cast<const SeqOneByteString*>(this)->synchronized_length());
2184
  }
2185
  if (instance_type == BYTE_ARRAY_TYPE) {
2186
    return ByteArray::SizeFor(
2187
        reinterpret_cast<const ByteArray*>(this)->synchronized_length());
2188
  }
2189
  if (instance_type == BYTECODE_ARRAY_TYPE) {
2190
    return BytecodeArray::SizeFor(
2191
        reinterpret_cast<const BytecodeArray*>(this)->synchronized_length());
2192
  }
2193
  if (instance_type == FREE_SPACE_TYPE) {
2194
    return reinterpret_cast<const FreeSpace*>(this)->relaxed_read_size();
2195
  }
2196 2197
  if (instance_type == STRING_TYPE ||
      instance_type == INTERNALIZED_STRING_TYPE) {
2198 2199
    // Strings may get concurrently truncated, hence we have to access its
    // length synchronized.
2200
    return SeqTwoByteString::SizeFor(
2201
        reinterpret_cast<const SeqTwoByteString*>(this)->synchronized_length());
2202
  }
2203 2204
  if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
    return FixedDoubleArray::SizeFor(
2205
        reinterpret_cast<const FixedDoubleArray*>(this)->synchronized_length());
2206
  }
2207 2208
  if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
      instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
2209 2210
    return reinterpret_cast<const FixedTypedArrayBase*>(this)->TypedArraySize(
        instance_type);
2211
  }
2212
  if (instance_type == SMALL_ORDERED_HASH_SET_TYPE) {
2213
    return reinterpret_cast<const SmallOrderedHashSet*>(this)->Size();
2214
  }
2215 2216 2217 2218
  if (instance_type == PROPERTY_ARRAY_TYPE) {
    return PropertyArray::SizeFor(
        reinterpret_cast<const PropertyArray*>(this)->synchronized_length());
  }
2219
  if (instance_type == SMALL_ORDERED_HASH_MAP_TYPE) {
2220
    return reinterpret_cast<const SmallOrderedHashMap*>(this)->Size();
2221
  }
2222 2223 2224 2225
  if (instance_type == FEEDBACK_VECTOR_TYPE) {
    return FeedbackVector::SizeFor(
        reinterpret_cast<const FeedbackVector*>(this)->length());
  }
2226 2227 2228
  if (instance_type == BIGINT_TYPE) {
    return BigInt::SizeFor(reinterpret_cast<const BigInt*>(this)->length());
  }
2229
  DCHECK(instance_type == CODE_TYPE);
2230
  return reinterpret_cast<const Code*>(this)->CodeSize();
2231 2232
}

2233 2234 2235
Object* JSBoundFunction::raw_bound_target_function() const {
  return READ_FIELD(this, kBoundTargetFunctionOffset);
}
2236

2237 2238 2239 2240 2241
ACCESSORS(JSBoundFunction, bound_target_function, JSReceiver,
          kBoundTargetFunctionOffset)
ACCESSORS(JSBoundFunction, bound_this, Object, kBoundThisOffset)
ACCESSORS(JSBoundFunction, bound_arguments, FixedArray, kBoundArgumentsOffset)

2242
ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2243
ACCESSORS(JSFunction, feedback_vector_cell, Cell, kFeedbackVectorOffset)
2244

2245 2246
ACCESSORS(JSGlobalObject, native_context, Context, kNativeContextOffset)
ACCESSORS(JSGlobalObject, global_proxy, JSObject, kGlobalProxyOffset)
2247

2248
ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
2249

2250 2251
ACCESSORS(AccessorInfo, name, Name, kNameOffset)
SMI_ACCESSORS(AccessorInfo, flags, kFlagsOffset)
2252 2253
ACCESSORS(AccessorInfo, expected_receiver_type, Object,
          kExpectedReceiverTypeOffset)
2254

2255 2256 2257 2258
ACCESSORS_CHECKED2(AccessorInfo, getter, Object, kGetterOffset, true,
                   Foreign::IsNormalized(value))
ACCESSORS_CHECKED2(AccessorInfo, setter, Object, kSetterOffset, true,
                   Foreign::IsNormalized(value));
2259
ACCESSORS(AccessorInfo, js_getter, Object, kJsGetterOffset)
2260
ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2261

2262 2263 2264 2265 2266 2267 2268
bool AccessorInfo::has_getter() {
  bool result = getter() != Smi::kZero;
  DCHECK_EQ(result, getter() != Smi::kZero &&
                        Foreign::cast(getter())->foreign_address() != nullptr);
  return result;
}

2269 2270 2271 2272
ACCESSORS(PromiseResolveThenableJobInfo, thenable, JSReceiver, kThenableOffset)
ACCESSORS(PromiseResolveThenableJobInfo, then, JSReceiver, kThenOffset)
ACCESSORS(PromiseResolveThenableJobInfo, resolve, JSFunction, kResolveOffset)
ACCESSORS(PromiseResolveThenableJobInfo, reject, JSFunction, kRejectOffset)
2273
ACCESSORS(PromiseResolveThenableJobInfo, context, Context, kContextOffset);
2274

2275 2276
ACCESSORS(PromiseReactionJobInfo, value, Object, kValueOffset);
ACCESSORS(PromiseReactionJobInfo, tasks, Object, kTasksOffset);
2277 2278 2279 2280 2281 2282
ACCESSORS(PromiseReactionJobInfo, deferred_promise, Object,
          kDeferredPromiseOffset);
ACCESSORS(PromiseReactionJobInfo, deferred_on_resolve, Object,
          kDeferredOnResolveOffset);
ACCESSORS(PromiseReactionJobInfo, deferred_on_reject, Object,
          kDeferredOnRejectOffset);
2283 2284
ACCESSORS(PromiseReactionJobInfo, context, Context, kContextOffset);

2285 2286 2287 2288 2289
ACCESSORS(AsyncGeneratorRequest, next, Object, kNextOffset)
SMI_ACCESSORS(AsyncGeneratorRequest, resume_mode, kResumeModeOffset)
ACCESSORS(AsyncGeneratorRequest, value, Object, kValueOffset)
ACCESSORS(AsyncGeneratorRequest, promise, Object, kPromiseOffset)

2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305
Map* PrototypeInfo::ObjectCreateMap() {
  return Map::cast(WeakCell::cast(object_create_map())->value());
}

// static
void PrototypeInfo::SetObjectCreateMap(Handle<PrototypeInfo> info,
                                       Handle<Map> map) {
  Handle<WeakCell> cell = Map::WeakCellForMap(map);
  info->set_object_create_map(*cell);
}

bool PrototypeInfo::HasObjectCreateMap() {
  Object* cache = object_create_map();
  return cache->IsWeakCell() && !WeakCell::cast(cache)->cleared();
}

2306 2307 2308 2309
bool FunctionTemplateInfo::instantiated() {
  return shared_function_info()->IsSharedFunctionInfo();
}

2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330
FunctionTemplateInfo* FunctionTemplateInfo::GetParent(Isolate* isolate) {
  Object* parent = parent_template();
  return parent->IsUndefined(isolate) ? nullptr
                                      : FunctionTemplateInfo::cast(parent);
}

ObjectTemplateInfo* ObjectTemplateInfo::GetParent(Isolate* isolate) {
  Object* maybe_ctor = constructor();
  if (maybe_ctor->IsUndefined(isolate)) return nullptr;
  FunctionTemplateInfo* constructor = FunctionTemplateInfo::cast(maybe_ctor);
  while (true) {
    constructor = constructor->GetParent(isolate);
    if (constructor == nullptr) return nullptr;
    Object* maybe_obj = constructor->instance_template();
    if (!maybe_obj->IsUndefined(isolate)) {
      return ObjectTemplateInfo::cast(maybe_obj);
    }
  }
  return nullptr;
}

2331
ACCESSORS(PrototypeInfo, weak_cell, Object, kWeakCellOffset)
2332
ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset)
2333
ACCESSORS(PrototypeInfo, object_create_map, Object, kObjectCreateMap)
2334
SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset)
2335
ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset)
2336 2337
SMI_ACCESSORS(PrototypeInfo, bit_field, kBitFieldOffset)
BOOL_ACCESSORS(PrototypeInfo, bit_field, should_be_fast_map, kShouldBeFastBit)
2338

2339 2340
ACCESSORS(Tuple2, value1, Object, kValue1Offset)
ACCESSORS(Tuple2, value2, Object, kValue2Offset)
2341 2342
ACCESSORS(Tuple3, value3, Object, kValue3Offset)

2343 2344
ACCESSORS(ContextExtension, scope_info, ScopeInfo, kScopeInfoOffset)
ACCESSORS(ContextExtension, extension, Object, kExtensionOffset)
2345

2346 2347 2348
SMI_ACCESSORS(ConstantElementsPair, elements_kind, kElementsKindOffset)
ACCESSORS(ConstantElementsPair, constant_values, FixedArrayBase,
          kConstantValuesOffset)
2349 2350 2351
bool ConstantElementsPair::is_empty() const {
  return constant_values()->length() == 0;
}
2352

2353 2354 2355 2356 2357
SMI_ACCESSORS(TemplateObjectDescription, hash, kHashOffset)
ACCESSORS(TemplateObjectDescription, raw_strings, FixedArray, kRawStringsOffset)
ACCESSORS(TemplateObjectDescription, cooked_strings, FixedArray,
          kCookedStringsOffset)

2358 2359 2360
ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
ACCESSORS(AccessorPair, setter, Object, kSetterOffset)

2361
ACCESSORS(AccessCheckInfo, callback, Object, kCallbackOffset)
2362 2363 2364
ACCESSORS(AccessCheckInfo, named_interceptor, Object, kNamedInterceptorOffset)
ACCESSORS(AccessCheckInfo, indexed_interceptor, Object,
          kIndexedInterceptorOffset)
2365 2366 2367 2368 2369
ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)

ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2370
ACCESSORS(InterceptorInfo, descriptor, Object, kDescriptorOffset)
2371 2372
ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2373
ACCESSORS(InterceptorInfo, definer, Object, kDefinerOffset)
2374
ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2375 2376 2377
SMI_ACCESSORS(InterceptorInfo, flags, kFlagsOffset)
BOOL_ACCESSORS(InterceptorInfo, flags, can_intercept_symbols,
               kCanInterceptSymbolsBit)
2378
BOOL_ACCESSORS(InterceptorInfo, flags, all_can_read, kAllCanReadBit)
2379
BOOL_ACCESSORS(InterceptorInfo, flags, non_masking, kNonMasking)
2380
BOOL_ACCESSORS(InterceptorInfo, flags, is_named, kNamed)
2381 2382

ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2383
ACCESSORS(CallHandlerInfo, js_callback, Object, kJsCallbackOffset)
2384 2385 2386
ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)

ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2387
ACCESSORS(TemplateInfo, serial_number, Object, kSerialNumberOffset)
2388
SMI_ACCESSORS(TemplateInfo, number_of_properties, kNumberOfProperties)
2389
ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2390
ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset)
2391 2392 2393 2394

ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
          kPrototypeTemplateOffset)
2395 2396 2397
ACCESSORS(FunctionTemplateInfo, prototype_provider_template, Object,
          kPrototypeProviderTemplateOffset)

2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
          kNamedPropertyHandlerOffset)
ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
          kIndexedPropertyHandlerOffset)
ACCESSORS(FunctionTemplateInfo, instance_template, Object,
          kInstanceTemplateOffset)
ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
          kInstanceCallHandlerOffset)
ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
          kAccessCheckInfoOffset)
2411 2412
ACCESSORS(FunctionTemplateInfo, shared_function_info, Object,
          kSharedFunctionInfoOffset)
2413 2414
ACCESSORS(FunctionTemplateInfo, cached_property_name, Object,
          kCachedPropertyNameOffset)
2415

2416
SMI_ACCESSORS(FunctionTemplateInfo, flag, kFlagOffset)
2417 2418

ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2419
ACCESSORS(ObjectTemplateInfo, data, Object, kDataOffset)
2420

2421
int ObjectTemplateInfo::embedder_field_count() const {
2422 2423
  Object* value = data();
  DCHECK(value->IsSmi());
jgruber's avatar
jgruber committed
2424
  return EmbedderFieldCount::decode(Smi::ToInt(value));
2425
}
2426

2427
void ObjectTemplateInfo::set_embedder_field_count(int count) {
jgruber's avatar
jgruber committed
2428 2429
  return set_data(
      Smi::FromInt(EmbedderFieldCount::update(Smi::ToInt(data()), count)));
2430
}
2431

2432 2433 2434
bool ObjectTemplateInfo::immutable_proto() const {
  Object* value = data();
  DCHECK(value->IsSmi());
jgruber's avatar
jgruber committed
2435
  return IsImmutablePrototype::decode(Smi::ToInt(value));
2436
}
2437

2438 2439
void ObjectTemplateInfo::set_immutable_proto(bool immutable) {
  return set_data(Smi::FromInt(
jgruber's avatar
jgruber committed
2440
      IsImmutablePrototype::update(Smi::ToInt(data()), immutable)));
2441
}
2442

2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464
ACCESSORS(AllocationSite, transition_info_or_boilerplate, Object,
          kTransitionInfoOrBoilerplateOffset)

JSObject* AllocationSite::boilerplate() const {
  DCHECK(PointsToLiteral());
  return JSObject::cast(transition_info_or_boilerplate());
}

void AllocationSite::set_boilerplate(JSObject* object, WriteBarrierMode mode) {
  set_transition_info_or_boilerplate(object, mode);
}

int AllocationSite::transition_info() const {
  DCHECK(!PointsToLiteral());
  return Smi::cast(transition_info_or_boilerplate())->value();
}

void AllocationSite::set_transition_info(int value) {
  DCHECK(!PointsToLiteral());
  set_transition_info_or_boilerplate(Smi::FromInt(value), SKIP_WRITE_BARRIER);
}

2465
ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
2466 2467 2468
SMI_ACCESSORS(AllocationSite, pretenure_data, kPretenureDataOffset)
SMI_ACCESSORS(AllocationSite, pretenure_create_count,
              kPretenureCreateCountOffset)
2469 2470
ACCESSORS(AllocationSite, dependent_code, DependentCode,
          kDependentCodeOffset)
2471
ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
2472
ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset)
2473

2474 2475 2476 2477 2478 2479 2480 2481 2482 2483
SMI_ACCESSORS(StackFrameInfo, line_number, kLineNumberIndex)
SMI_ACCESSORS(StackFrameInfo, column_number, kColumnNumberIndex)
SMI_ACCESSORS(StackFrameInfo, script_id, kScriptIdIndex)
ACCESSORS(StackFrameInfo, script_name, Object, kScriptNameIndex)
ACCESSORS(StackFrameInfo, script_name_or_source_url, Object,
          kScriptNameOrSourceUrlIndex)
ACCESSORS(StackFrameInfo, function_name, Object, kFunctionNameIndex)
SMI_ACCESSORS(StackFrameInfo, flag, kFlagIndex)
BOOL_ACCESSORS(StackFrameInfo, flag, is_eval, kIsEvalBit)
BOOL_ACCESSORS(StackFrameInfo, flag, is_constructor, kIsConstructorBit)
2484
BOOL_ACCESSORS(StackFrameInfo, flag, is_wasm, kIsWasmBit)
2485
SMI_ACCESSORS(StackFrameInfo, id, kIdIndex)
2486

2487 2488 2489
ACCESSORS(SourcePositionTableWithFrameCache, source_position_table, ByteArray,
          kSourcePositionTableIndex)
ACCESSORS(SourcePositionTableWithFrameCache, stack_frame_cache,
2490
          NumberDictionary, kStackFrameCacheIndex)
2491

2492
SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset)
2493 2494 2495 2496 2497
BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
               kHiddenPrototypeBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
               kNeedsAccessCheckBit)
2498 2499
BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
               kReadOnlyPrototypeBit)
2500 2501
BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
               kRemovePrototypeBit)
2502 2503
BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
               kDoNotCacheBit)
2504 2505
BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver,
               kAcceptAnyReceiver)
2506

2507 2508 2509
FeedbackVector* JSFunction::feedback_vector() const {
  DCHECK(feedback_vector_cell()->value()->IsFeedbackVector());
  return FeedbackVector::cast(feedback_vector_cell()->value());
2510
}
2511

2512 2513 2514 2515 2516 2517
// Code objects that are marked for deoptimization are not considered to be
// optimized. This is because the JSFunction might have been already
// deoptimized but its code() still needs to be unlinked, which will happen on
// its next activation.
// TODO(jupvfranco): rename this function. Maybe RunOptimizedCode,
// or IsValidOptimizedCode.
2518
bool JSFunction::IsOptimized() {
2519 2520
  return code()->kind() == Code::OPTIMIZED_FUNCTION &&
         !code()->marked_for_deoptimization();
2521 2522
}

2523 2524
bool JSFunction::HasOptimizedCode() {
  return IsOptimized() ||
2525 2526
         (has_feedback_vector() && feedback_vector()->has_optimized_code() &&
          !feedback_vector()->optimized_code()->marked_for_deoptimization());
2527 2528 2529 2530 2531 2532 2533 2534
}

bool JSFunction::HasOptimizationMarker() {
  return has_feedback_vector() && feedback_vector()->has_optimization_marker();
}

void JSFunction::ClearOptimizationMarker() {
  DCHECK(has_feedback_vector());
2535
  feedback_vector()->ClearOptimizationMarker();
2536 2537
}

2538 2539 2540 2541
bool JSFunction::IsInterpreted() {
  return code()->is_interpreter_trampoline_builtin();
}

2542 2543 2544 2545
bool JSFunction::ChecksOptimizationMarker() {
  return code()->checks_optimization_marker();
}

2546
bool JSFunction::IsMarkedForOptimization() {
2547 2548
  return has_feedback_vector() && feedback_vector()->optimization_marker() ==
                                      OptimizationMarker::kCompileOptimized;
2549 2550 2551
}


2552
bool JSFunction::IsMarkedForConcurrentOptimization() {
2553 2554 2555
  return has_feedback_vector() &&
         feedback_vector()->optimization_marker() ==
             OptimizationMarker::kCompileOptimizedConcurrent;
2556 2557 2558
}


2559
bool JSFunction::IsInOptimizationQueue() {
2560 2561
  return has_feedback_vector() && feedback_vector()->optimization_marker() ==
                                      OptimizationMarker::kInOptimizationQueue;
2562 2563 2564
}


2565
void JSFunction::CompleteInobjectSlackTrackingIfActive() {
2566
  if (!has_prototype_slot()) return;
2567 2568 2569 2570 2571
  if (has_initial_map() && initial_map()->IsInobjectSlackTrackingInProgress()) {
    initial_map()->CompleteInobjectSlackTracking();
  }
}

2572
AbstractCode* JSFunction::abstract_code() {
2573
  if (IsInterpreted()) {
2574 2575
    return AbstractCode::cast(shared()->bytecode_array());
  } else {
2576
    return AbstractCode::cast(code());
2577 2578
  }
}
2579

2580
Code* JSFunction::code() { return Code::cast(READ_FIELD(this, kCodeOffset)); }
2581

2582
void JSFunction::set_code(Code* value) {
2583
  DCHECK(!GetHeap()->InNewSpace(value));
2584 2585 2586
  WRITE_FIELD(this, kCodeOffset, value);
  GetHeap()->incremental_marking()->RecordWrite(
      this, HeapObject::RawField(this, kCodeOffset), value);
2587 2588 2589
}


2590
void JSFunction::set_code_no_write_barrier(Code* value) {
2591
  DCHECK(!GetHeap()->InNewSpace(value));
2592
  WRITE_FIELD(this, kCodeOffset, value);
2593 2594
}

2595 2596 2597 2598 2599
void JSFunction::ClearOptimizedCodeSlot(const char* reason) {
  if (has_feedback_vector() && feedback_vector()->has_optimized_code()) {
    if (FLAG_trace_opt) {
      PrintF("[evicting entry from optimizing code feedback slot (%s) for ",
             reason);
2600
      ShortPrint();
2601 2602 2603 2604 2605
      PrintF("]\n");
    }
    feedback_vector()->ClearOptimizedCode();
  }
}
2606

2607 2608 2609 2610 2611 2612 2613 2614
void JSFunction::SetOptimizationMarker(OptimizationMarker marker) {
  DCHECK(has_feedback_vector());
  DCHECK(ChecksOptimizationMarker());
  DCHECK(!HasOptimizedCode());

  feedback_vector()->SetOptimizationMarker(marker);
}

2615
bool JSFunction::has_feedback_vector() const {
2616
  return !feedback_vector_cell()->value()->IsUndefined(GetIsolate());
2617
}
2618

2619 2620 2621
JSFunction::FeedbackVectorState JSFunction::GetFeedbackVectorState(
    Isolate* isolate) const {
  Cell* cell = feedback_vector_cell();
2622 2623 2624
  if (shared()->HasAsmWasmData()) {
    return NO_VECTOR_NEEDED;
  } else if (cell == isolate->heap()->undefined_cell()) {
2625 2626 2627 2628 2629 2630 2631 2632
    return TOP_LEVEL_SCRIPT_NEEDS_VECTOR;
  } else if (cell->value() == isolate->heap()->undefined_value() ||
             !has_feedback_vector()) {
    return NEEDS_VECTOR;
  }
  return HAS_VECTOR;
}

2633 2634 2635 2636
Context* JSFunction::context() {
  return Context::cast(READ_FIELD(this, kContextOffset));
}

2637 2638 2639
bool JSFunction::has_context() const {
  return READ_FIELD(this, kContextOffset)->IsContext();
}
2640

2641 2642 2643 2644 2645
JSObject* JSFunction::global_proxy() {
  return context()->global_proxy();
}


2646 2647 2648
Context* JSFunction::native_context() { return context()->native_context(); }


2649
void JSFunction::set_context(Object* value) {
2650
  DCHECK(value->IsUndefined(GetIsolate()) || value->IsContext());
2651
  WRITE_FIELD(this, kContextOffset, value);
2652
  WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
2653 2654
}

2655 2656
ACCESSORS_CHECKED(JSFunction, prototype_or_initial_map, Object,
                  kPrototypeOrInitialMapOffset, map()->has_prototype_slot())
2657

2658 2659 2660
bool JSFunction::has_prototype_slot() const {
  return map()->has_prototype_slot();
}
2661 2662 2663 2664 2665 2666 2667

Map* JSFunction::initial_map() {
  return Map::cast(prototype_or_initial_map());
}


bool JSFunction::has_initial_map() {
2668
  DCHECK(has_prototype_slot());
2669 2670 2671 2672 2673
  return prototype_or_initial_map()->IsMap();
}


bool JSFunction::has_instance_prototype() {
2674
  DCHECK(has_prototype_slot());
2675 2676
  return has_initial_map() ||
         !prototype_or_initial_map()->IsTheHole(GetIsolate());
2677 2678 2679 2680
}


bool JSFunction::has_prototype() {
2681
  DCHECK(has_prototype_slot());
2682 2683 2684 2685 2686
  return map()->has_non_instance_prototype() || has_instance_prototype();
}


Object* JSFunction::instance_prototype() {
2687
  DCHECK(has_instance_prototype());
2688 2689 2690 2691 2692 2693 2694 2695
  if (has_initial_map()) return initial_map()->prototype();
  // When there is no initial map and the prototype is a JSObject, the
  // initial map field is used for the prototype field.
  return prototype_or_initial_map();
}


Object* JSFunction::prototype() {
2696
  DCHECK(has_prototype());
2697 2698
  // If the function's prototype property has been set to a non-JSObject
  // value, that value is stored in the constructor field of the map.
2699 2700 2701 2702
  if (map()->has_non_instance_prototype()) {
    Object* prototype = map()->GetConstructor();
    // The map must have a prototype in that field, not a back pointer.
    DCHECK(!prototype->IsMap());
2703
    DCHECK(!prototype->IsFunctionTemplateInfo());
2704 2705
    return prototype;
  }
2706 2707 2708
  return instance_prototype();
}

2709

2710
bool JSFunction::is_compiled() {
2711
  Builtins* builtins = GetIsolate()->builtins();
2712
  return code() != builtins->builtin(Builtins::kCompileLazy);
2713 2714
}

2715
ACCESSORS(JSProxy, target, JSReceiver, kTargetOffset)
2716
ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
2717

2718 2719
bool JSProxy::IsRevoked() const { return !handler()->IsJSReceiver(); }

2720 2721 2722 2723 2724 2725
// static
bool Foreign::IsNormalized(Object* value) {
  if (value == Smi::kZero) return true;
  return Foreign::cast(value)->foreign_address() != nullptr;
}

2726 2727
Address Foreign::foreign_address() {
  return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
2728 2729
}

2730 2731
void Foreign::set_foreign_address(Address value) {
  WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
2732 2733
}

2734
template <class Derived>
2735 2736 2737 2738 2739
void SmallOrderedHashTable<Derived>::SetDataEntry(int entry, int relative_index,
                                                  Object* value) {
  int entry_offset = GetDataEntryOffset(entry, relative_index);
  RELAXED_WRITE_FIELD(this, entry_offset, value);
  WRITE_BARRIER(GetHeap(), this, entry_offset, value);
2740
}
2741

2742
ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
2743
ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
2744
ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
2745
ACCESSORS(JSGeneratorObject, input_or_debug_pos, Object, kInputOrDebugPosOffset)
2746
SMI_ACCESSORS(JSGeneratorObject, resume_mode, kResumeModeOffset)
2747
SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
2748
ACCESSORS(JSGeneratorObject, register_file, FixedArray, kRegisterFileOffset)
2749

2750
bool JSGeneratorObject::is_suspended() const {
2751 2752 2753
  DCHECK_LT(kGeneratorExecuting, 0);
  DCHECK_LT(kGeneratorClosed, 0);
  return continuation() >= 0;
2754
}
2755

2756
bool JSGeneratorObject::is_closed() const {
2757 2758 2759
  return continuation() == kGeneratorClosed;
}

2760
bool JSGeneratorObject::is_executing() const {
2761 2762 2763
  return continuation() == kGeneratorExecuting;
}

2764 2765 2766 2767
ACCESSORS(JSAsyncGeneratorObject, queue, HeapObject, kQueueOffset)
ACCESSORS(JSAsyncGeneratorObject, awaited_promise, HeapObject,
          kAwaitedPromiseOffset)

2768 2769 2770
ACCESSORS(JSValue, value, Object, kValueOffset)


2771
HeapNumber* HeapNumber::cast(Object* object) {
2772
  SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
2773 2774 2775 2776 2777
  return reinterpret_cast<HeapNumber*>(object);
}


const HeapNumber* HeapNumber::cast(const Object* object) {
2778
  SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
2779 2780 2781 2782
  return reinterpret_cast<const HeapNumber*>(object);
}


2783
ACCESSORS(JSDate, value, Object, kValueOffset)
2784
ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
2785 2786 2787
ACCESSORS(JSDate, year, Object, kYearOffset)
ACCESSORS(JSDate, month, Object, kMonthOffset)
ACCESSORS(JSDate, day, Object, kDayOffset)
2788
ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
2789 2790 2791 2792 2793
ACCESSORS(JSDate, hour, Object, kHourOffset)
ACCESSORS(JSDate, min, Object, kMinOffset)
ACCESSORS(JSDate, sec, Object, kSecOffset)


2794 2795
SMI_ACCESSORS(JSMessageObject, type, kTypeOffset)
ACCESSORS(JSMessageObject, argument, Object, kArgumentsOffset)
2796 2797 2798 2799
ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
2800
SMI_ACCESSORS(JSMessageObject, error_level, kErrorLevelOffset)
2801

2802

2803

2804 2805 2806
ACCESSORS(PromiseCapability, promise, Object, kPromiseOffset)
ACCESSORS(PromiseCapability, resolve, Object, kResolveOffset)
ACCESSORS(PromiseCapability, reject, Object, kRejectOffset)
2807

2808
ACCESSORS(JSPromise, result, Object, kResultOffset)
2809 2810 2811
ACCESSORS(JSPromise, deferred_promise, Object, kDeferredPromiseOffset)
ACCESSORS(JSPromise, deferred_on_resolve, Object, kDeferredOnResolveOffset)
ACCESSORS(JSPromise, deferred_on_reject, Object, kDeferredOnRejectOffset)
2812 2813
ACCESSORS(JSPromise, fulfill_reactions, Object, kFulfillReactionsOffset)
ACCESSORS(JSPromise, reject_reactions, Object, kRejectReactionsOffset)
2814 2815
SMI_ACCESSORS(JSPromise, flags, kFlagsOffset)
BOOL_ACCESSORS(JSPromise, flags, has_handler, kHasHandlerBit)
2816
BOOL_ACCESSORS(JSPromise, flags, handled_hint, kHandledHintBit)
2817

2818

2819
ElementsKind JSObject::GetElementsKind() {
2820
  ElementsKind kind = map()->elements_kind();
2821 2822 2823 2824 2825 2826 2827 2828
#if VERIFY_HEAP && DEBUG
  FixedArrayBase* fixed_array =
      reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));

  // If a GC was caused while constructing this object, the elements
  // pointer may point to a one pointer filler map.
  if (ElementsAreSafeToExamine()) {
    Map* map = fixed_array->map();
2829
    if (IsSmiOrObjectElementsKind(kind)) {
2830 2831
      DCHECK(map == GetHeap()->fixed_array_map() ||
             map == GetHeap()->fixed_cow_array_map());
2832
    } else if (IsDoubleElementsKind(kind)) {
2833 2834 2835 2836 2837 2838 2839 2840
      DCHECK(fixed_array->IsFixedDoubleArray() ||
             fixed_array == GetHeap()->empty_fixed_array());
    } else if (kind == DICTIONARY_ELEMENTS) {
      DCHECK(fixed_array->IsFixedArray());
      DCHECK(fixed_array->IsDictionary());
    } else {
      DCHECK(kind > DICTIONARY_ELEMENTS);
    }
2841
    DCHECK(!IsSloppyArgumentsElementsKind(kind) ||
2842 2843 2844
           (elements()->IsFixedArray() && elements()->length() >= 2));
  }
#endif
2845
  return kind;
2846 2847
}

2848 2849
bool JSObject::HasObjectElements() {
  return IsObjectElementsKind(GetElementsKind());
2850 2851
}

2852
bool JSObject::HasSmiElements() { return IsSmiElementsKind(GetElementsKind()); }
2853

2854 2855
bool JSObject::HasSmiOrObjectElements() {
  return IsSmiOrObjectElementsKind(GetElementsKind());
2856 2857
}

2858 2859
bool JSObject::HasDoubleElements() {
  return IsDoubleElementsKind(GetElementsKind());
2860 2861
}

2862 2863
bool JSObject::HasHoleyElements() {
  return IsHoleyElementsKind(GetElementsKind());
2864 2865 2866
}


2867 2868 2869 2870 2871
bool JSObject::HasFastElements() {
  return IsFastElementsKind(GetElementsKind());
}


2872 2873 2874 2875 2876
bool JSObject::HasDictionaryElements() {
  return GetElementsKind() == DICTIONARY_ELEMENTS;
}


2877 2878 2879 2880 2881 2882 2883 2884 2885 2886
bool JSObject::HasFastArgumentsElements() {
  return GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
}


bool JSObject::HasSlowArgumentsElements() {
  return GetElementsKind() == SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
}


2887
bool JSObject::HasSloppyArgumentsElements() {
2888
  return IsSloppyArgumentsElementsKind(GetElementsKind());
2889 2890
}

2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901
bool JSObject::HasStringWrapperElements() {
  return IsStringWrapperElementsKind(GetElementsKind());
}

bool JSObject::HasFastStringWrapperElements() {
  return GetElementsKind() == FAST_STRING_WRAPPER_ELEMENTS;
}

bool JSObject::HasSlowStringWrapperElements() {
  return GetElementsKind() == SLOW_STRING_WRAPPER_ELEMENTS;
}
2902

2903
bool JSObject::HasFixedTypedArrayElements() {
2904 2905
  DCHECK_NOT_NULL(elements());
  return map()->has_fixed_typed_array_elements();
2906 2907
}

2908 2909 2910
#define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype, size)      \
  bool JSObject::HasFixed##Type##Elements() {                          \
    HeapObject* array = elements();                                    \
2911
    DCHECK_NOT_NULL(array);                                            \
2912 2913 2914
    if (!array->IsHeapObject()) return false;                          \
    return array->map()->instance_type() == FIXED_##TYPE##_ARRAY_TYPE; \
  }
2915 2916 2917 2918 2919 2920

TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK)

#undef FIXED_TYPED_ELEMENTS_CHECK


2921 2922 2923 2924 2925 2926 2927 2928 2929
bool JSObject::HasNamedInterceptor() {
  return map()->has_named_interceptor();
}


bool JSObject::HasIndexedInterceptor() {
  return map()->has_indexed_interceptor();
}

2930 2931
void JSGlobalObject::set_global_dictionary(GlobalDictionary* dictionary) {
  DCHECK(IsJSGlobalObject());
2932
  set_raw_properties_or_hash(dictionary);
2933
}
2934

2935
GlobalDictionary* JSGlobalObject::global_dictionary() {
2936
  DCHECK(!HasFastProperties());
2937
  DCHECK(IsJSGlobalObject());
2938
  return GlobalDictionary::cast(raw_properties_or_hash());
2939 2940
}

2941
NumberDictionary* JSObject::element_dictionary() {
2942
  DCHECK(HasDictionaryElements() || HasSlowStringWrapperElements());
2943
  return NumberDictionary::cast(elements());
2944 2945
}

2946
// static
2947 2948
Maybe<bool> Object::GreaterThan(Handle<Object> x, Handle<Object> y) {
  Maybe<ComparisonResult> result = Compare(x, y);
2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963
  if (result.IsJust()) {
    switch (result.FromJust()) {
      case ComparisonResult::kGreaterThan:
        return Just(true);
      case ComparisonResult::kLessThan:
      case ComparisonResult::kEqual:
      case ComparisonResult::kUndefined:
        return Just(false);
    }
  }
  return Nothing<bool>();
}


// static
2964 2965
Maybe<bool> Object::GreaterThanOrEqual(Handle<Object> x, Handle<Object> y) {
  Maybe<ComparisonResult> result = Compare(x, y);
2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980
  if (result.IsJust()) {
    switch (result.FromJust()) {
      case ComparisonResult::kEqual:
      case ComparisonResult::kGreaterThan:
        return Just(true);
      case ComparisonResult::kLessThan:
      case ComparisonResult::kUndefined:
        return Just(false);
    }
  }
  return Nothing<bool>();
}


// static
2981 2982
Maybe<bool> Object::LessThan(Handle<Object> x, Handle<Object> y) {
  Maybe<ComparisonResult> result = Compare(x, y);
2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997
  if (result.IsJust()) {
    switch (result.FromJust()) {
      case ComparisonResult::kLessThan:
        return Just(true);
      case ComparisonResult::kEqual:
      case ComparisonResult::kGreaterThan:
      case ComparisonResult::kUndefined:
        return Just(false);
    }
  }
  return Nothing<bool>();
}


// static
2998 2999
Maybe<bool> Object::LessThanOrEqual(Handle<Object> x, Handle<Object> y) {
  Maybe<ComparisonResult> result = Compare(x, y);
3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012
  if (result.IsJust()) {
    switch (result.FromJust()) {
      case ComparisonResult::kEqual:
      case ComparisonResult::kLessThan:
        return Just(true);
      case ComparisonResult::kGreaterThan:
      case ComparisonResult::kUndefined:
        return Just(false);
    }
  }
  return Nothing<bool>();
}

3013
MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
3014
                                                 Handle<Name> name) {
3015 3016
  LookupIterator it =
      LookupIterator::PropertyOrElement(name->GetIsolate(), object, name);
3017
  return GetProperty(&it);
3018 3019
}

3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030
MaybeHandle<Object> Object::SetPropertyOrElement(Handle<Object> object,
                                                 Handle<Name> name,
                                                 Handle<Object> value,
                                                 LanguageMode language_mode,
                                                 StoreFromKeyed store_mode) {
  LookupIterator it =
      LookupIterator::PropertyOrElement(name->GetIsolate(), object, name);
  MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode));
  return value;
}

3031
MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver,
3032
                                                 Handle<Name> name,
3033
                                                 Handle<JSReceiver> holder) {
3034 3035
  LookupIterator it = LookupIterator::PropertyOrElement(
      name->GetIsolate(), receiver, name, holder);
3036
  return GetProperty(&it);
3037 3038 3039
}


3040 3041
void JSReceiver::initialize_properties() {
  DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
3042
  DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_property_dictionary()));
3043
  if (map()->is_dictionary_map()) {
3044
    WRITE_FIELD(this, kPropertiesOrHashOffset,
3045
                GetHeap()->empty_property_dictionary());
3046
  } else {
3047
    WRITE_FIELD(this, kPropertiesOrHashOffset, GetHeap()->empty_fixed_array());
3048
  }
3049 3050
}

3051
bool JSReceiver::HasFastProperties() const {
3052 3053 3054
  DCHECK(
      raw_properties_or_hash()->IsSmi() ||
      (raw_properties_or_hash()->IsDictionary() == map()->is_dictionary_map()));
3055
  return !map()->is_dictionary_map();
3056 3057
}

3058
NameDictionary* JSReceiver::property_dictionary() const {
3059
  DCHECK(!IsJSGlobalObject());
3060
  DCHECK(!HasFastProperties());
3061 3062 3063 3064 3065 3066 3067

  Object* prop = raw_properties_or_hash();
  if (prop->IsSmi()) {
    return GetHeap()->empty_property_dictionary();
  }

  return NameDictionary::cast(prop);
3068 3069
}

3070 3071 3072 3073 3074
// TODO(gsathya): Pass isolate directly to this function and access
// the heap from this.
PropertyArray* JSReceiver::property_array() const {
  DCHECK(HasFastProperties());

3075
  Object* prop = raw_properties_or_hash();
3076 3077 3078 3079 3080 3081 3082
  if (prop->IsSmi() || prop == GetHeap()->empty_fixed_array()) {
    return GetHeap()->empty_property_array();
  }

  return PropertyArray::cast(prop);
}

3083 3084
Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object,
                                    Handle<Name> name) {
3085 3086
  LookupIterator it = LookupIterator::PropertyOrElement(object->GetIsolate(),
                                                        object, name, object);
3087
  return HasProperty(&it);
3088 3089 3090
}


3091 3092
Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
                                       uint32_t index) {
3093 3094 3095
  if (object->IsJSModuleNamespace()) return Just(false);

  if (object->IsJSObject()) {  // Shortcut.
3096 3097 3098 3099 3100 3101 3102 3103 3104 3105
    LookupIterator it(object->GetIsolate(), object, index, object,
                      LookupIterator::OWN);
    return HasProperty(&it);
  }

  Maybe<PropertyAttributes> attributes =
      JSReceiver::GetOwnPropertyAttributes(object, index);
  MAYBE_RETURN(attributes, Nothing<bool>());
  return Just(attributes.FromJust() != ABSENT);
}
3106

3107
Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
3108
    Handle<JSReceiver> object, Handle<Name> name) {
3109 3110
  LookupIterator it = LookupIterator::PropertyOrElement(name->GetIsolate(),
                                                        object, name, object);
3111
  return GetPropertyAttributes(&it);
3112 3113
}

3114

3115 3116
Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
    Handle<JSReceiver> object, Handle<Name> name) {
3117
  LookupIterator it = LookupIterator::PropertyOrElement(
3118
      name->GetIsolate(), object, name, object, LookupIterator::OWN);
3119 3120 3121
  return GetPropertyAttributes(&it);
}

3122 3123 3124 3125 3126 3127
Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
    Handle<JSReceiver> object, uint32_t index) {
  LookupIterator it(object->GetIsolate(), object, index, object,
                    LookupIterator::OWN);
  return GetPropertyAttributes(&it);
}
3128 3129

Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
3130
  LookupIterator it(object->GetIsolate(), object, index, object);
3131
  return HasProperty(&it);
3132 3133 3134 3135 3136 3137
}


Maybe<PropertyAttributes> JSReceiver::GetElementAttributes(
    Handle<JSReceiver> object, uint32_t index) {
  Isolate* isolate = object->GetIsolate();
3138
  LookupIterator it(isolate, object, index, object);
3139 3140 3141 3142 3143 3144 3145
  return GetPropertyAttributes(&it);
}


Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttributes(
    Handle<JSReceiver> object, uint32_t index) {
  Isolate* isolate = object->GetIsolate();
3146
  LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
3147
  return GetPropertyAttributes(&it);
3148 3149 3150
}


3151
bool JSGlobalObject::IsDetached() {
3152
  return JSGlobalProxy::cast(global_proxy())->IsDetachedFrom(this);
3153 3154 3155
}


3156
bool JSGlobalProxy::IsDetachedFrom(JSGlobalObject* global) const {
3157 3158 3159
  const PrototypeIterator iter(this->GetIsolate(),
                               const_cast<JSGlobalProxy*>(this));
  return iter.GetCurrent() != global;
3160 3161
}

3162 3163 3164
inline int JSGlobalProxy::SizeWithEmbedderFields(int embedder_field_count) {
  DCHECK_GE(embedder_field_count, 0);
  return kSize + embedder_field_count * kPointerSize;
3165 3166
}

3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177
BIT_FIELD_ACCESSORS(AccessorInfo, flags, all_can_read,
                    AccessorInfo::AllCanReadBit)
BIT_FIELD_ACCESSORS(AccessorInfo, flags, all_can_write,
                    AccessorInfo::AllCanWriteBit)
BIT_FIELD_ACCESSORS(AccessorInfo, flags, is_special_data_property,
                    AccessorInfo::IsSpecialDataPropertyBit)
BIT_FIELD_ACCESSORS(AccessorInfo, flags, replace_on_access,
                    AccessorInfo::ReplaceOnAccessBit)
BIT_FIELD_ACCESSORS(AccessorInfo, flags, is_sloppy, AccessorInfo::IsSloppyBit)
BIT_FIELD_ACCESSORS(AccessorInfo, flags, initial_property_attributes,
                    AccessorInfo::InitialAttributesBits)
3178

3179 3180 3181
bool FunctionTemplateInfo::IsTemplateFor(JSObject* object) {
  return IsTemplateFor(object->map());
}
3182

3183
bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
3184 3185 3186 3187
  if (!HasExpectedReceiverType()) return true;
  if (!receiver->IsJSObject()) return false;
  return FunctionTemplateInfo::cast(expected_receiver_type())
      ->IsTemplateFor(JSObject::cast(receiver)->map());
3188 3189 3190
}


3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210
bool AccessorInfo::HasExpectedReceiverType() {
  return expected_receiver_type()->IsFunctionTemplateInfo();
}


Object* AccessorPair::get(AccessorComponent component) {
  return component == ACCESSOR_GETTER ? getter() : setter();
}


void AccessorPair::set(AccessorComponent component, Object* value) {
  if (component == ACCESSOR_GETTER) {
    set_getter(value);
  } else {
    set_setter(value);
  }
}


void AccessorPair::SetComponents(Object* getter, Object* setter) {
3211 3212 3213
  Isolate* isolate = GetIsolate();
  if (!getter->IsNull(isolate)) set_getter(getter);
  if (!setter->IsNull(isolate)) set_setter(setter);
3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232
}


bool AccessorPair::Equals(AccessorPair* pair) {
  return (this == pair) || pair->Equals(getter(), setter());
}


bool AccessorPair::Equals(Object* getter_value, Object* setter_value) {
  return (getter() == getter_value) && (setter() == setter_value);
}


bool AccessorPair::ContainsAccessor() {
  return IsJSAccessor(getter()) || IsJSAccessor(setter());
}


bool AccessorPair::IsJSAccessor(Object* obj) {
3233
  return obj->IsCallable() || obj->IsUndefined(GetIsolate());
3234 3235
}

3236
template <typename Derived, typename Shape>
3237 3238
void Dictionary<Derived, Shape>::ClearEntry(int entry) {
  Object* the_hole = this->GetHeap()->the_hole_value();
3239 3240
  PropertyDetails details = PropertyDetails::Empty();
  Derived::cast(this)->SetEntry(entry, the_hole, the_hole, details);
3241 3242
}

3243
template <typename Derived, typename Shape>
3244
void Dictionary<Derived, Shape>::SetEntry(int entry, Object* key, Object* value,
3245
                                          PropertyDetails details) {
3246
  DCHECK(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3);
3247
  DCHECK(!key->IsName() || details.dictionary_index() > 0);
3248
  int index = DerivedHashTable::EntryToIndex(entry);
3249
  DisallowHeapAllocation no_gc;
3250 3251 3252 3253
  WriteBarrierMode mode = this->GetWriteBarrierMode(no_gc);
  this->set(index + Derived::kEntryKeyIndex, key, mode);
  this->set(index + Derived::kEntryValueIndex, value, mode);
  if (Shape::kHasDetails) DetailsAtPut(entry, details);
3254 3255
}

3256 3257 3258 3259
Object* GlobalDictionaryShape::Unwrap(Object* object) {
  return PropertyCell::cast(object)->name();
}

3260 3261
int GlobalDictionaryShape::GetMapRootIndex() {
  return Heap::kGlobalDictionaryMapRootIndex;
3262 3263
}

3264 3265
Name* NameDictionary::NameAt(int entry) { return Name::cast(KeyAt(entry)); }

3266 3267
int NameDictionaryShape::GetMapRootIndex() {
  return Heap::kNameDictionaryMapRootIndex;
3268 3269
}

3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294
PropertyCell* GlobalDictionary::CellAt(int entry) {
  DCHECK(KeyAt(entry)->IsPropertyCell());
  return PropertyCell::cast(KeyAt(entry));
}

bool GlobalDictionaryShape::IsLive(Isolate* isolate, Object* k) {
  Heap* heap = isolate->heap();
  DCHECK_NE(heap->the_hole_value(), k);
  return k != heap->undefined_value();
}

bool GlobalDictionaryShape::IsKey(Isolate* isolate, Object* k) {
  return IsLive(isolate, k) &&
         !PropertyCell::cast(k)->value()->IsTheHole(isolate);
}

Name* GlobalDictionary::NameAt(int entry) { return CellAt(entry)->name(); }
Object* GlobalDictionary::ValueAt(int entry) { return CellAt(entry)->value(); }

void GlobalDictionary::SetEntry(int entry, Object* key, Object* value,
                                PropertyDetails details) {
  DCHECK_EQ(key, PropertyCell::cast(value)->name());
  set(EntryToIndex(entry) + kEntryKeyIndex, value);
  DetailsAtPut(entry, details);
}
3295

3296 3297 3298 3299
void GlobalDictionary::ValueAtPut(int entry, Object* value) {
  set(EntryToIndex(entry), value);
}

3300
bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
3301
  DCHECK(other->IsNumber());
3302 3303 3304
  return key == static_cast<uint32_t>(other->Number());
}

3305
uint32_t NumberDictionaryShape::Hash(Isolate* isolate, uint32_t key) {
3306
  return ComputeIntegerHash(key, isolate->heap()->HashSeed());
3307 3308
}

3309
uint32_t NumberDictionaryShape::HashForObject(Isolate* isolate, Object* other) {
3310
  DCHECK(other->IsNumber());
3311 3312
  return ComputeIntegerHash(static_cast<uint32_t>(other->Number()),
                            isolate->heap()->HashSeed());
3313
}
3314

3315 3316
int NumberDictionaryShape::GetMapRootIndex() {
  return Heap::kNumberDictionaryMapRootIndex;
3317
}
3318

3319 3320 3321 3322
Handle<Object> NumberDictionaryShape::AsHandle(Isolate* isolate, uint32_t key) {
  return isolate->factory()->NewNumberFromUint(key);
}

3323

3324
bool NameDictionaryShape::IsMatch(Handle<Name> key, Object* other) {
3325 3326
  DCHECK(other->IsTheHole(key->GetIsolate()) ||
         Name::cast(other)->IsUniqueName());
3327 3328
  DCHECK(key->IsUniqueName());
  return *key == other;
3329 3330
}

3331
uint32_t NameDictionaryShape::Hash(Isolate* isolate, Handle<Name> key) {
3332 3333 3334
  return key->Hash();
}

3335
uint32_t NameDictionaryShape::HashForObject(Isolate* isolate, Object* other) {
3336
  return Name::cast(other)->Hash();
3337 3338
}

3339 3340 3341 3342 3343 3344 3345 3346
bool GlobalDictionaryShape::IsMatch(Handle<Name> key, Object* other) {
  DCHECK(PropertyCell::cast(other)->name()->IsUniqueName());
  return *key == PropertyCell::cast(other)->name();
}

uint32_t GlobalDictionaryShape::HashForObject(Isolate* isolate, Object* other) {
  return PropertyCell::cast(other)->name()->Hash();
}
3347

3348 3349
Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
                                             Handle<Name> key) {
3350
  DCHECK(key->IsUniqueName());
3351
  return key;
3352 3353 3354
}


3355 3356
template <typename Dictionary>
PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary* dict, int entry) {
3357
  DCHECK_LE(0, entry);  // Not found is -1, which is not caught by get().
3358
  return dict->CellAt(entry)->property_details();
3359 3360 3361 3362 3363 3364
}


template <typename Dictionary>
void GlobalDictionaryShape::DetailsAtPut(Dictionary* dict, int entry,
                                         PropertyDetails value) {
3365
  DCHECK_LE(0, entry);  // Not found is -1, which is not caught by get().
3366
  PropertyCell* cell = dict->CellAt(entry);
3367 3368 3369 3370
  if (cell->property_details().IsReadOnly() != value.IsReadOnly()) {
    cell->dependent_code()->DeoptimizeDependentCodeGroup(
        cell->GetIsolate(), DependentCode::kPropertyCellChangedGroup);
  }
3371 3372 3373
  cell->set_property_details(value);
}

3374
bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object* other) {
3375
  return key->SameValue(other);
3376 3377
}

3378
uint32_t ObjectHashTableShape::Hash(Isolate* isolate, Handle<Object> key) {
jgruber's avatar
jgruber committed
3379
  return Smi::ToInt(key->GetHash());
3380 3381
}

3382
uint32_t ObjectHashTableShape::HashForObject(Isolate* isolate, Object* other) {
jgruber's avatar
jgruber committed
3383
  return Smi::ToInt(other->GetHash());
3384 3385 3386
}


3387 3388
Handle<Object> ObjectHashTableShape::AsHandle(Isolate* isolate,
                                              Handle<Object> key) {
3389 3390 3391
  return key;
}

3392 3393
Handle<ObjectHashTable> ObjectHashTable::Shrink(Handle<ObjectHashTable> table) {
  return DerivedHashTable::Shrink(table);
3394 3395
}

3396
bool WeakHashTableShape::IsMatch(Handle<Object> key, Object* other) {
3397 3398 3399
  if (other->IsWeakCell()) other = WeakCell::cast(other)->value();
  return key->IsWeakCell() ? WeakCell::cast(*key)->value() == other
                           : *key == other;
3400 3401
}

3402
uint32_t WeakHashTableShape::Hash(Isolate* isolate, Handle<Object> key) {
3403 3404 3405 3406
  intptr_t hash =
      key->IsWeakCell()
          ? reinterpret_cast<intptr_t>(WeakCell::cast(*key)->value())
          : reinterpret_cast<intptr_t>(*key);
3407 3408 3409
  return (uint32_t)(hash & 0xFFFFFFFF);
}

3410
uint32_t WeakHashTableShape::HashForObject(Isolate* isolate, Object* other) {
3411
  if (other->IsWeakCell()) other = WeakCell::cast(other)->value();
3412 3413 3414 3415
  intptr_t hash = reinterpret_cast<intptr_t>(other);
  return (uint32_t)(hash & 0xFFFFFFFF);
}

3416 3417
Handle<Object> WeakHashTableShape::AsHandle(Isolate* isolate,
                                            Handle<Object> key) {
3418 3419 3420
  return key;
}

3421 3422
int WeakHashTableShape::GetMapRootIndex() {
  return Heap::kWeakHashTableMapRootIndex;
3423
}
3424

3425 3426 3427 3428 3429 3430 3431 3432
Relocatable::Relocatable(Isolate* isolate) {
  isolate_ = isolate;
  prev_ = isolate->relocatable_top();
  isolate->set_relocatable_top(this);
}


Relocatable::~Relocatable() {
3433
  DCHECK_EQ(isolate_->relocatable_top(), this);
3434
  isolate_->set_relocatable_top(prev_);
3435 3436 3437
}


3438 3439 3440
template<class Derived, class TableType>
Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
  TableType* table(TableType::cast(this->table()));
jgruber's avatar
jgruber committed
3441
  int index = Smi::ToInt(this->index());
3442
  Object* key = table->KeyAt(index);
3443
  DCHECK(!key->IsTheHole(table->GetIsolate()));
3444 3445 3446
  return key;
}

3447 3448 3449 3450 3451 3452 3453
// Predictably converts HeapObject* or Address to uint32 by calculating
// offset of the address in respective MemoryChunk.
static inline uint32_t ObjectAddressForHashing(void* object) {
  uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
  return value & MemoryChunk::kAlignmentMask;
}

3454 3455 3456 3457 3458 3459 3460 3461 3462 3463
static inline Handle<Object> MakeEntryPair(Isolate* isolate, uint32_t index,
                                           Handle<Object> value) {
  Handle<Object> key = isolate->factory()->Uint32ToString(index);
  Handle<FixedArray> entry_storage =
      isolate->factory()->NewUninitializedFixedArray(2);
  {
    entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
    entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
  }
  return isolate->factory()->NewJSArrayWithElements(entry_storage,
3464
                                                    PACKED_ELEMENTS, 2);
3465 3466
}

3467
static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
3468 3469 3470 3471 3472 3473 3474 3475
                                           Handle<Object> value) {
  Handle<FixedArray> entry_storage =
      isolate->factory()->NewUninitializedFixedArray(2);
  {
    entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
    entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
  }
  return isolate->factory()->NewJSArrayWithElements(entry_storage,
3476
                                                    PACKED_ELEMENTS, 2);
3477
}
3478

3479 3480 3481
ACCESSORS(JSIteratorResult, value, Object, kValueOffset)
ACCESSORS(JSIteratorResult, done, Object, kDoneOffset)

3482 3483 3484
ACCESSORS(JSAsyncFromSyncIterator, sync_iterator, JSReceiver,
          kSyncIteratorOffset)

3485 3486 3487
ACCESSORS(JSStringIterator, string, String, kStringOffset)
SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset)

3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505
bool ScopeInfo::IsAsmModule() { return AsmModuleField::decode(Flags()); }

bool ScopeInfo::HasSimpleParameters() {
  return HasSimpleParametersField::decode(Flags());
}

#define FIELD_ACCESSORS(name)                                                 \
  void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \
  int ScopeInfo::name() {                                                     \
    if (length() > 0) {                                                       \
      return Smi::ToInt(get(k##name));                                        \
    } else {                                                                  \
      return 0;                                                               \
    }                                                                         \
  }
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
#undef FIELD_ACCESSORS

3506 3507
}  // namespace internal
}  // namespace v8
3508

3509 3510
#include "src/objects/object-macros-undef.h"

3511
#endif  // V8_OBJECTS_INL_H_