1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // Review notes: 6 // 7 // - The use of macros in these inline functions may seem superfluous 8 // but it is absolutely needed to make sure gcc generates optimal 9 // code. gcc is not happy when attempting to inline too deep. 10 // 11 12 #ifndef V8_OBJECTS_INL_H_ 13 #define V8_OBJECTS_INL_H_ 14 15 #include "src/base/atomicops.h" 16 #include "src/base/bits.h" 17 #include "src/builtins/builtins.h" 18 #include "src/contexts-inl.h" 19 #include "src/conversions-inl.h" 20 #include "src/factory.h" 21 #include "src/feedback-vector-inl.h" 22 #include "src/field-index-inl.h" 23 #include "src/field-type.h" 24 #include "src/handles-inl.h" 25 #include "src/heap/heap-inl.h" 26 #include "src/heap/heap.h" 27 #include "src/isolate-inl.h" 28 #include "src/isolate.h" 29 #include "src/keys.h" 30 #include "src/layout-descriptor-inl.h" 31 #include "src/lookup-cache-inl.h" 32 #include "src/lookup.h" 33 #include "src/objects.h" 34 #include "src/objects/literal-objects.h" 35 #include "src/objects/module-info.h" 36 #include "src/objects/regexp-match-info.h" 37 #include "src/objects/scope-info.h" 38 #include "src/property.h" 39 #include "src/prototype.h" 40 #include "src/transitions-inl.h" 41 #include "src/v8memory.h" 42 43 namespace v8 { 44 namespace internal { 45 46 PropertyDetails::PropertyDetails(Smi* smi) { 47 value_ = smi->value(); 48 } 49 50 51 Smi* PropertyDetails::AsSmi() const { 52 // Ensure the upper 2 bits have the same value by sign extending it. This is 53 // necessary to be able to use the 31st bit of the property details. 54 int value = value_ << 1; 55 return Smi::FromInt(value >> 1); 56 } 57 58 59 int PropertyDetails::field_width_in_words() const { 60 DCHECK(location() == kField); 61 if (!FLAG_unbox_double_fields) return 1; 62 if (kDoubleSize == kPointerSize) return 1; 63 return representation().IsDouble() ? kDoubleSize / kPointerSize : 1; 64 } 65 66 #define INT_ACCESSORS(holder, name, offset) \ 67 int holder::name() const { return READ_INT_FIELD(this, offset); } \ 68 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); } 69 70 #define ACCESSORS_CHECKED2(holder, name, type, offset, get_condition, \ 71 set_condition) \ 72 type* holder::name() const { \ 73 DCHECK(get_condition); \ 74 return type::cast(READ_FIELD(this, offset)); \ 75 } \ 76 void holder::set_##name(type* value, WriteBarrierMode mode) { \ 77 DCHECK(set_condition); \ 78 WRITE_FIELD(this, offset, value); \ 79 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \ 80 } 81 #define ACCESSORS_CHECKED(holder, name, type, offset, condition) \ 82 ACCESSORS_CHECKED2(holder, name, type, offset, condition, condition) 83 84 #define ACCESSORS(holder, name, type, offset) \ 85 ACCESSORS_CHECKED(holder, name, type, offset, true) 86 87 // Getter that returns a Smi as an int and writes an int as a Smi. 88 #define SMI_ACCESSORS_CHECKED(holder, name, offset, condition) \ 89 int holder::name() const { \ 90 DCHECK(condition); \ 91 Object* value = READ_FIELD(this, offset); \ 92 return Smi::cast(value)->value(); \ 93 } \ 94 void holder::set_##name(int value) { \ 95 DCHECK(condition); \ 96 WRITE_FIELD(this, offset, Smi::FromInt(value)); \ 97 } 98 99 #define SMI_ACCESSORS(holder, name, offset) \ 100 SMI_ACCESSORS_CHECKED(holder, name, offset, true) 101 102 #define SYNCHRONIZED_SMI_ACCESSORS(holder, name, offset) \ 103 int holder::synchronized_##name() const { \ 104 Object* value = ACQUIRE_READ_FIELD(this, offset); \ 105 return Smi::cast(value)->value(); \ 106 } \ 107 void holder::synchronized_set_##name(int value) { \ 108 RELEASE_WRITE_FIELD(this, offset, Smi::FromInt(value)); \ 109 } 110 111 #define NOBARRIER_SMI_ACCESSORS(holder, name, offset) \ 112 int holder::nobarrier_##name() const { \ 113 Object* value = NOBARRIER_READ_FIELD(this, offset); \ 114 return Smi::cast(value)->value(); \ 115 } \ 116 void holder::nobarrier_set_##name(int value) { \ 117 NOBARRIER_WRITE_FIELD(this, offset, Smi::FromInt(value)); \ 118 } 119 120 #define BOOL_GETTER(holder, field, name, offset) \ 121 bool holder::name() const { \ 122 return BooleanBit::get(field(), offset); \ 123 } \ 124 125 126 #define BOOL_ACCESSORS(holder, field, name, offset) \ 127 bool holder::name() const { \ 128 return BooleanBit::get(field(), offset); \ 129 } \ 130 void holder::set_##name(bool value) { \ 131 set_##field(BooleanBit::set(field(), offset, value)); \ 132 } 133 134 #define TYPE_CHECKER(type, instancetype) \ 135 bool HeapObject::Is##type() const { \ 136 return map()->instance_type() == instancetype; \ 137 } 138 139 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE) 140 TYPE_CHECKER(BytecodeArray, BYTECODE_ARRAY_TYPE) 141 TYPE_CHECKER(Cell, CELL_TYPE) 142 TYPE_CHECKER(Code, CODE_TYPE) 143 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE) 144 TYPE_CHECKER(Foreign, FOREIGN_TYPE) 145 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE) 146 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE) 147 TYPE_CHECKER(JSArgumentsObject, JS_ARGUMENTS_TYPE) 148 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE) 149 TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE) 150 TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE) 151 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE) 152 TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE) 153 TYPE_CHECKER(JSDate, JS_DATE_TYPE) 154 TYPE_CHECKER(JSError, JS_ERROR_TYPE) 155 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE) 156 TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE) 157 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE) 158 TYPE_CHECKER(JSMap, JS_MAP_TYPE) 159 TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE) 160 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE) 161 TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE) 162 TYPE_CHECKER(JSPromiseCapability, JS_PROMISE_CAPABILITY_TYPE) 163 TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE) 164 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE) 165 TYPE_CHECKER(JSSet, JS_SET_TYPE) 166 TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE) 167 TYPE_CHECKER(JSAsyncFromSyncIterator, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE) 168 TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE) 169 TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE) 170 TYPE_CHECKER(JSValue, JS_VALUE_TYPE) 171 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE) 172 TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE) 173 TYPE_CHECKER(Map, MAP_TYPE) 174 TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE) 175 TYPE_CHECKER(Oddball, ODDBALL_TYPE) 176 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE) 177 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE) 178 TYPE_CHECKER(Symbol, SYMBOL_TYPE) 179 TYPE_CHECKER(TransitionArray, TRANSITION_ARRAY_TYPE) 180 TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE) 181 TYPE_CHECKER(WeakFixedArray, FIXED_ARRAY_TYPE) 182 183 #define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \ 184 TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE) 185 TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER) 186 #undef TYPED_ARRAY_TYPE_CHECKER 187 188 #undef TYPE_CHECKER 189 190 bool HeapObject::IsFixedArrayBase() const { 191 return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); 192 } 193 194 bool HeapObject::IsFixedArray() const { 195 InstanceType instance_type = map()->instance_type(); 196 return instance_type == FIXED_ARRAY_TYPE || 197 instance_type == TRANSITION_ARRAY_TYPE; 198 } 199 200 bool HeapObject::IsBoilerplateDescription() const { return IsFixedArray(); } 201 202 // External objects are not extensible, so the map check is enough. 203 bool HeapObject::IsExternal() const { 204 return map() == GetHeap()->external_map(); 205 } 206 207 #define IS_TYPE_FUNCTION_DEF(type_) \ 208 bool Object::Is##type_() const { \ 209 return IsHeapObject() && HeapObject::cast(this)->Is##type_(); \ 210 } 211 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF) 212 #undef IS_TYPE_FUNCTION_DEF 213 214 #define IS_TYPE_FUNCTION_DEF(Type, Value) \ 215 bool Object::Is##Type(Isolate* isolate) const { \ 216 return this == isolate->heap()->Value(); \ 217 } \ 218 bool HeapObject::Is##Type(Isolate* isolate) const { \ 219 return this == isolate->heap()->Value(); \ 220 } 221 ODDBALL_LIST(IS_TYPE_FUNCTION_DEF) 222 #undef IS_TYPE_FUNCTION_DEF 223 224 bool Object::IsNullOrUndefined(Isolate* isolate) const { 225 Heap* heap = isolate->heap(); 226 return this == heap->null_value() || this == heap->undefined_value(); 227 } 228 229 bool HeapObject::IsNullOrUndefined(Isolate* isolate) const { 230 Heap* heap = isolate->heap(); 231 return this == heap->null_value() || this == heap->undefined_value(); 232 } 233 234 bool HeapObject::IsString() const { 235 return map()->instance_type() < FIRST_NONSTRING_TYPE; 236 } 237 238 bool HeapObject::IsName() const { 239 return map()->instance_type() <= LAST_NAME_TYPE; 240 } 241 242 bool HeapObject::IsUniqueName() const { 243 return IsInternalizedString() || IsSymbol(); 244 } 245 246 bool Name::IsUniqueName() const { 247 uint32_t type = map()->instance_type(); 248 return (type & (kIsNotStringMask | kIsNotInternalizedMask)) != 249 (kStringTag | kNotInternalizedTag); 250 } 251 252 bool HeapObject::IsFunction() const { 253 STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); 254 return map()->instance_type() >= FIRST_FUNCTION_TYPE; 255 } 256 257 bool HeapObject::IsCallable() const { return map()->is_callable(); } 258 259 bool HeapObject::IsConstructor() const { return map()->is_constructor(); } 260 261 bool HeapObject::IsTemplateInfo() const { 262 return IsObjectTemplateInfo() || IsFunctionTemplateInfo(); 263 } 264 265 bool HeapObject::IsInternalizedString() const { 266 uint32_t type = map()->instance_type(); 267 STATIC_ASSERT(kNotInternalizedTag != 0); 268 return (type & (kIsNotStringMask | kIsNotInternalizedMask)) == 269 (kStringTag | kInternalizedTag); 270 } 271 272 bool HeapObject::IsConsString() const { 273 if (!IsString()) return false; 274 return StringShape(String::cast(this)).IsCons(); 275 } 276 277 bool HeapObject::IsThinString() const { 278 if (!IsString()) return false; 279 return StringShape(String::cast(this)).IsThin(); 280 } 281 282 bool HeapObject::IsSlicedString() const { 283 if (!IsString()) return false; 284 return StringShape(String::cast(this)).IsSliced(); 285 } 286 287 bool HeapObject::IsSeqString() const { 288 if (!IsString()) return false; 289 return StringShape(String::cast(this)).IsSequential(); 290 } 291 292 bool HeapObject::IsSeqOneByteString() const { 293 if (!IsString()) return false; 294 return StringShape(String::cast(this)).IsSequential() && 295 String::cast(this)->IsOneByteRepresentation(); 296 } 297 298 bool HeapObject::IsSeqTwoByteString() const { 299 if (!IsString()) return false; 300 return StringShape(String::cast(this)).IsSequential() && 301 String::cast(this)->IsTwoByteRepresentation(); 302 } 303 304 bool HeapObject::IsExternalString() const { 305 if (!IsString()) return false; 306 return StringShape(String::cast(this)).IsExternal(); 307 } 308 309 bool HeapObject::IsExternalOneByteString() const { 310 if (!IsString()) return false; 311 return StringShape(String::cast(this)).IsExternal() && 312 String::cast(this)->IsOneByteRepresentation(); 313 } 314 315 bool HeapObject::IsExternalTwoByteString() const { 316 if (!IsString()) return false; 317 return StringShape(String::cast(this)).IsExternal() && 318 String::cast(this)->IsTwoByteRepresentation(); 319 } 320 321 bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); } 322 323 bool HeapObject::IsFiller() const { 324 InstanceType instance_type = map()->instance_type(); 325 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE; 326 } 327 328 bool HeapObject::IsFixedTypedArrayBase() const { 329 InstanceType instance_type = map()->instance_type(); 330 return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE && 331 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE); 332 } 333 334 bool HeapObject::IsJSReceiver() const { 335 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 336 return map()->instance_type() >= FIRST_JS_RECEIVER_TYPE; 337 } 338 339 bool HeapObject::IsJSObject() const { 340 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 341 return map()->IsJSObjectMap(); 342 } 343 344 bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); } 345 346 bool HeapObject::IsJSArrayIterator() const { 347 InstanceType instance_type = map()->instance_type(); 348 return (instance_type >= FIRST_ARRAY_ITERATOR_TYPE && 349 instance_type <= LAST_ARRAY_ITERATOR_TYPE); 350 } 351 352 bool HeapObject::IsJSWeakCollection() const { 353 return IsJSWeakMap() || IsJSWeakSet(); 354 } 355 356 bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); } 357 358 bool HeapObject::IsDescriptorArray() const { return IsFixedArray(); } 359 360 bool HeapObject::IsFrameArray() const { return IsFixedArray(); } 361 362 bool HeapObject::IsArrayList() const { return IsFixedArray(); } 363 364 bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArray(); } 365 366 bool Object::IsLayoutDescriptor() const { 367 return IsSmi() || IsFixedTypedArrayBase(); 368 } 369 370 bool HeapObject::IsFeedbackVector() const { 371 return map() == GetHeap()->feedback_vector_map(); 372 } 373 374 bool HeapObject::IsFeedbackMetadata() const { return IsFixedArray(); } 375 376 bool HeapObject::IsDeoptimizationInputData() const { 377 // Must be a fixed array. 378 if (!IsFixedArray()) return false; 379 380 // There's no sure way to detect the difference between a fixed array and 381 // a deoptimization data array. Since this is used for asserts we can 382 // check that the length is zero or else the fixed size plus a multiple of 383 // the entry size. 384 int length = FixedArray::cast(this)->length(); 385 if (length == 0) return true; 386 387 length -= DeoptimizationInputData::kFirstDeoptEntryIndex; 388 return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0; 389 } 390 391 bool HeapObject::IsDeoptimizationOutputData() const { 392 if (!IsFixedArray()) return false; 393 // There's actually no way to see the difference between a fixed array and 394 // a deoptimization data array. Since this is used for asserts we can check 395 // that the length is plausible though. 396 if (FixedArray::cast(this)->length() % 2 != 0) return false; 397 return true; 398 } 399 400 bool HeapObject::IsHandlerTable() const { 401 if (!IsFixedArray()) return false; 402 // There's actually no way to see the difference between a fixed array and 403 // a handler table array. 404 return true; 405 } 406 407 bool HeapObject::IsTemplateList() const { 408 if (!IsFixedArray()) return false; 409 // There's actually no way to see the difference between a fixed array and 410 // a template list. 411 if (FixedArray::cast(this)->length() < 1) return false; 412 return true; 413 } 414 415 bool HeapObject::IsDependentCode() const { 416 if (!IsFixedArray()) return false; 417 // There's actually no way to see the difference between a fixed array and 418 // a dependent codes array. 419 return true; 420 } 421 422 bool HeapObject::IsContext() const { 423 Map* map = this->map(); 424 Heap* heap = GetHeap(); 425 return ( 426 map == heap->function_context_map() || map == heap->catch_context_map() || 427 map == heap->with_context_map() || map == heap->native_context_map() || 428 map == heap->block_context_map() || map == heap->module_context_map() || 429 map == heap->eval_context_map() || map == heap->script_context_map() || 430 map == heap->debug_evaluate_context_map()); 431 } 432 433 bool HeapObject::IsNativeContext() const { 434 return map() == GetHeap()->native_context_map(); 435 } 436 437 bool HeapObject::IsScriptContextTable() const { 438 return map() == GetHeap()->script_context_table_map(); 439 } 440 441 bool HeapObject::IsScopeInfo() const { 442 return map() == GetHeap()->scope_info_map(); 443 } 444 445 bool HeapObject::IsModuleInfo() const { 446 return map() == GetHeap()->module_info_map(); 447 } 448 449 template <> 450 inline bool Is<JSFunction>(Object* obj) { 451 return obj->IsJSFunction(); 452 } 453 454 bool HeapObject::IsAbstractCode() const { 455 return IsBytecodeArray() || IsCode(); 456 } 457 458 bool HeapObject::IsStringWrapper() const { 459 return IsJSValue() && JSValue::cast(this)->value()->IsString(); 460 } 461 462 bool HeapObject::IsBoolean() const { 463 return IsOddball() && 464 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0); 465 } 466 467 bool HeapObject::IsJSArrayBufferView() const { 468 return IsJSDataView() || IsJSTypedArray(); 469 } 470 471 template <> 472 inline bool Is<JSArray>(Object* obj) { 473 return obj->IsJSArray(); 474 } 475 476 bool HeapObject::IsHashTable() const { 477 return map() == GetHeap()->hash_table_map(); 478 } 479 480 bool HeapObject::IsWeakHashTable() const { return IsHashTable(); } 481 482 bool HeapObject::IsDictionary() const { 483 return IsHashTable() && this != GetHeap()->string_table(); 484 } 485 486 bool Object::IsNameDictionary() const { return IsDictionary(); } 487 488 bool Object::IsGlobalDictionary() const { return IsDictionary(); } 489 490 bool Object::IsSeededNumberDictionary() const { return IsDictionary(); } 491 492 bool HeapObject::IsUnseededNumberDictionary() const { 493 return map() == GetHeap()->unseeded_number_dictionary_map(); 494 } 495 496 bool HeapObject::IsStringTable() const { return IsHashTable(); } 497 498 bool HeapObject::IsStringSet() const { return IsHashTable(); } 499 500 bool HeapObject::IsObjectHashSet() const { return IsHashTable(); } 501 502 bool HeapObject::IsNormalizedMapCache() const { 503 return NormalizedMapCache::IsNormalizedMapCache(this); 504 } 505 506 int NormalizedMapCache::GetIndex(Handle<Map> map) { 507 return map->Hash() % NormalizedMapCache::kEntries; 508 } 509 510 bool NormalizedMapCache::IsNormalizedMapCache(const HeapObject* obj) { 511 if (!obj->IsFixedArray()) return false; 512 if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) { 513 return false; 514 } 515 #ifdef VERIFY_HEAP 516 if (FLAG_verify_heap) { 517 reinterpret_cast<NormalizedMapCache*>(const_cast<HeapObject*>(obj)) 518 ->NormalizedMapCacheVerify(); 519 } 520 #endif 521 return true; 522 } 523 524 bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); } 525 526 bool HeapObject::IsCodeCacheHashTable() const { return IsHashTable(); } 527 528 bool HeapObject::IsMapCache() const { return IsHashTable(); } 529 530 bool HeapObject::IsObjectHashTable() const { return IsHashTable(); } 531 532 bool HeapObject::IsOrderedHashTable() const { 533 return map() == GetHeap()->ordered_hash_table_map(); 534 } 535 536 bool Object::IsOrderedHashSet() const { return IsOrderedHashTable(); } 537 538 bool Object::IsOrderedHashMap() const { return IsOrderedHashTable(); } 539 540 bool Object::IsPrimitive() const { 541 return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap(); 542 } 543 544 bool HeapObject::IsJSGlobalProxy() const { 545 bool result = map()->instance_type() == JS_GLOBAL_PROXY_TYPE; 546 DCHECK(!result || map()->is_access_check_needed()); 547 return result; 548 } 549 550 bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); } 551 552 bool HeapObject::IsAccessCheckNeeded() const { 553 if (IsJSGlobalProxy()) { 554 const JSGlobalProxy* proxy = JSGlobalProxy::cast(this); 555 JSGlobalObject* global = proxy->GetIsolate()->context()->global_object(); 556 return proxy->IsDetachedFrom(global); 557 } 558 return map()->is_access_check_needed(); 559 } 560 561 bool HeapObject::IsStruct() const { 562 switch (map()->instance_type()) { 563 #define MAKE_STRUCT_CASE(NAME, Name, name) \ 564 case NAME##_TYPE: \ 565 return true; 566 STRUCT_LIST(MAKE_STRUCT_CASE) 567 #undef MAKE_STRUCT_CASE 568 default: 569 return false; 570 } 571 } 572 573 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \ 574 bool Object::Is##Name() const { \ 575 return IsHeapObject() && HeapObject::cast(this)->Is##Name(); \ 576 } \ 577 bool HeapObject::Is##Name() const { \ 578 return map()->instance_type() == NAME##_TYPE; \ 579 } 580 STRUCT_LIST(MAKE_STRUCT_PREDICATE) 581 #undef MAKE_STRUCT_PREDICATE 582 583 double Object::Number() const { 584 DCHECK(IsNumber()); 585 return IsSmi() 586 ? static_cast<double>(reinterpret_cast<const Smi*>(this)->value()) 587 : reinterpret_cast<const HeapNumber*>(this)->value(); 588 } 589 590 bool Object::IsNaN() const { 591 return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value()); 592 } 593 594 bool Object::IsMinusZero() const { 595 return this->IsHeapNumber() && 596 i::IsMinusZero(HeapNumber::cast(this)->value()); 597 } 598 599 // ------------------------------------ 600 // Cast operations 601 602 #define CAST_ACCESSOR(type) \ 603 type* type::cast(Object* object) { \ 604 SLOW_DCHECK(object->Is##type()); \ 605 return reinterpret_cast<type*>(object); \ 606 } \ 607 const type* type::cast(const Object* object) { \ 608 SLOW_DCHECK(object->Is##type()); \ 609 return reinterpret_cast<const type*>(object); \ 610 } 611 612 CAST_ACCESSOR(AbstractCode) 613 CAST_ACCESSOR(ArrayList) 614 CAST_ACCESSOR(BoilerplateDescription) 615 CAST_ACCESSOR(ByteArray) 616 CAST_ACCESSOR(BytecodeArray) 617 CAST_ACCESSOR(Cell) 618 CAST_ACCESSOR(Code) 619 CAST_ACCESSOR(CodeCacheHashTable) 620 CAST_ACCESSOR(CompilationCacheTable) 621 CAST_ACCESSOR(ConsString) 622 CAST_ACCESSOR(DeoptimizationInputData) 623 CAST_ACCESSOR(DeoptimizationOutputData) 624 CAST_ACCESSOR(DependentCode) 625 CAST_ACCESSOR(DescriptorArray) 626 CAST_ACCESSOR(ExternalOneByteString) 627 CAST_ACCESSOR(ExternalString) 628 CAST_ACCESSOR(ExternalTwoByteString) 629 CAST_ACCESSOR(FixedArray) 630 CAST_ACCESSOR(FixedArrayBase) 631 CAST_ACCESSOR(FixedDoubleArray) 632 CAST_ACCESSOR(FixedTypedArrayBase) 633 CAST_ACCESSOR(Foreign) 634 CAST_ACCESSOR(FrameArray) 635 CAST_ACCESSOR(GlobalDictionary) 636 CAST_ACCESSOR(HandlerTable) 637 CAST_ACCESSOR(HeapObject) 638 CAST_ACCESSOR(JSArray) 639 CAST_ACCESSOR(JSArrayBuffer) 640 CAST_ACCESSOR(JSArrayBufferView) 641 CAST_ACCESSOR(JSBoundFunction) 642 CAST_ACCESSOR(JSDataView) 643 CAST_ACCESSOR(JSDate) 644 CAST_ACCESSOR(JSFunction) 645 CAST_ACCESSOR(JSGeneratorObject) 646 CAST_ACCESSOR(JSGlobalObject) 647 CAST_ACCESSOR(JSGlobalProxy) 648 CAST_ACCESSOR(JSMap) 649 CAST_ACCESSOR(JSMapIterator) 650 CAST_ACCESSOR(JSMessageObject) 651 CAST_ACCESSOR(JSModuleNamespace) 652 CAST_ACCESSOR(JSObject) 653 CAST_ACCESSOR(JSProxy) 654 CAST_ACCESSOR(JSReceiver) 655 CAST_ACCESSOR(JSRegExp) 656 CAST_ACCESSOR(JSPromiseCapability) 657 CAST_ACCESSOR(JSPromise) 658 CAST_ACCESSOR(JSSet) 659 CAST_ACCESSOR(JSSetIterator) 660 CAST_ACCESSOR(JSAsyncFromSyncIterator) 661 CAST_ACCESSOR(JSStringIterator) 662 CAST_ACCESSOR(JSArrayIterator) 663 CAST_ACCESSOR(JSTypedArray) 664 CAST_ACCESSOR(JSValue) 665 CAST_ACCESSOR(JSWeakCollection) 666 CAST_ACCESSOR(JSWeakMap) 667 CAST_ACCESSOR(JSWeakSet) 668 CAST_ACCESSOR(LayoutDescriptor) 669 CAST_ACCESSOR(Map) 670 CAST_ACCESSOR(ModuleInfo) 671 CAST_ACCESSOR(Name) 672 CAST_ACCESSOR(NameDictionary) 673 CAST_ACCESSOR(NormalizedMapCache) 674 CAST_ACCESSOR(Object) 675 CAST_ACCESSOR(ObjectHashTable) 676 CAST_ACCESSOR(ObjectHashSet) 677 CAST_ACCESSOR(Oddball) 678 CAST_ACCESSOR(OrderedHashMap) 679 CAST_ACCESSOR(OrderedHashSet) 680 CAST_ACCESSOR(PropertyCell) 681 CAST_ACCESSOR(TemplateList) 682 CAST_ACCESSOR(RegExpMatchInfo) 683 CAST_ACCESSOR(ScopeInfo) 684 CAST_ACCESSOR(SeededNumberDictionary) 685 CAST_ACCESSOR(SeqOneByteString) 686 CAST_ACCESSOR(SeqString) 687 CAST_ACCESSOR(SeqTwoByteString) 688 CAST_ACCESSOR(SharedFunctionInfo) 689 CAST_ACCESSOR(SlicedString) 690 CAST_ACCESSOR(Smi) 691 CAST_ACCESSOR(String) 692 CAST_ACCESSOR(StringSet) 693 CAST_ACCESSOR(StringTable) 694 CAST_ACCESSOR(Struct) 695 CAST_ACCESSOR(Symbol) 696 CAST_ACCESSOR(TemplateInfo) 697 CAST_ACCESSOR(ThinString) 698 CAST_ACCESSOR(UnseededNumberDictionary) 699 CAST_ACCESSOR(WeakCell) 700 CAST_ACCESSOR(WeakFixedArray) 701 CAST_ACCESSOR(WeakHashTable) 702 703 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name) 704 STRUCT_LIST(MAKE_STRUCT_CAST) 705 #undef MAKE_STRUCT_CAST 706 707 #undef CAST_ACCESSOR 708 709 bool Object::HasValidElements() { 710 // Dictionary is covered under FixedArray. 711 return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); 712 } 713 714 bool Object::KeyEquals(Object* second) { 715 Object* first = this; 716 if (second->IsNumber()) { 717 if (first->IsNumber()) return first->Number() == second->Number(); 718 Object* temp = first; 719 first = second; 720 second = temp; 721 } 722 if (first->IsNumber()) { 723 DCHECK_LE(0, first->Number()); 724 uint32_t expected = static_cast<uint32_t>(first->Number()); 725 uint32_t index; 726 return Name::cast(second)->AsArrayIndex(&index) && index == expected; 727 } 728 return Name::cast(first)->Equals(Name::cast(second)); 729 } 730 731 bool Object::FilterKey(PropertyFilter filter) { 732 if (IsSymbol()) { 733 if (filter & SKIP_SYMBOLS) return true; 734 if (Symbol::cast(this)->is_private()) return true; 735 } else { 736 if (filter & SKIP_STRINGS) return true; 737 } 738 return false; 739 } 740 741 Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object, 742 Representation representation) { 743 if (!representation.IsDouble()) return object; 744 Handle<HeapNumber> result = isolate->factory()->NewHeapNumber(MUTABLE); 745 if (object->IsUninitialized(isolate)) { 746 result->set_value_as_bits(kHoleNanInt64); 747 } else if (object->IsMutableHeapNumber()) { 748 // Ensure that all bits of the double value are preserved. 749 result->set_value_as_bits(HeapNumber::cast(*object)->value_as_bits()); 750 } else { 751 result->set_value(object->Number()); 752 } 753 return result; 754 } 755 756 Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object, 757 Representation representation) { 758 DCHECK(!object->IsUninitialized(isolate)); 759 if (!representation.IsDouble()) { 760 DCHECK(object->FitsRepresentation(representation)); 761 return object; 762 } 763 return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value()); 764 } 765 766 StringShape::StringShape(const String* str) 767 : type_(str->map()->instance_type()) { 768 set_valid(); 769 DCHECK((type_ & kIsNotStringMask) == kStringTag); 770 } 771 772 StringShape::StringShape(Map* map) : type_(map->instance_type()) { 773 set_valid(); 774 DCHECK((type_ & kIsNotStringMask) == kStringTag); 775 } 776 777 StringShape::StringShape(InstanceType t) : type_(static_cast<uint32_t>(t)) { 778 set_valid(); 779 DCHECK((type_ & kIsNotStringMask) == kStringTag); 780 } 781 782 bool StringShape::IsInternalized() { 783 DCHECK(valid()); 784 STATIC_ASSERT(kNotInternalizedTag != 0); 785 return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) == 786 (kStringTag | kInternalizedTag); 787 } 788 789 bool String::IsOneByteRepresentation() const { 790 uint32_t type = map()->instance_type(); 791 return (type & kStringEncodingMask) == kOneByteStringTag; 792 } 793 794 bool String::IsTwoByteRepresentation() const { 795 uint32_t type = map()->instance_type(); 796 return (type & kStringEncodingMask) == kTwoByteStringTag; 797 } 798 799 bool String::IsOneByteRepresentationUnderneath() { 800 uint32_t type = map()->instance_type(); 801 STATIC_ASSERT(kIsIndirectStringTag != 0); 802 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0); 803 DCHECK(IsFlat()); 804 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { 805 case kOneByteStringTag: 806 return true; 807 case kTwoByteStringTag: 808 return false; 809 default: // Cons or sliced string. Need to go deeper. 810 return GetUnderlying()->IsOneByteRepresentation(); 811 } 812 } 813 814 bool String::IsTwoByteRepresentationUnderneath() { 815 uint32_t type = map()->instance_type(); 816 STATIC_ASSERT(kIsIndirectStringTag != 0); 817 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0); 818 DCHECK(IsFlat()); 819 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { 820 case kOneByteStringTag: 821 return false; 822 case kTwoByteStringTag: 823 return true; 824 default: // Cons or sliced string. Need to go deeper. 825 return GetUnderlying()->IsTwoByteRepresentation(); 826 } 827 } 828 829 bool String::HasOnlyOneByteChars() { 830 uint32_t type = map()->instance_type(); 831 return (type & kOneByteDataHintMask) == kOneByteDataHintTag || 832 IsOneByteRepresentation(); 833 } 834 835 bool StringShape::IsCons() { 836 return (type_ & kStringRepresentationMask) == kConsStringTag; 837 } 838 839 bool StringShape::IsThin() { 840 return (type_ & kStringRepresentationMask) == kThinStringTag; 841 } 842 843 bool StringShape::IsSliced() { 844 return (type_ & kStringRepresentationMask) == kSlicedStringTag; 845 } 846 847 bool StringShape::IsIndirect() { 848 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag; 849 } 850 851 bool StringShape::IsExternal() { 852 return (type_ & kStringRepresentationMask) == kExternalStringTag; 853 } 854 855 bool StringShape::IsSequential() { 856 return (type_ & kStringRepresentationMask) == kSeqStringTag; 857 } 858 859 StringRepresentationTag StringShape::representation_tag() { 860 uint32_t tag = (type_ & kStringRepresentationMask); 861 return static_cast<StringRepresentationTag>(tag); 862 } 863 864 uint32_t StringShape::encoding_tag() { return type_ & kStringEncodingMask; } 865 866 uint32_t StringShape::full_representation_tag() { 867 return (type_ & (kStringRepresentationMask | kStringEncodingMask)); 868 } 869 870 STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) == 871 Internals::kFullStringRepresentationMask); 872 873 STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) == 874 Internals::kStringEncodingMask); 875 876 bool StringShape::IsSequentialOneByte() { 877 return full_representation_tag() == (kSeqStringTag | kOneByteStringTag); 878 } 879 880 bool StringShape::IsSequentialTwoByte() { 881 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag); 882 } 883 884 bool StringShape::IsExternalOneByte() { 885 return full_representation_tag() == (kExternalStringTag | kOneByteStringTag); 886 } 887 888 STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) == 889 Internals::kExternalOneByteRepresentationTag); 890 891 STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag); 892 893 bool StringShape::IsExternalTwoByte() { 894 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag); 895 } 896 897 STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) == 898 Internals::kExternalTwoByteRepresentationTag); 899 900 STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag); 901 902 uc32 FlatStringReader::Get(int index) { 903 if (is_one_byte_) { 904 return Get<uint8_t>(index); 905 } else { 906 return Get<uc16>(index); 907 } 908 } 909 910 template <typename Char> 911 Char FlatStringReader::Get(int index) { 912 DCHECK_EQ(is_one_byte_, sizeof(Char) == 1); 913 DCHECK(0 <= index && index <= length_); 914 if (sizeof(Char) == 1) { 915 return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]); 916 } else { 917 return static_cast<Char>(static_cast<const uc16*>(start_)[index]); 918 } 919 } 920 921 Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) { 922 return key->AsHandle(isolate); 923 } 924 925 Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate, 926 HashTableKey* key) { 927 return key->AsHandle(isolate); 928 } 929 930 Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate, 931 HashTableKey* key) { 932 return key->AsHandle(isolate); 933 } 934 935 template <typename Char> 936 class SequentialStringKey : public HashTableKey { 937 public: 938 explicit SequentialStringKey(Vector<const Char> string, uint32_t seed) 939 : string_(string), hash_field_(0), seed_(seed) {} 940 941 uint32_t Hash() override { 942 hash_field_ = StringHasher::HashSequentialString<Char>( 943 string_.start(), string_.length(), seed_); 944 945 uint32_t result = hash_field_ >> String::kHashShift; 946 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. 947 return result; 948 } 949 950 uint32_t HashForObject(Object* other) override { 951 return String::cast(other)->Hash(); 952 } 953 954 Vector<const Char> string_; 955 uint32_t hash_field_; 956 uint32_t seed_; 957 }; 958 959 class OneByteStringKey : public SequentialStringKey<uint8_t> { 960 public: 961 OneByteStringKey(Vector<const uint8_t> str, uint32_t seed) 962 : SequentialStringKey<uint8_t>(str, seed) {} 963 964 bool IsMatch(Object* string) override { 965 return String::cast(string)->IsOneByteEqualTo(string_); 966 } 967 968 Handle<Object> AsHandle(Isolate* isolate) override; 969 }; 970 971 class SeqOneByteSubStringKey : public HashTableKey { 972 public: 973 SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length) 974 : string_(string), from_(from), length_(length) { 975 DCHECK(string_->IsSeqOneByteString()); 976 } 977 978 uint32_t Hash() override { 979 DCHECK(length_ >= 0); 980 DCHECK(from_ + length_ <= string_->length()); 981 const uint8_t* chars = string_->GetChars() + from_; 982 hash_field_ = StringHasher::HashSequentialString( 983 chars, length_, string_->GetHeap()->HashSeed()); 984 uint32_t result = hash_field_ >> String::kHashShift; 985 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. 986 return result; 987 } 988 989 uint32_t HashForObject(Object* other) override { 990 return String::cast(other)->Hash(); 991 } 992 993 bool IsMatch(Object* string) override; 994 Handle<Object> AsHandle(Isolate* isolate) override; 995 996 private: 997 Handle<SeqOneByteString> string_; 998 int from_; 999 int length_; 1000 uint32_t hash_field_; 1001 }; 1002 1003 class TwoByteStringKey : public SequentialStringKey<uc16> { 1004 public: 1005 explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed) 1006 : SequentialStringKey<uc16>(str, seed) {} 1007 1008 bool IsMatch(Object* string) override { 1009 return String::cast(string)->IsTwoByteEqualTo(string_); 1010 } 1011 1012 Handle<Object> AsHandle(Isolate* isolate) override; 1013 }; 1014 1015 // Utf8StringKey carries a vector of chars as key. 1016 class Utf8StringKey : public HashTableKey { 1017 public: 1018 explicit Utf8StringKey(Vector<const char> string, uint32_t seed) 1019 : string_(string), hash_field_(0), seed_(seed) {} 1020 1021 bool IsMatch(Object* string) override { 1022 return String::cast(string)->IsUtf8EqualTo(string_); 1023 } 1024 1025 uint32_t Hash() override { 1026 if (hash_field_ != 0) return hash_field_ >> String::kHashShift; 1027 hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_); 1028 uint32_t result = hash_field_ >> String::kHashShift; 1029 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. 1030 return result; 1031 } 1032 1033 uint32_t HashForObject(Object* other) override { 1034 return String::cast(other)->Hash(); 1035 } 1036 1037 Handle<Object> AsHandle(Isolate* isolate) override { 1038 if (hash_field_ == 0) Hash(); 1039 return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_, 1040 hash_field_); 1041 } 1042 1043 Vector<const char> string_; 1044 uint32_t hash_field_; 1045 int chars_; // Caches the number of characters when computing the hash code. 1046 uint32_t seed_; 1047 }; 1048 1049 Representation Object::OptimalRepresentation() { 1050 if (!FLAG_track_fields) return Representation::Tagged(); 1051 if (IsSmi()) { 1052 return Representation::Smi(); 1053 } else if (FLAG_track_double_fields && IsHeapNumber()) { 1054 return Representation::Double(); 1055 } else if (FLAG_track_computed_fields && 1056 IsUninitialized(HeapObject::cast(this)->GetIsolate())) { 1057 return Representation::None(); 1058 } else if (FLAG_track_heap_object_fields) { 1059 DCHECK(IsHeapObject()); 1060 return Representation::HeapObject(); 1061 } else { 1062 return Representation::Tagged(); 1063 } 1064 } 1065 1066 1067 ElementsKind Object::OptimalElementsKind() { 1068 if (IsSmi()) return FAST_SMI_ELEMENTS; 1069 if (IsNumber()) return FAST_DOUBLE_ELEMENTS; 1070 return FAST_ELEMENTS; 1071 } 1072 1073 1074 bool Object::FitsRepresentation(Representation representation) { 1075 if (FLAG_track_fields && representation.IsSmi()) { 1076 return IsSmi(); 1077 } else if (FLAG_track_double_fields && representation.IsDouble()) { 1078 return IsMutableHeapNumber() || IsNumber(); 1079 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { 1080 return IsHeapObject(); 1081 } else if (FLAG_track_fields && representation.IsNone()) { 1082 return false; 1083 } 1084 return true; 1085 } 1086 1087 bool Object::ToUint32(uint32_t* value) { 1088 if (IsSmi()) { 1089 int num = Smi::cast(this)->value(); 1090 if (num < 0) return false; 1091 *value = static_cast<uint32_t>(num); 1092 return true; 1093 } 1094 if (IsHeapNumber()) { 1095 double num = HeapNumber::cast(this)->value(); 1096 return DoubleToUint32IfEqualToSelf(num, value); 1097 } 1098 return false; 1099 } 1100 1101 // static 1102 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate, 1103 Handle<Object> object) { 1104 if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object); 1105 return ToObject(isolate, object, isolate->native_context()); 1106 } 1107 1108 1109 // static 1110 MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) { 1111 if (input->IsName()) return Handle<Name>::cast(input); 1112 return ConvertToName(isolate, input); 1113 } 1114 1115 // static 1116 MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate, 1117 Handle<Object> value) { 1118 if (value->IsSmi() || HeapObject::cast(*value)->IsName()) return value; 1119 return ConvertToPropertyKey(isolate, value); 1120 } 1121 1122 // static 1123 MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input, 1124 ToPrimitiveHint hint) { 1125 if (input->IsPrimitive()) return input; 1126 return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint); 1127 } 1128 1129 // static 1130 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) { 1131 if (input->IsNumber()) return input; 1132 return ConvertToNumber(HeapObject::cast(*input)->GetIsolate(), input); 1133 } 1134 1135 // static 1136 MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) { 1137 if (input->IsSmi()) return input; 1138 return ConvertToInteger(isolate, input); 1139 } 1140 1141 // static 1142 MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) { 1143 if (input->IsSmi()) return input; 1144 return ConvertToInt32(isolate, input); 1145 } 1146 1147 // static 1148 MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) { 1149 if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate); 1150 return ConvertToUint32(isolate, input); 1151 } 1152 1153 // static 1154 MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) { 1155 if (input->IsString()) return Handle<String>::cast(input); 1156 return ConvertToString(isolate, input); 1157 } 1158 1159 // static 1160 MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) { 1161 if (input->IsSmi()) { 1162 int value = std::max(Smi::cast(*input)->value(), 0); 1163 return handle(Smi::FromInt(value), isolate); 1164 } 1165 return ConvertToLength(isolate, input); 1166 } 1167 1168 // static 1169 MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input, 1170 MessageTemplate::Template error_index) { 1171 if (input->IsSmi() && Smi::cast(*input)->value() >= 0) return input; 1172 return ConvertToIndex(isolate, input, error_index); 1173 } 1174 1175 bool Object::HasSpecificClassOf(String* name) { 1176 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name); 1177 } 1178 1179 MaybeHandle<Object> Object::GetProperty(Handle<Object> object, 1180 Handle<Name> name) { 1181 LookupIterator it(object, name); 1182 if (!it.IsFound()) return it.factory()->undefined_value(); 1183 return GetProperty(&it); 1184 } 1185 1186 MaybeHandle<Object> JSReceiver::GetProperty(Handle<JSReceiver> receiver, 1187 Handle<Name> name) { 1188 LookupIterator it(receiver, name, receiver); 1189 if (!it.IsFound()) return it.factory()->undefined_value(); 1190 return Object::GetProperty(&it); 1191 } 1192 1193 MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object, 1194 uint32_t index) { 1195 LookupIterator it(isolate, object, index); 1196 if (!it.IsFound()) return it.factory()->undefined_value(); 1197 return GetProperty(&it); 1198 } 1199 1200 MaybeHandle<Object> JSReceiver::GetElement(Isolate* isolate, 1201 Handle<JSReceiver> receiver, 1202 uint32_t index) { 1203 LookupIterator it(isolate, receiver, index, receiver); 1204 if (!it.IsFound()) return it.factory()->undefined_value(); 1205 return Object::GetProperty(&it); 1206 } 1207 1208 Handle<Object> JSReceiver::GetDataProperty(Handle<JSReceiver> object, 1209 Handle<Name> name) { 1210 LookupIterator it(object, name, object, 1211 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); 1212 if (!it.IsFound()) return it.factory()->undefined_value(); 1213 return GetDataProperty(&it); 1214 } 1215 1216 MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object, 1217 uint32_t index, Handle<Object> value, 1218 LanguageMode language_mode) { 1219 LookupIterator it(isolate, object, index); 1220 MAYBE_RETURN_NULL( 1221 SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED)); 1222 return value; 1223 } 1224 1225 MaybeHandle<Object> JSReceiver::GetPrototype(Isolate* isolate, 1226 Handle<JSReceiver> receiver) { 1227 // We don't expect access checks to be needed on JSProxy objects. 1228 DCHECK(!receiver->IsAccessCheckNeeded() || receiver->IsJSObject()); 1229 PrototypeIterator iter(isolate, receiver, kStartAtReceiver, 1230 PrototypeIterator::END_AT_NON_HIDDEN); 1231 do { 1232 if (!iter.AdvanceFollowingProxies()) return MaybeHandle<Object>(); 1233 } while (!iter.IsAtEnd()); 1234 return PrototypeIterator::GetCurrent(iter); 1235 } 1236 1237 MaybeHandle<Object> JSReceiver::GetProperty(Isolate* isolate, 1238 Handle<JSReceiver> receiver, 1239 const char* name) { 1240 Handle<String> str = isolate->factory()->InternalizeUtf8String(name); 1241 return GetProperty(receiver, str); 1242 } 1243 1244 // static 1245 MUST_USE_RESULT MaybeHandle<FixedArray> JSReceiver::OwnPropertyKeys( 1246 Handle<JSReceiver> object) { 1247 return KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, 1248 ALL_PROPERTIES, 1249 GetKeysConversion::kConvertToString); 1250 } 1251 1252 bool JSObject::PrototypeHasNoElements(Isolate* isolate, JSObject* object) { 1253 DisallowHeapAllocation no_gc; 1254 HeapObject* prototype = HeapObject::cast(object->map()->prototype()); 1255 HeapObject* null = isolate->heap()->null_value(); 1256 HeapObject* empty = isolate->heap()->empty_fixed_array(); 1257 while (prototype != null) { 1258 Map* map = prototype->map(); 1259 if (map->instance_type() <= LAST_CUSTOM_ELEMENTS_RECEIVER) return false; 1260 if (JSObject::cast(prototype)->elements() != empty) return false; 1261 prototype = HeapObject::cast(map->prototype()); 1262 } 1263 return true; 1264 } 1265 1266 #define FIELD_ADDR(p, offset) \ 1267 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) 1268 1269 #define FIELD_ADDR_CONST(p, offset) \ 1270 (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag) 1271 1272 #define READ_FIELD(p, offset) \ 1273 (*reinterpret_cast<Object* const*>(FIELD_ADDR_CONST(p, offset))) 1274 1275 #define ACQUIRE_READ_FIELD(p, offset) \ 1276 reinterpret_cast<Object*>(base::Acquire_Load( \ 1277 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset)))) 1278 1279 #define NOBARRIER_READ_FIELD(p, offset) \ 1280 reinterpret_cast<Object*>(base::NoBarrier_Load( \ 1281 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset)))) 1282 1283 #define WRITE_FIELD(p, offset, value) \ 1284 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value) 1285 1286 #define RELEASE_WRITE_FIELD(p, offset, value) \ 1287 base::Release_Store( \ 1288 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \ 1289 reinterpret_cast<base::AtomicWord>(value)); 1290 1291 #define NOBARRIER_WRITE_FIELD(p, offset, value) \ 1292 base::NoBarrier_Store( \ 1293 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \ 1294 reinterpret_cast<base::AtomicWord>(value)); 1295 1296 #define WRITE_BARRIER(heap, object, offset, value) \ 1297 heap->incremental_marking()->RecordWrite( \ 1298 object, HeapObject::RawField(object, offset), value); \ 1299 heap->RecordWrite(object, offset, value); 1300 1301 #define FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(heap, array, start, length) \ 1302 do { \ 1303 heap->RecordFixedArrayElements(array, start, length); \ 1304 heap->incremental_marking()->IterateBlackObject(array); \ 1305 } while (false) 1306 1307 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \ 1308 if (mode != SKIP_WRITE_BARRIER) { \ 1309 if (mode == UPDATE_WRITE_BARRIER) { \ 1310 heap->incremental_marking()->RecordWrite( \ 1311 object, HeapObject::RawField(object, offset), value); \ 1312 } \ 1313 heap->RecordWrite(object, offset, value); \ 1314 } 1315 1316 #define READ_DOUBLE_FIELD(p, offset) \ 1317 ReadDoubleValue(FIELD_ADDR_CONST(p, offset)) 1318 1319 #define WRITE_DOUBLE_FIELD(p, offset, value) \ 1320 WriteDoubleValue(FIELD_ADDR(p, offset), value) 1321 1322 #define READ_INT_FIELD(p, offset) \ 1323 (*reinterpret_cast<const int*>(FIELD_ADDR_CONST(p, offset))) 1324 1325 #define WRITE_INT_FIELD(p, offset, value) \ 1326 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value) 1327 1328 #define READ_INTPTR_FIELD(p, offset) \ 1329 (*reinterpret_cast<const intptr_t*>(FIELD_ADDR_CONST(p, offset))) 1330 1331 #define WRITE_INTPTR_FIELD(p, offset, value) \ 1332 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value) 1333 1334 #define READ_UINT8_FIELD(p, offset) \ 1335 (*reinterpret_cast<const uint8_t*>(FIELD_ADDR_CONST(p, offset))) 1336 1337 #define WRITE_UINT8_FIELD(p, offset, value) \ 1338 (*reinterpret_cast<uint8_t*>(FIELD_ADDR(p, offset)) = value) 1339 1340 #define READ_INT8_FIELD(p, offset) \ 1341 (*reinterpret_cast<const int8_t*>(FIELD_ADDR_CONST(p, offset))) 1342 1343 #define WRITE_INT8_FIELD(p, offset, value) \ 1344 (*reinterpret_cast<int8_t*>(FIELD_ADDR(p, offset)) = value) 1345 1346 #define READ_UINT16_FIELD(p, offset) \ 1347 (*reinterpret_cast<const uint16_t*>(FIELD_ADDR_CONST(p, offset))) 1348 1349 #define WRITE_UINT16_FIELD(p, offset, value) \ 1350 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value) 1351 1352 #define READ_INT16_FIELD(p, offset) \ 1353 (*reinterpret_cast<const int16_t*>(FIELD_ADDR_CONST(p, offset))) 1354 1355 #define WRITE_INT16_FIELD(p, offset, value) \ 1356 (*reinterpret_cast<int16_t*>(FIELD_ADDR(p, offset)) = value) 1357 1358 #define READ_UINT32_FIELD(p, offset) \ 1359 (*reinterpret_cast<const uint32_t*>(FIELD_ADDR_CONST(p, offset))) 1360 1361 #define WRITE_UINT32_FIELD(p, offset, value) \ 1362 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value) 1363 1364 #define READ_INT32_FIELD(p, offset) \ 1365 (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset))) 1366 1367 #define WRITE_INT32_FIELD(p, offset, value) \ 1368 (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value) 1369 1370 #define READ_FLOAT_FIELD(p, offset) \ 1371 (*reinterpret_cast<const float*>(FIELD_ADDR_CONST(p, offset))) 1372 1373 #define WRITE_FLOAT_FIELD(p, offset, value) \ 1374 (*reinterpret_cast<float*>(FIELD_ADDR(p, offset)) = value) 1375 1376 #define READ_UINT64_FIELD(p, offset) \ 1377 (*reinterpret_cast<const uint64_t*>(FIELD_ADDR_CONST(p, offset))) 1378 1379 #define WRITE_UINT64_FIELD(p, offset, value) \ 1380 (*reinterpret_cast<uint64_t*>(FIELD_ADDR(p, offset)) = value) 1381 1382 #define READ_INT64_FIELD(p, offset) \ 1383 (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset))) 1384 1385 #define WRITE_INT64_FIELD(p, offset, value) \ 1386 (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value) 1387 1388 #define READ_BYTE_FIELD(p, offset) \ 1389 (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset))) 1390 1391 #define NOBARRIER_READ_BYTE_FIELD(p, offset) \ 1392 static_cast<byte>(base::NoBarrier_Load( \ 1393 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)))) 1394 1395 #define WRITE_BYTE_FIELD(p, offset, value) \ 1396 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value) 1397 1398 #define NOBARRIER_WRITE_BYTE_FIELD(p, offset, value) \ 1399 base::NoBarrier_Store( \ 1400 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \ 1401 static_cast<base::Atomic8>(value)); 1402 1403 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) { 1404 return reinterpret_cast<Object**>(FIELD_ADDR(obj, byte_offset)); 1405 } 1406 1407 1408 MapWord MapWord::FromMap(const Map* map) { 1409 return MapWord(reinterpret_cast<uintptr_t>(map)); 1410 } 1411 1412 1413 Map* MapWord::ToMap() { 1414 return reinterpret_cast<Map*>(value_); 1415 } 1416 1417 bool MapWord::IsForwardingAddress() const { 1418 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_)); 1419 } 1420 1421 1422 MapWord MapWord::FromForwardingAddress(HeapObject* object) { 1423 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag; 1424 return MapWord(reinterpret_cast<uintptr_t>(raw)); 1425 } 1426 1427 1428 HeapObject* MapWord::ToForwardingAddress() { 1429 DCHECK(IsForwardingAddress()); 1430 return HeapObject::FromAddress(reinterpret_cast<Address>(value_)); 1431 } 1432 1433 1434 #ifdef VERIFY_HEAP 1435 void HeapObject::VerifyObjectField(int offset) { 1436 VerifyPointer(READ_FIELD(this, offset)); 1437 } 1438 1439 void HeapObject::VerifySmiField(int offset) { 1440 CHECK(READ_FIELD(this, offset)->IsSmi()); 1441 } 1442 #endif 1443 1444 1445 Heap* HeapObject::GetHeap() const { 1446 Heap* heap = MemoryChunk::FromAddress( 1447 reinterpret_cast<Address>(const_cast<HeapObject*>(this))) 1448 ->heap(); 1449 SLOW_DCHECK(heap != NULL); 1450 return heap; 1451 } 1452 1453 1454 Isolate* HeapObject::GetIsolate() const { 1455 return GetHeap()->isolate(); 1456 } 1457 1458 1459 Map* HeapObject::map() const { 1460 #ifdef DEBUG 1461 // Clear mark potentially added by PathTracer. 1462 uintptr_t raw_value = 1463 map_word().ToRawValue() & ~static_cast<uintptr_t>(PathTracer::kMarkTag); 1464 return MapWord::FromRawValue(raw_value).ToMap(); 1465 #else 1466 return map_word().ToMap(); 1467 #endif 1468 } 1469 1470 1471 void HeapObject::set_map(Map* value) { 1472 set_map_word(MapWord::FromMap(value)); 1473 if (value != nullptr) { 1474 // TODO(1600) We are passing NULL as a slot because maps can never be on 1475 // evacuation candidate. 1476 value->GetHeap()->incremental_marking()->RecordWrite(this, nullptr, value); 1477 #ifdef VERIFY_HEAP 1478 value->GetHeap()->VerifyObjectLayoutChange(this, value); 1479 #endif 1480 } 1481 } 1482 1483 1484 Map* HeapObject::synchronized_map() { 1485 return synchronized_map_word().ToMap(); 1486 } 1487 1488 1489 void HeapObject::synchronized_set_map(Map* value) { 1490 synchronized_set_map_word(MapWord::FromMap(value)); 1491 if (value != nullptr) { 1492 // TODO(1600) We are passing NULL as a slot because maps can never be on 1493 // evacuation candidate. 1494 value->GetHeap()->incremental_marking()->RecordWrite(this, nullptr, value); 1495 #ifdef VERIFY_HEAP 1496 value->GetHeap()->VerifyObjectLayoutChange(this, value); 1497 #endif 1498 } 1499 } 1500 1501 1502 void HeapObject::synchronized_set_map_no_write_barrier(Map* value) { 1503 synchronized_set_map_word(MapWord::FromMap(value)); 1504 } 1505 1506 1507 // Unsafe accessor omitting write barrier. 1508 void HeapObject::set_map_no_write_barrier(Map* value) { 1509 set_map_word(MapWord::FromMap(value)); 1510 } 1511 1512 1513 MapWord HeapObject::map_word() const { 1514 return MapWord( 1515 reinterpret_cast<uintptr_t>(NOBARRIER_READ_FIELD(this, kMapOffset))); 1516 } 1517 1518 1519 void HeapObject::set_map_word(MapWord map_word) { 1520 NOBARRIER_WRITE_FIELD( 1521 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_)); 1522 } 1523 1524 1525 MapWord HeapObject::synchronized_map_word() const { 1526 return MapWord( 1527 reinterpret_cast<uintptr_t>(ACQUIRE_READ_FIELD(this, kMapOffset))); 1528 } 1529 1530 1531 void HeapObject::synchronized_set_map_word(MapWord map_word) { 1532 RELEASE_WRITE_FIELD( 1533 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_)); 1534 } 1535 1536 1537 int HeapObject::Size() { 1538 return SizeFromMap(map()); 1539 } 1540 1541 1542 double HeapNumber::value() const { 1543 return READ_DOUBLE_FIELD(this, kValueOffset); 1544 } 1545 1546 1547 void HeapNumber::set_value(double value) { 1548 WRITE_DOUBLE_FIELD(this, kValueOffset, value); 1549 } 1550 1551 uint64_t HeapNumber::value_as_bits() const { 1552 return READ_UINT64_FIELD(this, kValueOffset); 1553 } 1554 1555 void HeapNumber::set_value_as_bits(uint64_t bits) { 1556 WRITE_UINT64_FIELD(this, kValueOffset, bits); 1557 } 1558 1559 int HeapNumber::get_exponent() { 1560 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >> 1561 kExponentShift) - kExponentBias; 1562 } 1563 1564 1565 int HeapNumber::get_sign() { 1566 return READ_INT_FIELD(this, kExponentOffset) & kSignMask; 1567 } 1568 1569 ACCESSORS(JSReceiver, properties, FixedArray, kPropertiesOffset) 1570 1571 1572 Object** FixedArray::GetFirstElementAddress() { 1573 return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0))); 1574 } 1575 1576 1577 bool FixedArray::ContainsOnlySmisOrHoles() { 1578 Object* the_hole = GetHeap()->the_hole_value(); 1579 Object** current = GetFirstElementAddress(); 1580 for (int i = 0; i < length(); ++i) { 1581 Object* candidate = *current++; 1582 if (!candidate->IsSmi() && candidate != the_hole) return false; 1583 } 1584 return true; 1585 } 1586 1587 1588 FixedArrayBase* JSObject::elements() const { 1589 Object* array = READ_FIELD(this, kElementsOffset); 1590 return static_cast<FixedArrayBase*>(array); 1591 } 1592 1593 1594 void AllocationSite::Initialize() { 1595 set_transition_info(Smi::kZero); 1596 SetElementsKind(GetInitialFastElementsKind()); 1597 set_nested_site(Smi::kZero); 1598 set_pretenure_data(0); 1599 set_pretenure_create_count(0); 1600 set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()), 1601 SKIP_WRITE_BARRIER); 1602 } 1603 1604 1605 bool AllocationSite::IsZombie() { return pretenure_decision() == kZombie; } 1606 1607 1608 bool AllocationSite::IsMaybeTenure() { 1609 return pretenure_decision() == kMaybeTenure; 1610 } 1611 1612 1613 bool AllocationSite::PretenuringDecisionMade() { 1614 return pretenure_decision() != kUndecided; 1615 } 1616 1617 1618 void AllocationSite::MarkZombie() { 1619 DCHECK(!IsZombie()); 1620 Initialize(); 1621 set_pretenure_decision(kZombie); 1622 } 1623 1624 1625 ElementsKind AllocationSite::GetElementsKind() { 1626 DCHECK(!SitePointsToLiteral()); 1627 int value = Smi::cast(transition_info())->value(); 1628 return ElementsKindBits::decode(value); 1629 } 1630 1631 1632 void AllocationSite::SetElementsKind(ElementsKind kind) { 1633 int value = Smi::cast(transition_info())->value(); 1634 set_transition_info(Smi::FromInt(ElementsKindBits::update(value, kind)), 1635 SKIP_WRITE_BARRIER); 1636 } 1637 1638 1639 bool AllocationSite::CanInlineCall() { 1640 int value = Smi::cast(transition_info())->value(); 1641 return DoNotInlineBit::decode(value) == 0; 1642 } 1643 1644 1645 void AllocationSite::SetDoNotInlineCall() { 1646 int value = Smi::cast(transition_info())->value(); 1647 set_transition_info(Smi::FromInt(DoNotInlineBit::update(value, true)), 1648 SKIP_WRITE_BARRIER); 1649 } 1650 1651 1652 bool AllocationSite::SitePointsToLiteral() { 1653 // If transition_info is a smi, then it represents an ElementsKind 1654 // for a constructed array. Otherwise, it must be a boilerplate 1655 // for an object or array literal. 1656 return transition_info()->IsJSArray() || transition_info()->IsJSObject(); 1657 } 1658 1659 1660 // Heuristic: We only need to create allocation site info if the boilerplate 1661 // elements kind is the initial elements kind. 1662 AllocationSiteMode AllocationSite::GetMode( 1663 ElementsKind boilerplate_elements_kind) { 1664 if (IsFastSmiElementsKind(boilerplate_elements_kind)) { 1665 return TRACK_ALLOCATION_SITE; 1666 } 1667 1668 return DONT_TRACK_ALLOCATION_SITE; 1669 } 1670 1671 inline bool AllocationSite::CanTrack(InstanceType type) { 1672 if (FLAG_turbo) { 1673 // TurboFan doesn't care at all about String pretenuring feedback, 1674 // so don't bother even trying to track that. 1675 return type == JS_ARRAY_TYPE || type == JS_OBJECT_TYPE; 1676 } 1677 if (FLAG_allocation_site_pretenuring) { 1678 return type == JS_ARRAY_TYPE || 1679 type == JS_OBJECT_TYPE || 1680 type < FIRST_NONSTRING_TYPE; 1681 } 1682 return type == JS_ARRAY_TYPE; 1683 } 1684 1685 1686 AllocationSite::PretenureDecision AllocationSite::pretenure_decision() { 1687 int value = pretenure_data(); 1688 return PretenureDecisionBits::decode(value); 1689 } 1690 1691 1692 void AllocationSite::set_pretenure_decision(PretenureDecision decision) { 1693 int value = pretenure_data(); 1694 set_pretenure_data(PretenureDecisionBits::update(value, decision)); 1695 } 1696 1697 1698 bool AllocationSite::deopt_dependent_code() { 1699 int value = pretenure_data(); 1700 return DeoptDependentCodeBit::decode(value); 1701 } 1702 1703 1704 void AllocationSite::set_deopt_dependent_code(bool deopt) { 1705 int value = pretenure_data(); 1706 set_pretenure_data(DeoptDependentCodeBit::update(value, deopt)); 1707 } 1708 1709 1710 int AllocationSite::memento_found_count() { 1711 int value = pretenure_data(); 1712 return MementoFoundCountBits::decode(value); 1713 } 1714 1715 1716 inline void AllocationSite::set_memento_found_count(int count) { 1717 int value = pretenure_data(); 1718 // Verify that we can count more mementos than we can possibly find in one 1719 // new space collection. 1720 DCHECK((GetHeap()->MaxSemiSpaceSize() / 1721 (Heap::kMinObjectSizeInWords * kPointerSize + 1722 AllocationMemento::kSize)) < MementoFoundCountBits::kMax); 1723 DCHECK(count < MementoFoundCountBits::kMax); 1724 set_pretenure_data(MementoFoundCountBits::update(value, count)); 1725 } 1726 1727 1728 int AllocationSite::memento_create_count() { return pretenure_create_count(); } 1729 1730 1731 void AllocationSite::set_memento_create_count(int count) { 1732 set_pretenure_create_count(count); 1733 } 1734 1735 1736 bool AllocationSite::IncrementMementoFoundCount(int increment) { 1737 if (IsZombie()) return false; 1738 1739 int value = memento_found_count(); 1740 set_memento_found_count(value + increment); 1741 return memento_found_count() >= kPretenureMinimumCreated; 1742 } 1743 1744 1745 inline void AllocationSite::IncrementMementoCreateCount() { 1746 DCHECK(FLAG_allocation_site_pretenuring); 1747 int value = memento_create_count(); 1748 set_memento_create_count(value + 1); 1749 } 1750 1751 1752 inline bool AllocationSite::MakePretenureDecision( 1753 PretenureDecision current_decision, 1754 double ratio, 1755 bool maximum_size_scavenge) { 1756 // Here we just allow state transitions from undecided or maybe tenure 1757 // to don't tenure, maybe tenure, or tenure. 1758 if ((current_decision == kUndecided || current_decision == kMaybeTenure)) { 1759 if (ratio >= kPretenureRatio) { 1760 // We just transition into tenure state when the semi-space was at 1761 // maximum capacity. 1762 if (maximum_size_scavenge) { 1763 set_deopt_dependent_code(true); 1764 set_pretenure_decision(kTenure); 1765 // Currently we just need to deopt when we make a state transition to 1766 // tenure. 1767 return true; 1768 } 1769 set_pretenure_decision(kMaybeTenure); 1770 } else { 1771 set_pretenure_decision(kDontTenure); 1772 } 1773 } 1774 return false; 1775 } 1776 1777 1778 inline bool AllocationSite::DigestPretenuringFeedback( 1779 bool maximum_size_scavenge) { 1780 bool deopt = false; 1781 int create_count = memento_create_count(); 1782 int found_count = memento_found_count(); 1783 bool minimum_mementos_created = create_count >= kPretenureMinimumCreated; 1784 double ratio = 1785 minimum_mementos_created || FLAG_trace_pretenuring_statistics ? 1786 static_cast<double>(found_count) / create_count : 0.0; 1787 PretenureDecision current_decision = pretenure_decision(); 1788 1789 if (minimum_mementos_created) { 1790 deopt = MakePretenureDecision( 1791 current_decision, ratio, maximum_size_scavenge); 1792 } 1793 1794 if (FLAG_trace_pretenuring_statistics) { 1795 PrintIsolate(GetIsolate(), 1796 "pretenuring: AllocationSite(%p): (created, found, ratio) " 1797 "(%d, %d, %f) %s => %s\n", 1798 static_cast<void*>(this), create_count, found_count, ratio, 1799 PretenureDecisionName(current_decision), 1800 PretenureDecisionName(pretenure_decision())); 1801 } 1802 1803 // Clear feedback calculation fields until the next gc. 1804 set_memento_found_count(0); 1805 set_memento_create_count(0); 1806 return deopt; 1807 } 1808 1809 1810 bool AllocationMemento::IsValid() { 1811 return allocation_site()->IsAllocationSite() && 1812 !AllocationSite::cast(allocation_site())->IsZombie(); 1813 } 1814 1815 1816 AllocationSite* AllocationMemento::GetAllocationSite() { 1817 DCHECK(IsValid()); 1818 return AllocationSite::cast(allocation_site()); 1819 } 1820 1821 Address AllocationMemento::GetAllocationSiteUnchecked() { 1822 return reinterpret_cast<Address>(allocation_site()); 1823 } 1824 1825 void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) { 1826 JSObject::ValidateElements(object); 1827 ElementsKind elements_kind = object->map()->elements_kind(); 1828 if (!IsFastObjectElementsKind(elements_kind)) { 1829 if (IsFastHoleyElementsKind(elements_kind)) { 1830 TransitionElementsKind(object, FAST_HOLEY_ELEMENTS); 1831 } else { 1832 TransitionElementsKind(object, FAST_ELEMENTS); 1833 } 1834 } 1835 } 1836 1837 1838 void JSObject::EnsureCanContainElements(Handle<JSObject> object, 1839 Object** objects, 1840 uint32_t count, 1841 EnsureElementsMode mode) { 1842 ElementsKind current_kind = object->GetElementsKind(); 1843 ElementsKind target_kind = current_kind; 1844 { 1845 DisallowHeapAllocation no_allocation; 1846 DCHECK(mode != ALLOW_COPIED_DOUBLE_ELEMENTS); 1847 bool is_holey = IsFastHoleyElementsKind(current_kind); 1848 if (current_kind == FAST_HOLEY_ELEMENTS) return; 1849 Object* the_hole = object->GetHeap()->the_hole_value(); 1850 for (uint32_t i = 0; i < count; ++i) { 1851 Object* current = *objects++; 1852 if (current == the_hole) { 1853 is_holey = true; 1854 target_kind = GetHoleyElementsKind(target_kind); 1855 } else if (!current->IsSmi()) { 1856 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) { 1857 if (IsFastSmiElementsKind(target_kind)) { 1858 if (is_holey) { 1859 target_kind = FAST_HOLEY_DOUBLE_ELEMENTS; 1860 } else { 1861 target_kind = FAST_DOUBLE_ELEMENTS; 1862 } 1863 } 1864 } else if (is_holey) { 1865 target_kind = FAST_HOLEY_ELEMENTS; 1866 break; 1867 } else { 1868 target_kind = FAST_ELEMENTS; 1869 } 1870 } 1871 } 1872 } 1873 if (target_kind != current_kind) { 1874 TransitionElementsKind(object, target_kind); 1875 } 1876 } 1877 1878 1879 void JSObject::EnsureCanContainElements(Handle<JSObject> object, 1880 Handle<FixedArrayBase> elements, 1881 uint32_t length, 1882 EnsureElementsMode mode) { 1883 Heap* heap = object->GetHeap(); 1884 if (elements->map() != heap->fixed_double_array_map()) { 1885 DCHECK(elements->map() == heap->fixed_array_map() || 1886 elements->map() == heap->fixed_cow_array_map()); 1887 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) { 1888 mode = DONT_ALLOW_DOUBLE_ELEMENTS; 1889 } 1890 Object** objects = 1891 Handle<FixedArray>::cast(elements)->GetFirstElementAddress(); 1892 EnsureCanContainElements(object, objects, length, mode); 1893 return; 1894 } 1895 1896 DCHECK(mode == ALLOW_COPIED_DOUBLE_ELEMENTS); 1897 if (object->GetElementsKind() == FAST_HOLEY_SMI_ELEMENTS) { 1898 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS); 1899 } else if (object->GetElementsKind() == FAST_SMI_ELEMENTS) { 1900 Handle<FixedDoubleArray> double_array = 1901 Handle<FixedDoubleArray>::cast(elements); 1902 for (uint32_t i = 0; i < length; ++i) { 1903 if (double_array->is_the_hole(i)) { 1904 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS); 1905 return; 1906 } 1907 } 1908 TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS); 1909 } 1910 } 1911 1912 1913 void JSObject::SetMapAndElements(Handle<JSObject> object, 1914 Handle<Map> new_map, 1915 Handle<FixedArrayBase> value) { 1916 JSObject::MigrateToMap(object, new_map); 1917 DCHECK((object->map()->has_fast_smi_or_object_elements() || 1918 (*value == object->GetHeap()->empty_fixed_array()) || 1919 object->map()->has_fast_string_wrapper_elements()) == 1920 (value->map() == object->GetHeap()->fixed_array_map() || 1921 value->map() == object->GetHeap()->fixed_cow_array_map())); 1922 DCHECK((*value == object->GetHeap()->empty_fixed_array()) || 1923 (object->map()->has_fast_double_elements() == 1924 value->IsFixedDoubleArray())); 1925 object->set_elements(*value); 1926 } 1927 1928 1929 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { 1930 WRITE_FIELD(this, kElementsOffset, value); 1931 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); 1932 } 1933 1934 1935 void JSObject::initialize_elements() { 1936 FixedArrayBase* elements = map()->GetInitialElements(); 1937 WRITE_FIELD(this, kElementsOffset, elements); 1938 } 1939 1940 1941 InterceptorInfo* JSObject::GetIndexedInterceptor() { 1942 return map()->GetIndexedInterceptor(); 1943 } 1944 1945 InterceptorInfo* JSObject::GetNamedInterceptor() { 1946 return map()->GetNamedInterceptor(); 1947 } 1948 1949 InterceptorInfo* Map::GetNamedInterceptor() { 1950 DCHECK(has_named_interceptor()); 1951 JSFunction* constructor = JSFunction::cast(GetConstructor()); 1952 DCHECK(constructor->shared()->IsApiFunction()); 1953 return InterceptorInfo::cast( 1954 constructor->shared()->get_api_func_data()->named_property_handler()); 1955 } 1956 1957 InterceptorInfo* Map::GetIndexedInterceptor() { 1958 DCHECK(has_indexed_interceptor()); 1959 JSFunction* constructor = JSFunction::cast(GetConstructor()); 1960 DCHECK(constructor->shared()->IsApiFunction()); 1961 return InterceptorInfo::cast( 1962 constructor->shared()->get_api_func_data()->indexed_property_handler()); 1963 } 1964 1965 double Oddball::to_number_raw() const { 1966 return READ_DOUBLE_FIELD(this, kToNumberRawOffset); 1967 } 1968 1969 void Oddball::set_to_number_raw(double value) { 1970 WRITE_DOUBLE_FIELD(this, kToNumberRawOffset, value); 1971 } 1972 1973 ACCESSORS(Oddball, to_string, String, kToStringOffset) 1974 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) 1975 ACCESSORS(Oddball, type_of, String, kTypeOfOffset) 1976 1977 1978 byte Oddball::kind() const { 1979 return Smi::cast(READ_FIELD(this, kKindOffset))->value(); 1980 } 1981 1982 1983 void Oddball::set_kind(byte value) { 1984 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value)); 1985 } 1986 1987 1988 // static 1989 Handle<Object> Oddball::ToNumber(Handle<Oddball> input) { 1990 return handle(input->to_number(), input->GetIsolate()); 1991 } 1992 1993 1994 ACCESSORS(Cell, value, Object, kValueOffset) 1995 ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset) 1996 ACCESSORS(PropertyCell, property_details_raw, Object, kDetailsOffset) 1997 ACCESSORS(PropertyCell, value, Object, kValueOffset) 1998 1999 2000 PropertyDetails PropertyCell::property_details() { 2001 return PropertyDetails(Smi::cast(property_details_raw())); 2002 } 2003 2004 2005 void PropertyCell::set_property_details(PropertyDetails details) { 2006 set_property_details_raw(details.AsSmi()); 2007 } 2008 2009 2010 Object* WeakCell::value() const { return READ_FIELD(this, kValueOffset); } 2011 2012 2013 void WeakCell::clear() { 2014 // Either the garbage collector is clearing the cell or we are simply 2015 // initializing the root empty weak cell. 2016 DCHECK(GetHeap()->gc_state() == Heap::MARK_COMPACT || 2017 this == GetHeap()->empty_weak_cell()); 2018 WRITE_FIELD(this, kValueOffset, Smi::kZero); 2019 } 2020 2021 2022 void WeakCell::initialize(HeapObject* val) { 2023 WRITE_FIELD(this, kValueOffset, val); 2024 // We just have to execute the generational barrier here because we never 2025 // mark through a weak cell and collect evacuation candidates when we process 2026 // all weak cells. 2027 WriteBarrierMode mode = ObjectMarking::IsBlack(this) 2028 ? UPDATE_WRITE_BARRIER 2029 : UPDATE_WEAK_WRITE_BARRIER; 2030 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kValueOffset, val, mode); 2031 } 2032 2033 bool WeakCell::cleared() const { return value() == Smi::kZero; } 2034 2035 Object* WeakCell::next() const { return READ_FIELD(this, kNextOffset); } 2036 2037 2038 void WeakCell::set_next(Object* val, WriteBarrierMode mode) { 2039 WRITE_FIELD(this, kNextOffset, val); 2040 if (mode == UPDATE_WRITE_BARRIER) { 2041 WRITE_BARRIER(GetHeap(), this, kNextOffset, val); 2042 } 2043 } 2044 2045 2046 void WeakCell::clear_next(Object* the_hole_value) { 2047 DCHECK_EQ(GetHeap()->the_hole_value(), the_hole_value); 2048 set_next(the_hole_value, SKIP_WRITE_BARRIER); 2049 } 2050 2051 bool WeakCell::next_cleared() { return next()->IsTheHole(GetIsolate()); } 2052 2053 int JSObject::GetHeaderSize() { return GetHeaderSize(map()->instance_type()); } 2054 2055 2056 int JSObject::GetHeaderSize(InstanceType type) { 2057 // Check for the most common kind of JavaScript object before 2058 // falling into the generic switch. This speeds up the internal 2059 // field operations considerably on average. 2060 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize; 2061 switch (type) { 2062 case JS_API_OBJECT_TYPE: 2063 case JS_SPECIAL_API_OBJECT_TYPE: 2064 return JSObject::kHeaderSize; 2065 case JS_GENERATOR_OBJECT_TYPE: 2066 return JSGeneratorObject::kSize; 2067 case JS_GLOBAL_PROXY_TYPE: 2068 return JSGlobalProxy::kSize; 2069 case JS_GLOBAL_OBJECT_TYPE: 2070 return JSGlobalObject::kSize; 2071 case JS_BOUND_FUNCTION_TYPE: 2072 return JSBoundFunction::kSize; 2073 case JS_FUNCTION_TYPE: 2074 return JSFunction::kSize; 2075 case JS_VALUE_TYPE: 2076 return JSValue::kSize; 2077 case JS_DATE_TYPE: 2078 return JSDate::kSize; 2079 case JS_ARRAY_TYPE: 2080 return JSArray::kSize; 2081 case JS_ARRAY_BUFFER_TYPE: 2082 return JSArrayBuffer::kSize; 2083 case JS_TYPED_ARRAY_TYPE: 2084 return JSTypedArray::kSize; 2085 case JS_DATA_VIEW_TYPE: 2086 return JSDataView::kSize; 2087 case JS_SET_TYPE: 2088 return JSSet::kSize; 2089 case JS_MAP_TYPE: 2090 return JSMap::kSize; 2091 case JS_SET_ITERATOR_TYPE: 2092 return JSSetIterator::kSize; 2093 case JS_MAP_ITERATOR_TYPE: 2094 return JSMapIterator::kSize; 2095 case JS_WEAK_MAP_TYPE: 2096 return JSWeakMap::kSize; 2097 case JS_WEAK_SET_TYPE: 2098 return JSWeakSet::kSize; 2099 case JS_PROMISE_CAPABILITY_TYPE: 2100 return JSPromiseCapability::kSize; 2101 case JS_PROMISE_TYPE: 2102 return JSPromise::kSize; 2103 case JS_REGEXP_TYPE: 2104 return JSRegExp::kSize; 2105 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 2106 return JSObject::kHeaderSize; 2107 case JS_MESSAGE_OBJECT_TYPE: 2108 return JSMessageObject::kSize; 2109 case JS_ARGUMENTS_TYPE: 2110 return JSArgumentsObject::kHeaderSize; 2111 case JS_ERROR_TYPE: 2112 return JSObject::kHeaderSize; 2113 case JS_STRING_ITERATOR_TYPE: 2114 return JSStringIterator::kSize; 2115 case JS_MODULE_NAMESPACE_TYPE: 2116 return JSModuleNamespace::kHeaderSize; 2117 default: 2118 if (type >= FIRST_ARRAY_ITERATOR_TYPE && 2119 type <= LAST_ARRAY_ITERATOR_TYPE) { 2120 return JSArrayIterator::kSize; 2121 } 2122 UNREACHABLE(); 2123 return 0; 2124 } 2125 } 2126 2127 inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) { 2128 return instance_type <= LAST_SPECIAL_RECEIVER_TYPE; 2129 } 2130 2131 int JSObject::GetInternalFieldCount(Map* map) { 2132 int instance_size = map->instance_size(); 2133 if (instance_size == kVariableSizeSentinel) return 0; 2134 InstanceType instance_type = map->instance_type(); 2135 return ((instance_size - GetHeaderSize(instance_type)) >> kPointerSizeLog2) - 2136 map->GetInObjectProperties(); 2137 } 2138 2139 2140 int JSObject::GetInternalFieldCount() { return GetInternalFieldCount(map()); } 2141 2142 2143 int JSObject::GetInternalFieldOffset(int index) { 2144 DCHECK(index < GetInternalFieldCount() && index >= 0); 2145 return GetHeaderSize() + (kPointerSize * index); 2146 } 2147 2148 2149 Object* JSObject::GetInternalField(int index) { 2150 DCHECK(index < GetInternalFieldCount() && index >= 0); 2151 // Internal objects do follow immediately after the header, whereas in-object 2152 // properties are at the end of the object. Therefore there is no need 2153 // to adjust the index here. 2154 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index)); 2155 } 2156 2157 2158 void JSObject::SetInternalField(int index, Object* value) { 2159 DCHECK(index < GetInternalFieldCount() && index >= 0); 2160 // Internal objects do follow immediately after the header, whereas in-object 2161 // properties are at the end of the object. Therefore there is no need 2162 // to adjust the index here. 2163 int offset = GetHeaderSize() + (kPointerSize * index); 2164 WRITE_FIELD(this, offset, value); 2165 WRITE_BARRIER(GetHeap(), this, offset, value); 2166 } 2167 2168 2169 void JSObject::SetInternalField(int index, Smi* value) { 2170 DCHECK(index < GetInternalFieldCount() && index >= 0); 2171 // Internal objects do follow immediately after the header, whereas in-object 2172 // properties are at the end of the object. Therefore there is no need 2173 // to adjust the index here. 2174 int offset = GetHeaderSize() + (kPointerSize * index); 2175 WRITE_FIELD(this, offset, value); 2176 } 2177 2178 2179 bool JSObject::IsUnboxedDoubleField(FieldIndex index) { 2180 if (!FLAG_unbox_double_fields) return false; 2181 return map()->IsUnboxedDoubleField(index); 2182 } 2183 2184 2185 bool Map::IsUnboxedDoubleField(FieldIndex index) { 2186 if (!FLAG_unbox_double_fields) return false; 2187 if (index.is_hidden_field() || !index.is_inobject()) return false; 2188 return !layout_descriptor()->IsTagged(index.property_index()); 2189 } 2190 2191 2192 // Access fast-case object properties at index. The use of these routines 2193 // is needed to correctly distinguish between properties stored in-object and 2194 // properties stored in the properties array. 2195 Object* JSObject::RawFastPropertyAt(FieldIndex index) { 2196 DCHECK(!IsUnboxedDoubleField(index)); 2197 if (index.is_inobject()) { 2198 return READ_FIELD(this, index.offset()); 2199 } else { 2200 return properties()->get(index.outobject_array_index()); 2201 } 2202 } 2203 2204 2205 double JSObject::RawFastDoublePropertyAt(FieldIndex index) { 2206 DCHECK(IsUnboxedDoubleField(index)); 2207 return READ_DOUBLE_FIELD(this, index.offset()); 2208 } 2209 2210 uint64_t JSObject::RawFastDoublePropertyAsBitsAt(FieldIndex index) { 2211 DCHECK(IsUnboxedDoubleField(index)); 2212 return READ_UINT64_FIELD(this, index.offset()); 2213 } 2214 2215 void JSObject::RawFastPropertyAtPut(FieldIndex index, Object* value) { 2216 if (index.is_inobject()) { 2217 int offset = index.offset(); 2218 WRITE_FIELD(this, offset, value); 2219 WRITE_BARRIER(GetHeap(), this, offset, value); 2220 } else { 2221 properties()->set(index.outobject_array_index(), value); 2222 } 2223 } 2224 2225 void JSObject::RawFastDoublePropertyAsBitsAtPut(FieldIndex index, 2226 uint64_t bits) { 2227 WRITE_UINT64_FIELD(this, index.offset(), bits); 2228 } 2229 2230 void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { 2231 if (IsUnboxedDoubleField(index)) { 2232 DCHECK(value->IsMutableHeapNumber()); 2233 // Ensure that all bits of the double value are preserved. 2234 RawFastDoublePropertyAsBitsAtPut(index, 2235 HeapNumber::cast(value)->value_as_bits()); 2236 } else { 2237 RawFastPropertyAtPut(index, value); 2238 } 2239 } 2240 2241 void JSObject::WriteToField(int descriptor, PropertyDetails details, 2242 Object* value) { 2243 DCHECK_EQ(kField, details.location()); 2244 DCHECK_EQ(kData, details.kind()); 2245 DisallowHeapAllocation no_gc; 2246 FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor); 2247 if (details.representation().IsDouble()) { 2248 // Nothing more to be done. 2249 if (value->IsUninitialized(this->GetIsolate())) { 2250 return; 2251 } 2252 // Manipulating the signaling NaN used for the hole and uninitialized 2253 // double field sentinel in C++, e.g. with bit_cast or value()/set_value(), 2254 // will change its value on ia32 (the x87 stack is used to return values 2255 // and stores to the stack silently clear the signalling bit). 2256 uint64_t bits; 2257 if (value->IsSmi()) { 2258 bits = bit_cast<uint64_t>(static_cast<double>(Smi::cast(value)->value())); 2259 } else { 2260 DCHECK(value->IsHeapNumber()); 2261 bits = HeapNumber::cast(value)->value_as_bits(); 2262 } 2263 if (IsUnboxedDoubleField(index)) { 2264 RawFastDoublePropertyAsBitsAtPut(index, bits); 2265 } else { 2266 HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index)); 2267 DCHECK(box->IsMutableHeapNumber()); 2268 box->set_value_as_bits(bits); 2269 } 2270 } else { 2271 RawFastPropertyAtPut(index, value); 2272 } 2273 } 2274 2275 int JSObject::GetInObjectPropertyOffset(int index) { 2276 return map()->GetInObjectPropertyOffset(index); 2277 } 2278 2279 2280 Object* JSObject::InObjectPropertyAt(int index) { 2281 int offset = GetInObjectPropertyOffset(index); 2282 return READ_FIELD(this, offset); 2283 } 2284 2285 2286 Object* JSObject::InObjectPropertyAtPut(int index, 2287 Object* value, 2288 WriteBarrierMode mode) { 2289 // Adjust for the number of properties stored in the object. 2290 int offset = GetInObjectPropertyOffset(index); 2291 WRITE_FIELD(this, offset, value); 2292 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); 2293 return value; 2294 } 2295 2296 2297 void JSObject::InitializeBody(Map* map, int start_offset, 2298 Object* pre_allocated_value, 2299 Object* filler_value) { 2300 DCHECK(!filler_value->IsHeapObject() || 2301 !GetHeap()->InNewSpace(filler_value)); 2302 DCHECK(!pre_allocated_value->IsHeapObject() || 2303 !GetHeap()->InNewSpace(pre_allocated_value)); 2304 int size = map->instance_size(); 2305 int offset = start_offset; 2306 if (filler_value != pre_allocated_value) { 2307 int end_of_pre_allocated_offset = 2308 size - (map->unused_property_fields() * kPointerSize); 2309 DCHECK_LE(kHeaderSize, end_of_pre_allocated_offset); 2310 while (offset < end_of_pre_allocated_offset) { 2311 WRITE_FIELD(this, offset, pre_allocated_value); 2312 offset += kPointerSize; 2313 } 2314 } 2315 while (offset < size) { 2316 WRITE_FIELD(this, offset, filler_value); 2317 offset += kPointerSize; 2318 } 2319 } 2320 2321 2322 bool Map::TooManyFastProperties(StoreFromKeyed store_mode) { 2323 if (unused_property_fields() != 0) return false; 2324 if (is_prototype_map()) return false; 2325 int minimum = store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ? 128 : 12; 2326 int limit = Max(minimum, GetInObjectProperties()); 2327 int external = NumberOfFields() - GetInObjectProperties(); 2328 return external > limit; 2329 } 2330 2331 2332 void Struct::InitializeBody(int object_size) { 2333 Object* value = GetHeap()->undefined_value(); 2334 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { 2335 WRITE_FIELD(this, offset, value); 2336 } 2337 } 2338 2339 bool Object::ToArrayLength(uint32_t* index) { return Object::ToUint32(index); } 2340 2341 2342 bool Object::ToArrayIndex(uint32_t* index) { 2343 return Object::ToUint32(index) && *index != kMaxUInt32; 2344 } 2345 2346 2347 void Object::VerifyApiCallResultType() { 2348 #if DEBUG 2349 if (IsSmi()) return; 2350 DCHECK(IsHeapObject()); 2351 Isolate* isolate = HeapObject::cast(this)->GetIsolate(); 2352 if (!(IsString() || IsSymbol() || IsJSReceiver() || IsHeapNumber() || 2353 IsUndefined(isolate) || IsTrue(isolate) || IsFalse(isolate) || 2354 IsNull(isolate))) { 2355 FATAL("API call returned invalid object"); 2356 } 2357 #endif // DEBUG 2358 } 2359 2360 2361 Object* FixedArray::get(int index) const { 2362 SLOW_DCHECK(index >= 0 && index < this->length()); 2363 return NOBARRIER_READ_FIELD(this, kHeaderSize + index * kPointerSize); 2364 } 2365 2366 Handle<Object> FixedArray::get(FixedArray* array, int index, Isolate* isolate) { 2367 return handle(array->get(index), isolate); 2368 } 2369 2370 template <class T> 2371 MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const { 2372 Object* obj = get(index); 2373 if (obj->IsUndefined(isolate)) return MaybeHandle<T>(); 2374 return Handle<T>(T::cast(obj), isolate); 2375 } 2376 2377 template <class T> 2378 Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const { 2379 Object* obj = get(index); 2380 CHECK(!obj->IsUndefined(isolate)); 2381 return Handle<T>(T::cast(obj), isolate); 2382 } 2383 bool FixedArray::is_the_hole(Isolate* isolate, int index) { 2384 return get(index)->IsTheHole(isolate); 2385 } 2386 2387 void FixedArray::set(int index, Smi* value) { 2388 DCHECK(map() != GetHeap()->fixed_cow_array_map()); 2389 DCHECK(index >= 0 && index < this->length()); 2390 DCHECK(reinterpret_cast<Object*>(value)->IsSmi()); 2391 int offset = kHeaderSize + index * kPointerSize; 2392 NOBARRIER_WRITE_FIELD(this, offset, value); 2393 } 2394 2395 2396 void FixedArray::set(int index, Object* value) { 2397 DCHECK_NE(GetHeap()->fixed_cow_array_map(), map()); 2398 DCHECK(IsFixedArray()); 2399 DCHECK_GE(index, 0); 2400 DCHECK_LT(index, this->length()); 2401 int offset = kHeaderSize + index * kPointerSize; 2402 NOBARRIER_WRITE_FIELD(this, offset, value); 2403 WRITE_BARRIER(GetHeap(), this, offset, value); 2404 } 2405 2406 2407 double FixedDoubleArray::get_scalar(int index) { 2408 DCHECK(map() != GetHeap()->fixed_cow_array_map() && 2409 map() != GetHeap()->fixed_array_map()); 2410 DCHECK(index >= 0 && index < this->length()); 2411 DCHECK(!is_the_hole(index)); 2412 return READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize); 2413 } 2414 2415 2416 uint64_t FixedDoubleArray::get_representation(int index) { 2417 DCHECK(map() != GetHeap()->fixed_cow_array_map() && 2418 map() != GetHeap()->fixed_array_map()); 2419 DCHECK(index >= 0 && index < this->length()); 2420 int offset = kHeaderSize + index * kDoubleSize; 2421 return READ_UINT64_FIELD(this, offset); 2422 } 2423 2424 Handle<Object> FixedDoubleArray::get(FixedDoubleArray* array, int index, 2425 Isolate* isolate) { 2426 if (array->is_the_hole(index)) { 2427 return isolate->factory()->the_hole_value(); 2428 } else { 2429 return isolate->factory()->NewNumber(array->get_scalar(index)); 2430 } 2431 } 2432 2433 2434 void FixedDoubleArray::set(int index, double value) { 2435 DCHECK(map() != GetHeap()->fixed_cow_array_map() && 2436 map() != GetHeap()->fixed_array_map()); 2437 int offset = kHeaderSize + index * kDoubleSize; 2438 if (std::isnan(value)) { 2439 WRITE_DOUBLE_FIELD(this, offset, std::numeric_limits<double>::quiet_NaN()); 2440 } else { 2441 WRITE_DOUBLE_FIELD(this, offset, value); 2442 } 2443 DCHECK(!is_the_hole(index)); 2444 } 2445 2446 void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) { 2447 set_the_hole(index); 2448 } 2449 2450 void FixedDoubleArray::set_the_hole(int index) { 2451 DCHECK(map() != GetHeap()->fixed_cow_array_map() && 2452 map() != GetHeap()->fixed_array_map()); 2453 int offset = kHeaderSize + index * kDoubleSize; 2454 WRITE_UINT64_FIELD(this, offset, kHoleNanInt64); 2455 } 2456 2457 bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) { 2458 return is_the_hole(index); 2459 } 2460 2461 bool FixedDoubleArray::is_the_hole(int index) { 2462 return get_representation(index) == kHoleNanInt64; 2463 } 2464 2465 2466 double* FixedDoubleArray::data_start() { 2467 return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize)); 2468 } 2469 2470 2471 void FixedDoubleArray::FillWithHoles(int from, int to) { 2472 for (int i = from; i < to; i++) { 2473 set_the_hole(i); 2474 } 2475 } 2476 2477 2478 Object* WeakFixedArray::Get(int index) const { 2479 Object* raw = FixedArray::cast(this)->get(index + kFirstIndex); 2480 if (raw->IsSmi()) return raw; 2481 DCHECK(raw->IsWeakCell()); 2482 return WeakCell::cast(raw)->value(); 2483 } 2484 2485 2486 bool WeakFixedArray::IsEmptySlot(int index) const { 2487 DCHECK(index < Length()); 2488 return Get(index)->IsSmi(); 2489 } 2490 2491 2492 void WeakFixedArray::Clear(int index) { 2493 FixedArray::cast(this)->set(index + kFirstIndex, Smi::kZero); 2494 } 2495 2496 2497 int WeakFixedArray::Length() const { 2498 return FixedArray::cast(this)->length() - kFirstIndex; 2499 } 2500 2501 2502 int WeakFixedArray::last_used_index() const { 2503 return Smi::cast(FixedArray::cast(this)->get(kLastUsedIndexIndex))->value(); 2504 } 2505 2506 2507 void WeakFixedArray::set_last_used_index(int index) { 2508 FixedArray::cast(this)->set(kLastUsedIndexIndex, Smi::FromInt(index)); 2509 } 2510 2511 2512 template <class T> 2513 T* WeakFixedArray::Iterator::Next() { 2514 if (list_ != NULL) { 2515 // Assert that list did not change during iteration. 2516 DCHECK_EQ(last_used_index_, list_->last_used_index()); 2517 while (index_ < list_->Length()) { 2518 Object* item = list_->Get(index_++); 2519 if (item != Empty()) return T::cast(item); 2520 } 2521 list_ = NULL; 2522 } 2523 return NULL; 2524 } 2525 2526 2527 int ArrayList::Length() { 2528 if (FixedArray::cast(this)->length() == 0) return 0; 2529 return Smi::cast(FixedArray::cast(this)->get(kLengthIndex))->value(); 2530 } 2531 2532 2533 void ArrayList::SetLength(int length) { 2534 return FixedArray::cast(this)->set(kLengthIndex, Smi::FromInt(length)); 2535 } 2536 2537 2538 Object* ArrayList::Get(int index) { 2539 return FixedArray::cast(this)->get(kFirstIndex + index); 2540 } 2541 2542 2543 Object** ArrayList::Slot(int index) { 2544 return data_start() + kFirstIndex + index; 2545 } 2546 2547 void ArrayList::Set(int index, Object* obj, WriteBarrierMode mode) { 2548 FixedArray::cast(this)->set(kFirstIndex + index, obj, mode); 2549 } 2550 2551 2552 void ArrayList::Clear(int index, Object* undefined) { 2553 DCHECK(undefined->IsUndefined(GetIsolate())); 2554 FixedArray::cast(this) 2555 ->set(kFirstIndex + index, undefined, SKIP_WRITE_BARRIER); 2556 } 2557 2558 int RegExpMatchInfo::NumberOfCaptureRegisters() { 2559 DCHECK_GE(length(), kLastMatchOverhead); 2560 Object* obj = get(kNumberOfCapturesIndex); 2561 return Smi::cast(obj)->value(); 2562 } 2563 2564 void RegExpMatchInfo::SetNumberOfCaptureRegisters(int value) { 2565 DCHECK_GE(length(), kLastMatchOverhead); 2566 set(kNumberOfCapturesIndex, Smi::FromInt(value)); 2567 } 2568 2569 String* RegExpMatchInfo::LastSubject() { 2570 DCHECK_GE(length(), kLastMatchOverhead); 2571 Object* obj = get(kLastSubjectIndex); 2572 return String::cast(obj); 2573 } 2574 2575 void RegExpMatchInfo::SetLastSubject(String* value) { 2576 DCHECK_GE(length(), kLastMatchOverhead); 2577 set(kLastSubjectIndex, value); 2578 } 2579 2580 Object* RegExpMatchInfo::LastInput() { 2581 DCHECK_GE(length(), kLastMatchOverhead); 2582 return get(kLastInputIndex); 2583 } 2584 2585 void RegExpMatchInfo::SetLastInput(Object* value) { 2586 DCHECK_GE(length(), kLastMatchOverhead); 2587 set(kLastInputIndex, value); 2588 } 2589 2590 int RegExpMatchInfo::Capture(int i) { 2591 DCHECK_LT(i, NumberOfCaptureRegisters()); 2592 Object* obj = get(kFirstCaptureIndex + i); 2593 return Smi::cast(obj)->value(); 2594 } 2595 2596 void RegExpMatchInfo::SetCapture(int i, int value) { 2597 DCHECK_LT(i, NumberOfCaptureRegisters()); 2598 set(kFirstCaptureIndex + i, Smi::FromInt(value)); 2599 } 2600 2601 WriteBarrierMode HeapObject::GetWriteBarrierMode( 2602 const DisallowHeapAllocation& promise) { 2603 Heap* heap = GetHeap(); 2604 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER; 2605 if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER; 2606 return UPDATE_WRITE_BARRIER; 2607 } 2608 2609 2610 AllocationAlignment HeapObject::RequiredAlignment() { 2611 #ifdef V8_HOST_ARCH_32_BIT 2612 if ((IsFixedFloat64Array() || IsFixedDoubleArray()) && 2613 FixedArrayBase::cast(this)->length() != 0) { 2614 return kDoubleAligned; 2615 } 2616 if (IsHeapNumber()) return kDoubleUnaligned; 2617 #endif // V8_HOST_ARCH_32_BIT 2618 return kWordAligned; 2619 } 2620 2621 2622 void FixedArray::set(int index, 2623 Object* value, 2624 WriteBarrierMode mode) { 2625 DCHECK_NE(map(), GetHeap()->fixed_cow_array_map()); 2626 DCHECK_GE(index, 0); 2627 DCHECK_LT(index, this->length()); 2628 int offset = kHeaderSize + index * kPointerSize; 2629 NOBARRIER_WRITE_FIELD(this, offset, value); 2630 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); 2631 } 2632 2633 2634 void FixedArray::NoWriteBarrierSet(FixedArray* array, 2635 int index, 2636 Object* value) { 2637 DCHECK_NE(array->map(), array->GetHeap()->fixed_cow_array_map()); 2638 DCHECK_GE(index, 0); 2639 DCHECK_LT(index, array->length()); 2640 DCHECK(!array->GetHeap()->InNewSpace(value)); 2641 NOBARRIER_WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value); 2642 } 2643 2644 void FixedArray::set_undefined(int index) { 2645 set_undefined(GetIsolate(), index); 2646 } 2647 2648 void FixedArray::set_undefined(Isolate* isolate, int index) { 2649 FixedArray::NoWriteBarrierSet(this, index, 2650 isolate->heap()->undefined_value()); 2651 } 2652 2653 void FixedArray::set_null(int index) { set_null(GetIsolate(), index); } 2654 2655 void FixedArray::set_null(Isolate* isolate, int index) { 2656 FixedArray::NoWriteBarrierSet(this, index, isolate->heap()->null_value()); 2657 } 2658 2659 void FixedArray::set_the_hole(int index) { set_the_hole(GetIsolate(), index); } 2660 2661 void FixedArray::set_the_hole(Isolate* isolate, int index) { 2662 FixedArray::NoWriteBarrierSet(this, index, isolate->heap()->the_hole_value()); 2663 } 2664 2665 void FixedArray::FillWithHoles(int from, int to) { 2666 Isolate* isolate = GetIsolate(); 2667 for (int i = from; i < to; i++) { 2668 set_the_hole(isolate, i); 2669 } 2670 } 2671 2672 2673 Object** FixedArray::data_start() { 2674 return HeapObject::RawField(this, kHeaderSize); 2675 } 2676 2677 2678 Object** FixedArray::RawFieldOfElementAt(int index) { 2679 return HeapObject::RawField(this, OffsetOfElementAt(index)); 2680 } 2681 2682 #define DEFINE_FRAME_ARRAY_ACCESSORS(name, type) \ 2683 type* FrameArray::name(int frame_ix) const { \ 2684 Object* obj = \ 2685 get(kFirstIndex + frame_ix * kElementsPerFrame + k##name##Offset); \ 2686 return type::cast(obj); \ 2687 } \ 2688 \ 2689 void FrameArray::Set##name(int frame_ix, type* value) { \ 2690 set(kFirstIndex + frame_ix * kElementsPerFrame + k##name##Offset, value); \ 2691 } 2692 FRAME_ARRAY_FIELD_LIST(DEFINE_FRAME_ARRAY_ACCESSORS) 2693 #undef DEFINE_FRAME_ARRAY_ACCESSORS 2694 2695 bool FrameArray::IsWasmFrame(int frame_ix) const { 2696 const int flags = Flags(frame_ix)->value(); 2697 return (flags & kIsWasmFrame) != 0; 2698 } 2699 2700 bool FrameArray::IsAsmJsWasmFrame(int frame_ix) const { 2701 const int flags = Flags(frame_ix)->value(); 2702 return (flags & kIsAsmJsWasmFrame) != 0; 2703 } 2704 2705 int FrameArray::FrameCount() const { 2706 const int frame_count = Smi::cast(get(kFrameCountIndex))->value(); 2707 DCHECK_LE(0, frame_count); 2708 return frame_count; 2709 } 2710 2711 bool DescriptorArray::IsEmpty() { 2712 DCHECK(length() >= kFirstIndex || 2713 this == GetHeap()->empty_descriptor_array()); 2714 return length() < kFirstIndex; 2715 } 2716 2717 2718 int DescriptorArray::number_of_descriptors() { 2719 DCHECK(length() >= kFirstIndex || IsEmpty()); 2720 int len = length(); 2721 return len == 0 ? 0 : Smi::cast(get(kDescriptorLengthIndex))->value(); 2722 } 2723 2724 2725 int DescriptorArray::number_of_descriptors_storage() { 2726 int len = length(); 2727 return len == 0 ? 0 : (len - kFirstIndex) / kEntrySize; 2728 } 2729 2730 2731 int DescriptorArray::NumberOfSlackDescriptors() { 2732 return number_of_descriptors_storage() - number_of_descriptors(); 2733 } 2734 2735 2736 void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) { 2737 WRITE_FIELD( 2738 this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors)); 2739 } 2740 2741 2742 inline int DescriptorArray::number_of_entries() { 2743 return number_of_descriptors(); 2744 } 2745 2746 2747 bool DescriptorArray::HasEnumCache() { 2748 return !IsEmpty() && !get(kEnumCacheIndex)->IsSmi(); 2749 } 2750 2751 2752 void DescriptorArray::CopyEnumCacheFrom(DescriptorArray* array) { 2753 set(kEnumCacheIndex, array->get(kEnumCacheIndex)); 2754 } 2755 2756 2757 FixedArray* DescriptorArray::GetEnumCache() { 2758 DCHECK(HasEnumCache()); 2759 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); 2760 return FixedArray::cast(bridge->get(kEnumCacheBridgeCacheIndex)); 2761 } 2762 2763 2764 bool DescriptorArray::HasEnumIndicesCache() { 2765 if (IsEmpty()) return false; 2766 Object* object = get(kEnumCacheIndex); 2767 if (object->IsSmi()) return false; 2768 FixedArray* bridge = FixedArray::cast(object); 2769 return !bridge->get(kEnumCacheBridgeIndicesCacheIndex)->IsSmi(); 2770 } 2771 2772 2773 FixedArray* DescriptorArray::GetEnumIndicesCache() { 2774 DCHECK(HasEnumIndicesCache()); 2775 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); 2776 return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex)); 2777 } 2778 2779 2780 Object** DescriptorArray::GetEnumCacheSlot() { 2781 DCHECK(HasEnumCache()); 2782 return HeapObject::RawField(reinterpret_cast<HeapObject*>(this), 2783 kEnumCacheOffset); 2784 } 2785 2786 // Perform a binary search in a fixed array. 2787 template <SearchMode search_mode, typename T> 2788 int BinarySearch(T* array, Name* name, int valid_entries, 2789 int* out_insertion_index) { 2790 DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == NULL); 2791 int low = 0; 2792 int high = array->number_of_entries() - 1; 2793 uint32_t hash = name->hash_field(); 2794 int limit = high; 2795 2796 DCHECK(low <= high); 2797 2798 while (low != high) { 2799 int mid = low + (high - low) / 2; 2800 Name* mid_name = array->GetSortedKey(mid); 2801 uint32_t mid_hash = mid_name->hash_field(); 2802 2803 if (mid_hash >= hash) { 2804 high = mid; 2805 } else { 2806 low = mid + 1; 2807 } 2808 } 2809 2810 for (; low <= limit; ++low) { 2811 int sort_index = array->GetSortedKeyIndex(low); 2812 Name* entry = array->GetKey(sort_index); 2813 uint32_t current_hash = entry->hash_field(); 2814 if (current_hash != hash) { 2815 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { 2816 *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1); 2817 } 2818 return T::kNotFound; 2819 } 2820 if (entry == name) { 2821 if (search_mode == ALL_ENTRIES || sort_index < valid_entries) { 2822 return sort_index; 2823 } 2824 return T::kNotFound; 2825 } 2826 } 2827 2828 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { 2829 *out_insertion_index = limit + 1; 2830 } 2831 return T::kNotFound; 2832 } 2833 2834 2835 // Perform a linear search in this fixed array. len is the number of entry 2836 // indices that are valid. 2837 template <SearchMode search_mode, typename T> 2838 int LinearSearch(T* array, Name* name, int valid_entries, 2839 int* out_insertion_index) { 2840 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { 2841 uint32_t hash = name->hash_field(); 2842 int len = array->number_of_entries(); 2843 for (int number = 0; number < len; number++) { 2844 int sorted_index = array->GetSortedKeyIndex(number); 2845 Name* entry = array->GetKey(sorted_index); 2846 uint32_t current_hash = entry->hash_field(); 2847 if (current_hash > hash) { 2848 *out_insertion_index = sorted_index; 2849 return T::kNotFound; 2850 } 2851 if (entry == name) return sorted_index; 2852 } 2853 *out_insertion_index = len; 2854 return T::kNotFound; 2855 } else { 2856 DCHECK_LE(valid_entries, array->number_of_entries()); 2857 DCHECK_NULL(out_insertion_index); // Not supported here. 2858 for (int number = 0; number < valid_entries; number++) { 2859 if (array->GetKey(number) == name) return number; 2860 } 2861 return T::kNotFound; 2862 } 2863 } 2864 2865 2866 template <SearchMode search_mode, typename T> 2867 int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) { 2868 SLOW_DCHECK(array->IsSortedNoDuplicates()); 2869 2870 if (valid_entries == 0) { 2871 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { 2872 *out_insertion_index = 0; 2873 } 2874 return T::kNotFound; 2875 } 2876 2877 // Fast case: do linear search for small arrays. 2878 const int kMaxElementsForLinearSearch = 8; 2879 if (valid_entries <= kMaxElementsForLinearSearch) { 2880 return LinearSearch<search_mode>(array, name, valid_entries, 2881 out_insertion_index); 2882 } 2883 2884 // Slow case: perform binary search. 2885 return BinarySearch<search_mode>(array, name, valid_entries, 2886 out_insertion_index); 2887 } 2888 2889 2890 int DescriptorArray::Search(Name* name, int valid_descriptors) { 2891 DCHECK(name->IsUniqueName()); 2892 return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors, NULL); 2893 } 2894 2895 int DescriptorArray::SearchWithCache(Isolate* isolate, Name* name, Map* map) { 2896 DCHECK(name->IsUniqueName()); 2897 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 2898 if (number_of_own_descriptors == 0) return kNotFound; 2899 2900 DescriptorLookupCache* cache = isolate->descriptor_lookup_cache(); 2901 int number = cache->Lookup(map, name); 2902 2903 if (number == DescriptorLookupCache::kAbsent) { 2904 number = Search(name, number_of_own_descriptors); 2905 cache->Update(map, name, number); 2906 } 2907 2908 return number; 2909 } 2910 2911 PropertyDetails Map::GetLastDescriptorDetails() { 2912 return instance_descriptors()->GetDetails(LastAdded()); 2913 } 2914 2915 2916 int Map::LastAdded() { 2917 int number_of_own_descriptors = NumberOfOwnDescriptors(); 2918 DCHECK(number_of_own_descriptors > 0); 2919 return number_of_own_descriptors - 1; 2920 } 2921 2922 2923 int Map::NumberOfOwnDescriptors() { 2924 return NumberOfOwnDescriptorsBits::decode(bit_field3()); 2925 } 2926 2927 2928 void Map::SetNumberOfOwnDescriptors(int number) { 2929 DCHECK(number <= instance_descriptors()->number_of_descriptors()); 2930 set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number)); 2931 } 2932 2933 2934 int Map::EnumLength() { return EnumLengthBits::decode(bit_field3()); } 2935 2936 2937 void Map::SetEnumLength(int length) { 2938 if (length != kInvalidEnumCacheSentinel) { 2939 DCHECK(length >= 0); 2940 DCHECK(length == 0 || instance_descriptors()->HasEnumCache()); 2941 DCHECK(length <= NumberOfOwnDescriptors()); 2942 } 2943 set_bit_field3(EnumLengthBits::update(bit_field3(), length)); 2944 } 2945 2946 2947 FixedArrayBase* Map::GetInitialElements() { 2948 FixedArrayBase* result = nullptr; 2949 if (has_fast_elements() || has_fast_string_wrapper_elements()) { 2950 result = GetHeap()->empty_fixed_array(); 2951 } else if (has_fast_sloppy_arguments_elements()) { 2952 result = GetHeap()->empty_sloppy_arguments_elements(); 2953 } else if (has_fixed_typed_array_elements()) { 2954 result = GetHeap()->EmptyFixedTypedArrayForMap(this); 2955 } else { 2956 UNREACHABLE(); 2957 } 2958 DCHECK(!GetHeap()->InNewSpace(result)); 2959 return result; 2960 } 2961 2962 Object** DescriptorArray::GetKeySlot(int descriptor_number) { 2963 DCHECK(descriptor_number < number_of_descriptors()); 2964 return RawFieldOfElementAt(ToKeyIndex(descriptor_number)); 2965 } 2966 2967 2968 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) { 2969 return GetKeySlot(descriptor_number); 2970 } 2971 2972 2973 Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) { 2974 return GetValueSlot(descriptor_number - 1) + 1; 2975 } 2976 2977 2978 Name* DescriptorArray::GetKey(int descriptor_number) { 2979 DCHECK(descriptor_number < number_of_descriptors()); 2980 return Name::cast(get(ToKeyIndex(descriptor_number))); 2981 } 2982 2983 2984 int DescriptorArray::GetSortedKeyIndex(int descriptor_number) { 2985 return GetDetails(descriptor_number).pointer(); 2986 } 2987 2988 2989 Name* DescriptorArray::GetSortedKey(int descriptor_number) { 2990 return GetKey(GetSortedKeyIndex(descriptor_number)); 2991 } 2992 2993 2994 void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) { 2995 PropertyDetails details = GetDetails(descriptor_index); 2996 set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi()); 2997 } 2998 2999 3000 Object** DescriptorArray::GetValueSlot(int descriptor_number) { 3001 DCHECK(descriptor_number < number_of_descriptors()); 3002 return RawFieldOfElementAt(ToValueIndex(descriptor_number)); 3003 } 3004 3005 3006 int DescriptorArray::GetValueOffset(int descriptor_number) { 3007 return OffsetOfElementAt(ToValueIndex(descriptor_number)); 3008 } 3009 3010 3011 Object* DescriptorArray::GetValue(int descriptor_number) { 3012 DCHECK(descriptor_number < number_of_descriptors()); 3013 return get(ToValueIndex(descriptor_number)); 3014 } 3015 3016 3017 void DescriptorArray::SetValue(int descriptor_index, Object* value) { 3018 set(ToValueIndex(descriptor_index), value); 3019 } 3020 3021 3022 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) { 3023 DCHECK(descriptor_number < number_of_descriptors()); 3024 Object* details = get(ToDetailsIndex(descriptor_number)); 3025 return PropertyDetails(Smi::cast(details)); 3026 } 3027 3028 int DescriptorArray::GetFieldIndex(int descriptor_number) { 3029 DCHECK(GetDetails(descriptor_number).location() == kField); 3030 return GetDetails(descriptor_number).field_index(); 3031 } 3032 3033 FieldType* DescriptorArray::GetFieldType(int descriptor_number) { 3034 DCHECK(GetDetails(descriptor_number).location() == kField); 3035 Object* wrapped_type = GetValue(descriptor_number); 3036 return Map::UnwrapFieldType(wrapped_type); 3037 } 3038 3039 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { 3040 desc->Init(handle(GetKey(descriptor_number), GetIsolate()), 3041 handle(GetValue(descriptor_number), GetIsolate()), 3042 GetDetails(descriptor_number)); 3043 } 3044 3045 void DescriptorArray::Set(int descriptor_number, Name* key, Object* value, 3046 PropertyDetails details) { 3047 // Range check. 3048 DCHECK(descriptor_number < number_of_descriptors()); 3049 set(ToKeyIndex(descriptor_number), key); 3050 set(ToValueIndex(descriptor_number), value); 3051 set(ToDetailsIndex(descriptor_number), details.AsSmi()); 3052 } 3053 3054 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { 3055 Name* key = *desc->GetKey(); 3056 Object* value = *desc->GetValue(); 3057 Set(descriptor_number, key, value, desc->GetDetails()); 3058 } 3059 3060 3061 void DescriptorArray::Append(Descriptor* desc) { 3062 DisallowHeapAllocation no_gc; 3063 int descriptor_number = number_of_descriptors(); 3064 SetNumberOfDescriptors(descriptor_number + 1); 3065 Set(descriptor_number, desc); 3066 3067 uint32_t hash = desc->GetKey()->Hash(); 3068 3069 int insertion; 3070 3071 for (insertion = descriptor_number; insertion > 0; --insertion) { 3072 Name* key = GetSortedKey(insertion - 1); 3073 if (key->Hash() <= hash) break; 3074 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1)); 3075 } 3076 3077 SetSortedKey(insertion, descriptor_number); 3078 } 3079 3080 3081 void DescriptorArray::SwapSortedKeys(int first, int second) { 3082 int first_key = GetSortedKeyIndex(first); 3083 SetSortedKey(first, GetSortedKeyIndex(second)); 3084 SetSortedKey(second, first_key); 3085 } 3086 3087 3088 int HashTableBase::NumberOfElements() { 3089 return Smi::cast(get(kNumberOfElementsIndex))->value(); 3090 } 3091 3092 3093 int HashTableBase::NumberOfDeletedElements() { 3094 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); 3095 } 3096 3097 3098 int HashTableBase::Capacity() { 3099 return Smi::cast(get(kCapacityIndex))->value(); 3100 } 3101 3102 3103 void HashTableBase::ElementAdded() { 3104 SetNumberOfElements(NumberOfElements() + 1); 3105 } 3106 3107 3108 void HashTableBase::ElementRemoved() { 3109 SetNumberOfElements(NumberOfElements() - 1); 3110 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1); 3111 } 3112 3113 3114 void HashTableBase::ElementsRemoved(int n) { 3115 SetNumberOfElements(NumberOfElements() - n); 3116 SetNumberOfDeletedElements(NumberOfDeletedElements() + n); 3117 } 3118 3119 3120 // static 3121 int HashTableBase::ComputeCapacity(int at_least_space_for) { 3122 int capacity = base::bits::RoundUpToPowerOfTwo32(at_least_space_for * 2); 3123 return Max(capacity, kMinCapacity); 3124 } 3125 3126 bool HashTableBase::IsKey(Isolate* isolate, Object* k) { 3127 Heap* heap = isolate->heap(); 3128 return k != heap->the_hole_value() && k != heap->undefined_value(); 3129 } 3130 3131 bool HashTableBase::IsKey(Object* k) { 3132 Isolate* isolate = this->GetIsolate(); 3133 return !k->IsTheHole(isolate) && !k->IsUndefined(isolate); 3134 } 3135 3136 3137 void HashTableBase::SetNumberOfElements(int nof) { 3138 set(kNumberOfElementsIndex, Smi::FromInt(nof)); 3139 } 3140 3141 3142 void HashTableBase::SetNumberOfDeletedElements(int nod) { 3143 set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod)); 3144 } 3145 3146 template <typename Key> 3147 Map* BaseShape<Key>::GetMap(Isolate* isolate) { 3148 return isolate->heap()->hash_table_map(); 3149 } 3150 3151 template <typename Derived, typename Shape, typename Key> 3152 int HashTable<Derived, Shape, Key>::FindEntry(Key key) { 3153 return FindEntry(GetIsolate(), key); 3154 } 3155 3156 3157 template<typename Derived, typename Shape, typename Key> 3158 int HashTable<Derived, Shape, Key>::FindEntry(Isolate* isolate, Key key) { 3159 return FindEntry(isolate, key, HashTable::Hash(key)); 3160 } 3161 3162 // Find entry for key otherwise return kNotFound. 3163 template <typename Derived, typename Shape, typename Key> 3164 int HashTable<Derived, Shape, Key>::FindEntry(Isolate* isolate, Key key, 3165 int32_t hash) { 3166 uint32_t capacity = Capacity(); 3167 uint32_t entry = FirstProbe(hash, capacity); 3168 uint32_t count = 1; 3169 // EnsureCapacity will guarantee the hash table is never full. 3170 Object* undefined = isolate->heap()->undefined_value(); 3171 Object* the_hole = isolate->heap()->the_hole_value(); 3172 while (true) { 3173 Object* element = KeyAt(entry); 3174 // Empty entry. Uses raw unchecked accessors because it is called by the 3175 // string table during bootstrapping. 3176 if (element == undefined) break; 3177 if (element != the_hole && Shape::IsMatch(key, element)) return entry; 3178 entry = NextProbe(entry, count++, capacity); 3179 } 3180 return kNotFound; 3181 } 3182 3183 template <typename Derived, typename Shape, typename Key> 3184 bool HashTable<Derived, Shape, Key>::Has(Key key) { 3185 return FindEntry(key) != kNotFound; 3186 } 3187 3188 template <typename Derived, typename Shape, typename Key> 3189 bool HashTable<Derived, Shape, Key>::Has(Isolate* isolate, Key key) { 3190 return FindEntry(isolate, key) != kNotFound; 3191 } 3192 3193 bool ObjectHashSet::Has(Isolate* isolate, Handle<Object> key, int32_t hash) { 3194 return FindEntry(isolate, key, hash) != kNotFound; 3195 } 3196 3197 bool ObjectHashSet::Has(Isolate* isolate, Handle<Object> key) { 3198 Object* hash = key->GetHash(); 3199 if (!hash->IsSmi()) return false; 3200 return FindEntry(isolate, key, Smi::cast(hash)->value()) != kNotFound; 3201 } 3202 3203 bool StringSetShape::IsMatch(String* key, Object* value) { 3204 return value->IsString() && key->Equals(String::cast(value)); 3205 } 3206 3207 uint32_t StringSetShape::Hash(String* key) { return key->Hash(); } 3208 3209 uint32_t StringSetShape::HashForObject(String* key, Object* object) { 3210 return object->IsString() ? String::cast(object)->Hash() : 0; 3211 } 3212 3213 bool SeededNumberDictionary::requires_slow_elements() { 3214 Object* max_index_object = get(kMaxNumberKeyIndex); 3215 if (!max_index_object->IsSmi()) return false; 3216 return 0 != 3217 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask); 3218 } 3219 3220 3221 uint32_t SeededNumberDictionary::max_number_key() { 3222 DCHECK(!requires_slow_elements()); 3223 Object* max_index_object = get(kMaxNumberKeyIndex); 3224 if (!max_index_object->IsSmi()) return 0; 3225 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value()); 3226 return value >> kRequiresSlowElementsTagSize; 3227 } 3228 3229 3230 void SeededNumberDictionary::set_requires_slow_elements() { 3231 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask)); 3232 } 3233 3234 3235 template <class T> 3236 PodArray<T>* PodArray<T>::cast(Object* object) { 3237 SLOW_DCHECK(object->IsByteArray()); 3238 return reinterpret_cast<PodArray<T>*>(object); 3239 } 3240 template <class T> 3241 const PodArray<T>* PodArray<T>::cast(const Object* object) { 3242 SLOW_DCHECK(object->IsByteArray()); 3243 return reinterpret_cast<const PodArray<T>*>(object); 3244 } 3245 3246 // static 3247 template <class T> 3248 Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length, 3249 PretenureFlag pretenure) { 3250 return Handle<PodArray<T>>::cast( 3251 isolate->factory()->NewByteArray(length * sizeof(T), pretenure)); 3252 } 3253 3254 // static 3255 template <class Traits> 3256 STATIC_CONST_MEMBER_DEFINITION const InstanceType 3257 FixedTypedArray<Traits>::kInstanceType; 3258 3259 3260 template <class Traits> 3261 FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) { 3262 SLOW_DCHECK(object->IsHeapObject() && 3263 HeapObject::cast(object)->map()->instance_type() == 3264 Traits::kInstanceType); 3265 return reinterpret_cast<FixedTypedArray<Traits>*>(object); 3266 } 3267 3268 3269 template <class Traits> 3270 const FixedTypedArray<Traits>* 3271 FixedTypedArray<Traits>::cast(const Object* object) { 3272 SLOW_DCHECK(object->IsHeapObject() && 3273 HeapObject::cast(object)->map()->instance_type() == 3274 Traits::kInstanceType); 3275 return reinterpret_cast<FixedTypedArray<Traits>*>(object); 3276 } 3277 3278 3279 #define DEFINE_DEOPT_ELEMENT_ACCESSORS(name, type) \ 3280 type* DeoptimizationInputData::name() { \ 3281 return type::cast(get(k##name##Index)); \ 3282 } \ 3283 void DeoptimizationInputData::Set##name(type* value) { \ 3284 set(k##name##Index, value); \ 3285 } 3286 3287 DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray) 3288 DEFINE_DEOPT_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi) 3289 DEFINE_DEOPT_ELEMENT_ACCESSORS(LiteralArray, FixedArray) 3290 DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrAstId, Smi) 3291 DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi) 3292 DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi) 3293 DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object) 3294 DEFINE_DEOPT_ELEMENT_ACCESSORS(WeakCellCache, Object) 3295 DEFINE_DEOPT_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>) 3296 3297 #undef DEFINE_DEOPT_ELEMENT_ACCESSORS 3298 3299 3300 #define DEFINE_DEOPT_ENTRY_ACCESSORS(name, type) \ 3301 type* DeoptimizationInputData::name(int i) { \ 3302 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \ 3303 } \ 3304 void DeoptimizationInputData::Set##name(int i, type* value) { \ 3305 set(IndexForEntry(i) + k##name##Offset, value); \ 3306 } 3307 3308 DEFINE_DEOPT_ENTRY_ACCESSORS(AstIdRaw, Smi) 3309 DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi) 3310 DEFINE_DEOPT_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi) 3311 DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi) 3312 3313 #undef DEFINE_DEOPT_ENTRY_ACCESSORS 3314 3315 3316 BailoutId DeoptimizationInputData::AstId(int i) { 3317 return BailoutId(AstIdRaw(i)->value()); 3318 } 3319 3320 3321 void DeoptimizationInputData::SetAstId(int i, BailoutId value) { 3322 SetAstIdRaw(i, Smi::FromInt(value.ToInt())); 3323 } 3324 3325 3326 int DeoptimizationInputData::DeoptCount() { 3327 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize; 3328 } 3329 3330 3331 int DeoptimizationOutputData::DeoptPoints() { return length() / 2; } 3332 3333 3334 BailoutId DeoptimizationOutputData::AstId(int index) { 3335 return BailoutId(Smi::cast(get(index * 2))->value()); 3336 } 3337 3338 3339 void DeoptimizationOutputData::SetAstId(int index, BailoutId id) { 3340 set(index * 2, Smi::FromInt(id.ToInt())); 3341 } 3342 3343 3344 Smi* DeoptimizationOutputData::PcAndState(int index) { 3345 return Smi::cast(get(1 + index * 2)); 3346 } 3347 3348 3349 void DeoptimizationOutputData::SetPcAndState(int index, Smi* offset) { 3350 set(1 + index * 2, offset); 3351 } 3352 3353 int HandlerTable::GetRangeStart(int index) const { 3354 return Smi::cast(get(index * kRangeEntrySize + kRangeStartIndex))->value(); 3355 } 3356 3357 int HandlerTable::GetRangeEnd(int index) const { 3358 return Smi::cast(get(index * kRangeEntrySize + kRangeEndIndex))->value(); 3359 } 3360 3361 int HandlerTable::GetRangeHandler(int index) const { 3362 return HandlerOffsetField::decode( 3363 Smi::cast(get(index * kRangeEntrySize + kRangeHandlerIndex))->value()); 3364 } 3365 3366 int HandlerTable::GetRangeData(int index) const { 3367 return Smi::cast(get(index * kRangeEntrySize + kRangeDataIndex))->value(); 3368 } 3369 3370 void HandlerTable::SetRangeStart(int index, int value) { 3371 set(index * kRangeEntrySize + kRangeStartIndex, Smi::FromInt(value)); 3372 } 3373 3374 3375 void HandlerTable::SetRangeEnd(int index, int value) { 3376 set(index * kRangeEntrySize + kRangeEndIndex, Smi::FromInt(value)); 3377 } 3378 3379 3380 void HandlerTable::SetRangeHandler(int index, int offset, 3381 CatchPrediction prediction) { 3382 int value = HandlerOffsetField::encode(offset) | 3383 HandlerPredictionField::encode(prediction); 3384 set(index * kRangeEntrySize + kRangeHandlerIndex, Smi::FromInt(value)); 3385 } 3386 3387 void HandlerTable::SetRangeData(int index, int value) { 3388 set(index * kRangeEntrySize + kRangeDataIndex, Smi::FromInt(value)); 3389 } 3390 3391 3392 void HandlerTable::SetReturnOffset(int index, int value) { 3393 set(index * kReturnEntrySize + kReturnOffsetIndex, Smi::FromInt(value)); 3394 } 3395 3396 void HandlerTable::SetReturnHandler(int index, int offset) { 3397 int value = HandlerOffsetField::encode(offset); 3398 set(index * kReturnEntrySize + kReturnHandlerIndex, Smi::FromInt(value)); 3399 } 3400 3401 int HandlerTable::NumberOfRangeEntries() const { 3402 return length() / kRangeEntrySize; 3403 } 3404 3405 template <typename Derived, typename Shape, typename Key> 3406 HashTable<Derived, Shape, Key>* 3407 HashTable<Derived, Shape, Key>::cast(Object* obj) { 3408 SLOW_DCHECK(obj->IsHashTable()); 3409 return reinterpret_cast<HashTable*>(obj); 3410 } 3411 3412 3413 template <typename Derived, typename Shape, typename Key> 3414 const HashTable<Derived, Shape, Key>* 3415 HashTable<Derived, Shape, Key>::cast(const Object* obj) { 3416 SLOW_DCHECK(obj->IsHashTable()); 3417 return reinterpret_cast<const HashTable*>(obj); 3418 } 3419 3420 3421 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset) 3422 SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset) 3423 3424 SMI_ACCESSORS(FreeSpace, size, kSizeOffset) 3425 NOBARRIER_SMI_ACCESSORS(FreeSpace, size, kSizeOffset) 3426 3427 SMI_ACCESSORS(String, length, kLengthOffset) 3428 SYNCHRONIZED_SMI_ACCESSORS(String, length, kLengthOffset) 3429 3430 3431 int FreeSpace::Size() { return size(); } 3432 3433 3434 FreeSpace* FreeSpace::next() { 3435 DCHECK(map() == GetHeap()->root(Heap::kFreeSpaceMapRootIndex) || 3436 (!GetHeap()->deserialization_complete() && map() == NULL)); 3437 DCHECK_LE(kNextOffset + kPointerSize, nobarrier_size()); 3438 return reinterpret_cast<FreeSpace*>( 3439 Memory::Address_at(address() + kNextOffset)); 3440 } 3441 3442 3443 void FreeSpace::set_next(FreeSpace* next) { 3444 DCHECK(map() == GetHeap()->root(Heap::kFreeSpaceMapRootIndex) || 3445 (!GetHeap()->deserialization_complete() && map() == NULL)); 3446 DCHECK_LE(kNextOffset + kPointerSize, nobarrier_size()); 3447 base::NoBarrier_Store( 3448 reinterpret_cast<base::AtomicWord*>(address() + kNextOffset), 3449 reinterpret_cast<base::AtomicWord>(next)); 3450 } 3451 3452 3453 FreeSpace* FreeSpace::cast(HeapObject* o) { 3454 SLOW_DCHECK(!o->GetHeap()->deserialization_complete() || o->IsFreeSpace()); 3455 return reinterpret_cast<FreeSpace*>(o); 3456 } 3457 3458 3459 uint32_t Name::hash_field() { 3460 return READ_UINT32_FIELD(this, kHashFieldOffset); 3461 } 3462 3463 3464 void Name::set_hash_field(uint32_t value) { 3465 WRITE_UINT32_FIELD(this, kHashFieldOffset, value); 3466 #if V8_HOST_ARCH_64_BIT 3467 #if V8_TARGET_LITTLE_ENDIAN 3468 WRITE_UINT32_FIELD(this, kHashFieldSlot + kIntSize, 0); 3469 #else 3470 WRITE_UINT32_FIELD(this, kHashFieldSlot, 0); 3471 #endif 3472 #endif 3473 } 3474 3475 3476 bool Name::Equals(Name* other) { 3477 if (other == this) return true; 3478 if ((this->IsInternalizedString() && other->IsInternalizedString()) || 3479 this->IsSymbol() || other->IsSymbol()) { 3480 return false; 3481 } 3482 return String::cast(this)->SlowEquals(String::cast(other)); 3483 } 3484 3485 3486 bool Name::Equals(Handle<Name> one, Handle<Name> two) { 3487 if (one.is_identical_to(two)) return true; 3488 if ((one->IsInternalizedString() && two->IsInternalizedString()) || 3489 one->IsSymbol() || two->IsSymbol()) { 3490 return false; 3491 } 3492 return String::SlowEquals(Handle<String>::cast(one), 3493 Handle<String>::cast(two)); 3494 } 3495 3496 3497 ACCESSORS(Symbol, name, Object, kNameOffset) 3498 SMI_ACCESSORS(Symbol, flags, kFlagsOffset) 3499 BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit) 3500 BOOL_ACCESSORS(Symbol, flags, is_well_known_symbol, kWellKnownSymbolBit) 3501 BOOL_ACCESSORS(Symbol, flags, is_public, kPublicBit) 3502 3503 bool String::Equals(String* other) { 3504 if (other == this) return true; 3505 if (this->IsInternalizedString() && other->IsInternalizedString()) { 3506 return false; 3507 } 3508 return SlowEquals(other); 3509 } 3510 3511 3512 bool String::Equals(Handle<String> one, Handle<String> two) { 3513 if (one.is_identical_to(two)) return true; 3514 if (one->IsInternalizedString() && two->IsInternalizedString()) { 3515 return false; 3516 } 3517 return SlowEquals(one, two); 3518 } 3519 3520 3521 Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) { 3522 if (string->IsConsString()) { 3523 Handle<ConsString> cons = Handle<ConsString>::cast(string); 3524 if (cons->IsFlat()) { 3525 string = handle(cons->first()); 3526 } else { 3527 return SlowFlatten(cons, pretenure); 3528 } 3529 } 3530 if (string->IsThinString()) { 3531 string = handle(Handle<ThinString>::cast(string)->actual()); 3532 DCHECK(!string->IsConsString()); 3533 } 3534 return string; 3535 } 3536 3537 3538 uint16_t String::Get(int index) { 3539 DCHECK(index >= 0 && index < length()); 3540 switch (StringShape(this).full_representation_tag()) { 3541 case kSeqStringTag | kOneByteStringTag: 3542 return SeqOneByteString::cast(this)->SeqOneByteStringGet(index); 3543 case kSeqStringTag | kTwoByteStringTag: 3544 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); 3545 case kConsStringTag | kOneByteStringTag: 3546 case kConsStringTag | kTwoByteStringTag: 3547 return ConsString::cast(this)->ConsStringGet(index); 3548 case kExternalStringTag | kOneByteStringTag: 3549 return ExternalOneByteString::cast(this)->ExternalOneByteStringGet(index); 3550 case kExternalStringTag | kTwoByteStringTag: 3551 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); 3552 case kSlicedStringTag | kOneByteStringTag: 3553 case kSlicedStringTag | kTwoByteStringTag: 3554 return SlicedString::cast(this)->SlicedStringGet(index); 3555 case kThinStringTag | kOneByteStringTag: 3556 case kThinStringTag | kTwoByteStringTag: 3557 return ThinString::cast(this)->ThinStringGet(index); 3558 default: 3559 break; 3560 } 3561 3562 UNREACHABLE(); 3563 return 0; 3564 } 3565 3566 3567 void String::Set(int index, uint16_t value) { 3568 DCHECK(index >= 0 && index < length()); 3569 DCHECK(StringShape(this).IsSequential()); 3570 3571 return this->IsOneByteRepresentation() 3572 ? SeqOneByteString::cast(this)->SeqOneByteStringSet(index, value) 3573 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); 3574 } 3575 3576 3577 bool String::IsFlat() { 3578 if (!StringShape(this).IsCons()) return true; 3579 return ConsString::cast(this)->second()->length() == 0; 3580 } 3581 3582 3583 String* String::GetUnderlying() { 3584 // Giving direct access to underlying string only makes sense if the 3585 // wrapping string is already flattened. 3586 DCHECK(this->IsFlat()); 3587 DCHECK(StringShape(this).IsIndirect()); 3588 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset); 3589 STATIC_ASSERT(ConsString::kFirstOffset == ThinString::kActualOffset); 3590 const int kUnderlyingOffset = SlicedString::kParentOffset; 3591 return String::cast(READ_FIELD(this, kUnderlyingOffset)); 3592 } 3593 3594 3595 template<class Visitor> 3596 ConsString* String::VisitFlat(Visitor* visitor, 3597 String* string, 3598 const int offset) { 3599 int slice_offset = offset; 3600 const int length = string->length(); 3601 DCHECK(offset <= length); 3602 while (true) { 3603 int32_t type = string->map()->instance_type(); 3604 switch (type & (kStringRepresentationMask | kStringEncodingMask)) { 3605 case kSeqStringTag | kOneByteStringTag: 3606 visitor->VisitOneByteString( 3607 SeqOneByteString::cast(string)->GetChars() + slice_offset, 3608 length - offset); 3609 return NULL; 3610 3611 case kSeqStringTag | kTwoByteStringTag: 3612 visitor->VisitTwoByteString( 3613 SeqTwoByteString::cast(string)->GetChars() + slice_offset, 3614 length - offset); 3615 return NULL; 3616 3617 case kExternalStringTag | kOneByteStringTag: 3618 visitor->VisitOneByteString( 3619 ExternalOneByteString::cast(string)->GetChars() + slice_offset, 3620 length - offset); 3621 return NULL; 3622 3623 case kExternalStringTag | kTwoByteStringTag: 3624 visitor->VisitTwoByteString( 3625 ExternalTwoByteString::cast(string)->GetChars() + slice_offset, 3626 length - offset); 3627 return NULL; 3628 3629 case kSlicedStringTag | kOneByteStringTag: 3630 case kSlicedStringTag | kTwoByteStringTag: { 3631 SlicedString* slicedString = SlicedString::cast(string); 3632 slice_offset += slicedString->offset(); 3633 string = slicedString->parent(); 3634 continue; 3635 } 3636 3637 case kConsStringTag | kOneByteStringTag: 3638 case kConsStringTag | kTwoByteStringTag: 3639 return ConsString::cast(string); 3640 3641 case kThinStringTag | kOneByteStringTag: 3642 case kThinStringTag | kTwoByteStringTag: 3643 string = ThinString::cast(string)->actual(); 3644 continue; 3645 3646 default: 3647 UNREACHABLE(); 3648 return NULL; 3649 } 3650 } 3651 } 3652 3653 3654 template <> 3655 inline Vector<const uint8_t> String::GetCharVector() { 3656 String::FlatContent flat = GetFlatContent(); 3657 DCHECK(flat.IsOneByte()); 3658 return flat.ToOneByteVector(); 3659 } 3660 3661 3662 template <> 3663 inline Vector<const uc16> String::GetCharVector() { 3664 String::FlatContent flat = GetFlatContent(); 3665 DCHECK(flat.IsTwoByte()); 3666 return flat.ToUC16Vector(); 3667 } 3668 3669 uint32_t String::ToValidIndex(Object* number) { 3670 uint32_t index = PositiveNumberToUint32(number); 3671 uint32_t length_value = static_cast<uint32_t>(length()); 3672 if (index > length_value) return length_value; 3673 return index; 3674 } 3675 3676 uint16_t SeqOneByteString::SeqOneByteStringGet(int index) { 3677 DCHECK(index >= 0 && index < length()); 3678 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 3679 } 3680 3681 3682 void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) { 3683 DCHECK(index >= 0 && index < length() && value <= kMaxOneByteCharCode); 3684 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, 3685 static_cast<byte>(value)); 3686 } 3687 3688 3689 Address SeqOneByteString::GetCharsAddress() { 3690 return FIELD_ADDR(this, kHeaderSize); 3691 } 3692 3693 3694 uint8_t* SeqOneByteString::GetChars() { 3695 return reinterpret_cast<uint8_t*>(GetCharsAddress()); 3696 } 3697 3698 3699 Address SeqTwoByteString::GetCharsAddress() { 3700 return FIELD_ADDR(this, kHeaderSize); 3701 } 3702 3703 3704 uc16* SeqTwoByteString::GetChars() { 3705 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize)); 3706 } 3707 3708 3709 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) { 3710 DCHECK(index >= 0 && index < length()); 3711 return READ_UINT16_FIELD(this, kHeaderSize + index * kShortSize); 3712 } 3713 3714 3715 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { 3716 DCHECK(index >= 0 && index < length()); 3717 WRITE_UINT16_FIELD(this, kHeaderSize + index * kShortSize, value); 3718 } 3719 3720 3721 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) { 3722 return SizeFor(length()); 3723 } 3724 3725 3726 int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) { 3727 return SizeFor(length()); 3728 } 3729 3730 3731 String* SlicedString::parent() { 3732 return String::cast(READ_FIELD(this, kParentOffset)); 3733 } 3734 3735 3736 void SlicedString::set_parent(String* parent, WriteBarrierMode mode) { 3737 DCHECK(parent->IsSeqString() || parent->IsExternalString()); 3738 WRITE_FIELD(this, kParentOffset, parent); 3739 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kParentOffset, parent, mode); 3740 } 3741 3742 3743 SMI_ACCESSORS(SlicedString, offset, kOffsetOffset) 3744 3745 3746 String* ConsString::first() { 3747 return String::cast(READ_FIELD(this, kFirstOffset)); 3748 } 3749 3750 3751 Object* ConsString::unchecked_first() { 3752 return READ_FIELD(this, kFirstOffset); 3753 } 3754 3755 3756 void ConsString::set_first(String* value, WriteBarrierMode mode) { 3757 WRITE_FIELD(this, kFirstOffset, value); 3758 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode); 3759 } 3760 3761 3762 String* ConsString::second() { 3763 return String::cast(READ_FIELD(this, kSecondOffset)); 3764 } 3765 3766 3767 Object* ConsString::unchecked_second() { 3768 return READ_FIELD(this, kSecondOffset); 3769 } 3770 3771 3772 void ConsString::set_second(String* value, WriteBarrierMode mode) { 3773 WRITE_FIELD(this, kSecondOffset, value); 3774 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode); 3775 } 3776 3777 ACCESSORS(ThinString, actual, String, kActualOffset); 3778 3779 bool ExternalString::is_short() { 3780 InstanceType type = map()->instance_type(); 3781 return (type & kShortExternalStringMask) == kShortExternalStringTag; 3782 } 3783 3784 3785 const ExternalOneByteString::Resource* ExternalOneByteString::resource() { 3786 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)); 3787 } 3788 3789 3790 void ExternalOneByteString::update_data_cache() { 3791 if (is_short()) return; 3792 const char** data_field = 3793 reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset)); 3794 *data_field = resource()->data(); 3795 } 3796 3797 3798 void ExternalOneByteString::set_resource( 3799 const ExternalOneByteString::Resource* resource) { 3800 DCHECK(IsAligned(reinterpret_cast<intptr_t>(resource), kPointerSize)); 3801 *reinterpret_cast<const Resource**>( 3802 FIELD_ADDR(this, kResourceOffset)) = resource; 3803 if (resource != NULL) update_data_cache(); 3804 } 3805 3806 3807 const uint8_t* ExternalOneByteString::GetChars() { 3808 return reinterpret_cast<const uint8_t*>(resource()->data()); 3809 } 3810 3811 3812 uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) { 3813 DCHECK(index >= 0 && index < length()); 3814 return GetChars()[index]; 3815 } 3816 3817 3818 const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() { 3819 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)); 3820 } 3821 3822 3823 void ExternalTwoByteString::update_data_cache() { 3824 if (is_short()) return; 3825 const uint16_t** data_field = 3826 reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset)); 3827 *data_field = resource()->data(); 3828 } 3829 3830 3831 void ExternalTwoByteString::set_resource( 3832 const ExternalTwoByteString::Resource* resource) { 3833 *reinterpret_cast<const Resource**>( 3834 FIELD_ADDR(this, kResourceOffset)) = resource; 3835 if (resource != NULL) update_data_cache(); 3836 } 3837 3838 3839 const uint16_t* ExternalTwoByteString::GetChars() { 3840 return resource()->data(); 3841 } 3842 3843 3844 uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) { 3845 DCHECK(index >= 0 && index < length()); 3846 return GetChars()[index]; 3847 } 3848 3849 3850 const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData( 3851 unsigned start) { 3852 return GetChars() + start; 3853 } 3854 3855 3856 int ConsStringIterator::OffsetForDepth(int depth) { return depth & kDepthMask; } 3857 3858 3859 void ConsStringIterator::PushLeft(ConsString* string) { 3860 frames_[depth_++ & kDepthMask] = string; 3861 } 3862 3863 3864 void ConsStringIterator::PushRight(ConsString* string) { 3865 // Inplace update. 3866 frames_[(depth_-1) & kDepthMask] = string; 3867 } 3868 3869 3870 void ConsStringIterator::AdjustMaximumDepth() { 3871 if (depth_ > maximum_depth_) maximum_depth_ = depth_; 3872 } 3873 3874 3875 void ConsStringIterator::Pop() { 3876 DCHECK(depth_ > 0); 3877 DCHECK(depth_ <= maximum_depth_); 3878 depth_--; 3879 } 3880 3881 3882 uint16_t StringCharacterStream::GetNext() { 3883 DCHECK(buffer8_ != NULL && end_ != NULL); 3884 // Advance cursor if needed. 3885 if (buffer8_ == end_) HasMore(); 3886 DCHECK(buffer8_ < end_); 3887 return is_one_byte_ ? *buffer8_++ : *buffer16_++; 3888 } 3889 3890 3891 StringCharacterStream::StringCharacterStream(String* string, int offset) 3892 : is_one_byte_(false) { 3893 Reset(string, offset); 3894 } 3895 3896 3897 void StringCharacterStream::Reset(String* string, int offset) { 3898 buffer8_ = NULL; 3899 end_ = NULL; 3900 ConsString* cons_string = String::VisitFlat(this, string, offset); 3901 iter_.Reset(cons_string, offset); 3902 if (cons_string != NULL) { 3903 string = iter_.Next(&offset); 3904 if (string != NULL) String::VisitFlat(this, string, offset); 3905 } 3906 } 3907 3908 3909 bool StringCharacterStream::HasMore() { 3910 if (buffer8_ != end_) return true; 3911 int offset; 3912 String* string = iter_.Next(&offset); 3913 DCHECK_EQ(offset, 0); 3914 if (string == NULL) return false; 3915 String::VisitFlat(this, string); 3916 DCHECK(buffer8_ != end_); 3917 return true; 3918 } 3919 3920 3921 void StringCharacterStream::VisitOneByteString( 3922 const uint8_t* chars, int length) { 3923 is_one_byte_ = true; 3924 buffer8_ = chars; 3925 end_ = chars + length; 3926 } 3927 3928 3929 void StringCharacterStream::VisitTwoByteString( 3930 const uint16_t* chars, int length) { 3931 is_one_byte_ = false; 3932 buffer16_ = chars; 3933 end_ = reinterpret_cast<const uint8_t*>(chars + length); 3934 } 3935 3936 3937 int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kPointerSize); } 3938 3939 byte ByteArray::get(int index) { 3940 DCHECK(index >= 0 && index < this->length()); 3941 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 3942 } 3943 3944 void ByteArray::set(int index, byte value) { 3945 DCHECK(index >= 0 && index < this->length()); 3946 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value); 3947 } 3948 3949 void ByteArray::copy_in(int index, const byte* buffer, int length) { 3950 DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index && 3951 index + length <= this->length()); 3952 byte* dst_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize); 3953 memcpy(dst_addr, buffer, length); 3954 } 3955 3956 void ByteArray::copy_out(int index, byte* buffer, int length) { 3957 DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index && 3958 index + length <= this->length()); 3959 const byte* src_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize); 3960 memcpy(buffer, src_addr, length); 3961 } 3962 3963 int ByteArray::get_int(int index) { 3964 DCHECK(index >= 0 && index < this->length() / kIntSize); 3965 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize); 3966 } 3967 3968 void ByteArray::set_int(int index, int value) { 3969 DCHECK(index >= 0 && index < this->length() / kIntSize); 3970 WRITE_INT_FIELD(this, kHeaderSize + index * kIntSize, value); 3971 } 3972 3973 ByteArray* ByteArray::FromDataStartAddress(Address address) { 3974 DCHECK_TAG_ALIGNED(address); 3975 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag); 3976 } 3977 3978 3979 int ByteArray::ByteArraySize() { return SizeFor(this->length()); } 3980 3981 3982 Address ByteArray::GetDataStartAddress() { 3983 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize; 3984 } 3985 3986 3987 byte BytecodeArray::get(int index) { 3988 DCHECK(index >= 0 && index < this->length()); 3989 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 3990 } 3991 3992 3993 void BytecodeArray::set(int index, byte value) { 3994 DCHECK(index >= 0 && index < this->length()); 3995 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value); 3996 } 3997 3998 3999 void BytecodeArray::set_frame_size(int frame_size) { 4000 DCHECK_GE(frame_size, 0); 4001 DCHECK(IsAligned(frame_size, static_cast<unsigned>(kPointerSize))); 4002 WRITE_INT_FIELD(this, kFrameSizeOffset, frame_size); 4003 } 4004 4005 4006 int BytecodeArray::frame_size() const { 4007 return READ_INT_FIELD(this, kFrameSizeOffset); 4008 } 4009 4010 4011 int BytecodeArray::register_count() const { 4012 return frame_size() / kPointerSize; 4013 } 4014 4015 4016 void BytecodeArray::set_parameter_count(int number_of_parameters) { 4017 DCHECK_GE(number_of_parameters, 0); 4018 // Parameter count is stored as the size on stack of the parameters to allow 4019 // it to be used directly by generated code. 4020 WRITE_INT_FIELD(this, kParameterSizeOffset, 4021 (number_of_parameters << kPointerSizeLog2)); 4022 } 4023 4024 int BytecodeArray::interrupt_budget() const { 4025 return READ_INT_FIELD(this, kInterruptBudgetOffset); 4026 } 4027 4028 void BytecodeArray::set_interrupt_budget(int interrupt_budget) { 4029 DCHECK_GE(interrupt_budget, 0); 4030 WRITE_INT_FIELD(this, kInterruptBudgetOffset, interrupt_budget); 4031 } 4032 4033 int BytecodeArray::osr_loop_nesting_level() const { 4034 return READ_INT8_FIELD(this, kOSRNestingLevelOffset); 4035 } 4036 4037 void BytecodeArray::set_osr_loop_nesting_level(int depth) { 4038 DCHECK(0 <= depth && depth <= AbstractCode::kMaxLoopNestingMarker); 4039 STATIC_ASSERT(AbstractCode::kMaxLoopNestingMarker < kMaxInt8); 4040 WRITE_INT8_FIELD(this, kOSRNestingLevelOffset, depth); 4041 } 4042 4043 BytecodeArray::Age BytecodeArray::bytecode_age() const { 4044 return static_cast<Age>(READ_INT8_FIELD(this, kBytecodeAgeOffset)); 4045 } 4046 4047 void BytecodeArray::set_bytecode_age(BytecodeArray::Age age) { 4048 DCHECK_GE(age, kFirstBytecodeAge); 4049 DCHECK_LE(age, kLastBytecodeAge); 4050 STATIC_ASSERT(kLastBytecodeAge <= kMaxInt8); 4051 WRITE_INT8_FIELD(this, kBytecodeAgeOffset, static_cast<int8_t>(age)); 4052 } 4053 4054 int BytecodeArray::parameter_count() const { 4055 // Parameter count is stored as the size on stack of the parameters to allow 4056 // it to be used directly by generated code. 4057 return READ_INT_FIELD(this, kParameterSizeOffset) >> kPointerSizeLog2; 4058 } 4059 4060 ACCESSORS(BytecodeArray, constant_pool, FixedArray, kConstantPoolOffset) 4061 ACCESSORS(BytecodeArray, handler_table, FixedArray, kHandlerTableOffset) 4062 ACCESSORS(BytecodeArray, source_position_table, ByteArray, 4063 kSourcePositionTableOffset) 4064 4065 Address BytecodeArray::GetFirstBytecodeAddress() { 4066 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize; 4067 } 4068 4069 4070 int BytecodeArray::BytecodeArraySize() { return SizeFor(this->length()); } 4071 4072 int BytecodeArray::SizeIncludingMetadata() { 4073 int size = BytecodeArraySize(); 4074 size += constant_pool()->Size(); 4075 size += handler_table()->Size(); 4076 size += source_position_table()->Size(); 4077 return size; 4078 } 4079 4080 ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset) 4081 4082 4083 void* FixedTypedArrayBase::external_pointer() const { 4084 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset); 4085 return reinterpret_cast<void*>(ptr); 4086 } 4087 4088 4089 void FixedTypedArrayBase::set_external_pointer(void* value, 4090 WriteBarrierMode mode) { 4091 intptr_t ptr = reinterpret_cast<intptr_t>(value); 4092 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr); 4093 } 4094 4095 4096 void* FixedTypedArrayBase::DataPtr() { 4097 return reinterpret_cast<void*>( 4098 reinterpret_cast<intptr_t>(base_pointer()) + 4099 reinterpret_cast<intptr_t>(external_pointer())); 4100 } 4101 4102 4103 int FixedTypedArrayBase::ElementSize(InstanceType type) { 4104 int element_size; 4105 switch (type) { 4106 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 4107 case FIXED_##TYPE##_ARRAY_TYPE: \ 4108 element_size = size; \ 4109 break; 4110 4111 TYPED_ARRAYS(TYPED_ARRAY_CASE) 4112 #undef TYPED_ARRAY_CASE 4113 default: 4114 UNREACHABLE(); 4115 return 0; 4116 } 4117 return element_size; 4118 } 4119 4120 4121 int FixedTypedArrayBase::DataSize(InstanceType type) { 4122 if (base_pointer() == Smi::kZero) return 0; 4123 return length() * ElementSize(type); 4124 } 4125 4126 4127 int FixedTypedArrayBase::DataSize() { 4128 return DataSize(map()->instance_type()); 4129 } 4130 4131 4132 int FixedTypedArrayBase::size() { 4133 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize()); 4134 } 4135 4136 4137 int FixedTypedArrayBase::TypedArraySize(InstanceType type) { 4138 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type)); 4139 } 4140 4141 4142 int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) { 4143 return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type)); 4144 } 4145 4146 4147 uint8_t Uint8ArrayTraits::defaultValue() { return 0; } 4148 4149 4150 uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; } 4151 4152 4153 int8_t Int8ArrayTraits::defaultValue() { return 0; } 4154 4155 4156 uint16_t Uint16ArrayTraits::defaultValue() { return 0; } 4157 4158 4159 int16_t Int16ArrayTraits::defaultValue() { return 0; } 4160 4161 4162 uint32_t Uint32ArrayTraits::defaultValue() { return 0; } 4163 4164 4165 int32_t Int32ArrayTraits::defaultValue() { return 0; } 4166 4167 4168 float Float32ArrayTraits::defaultValue() { 4169 return std::numeric_limits<float>::quiet_NaN(); 4170 } 4171 4172 4173 double Float64ArrayTraits::defaultValue() { 4174 return std::numeric_limits<double>::quiet_NaN(); 4175 } 4176 4177 4178 template <class Traits> 4179 typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) { 4180 DCHECK((index >= 0) && (index < this->length())); 4181 ElementType* ptr = reinterpret_cast<ElementType*>(DataPtr()); 4182 return ptr[index]; 4183 } 4184 4185 4186 template <class Traits> 4187 void FixedTypedArray<Traits>::set(int index, ElementType value) { 4188 DCHECK((index >= 0) && (index < this->length())); 4189 ElementType* ptr = reinterpret_cast<ElementType*>(DataPtr()); 4190 ptr[index] = value; 4191 } 4192 4193 4194 template <class Traits> 4195 typename Traits::ElementType FixedTypedArray<Traits>::from_int(int value) { 4196 return static_cast<ElementType>(value); 4197 } 4198 4199 4200 template <> inline 4201 uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_int(int value) { 4202 if (value < 0) return 0; 4203 if (value > 0xFF) return 0xFF; 4204 return static_cast<uint8_t>(value); 4205 } 4206 4207 4208 template <class Traits> 4209 typename Traits::ElementType FixedTypedArray<Traits>::from_double( 4210 double value) { 4211 return static_cast<ElementType>(DoubleToInt32(value)); 4212 } 4213 4214 4215 template<> inline 4216 uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_double(double value) { 4217 // Handle NaNs and less than zero values which clamp to zero. 4218 if (!(value > 0)) return 0; 4219 if (value > 0xFF) return 0xFF; 4220 return static_cast<uint8_t>(lrint(value)); 4221 } 4222 4223 4224 template<> inline 4225 float FixedTypedArray<Float32ArrayTraits>::from_double(double value) { 4226 return static_cast<float>(value); 4227 } 4228 4229 4230 template<> inline 4231 double FixedTypedArray<Float64ArrayTraits>::from_double(double value) { 4232 return value; 4233 } 4234 4235 template <class Traits> 4236 Handle<Object> FixedTypedArray<Traits>::get(FixedTypedArray<Traits>* array, 4237 int index) { 4238 return Traits::ToHandle(array->GetIsolate(), array->get_scalar(index)); 4239 } 4240 4241 4242 template <class Traits> 4243 void FixedTypedArray<Traits>::SetValue(uint32_t index, Object* value) { 4244 ElementType cast_value = Traits::defaultValue(); 4245 if (value->IsSmi()) { 4246 int int_value = Smi::cast(value)->value(); 4247 cast_value = from_int(int_value); 4248 } else if (value->IsHeapNumber()) { 4249 double double_value = HeapNumber::cast(value)->value(); 4250 cast_value = from_double(double_value); 4251 } else { 4252 // Clamp undefined to the default value. All other types have been 4253 // converted to a number type further up in the call chain. 4254 DCHECK(value->IsUndefined(GetIsolate())); 4255 } 4256 set(index, cast_value); 4257 } 4258 4259 4260 Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) { 4261 return handle(Smi::FromInt(scalar), isolate); 4262 } 4263 4264 4265 Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate, 4266 uint8_t scalar) { 4267 return handle(Smi::FromInt(scalar), isolate); 4268 } 4269 4270 4271 Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) { 4272 return handle(Smi::FromInt(scalar), isolate); 4273 } 4274 4275 4276 Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) { 4277 return handle(Smi::FromInt(scalar), isolate); 4278 } 4279 4280 4281 Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) { 4282 return handle(Smi::FromInt(scalar), isolate); 4283 } 4284 4285 4286 Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) { 4287 return isolate->factory()->NewNumberFromUint(scalar); 4288 } 4289 4290 4291 Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) { 4292 return isolate->factory()->NewNumberFromInt(scalar); 4293 } 4294 4295 4296 Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) { 4297 return isolate->factory()->NewNumber(scalar); 4298 } 4299 4300 4301 Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) { 4302 return isolate->factory()->NewNumber(scalar); 4303 } 4304 4305 4306 int Map::visitor_id() { 4307 return READ_BYTE_FIELD(this, kVisitorIdOffset); 4308 } 4309 4310 4311 void Map::set_visitor_id(int id) { 4312 DCHECK(0 <= id && id < 256); 4313 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id)); 4314 } 4315 4316 4317 int Map::instance_size() { 4318 return NOBARRIER_READ_BYTE_FIELD( 4319 this, kInstanceSizeOffset) << kPointerSizeLog2; 4320 } 4321 4322 4323 int Map::inobject_properties_or_constructor_function_index() { 4324 return READ_BYTE_FIELD(this, 4325 kInObjectPropertiesOrConstructorFunctionIndexOffset); 4326 } 4327 4328 4329 void Map::set_inobject_properties_or_constructor_function_index(int value) { 4330 DCHECK(0 <= value && value < 256); 4331 WRITE_BYTE_FIELD(this, kInObjectPropertiesOrConstructorFunctionIndexOffset, 4332 static_cast<byte>(value)); 4333 } 4334 4335 4336 int Map::GetInObjectProperties() { 4337 DCHECK(IsJSObjectMap()); 4338 return inobject_properties_or_constructor_function_index(); 4339 } 4340 4341 4342 void Map::SetInObjectProperties(int value) { 4343 DCHECK(IsJSObjectMap()); 4344 set_inobject_properties_or_constructor_function_index(value); 4345 } 4346 4347 4348 int Map::GetConstructorFunctionIndex() { 4349 DCHECK(IsPrimitiveMap()); 4350 return inobject_properties_or_constructor_function_index(); 4351 } 4352 4353 4354 void Map::SetConstructorFunctionIndex(int value) { 4355 DCHECK(IsPrimitiveMap()); 4356 set_inobject_properties_or_constructor_function_index(value); 4357 } 4358 4359 4360 int Map::GetInObjectPropertyOffset(int index) { 4361 // Adjust for the number of properties stored in the object. 4362 index -= GetInObjectProperties(); 4363 DCHECK(index <= 0); 4364 return instance_size() + (index * kPointerSize); 4365 } 4366 4367 4368 Handle<Map> Map::AddMissingTransitionsForTesting( 4369 Handle<Map> split_map, Handle<DescriptorArray> descriptors, 4370 Handle<LayoutDescriptor> full_layout_descriptor) { 4371 return AddMissingTransitions(split_map, descriptors, full_layout_descriptor); 4372 } 4373 4374 4375 int HeapObject::SizeFromMap(Map* map) { 4376 int instance_size = map->instance_size(); 4377 if (instance_size != kVariableSizeSentinel) return instance_size; 4378 // Only inline the most frequent cases. 4379 InstanceType instance_type = map->instance_type(); 4380 if (instance_type == FIXED_ARRAY_TYPE || 4381 instance_type == TRANSITION_ARRAY_TYPE) { 4382 return FixedArray::SizeFor( 4383 reinterpret_cast<FixedArray*>(this)->synchronized_length()); 4384 } 4385 if (instance_type == ONE_BYTE_STRING_TYPE || 4386 instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) { 4387 // Strings may get concurrently truncated, hence we have to access its 4388 // length synchronized. 4389 return SeqOneByteString::SizeFor( 4390 reinterpret_cast<SeqOneByteString*>(this)->synchronized_length()); 4391 } 4392 if (instance_type == BYTE_ARRAY_TYPE) { 4393 return reinterpret_cast<ByteArray*>(this)->ByteArraySize(); 4394 } 4395 if (instance_type == BYTECODE_ARRAY_TYPE) { 4396 return reinterpret_cast<BytecodeArray*>(this)->BytecodeArraySize(); 4397 } 4398 if (instance_type == FREE_SPACE_TYPE) { 4399 return reinterpret_cast<FreeSpace*>(this)->nobarrier_size(); 4400 } 4401 if (instance_type == STRING_TYPE || 4402 instance_type == INTERNALIZED_STRING_TYPE) { 4403 // Strings may get concurrently truncated, hence we have to access its 4404 // length synchronized. 4405 return SeqTwoByteString::SizeFor( 4406 reinterpret_cast<SeqTwoByteString*>(this)->synchronized_length()); 4407 } 4408 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) { 4409 return FixedDoubleArray::SizeFor( 4410 reinterpret_cast<FixedDoubleArray*>(this)->length()); 4411 } 4412 if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE && 4413 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) { 4414 return reinterpret_cast<FixedTypedArrayBase*>( 4415 this)->TypedArraySize(instance_type); 4416 } 4417 DCHECK(instance_type == CODE_TYPE); 4418 return reinterpret_cast<Code*>(this)->CodeSize(); 4419 } 4420 4421 4422 void Map::set_instance_size(int value) { 4423 DCHECK_EQ(0, value & (kPointerSize - 1)); 4424 value >>= kPointerSizeLog2; 4425 DCHECK(0 <= value && value < 256); 4426 NOBARRIER_WRITE_BYTE_FIELD( 4427 this, kInstanceSizeOffset, static_cast<byte>(value)); 4428 } 4429 4430 4431 void Map::clear_unused() { WRITE_BYTE_FIELD(this, kUnusedOffset, 0); } 4432 4433 4434 InstanceType Map::instance_type() { 4435 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset)); 4436 } 4437 4438 4439 void Map::set_instance_type(InstanceType value) { 4440 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value); 4441 } 4442 4443 4444 int Map::unused_property_fields() { 4445 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset); 4446 } 4447 4448 4449 void Map::set_unused_property_fields(int value) { 4450 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255)); 4451 } 4452 4453 4454 byte Map::bit_field() const { return READ_BYTE_FIELD(this, kBitFieldOffset); } 4455 4456 4457 void Map::set_bit_field(byte value) { 4458 WRITE_BYTE_FIELD(this, kBitFieldOffset, value); 4459 } 4460 4461 4462 byte Map::bit_field2() const { return READ_BYTE_FIELD(this, kBitField2Offset); } 4463 4464 4465 void Map::set_bit_field2(byte value) { 4466 WRITE_BYTE_FIELD(this, kBitField2Offset, value); 4467 } 4468 4469 4470 void Map::set_non_instance_prototype(bool value) { 4471 if (value) { 4472 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype)); 4473 } else { 4474 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype)); 4475 } 4476 } 4477 4478 4479 bool Map::has_non_instance_prototype() { 4480 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0; 4481 } 4482 4483 4484 void Map::set_is_constructor(bool value) { 4485 if (value) { 4486 set_bit_field(bit_field() | (1 << kIsConstructor)); 4487 } else { 4488 set_bit_field(bit_field() & ~(1 << kIsConstructor)); 4489 } 4490 } 4491 4492 4493 bool Map::is_constructor() const { 4494 return ((1 << kIsConstructor) & bit_field()) != 0; 4495 } 4496 4497 void Map::set_has_hidden_prototype(bool value) { 4498 set_bit_field3(HasHiddenPrototype::update(bit_field3(), value)); 4499 } 4500 4501 bool Map::has_hidden_prototype() const { 4502 return HasHiddenPrototype::decode(bit_field3()); 4503 } 4504 4505 4506 void Map::set_has_indexed_interceptor() { 4507 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor)); 4508 } 4509 4510 4511 bool Map::has_indexed_interceptor() { 4512 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0; 4513 } 4514 4515 4516 void Map::set_is_undetectable() { 4517 set_bit_field(bit_field() | (1 << kIsUndetectable)); 4518 } 4519 4520 4521 bool Map::is_undetectable() { 4522 return ((1 << kIsUndetectable) & bit_field()) != 0; 4523 } 4524 4525 4526 void Map::set_has_named_interceptor() { 4527 set_bit_field(bit_field() | (1 << kHasNamedInterceptor)); 4528 } 4529 4530 4531 bool Map::has_named_interceptor() { 4532 return ((1 << kHasNamedInterceptor) & bit_field()) != 0; 4533 } 4534 4535 4536 void Map::set_is_access_check_needed(bool access_check_needed) { 4537 if (access_check_needed) { 4538 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded)); 4539 } else { 4540 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded)); 4541 } 4542 } 4543 4544 4545 bool Map::is_access_check_needed() { 4546 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0; 4547 } 4548 4549 4550 void Map::set_is_extensible(bool value) { 4551 if (value) { 4552 set_bit_field2(bit_field2() | (1 << kIsExtensible)); 4553 } else { 4554 set_bit_field2(bit_field2() & ~(1 << kIsExtensible)); 4555 } 4556 } 4557 4558 bool Map::is_extensible() { 4559 return ((1 << kIsExtensible) & bit_field2()) != 0; 4560 } 4561 4562 4563 void Map::set_is_prototype_map(bool value) { 4564 set_bit_field2(IsPrototypeMapBits::update(bit_field2(), value)); 4565 } 4566 4567 bool Map::is_prototype_map() const { 4568 return IsPrototypeMapBits::decode(bit_field2()); 4569 } 4570 4571 bool Map::should_be_fast_prototype_map() const { 4572 if (!prototype_info()->IsPrototypeInfo()) return false; 4573 return PrototypeInfo::cast(prototype_info())->should_be_fast_map(); 4574 } 4575 4576 void Map::set_elements_kind(ElementsKind elements_kind) { 4577 DCHECK(static_cast<int>(elements_kind) < kElementsKindCount); 4578 DCHECK(kElementsKindCount <= (1 << Map::ElementsKindBits::kSize)); 4579 set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind)); 4580 DCHECK(this->elements_kind() == elements_kind); 4581 } 4582 4583 4584 ElementsKind Map::elements_kind() { 4585 return Map::ElementsKindBits::decode(bit_field2()); 4586 } 4587 4588 4589 bool Map::has_fast_smi_elements() { 4590 return IsFastSmiElementsKind(elements_kind()); 4591 } 4592 4593 bool Map::has_fast_object_elements() { 4594 return IsFastObjectElementsKind(elements_kind()); 4595 } 4596 4597 bool Map::has_fast_smi_or_object_elements() { 4598 return IsFastSmiOrObjectElementsKind(elements_kind()); 4599 } 4600 4601 bool Map::has_fast_double_elements() { 4602 return IsFastDoubleElementsKind(elements_kind()); 4603 } 4604 4605 bool Map::has_fast_elements() { return IsFastElementsKind(elements_kind()); } 4606 4607 bool Map::has_sloppy_arguments_elements() { 4608 return IsSloppyArgumentsElements(elements_kind()); 4609 } 4610 4611 bool Map::has_fast_sloppy_arguments_elements() { 4612 return elements_kind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS; 4613 } 4614 4615 bool Map::has_fast_string_wrapper_elements() { 4616 return elements_kind() == FAST_STRING_WRAPPER_ELEMENTS; 4617 } 4618 4619 bool Map::has_fixed_typed_array_elements() { 4620 return IsFixedTypedArrayElementsKind(elements_kind()); 4621 } 4622 4623 bool Map::has_dictionary_elements() { 4624 return IsDictionaryElementsKind(elements_kind()); 4625 } 4626 4627 4628 void Map::set_dictionary_map(bool value) { 4629 uint32_t new_bit_field3 = DictionaryMap::update(bit_field3(), value); 4630 new_bit_field3 = IsUnstable::update(new_bit_field3, value); 4631 set_bit_field3(new_bit_field3); 4632 } 4633 4634 4635 bool Map::is_dictionary_map() { 4636 return DictionaryMap::decode(bit_field3()); 4637 } 4638 4639 4640 Code::Flags Code::flags() { 4641 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset)); 4642 } 4643 4644 4645 void Map::set_owns_descriptors(bool owns_descriptors) { 4646 set_bit_field3(OwnsDescriptors::update(bit_field3(), owns_descriptors)); 4647 } 4648 4649 4650 bool Map::owns_descriptors() { 4651 return OwnsDescriptors::decode(bit_field3()); 4652 } 4653 4654 4655 void Map::set_is_callable() { set_bit_field(bit_field() | (1 << kIsCallable)); } 4656 4657 4658 bool Map::is_callable() const { 4659 return ((1 << kIsCallable) & bit_field()) != 0; 4660 } 4661 4662 4663 void Map::deprecate() { 4664 set_bit_field3(Deprecated::update(bit_field3(), true)); 4665 } 4666 4667 4668 bool Map::is_deprecated() { 4669 return Deprecated::decode(bit_field3()); 4670 } 4671 4672 4673 void Map::set_migration_target(bool value) { 4674 set_bit_field3(IsMigrationTarget::update(bit_field3(), value)); 4675 } 4676 4677 4678 bool Map::is_migration_target() { 4679 return IsMigrationTarget::decode(bit_field3()); 4680 } 4681 4682 void Map::set_immutable_proto(bool value) { 4683 set_bit_field3(ImmutablePrototype::update(bit_field3(), value)); 4684 } 4685 4686 bool Map::is_immutable_proto() { 4687 return ImmutablePrototype::decode(bit_field3()); 4688 } 4689 4690 void Map::set_new_target_is_base(bool value) { 4691 set_bit_field3(NewTargetIsBase::update(bit_field3(), value)); 4692 } 4693 4694 4695 bool Map::new_target_is_base() { return NewTargetIsBase::decode(bit_field3()); } 4696 4697 4698 void Map::set_construction_counter(int value) { 4699 set_bit_field3(ConstructionCounter::update(bit_field3(), value)); 4700 } 4701 4702 4703 int Map::construction_counter() { 4704 return ConstructionCounter::decode(bit_field3()); 4705 } 4706 4707 4708 void Map::mark_unstable() { 4709 set_bit_field3(IsUnstable::update(bit_field3(), true)); 4710 } 4711 4712 4713 bool Map::is_stable() { 4714 return !IsUnstable::decode(bit_field3()); 4715 } 4716 4717 4718 bool Map::has_code_cache() { 4719 // Code caches are always fixed arrays. The empty fixed array is used as a 4720 // sentinel for an absent code cache. 4721 return code_cache()->length() != 0; 4722 } 4723 4724 4725 bool Map::CanBeDeprecated() { 4726 int descriptor = LastAdded(); 4727 for (int i = 0; i <= descriptor; i++) { 4728 PropertyDetails details = instance_descriptors()->GetDetails(i); 4729 if (details.representation().IsNone()) return true; 4730 if (details.representation().IsSmi()) return true; 4731 if (details.representation().IsDouble()) return true; 4732 if (details.representation().IsHeapObject()) return true; 4733 if (details.kind() == kData && details.location() == kDescriptor) { 4734 return true; 4735 } 4736 } 4737 return false; 4738 } 4739 4740 4741 void Map::NotifyLeafMapLayoutChange() { 4742 if (is_stable()) { 4743 mark_unstable(); 4744 dependent_code()->DeoptimizeDependentCodeGroup( 4745 GetIsolate(), 4746 DependentCode::kPrototypeCheckGroup); 4747 } 4748 } 4749 4750 4751 bool Map::CanTransition() { 4752 // Only JSObject and subtypes have map transitions and back pointers. 4753 STATIC_ASSERT(LAST_TYPE == LAST_JS_OBJECT_TYPE); 4754 return instance_type() >= FIRST_JS_OBJECT_TYPE; 4755 } 4756 4757 4758 bool Map::IsBooleanMap() { return this == GetHeap()->boolean_map(); } 4759 bool Map::IsPrimitiveMap() { 4760 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); 4761 return instance_type() <= LAST_PRIMITIVE_TYPE; 4762 } 4763 bool Map::IsJSReceiverMap() { 4764 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 4765 return instance_type() >= FIRST_JS_RECEIVER_TYPE; 4766 } 4767 bool Map::IsJSObjectMap() { 4768 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 4769 return instance_type() >= FIRST_JS_OBJECT_TYPE; 4770 } 4771 bool Map::IsJSArrayMap() { return instance_type() == JS_ARRAY_TYPE; } 4772 bool Map::IsJSFunctionMap() { return instance_type() == JS_FUNCTION_TYPE; } 4773 bool Map::IsStringMap() { return instance_type() < FIRST_NONSTRING_TYPE; } 4774 bool Map::IsJSProxyMap() { return instance_type() == JS_PROXY_TYPE; } 4775 bool Map::IsJSGlobalProxyMap() { 4776 return instance_type() == JS_GLOBAL_PROXY_TYPE; 4777 } 4778 bool Map::IsJSGlobalObjectMap() { 4779 return instance_type() == JS_GLOBAL_OBJECT_TYPE; 4780 } 4781 bool Map::IsJSTypedArrayMap() { return instance_type() == JS_TYPED_ARRAY_TYPE; } 4782 bool Map::IsJSDataViewMap() { return instance_type() == JS_DATA_VIEW_TYPE; } 4783 4784 bool Map::IsSpecialReceiverMap() { 4785 bool result = IsSpecialReceiverInstanceType(instance_type()); 4786 DCHECK_IMPLIES(!result, 4787 !has_named_interceptor() && !is_access_check_needed()); 4788 return result; 4789 } 4790 4791 bool Map::CanOmitMapChecks() { 4792 return is_stable() && FLAG_omit_map_checks_for_leaf_maps; 4793 } 4794 4795 4796 DependentCode* DependentCode::next_link() { 4797 return DependentCode::cast(get(kNextLinkIndex)); 4798 } 4799 4800 4801 void DependentCode::set_next_link(DependentCode* next) { 4802 set(kNextLinkIndex, next); 4803 } 4804 4805 4806 int DependentCode::flags() { return Smi::cast(get(kFlagsIndex))->value(); } 4807 4808 4809 void DependentCode::set_flags(int flags) { 4810 set(kFlagsIndex, Smi::FromInt(flags)); 4811 } 4812 4813 4814 int DependentCode::count() { return CountField::decode(flags()); } 4815 4816 void DependentCode::set_count(int value) { 4817 set_flags(CountField::update(flags(), value)); 4818 } 4819 4820 4821 DependentCode::DependencyGroup DependentCode::group() { 4822 return static_cast<DependencyGroup>(GroupField::decode(flags())); 4823 } 4824 4825 4826 void DependentCode::set_group(DependentCode::DependencyGroup group) { 4827 set_flags(GroupField::update(flags(), static_cast<int>(group))); 4828 } 4829 4830 4831 void DependentCode::set_object_at(int i, Object* object) { 4832 set(kCodesStartIndex + i, object); 4833 } 4834 4835 4836 Object* DependentCode::object_at(int i) { 4837 return get(kCodesStartIndex + i); 4838 } 4839 4840 4841 void DependentCode::clear_at(int i) { 4842 set_undefined(kCodesStartIndex + i); 4843 } 4844 4845 4846 void DependentCode::copy(int from, int to) { 4847 set(kCodesStartIndex + to, get(kCodesStartIndex + from)); 4848 } 4849 4850 4851 void Code::set_flags(Code::Flags flags) { 4852 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1); 4853 WRITE_INT_FIELD(this, kFlagsOffset, flags); 4854 } 4855 4856 4857 Code::Kind Code::kind() { 4858 return ExtractKindFromFlags(flags()); 4859 } 4860 4861 bool Code::IsCodeStubOrIC() { 4862 switch (kind()) { 4863 case STUB: 4864 case HANDLER: 4865 #define CASE_KIND(kind) case kind: 4866 IC_KIND_LIST(CASE_KIND) 4867 #undef CASE_KIND 4868 return true; 4869 default: 4870 return false; 4871 } 4872 } 4873 4874 ExtraICState Code::extra_ic_state() { 4875 DCHECK(is_binary_op_stub() || is_compare_ic_stub() || 4876 is_to_boolean_ic_stub() || is_debug_stub()); 4877 return ExtractExtraICStateFromFlags(flags()); 4878 } 4879 4880 4881 // For initialization. 4882 void Code::set_raw_kind_specific_flags1(int value) { 4883 WRITE_INT_FIELD(this, kKindSpecificFlags1Offset, value); 4884 } 4885 4886 4887 void Code::set_raw_kind_specific_flags2(int value) { 4888 WRITE_INT_FIELD(this, kKindSpecificFlags2Offset, value); 4889 } 4890 4891 4892 inline bool Code::is_crankshafted() { 4893 return IsCrankshaftedField::decode( 4894 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)); 4895 } 4896 4897 4898 inline bool Code::is_hydrogen_stub() { 4899 return is_crankshafted() && kind() != OPTIMIZED_FUNCTION; 4900 } 4901 4902 inline bool Code::is_interpreter_trampoline_builtin() { 4903 Builtins* builtins = GetIsolate()->builtins(); 4904 return this == *builtins->InterpreterEntryTrampoline() || 4905 this == *builtins->InterpreterEnterBytecodeAdvance() || 4906 this == *builtins->InterpreterEnterBytecodeDispatch(); 4907 } 4908 4909 inline bool Code::has_unwinding_info() const { 4910 return HasUnwindingInfoField::decode(READ_UINT32_FIELD(this, kFlagsOffset)); 4911 } 4912 4913 inline void Code::set_has_unwinding_info(bool state) { 4914 uint32_t previous = READ_UINT32_FIELD(this, kFlagsOffset); 4915 uint32_t updated_value = HasUnwindingInfoField::update(previous, state); 4916 WRITE_UINT32_FIELD(this, kFlagsOffset, updated_value); 4917 } 4918 4919 inline void Code::set_is_crankshafted(bool value) { 4920 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 4921 int updated = IsCrankshaftedField::update(previous, value); 4922 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated); 4923 } 4924 4925 4926 inline bool Code::is_turbofanned() { 4927 return IsTurbofannedField::decode( 4928 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 4929 } 4930 4931 4932 inline void Code::set_is_turbofanned(bool value) { 4933 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 4934 int updated = IsTurbofannedField::update(previous, value); 4935 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 4936 } 4937 4938 4939 inline bool Code::can_have_weak_objects() { 4940 DCHECK(kind() == OPTIMIZED_FUNCTION); 4941 return CanHaveWeakObjectsField::decode( 4942 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 4943 } 4944 4945 4946 inline void Code::set_can_have_weak_objects(bool value) { 4947 DCHECK(kind() == OPTIMIZED_FUNCTION); 4948 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 4949 int updated = CanHaveWeakObjectsField::update(previous, value); 4950 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 4951 } 4952 4953 inline bool Code::is_construct_stub() { 4954 DCHECK(kind() == BUILTIN); 4955 return IsConstructStubField::decode( 4956 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 4957 } 4958 4959 inline void Code::set_is_construct_stub(bool value) { 4960 DCHECK(kind() == BUILTIN); 4961 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 4962 int updated = IsConstructStubField::update(previous, value); 4963 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 4964 } 4965 4966 inline bool Code::is_promise_rejection() { 4967 DCHECK(kind() == BUILTIN); 4968 return IsPromiseRejectionField::decode( 4969 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 4970 } 4971 4972 inline void Code::set_is_promise_rejection(bool value) { 4973 DCHECK(kind() == BUILTIN); 4974 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 4975 int updated = IsPromiseRejectionField::update(previous, value); 4976 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 4977 } 4978 4979 inline bool Code::is_exception_caught() { 4980 DCHECK(kind() == BUILTIN); 4981 return IsExceptionCaughtField::decode( 4982 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 4983 } 4984 4985 inline void Code::set_is_exception_caught(bool value) { 4986 DCHECK(kind() == BUILTIN); 4987 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 4988 int updated = IsExceptionCaughtField::update(previous, value); 4989 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 4990 } 4991 4992 bool Code::has_deoptimization_support() { 4993 DCHECK_EQ(FUNCTION, kind()); 4994 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 4995 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags); 4996 } 4997 4998 4999 void Code::set_has_deoptimization_support(bool value) { 5000 DCHECK_EQ(FUNCTION, kind()); 5001 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 5002 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value); 5003 WRITE_UINT32_FIELD(this, kFullCodeFlags, flags); 5004 } 5005 5006 5007 bool Code::has_debug_break_slots() { 5008 DCHECK_EQ(FUNCTION, kind()); 5009 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 5010 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags); 5011 } 5012 5013 5014 void Code::set_has_debug_break_slots(bool value) { 5015 DCHECK_EQ(FUNCTION, kind()); 5016 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 5017 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value); 5018 WRITE_UINT32_FIELD(this, kFullCodeFlags, flags); 5019 } 5020 5021 5022 bool Code::has_reloc_info_for_serialization() { 5023 DCHECK_EQ(FUNCTION, kind()); 5024 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 5025 return FullCodeFlagsHasRelocInfoForSerialization::decode(flags); 5026 } 5027 5028 5029 void Code::set_has_reloc_info_for_serialization(bool value) { 5030 DCHECK_EQ(FUNCTION, kind()); 5031 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 5032 flags = FullCodeFlagsHasRelocInfoForSerialization::update(flags, value); 5033 WRITE_UINT32_FIELD(this, kFullCodeFlags, flags); 5034 } 5035 5036 5037 int Code::allow_osr_at_loop_nesting_level() { 5038 DCHECK_EQ(FUNCTION, kind()); 5039 int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 5040 return AllowOSRAtLoopNestingLevelField::decode(fields); 5041 } 5042 5043 5044 void Code::set_allow_osr_at_loop_nesting_level(int level) { 5045 DCHECK_EQ(FUNCTION, kind()); 5046 DCHECK(level >= 0 && level <= AbstractCode::kMaxLoopNestingMarker); 5047 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 5048 int updated = AllowOSRAtLoopNestingLevelField::update(previous, level); 5049 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated); 5050 } 5051 5052 5053 int Code::profiler_ticks() { 5054 DCHECK_EQ(FUNCTION, kind()); 5055 return ProfilerTicksField::decode( 5056 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 5057 } 5058 5059 5060 void Code::set_profiler_ticks(int ticks) { 5061 if (kind() == FUNCTION) { 5062 unsigned previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 5063 unsigned updated = ProfilerTicksField::update(previous, ticks); 5064 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 5065 } 5066 } 5067 5068 int Code::builtin_index() { return READ_INT_FIELD(this, kBuiltinIndexOffset); } 5069 5070 void Code::set_builtin_index(int index) { 5071 WRITE_INT_FIELD(this, kBuiltinIndexOffset, index); 5072 } 5073 5074 5075 unsigned Code::stack_slots() { 5076 DCHECK(is_crankshafted()); 5077 return StackSlotsField::decode( 5078 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 5079 } 5080 5081 5082 void Code::set_stack_slots(unsigned slots) { 5083 CHECK(slots <= (1 << kStackSlotsBitCount)); 5084 DCHECK(is_crankshafted()); 5085 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 5086 int updated = StackSlotsField::update(previous, slots); 5087 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 5088 } 5089 5090 5091 unsigned Code::safepoint_table_offset() { 5092 DCHECK(is_crankshafted()); 5093 return SafepointTableOffsetField::decode( 5094 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)); 5095 } 5096 5097 5098 void Code::set_safepoint_table_offset(unsigned offset) { 5099 CHECK(offset <= (1 << kSafepointTableOffsetBitCount)); 5100 DCHECK(is_crankshafted()); 5101 DCHECK(IsAligned(offset, static_cast<unsigned>(kIntSize))); 5102 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 5103 int updated = SafepointTableOffsetField::update(previous, offset); 5104 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated); 5105 } 5106 5107 5108 unsigned Code::back_edge_table_offset() { 5109 DCHECK_EQ(FUNCTION, kind()); 5110 return BackEdgeTableOffsetField::decode( 5111 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)) << kPointerSizeLog2; 5112 } 5113 5114 5115 void Code::set_back_edge_table_offset(unsigned offset) { 5116 DCHECK_EQ(FUNCTION, kind()); 5117 DCHECK(IsAligned(offset, static_cast<unsigned>(kPointerSize))); 5118 offset = offset >> kPointerSizeLog2; 5119 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 5120 int updated = BackEdgeTableOffsetField::update(previous, offset); 5121 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated); 5122 } 5123 5124 5125 bool Code::back_edges_patched_for_osr() { 5126 DCHECK_EQ(FUNCTION, kind()); 5127 return allow_osr_at_loop_nesting_level() > 0; 5128 } 5129 5130 5131 uint16_t Code::to_boolean_state() { return extra_ic_state(); } 5132 5133 5134 bool Code::marked_for_deoptimization() { 5135 DCHECK(kind() == OPTIMIZED_FUNCTION); 5136 return MarkedForDeoptimizationField::decode( 5137 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 5138 } 5139 5140 5141 void Code::set_marked_for_deoptimization(bool flag) { 5142 DCHECK(kind() == OPTIMIZED_FUNCTION); 5143 DCHECK(!flag || AllowDeoptimization::IsAllowed(GetIsolate())); 5144 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 5145 int updated = MarkedForDeoptimizationField::update(previous, flag); 5146 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 5147 } 5148 5149 5150 bool Code::is_inline_cache_stub() { 5151 Kind kind = this->kind(); 5152 switch (kind) { 5153 #define CASE(name) case name: return true; 5154 IC_KIND_LIST(CASE) 5155 #undef CASE 5156 default: return false; 5157 } 5158 } 5159 5160 bool Code::is_debug_stub() { 5161 if (kind() != BUILTIN) return false; 5162 switch (builtin_index()) { 5163 #define CASE_DEBUG_BUILTIN(name) case Builtins::k##name: 5164 BUILTIN_LIST_DBG(CASE_DEBUG_BUILTIN) 5165 #undef CASE_DEBUG_BUILTIN 5166 return true; 5167 default: 5168 return false; 5169 } 5170 return false; 5171 } 5172 bool Code::is_handler() { return kind() == HANDLER; } 5173 bool Code::is_stub() { return kind() == STUB; } 5174 bool Code::is_binary_op_stub() { return kind() == BINARY_OP_IC; } 5175 bool Code::is_compare_ic_stub() { return kind() == COMPARE_IC; } 5176 bool Code::is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; } 5177 bool Code::is_optimized_code() { return kind() == OPTIMIZED_FUNCTION; } 5178 bool Code::is_wasm_code() { return kind() == WASM_FUNCTION; } 5179 5180 Address Code::constant_pool() { 5181 Address constant_pool = NULL; 5182 if (FLAG_enable_embedded_constant_pool) { 5183 int offset = constant_pool_offset(); 5184 if (offset < instruction_size()) { 5185 constant_pool = FIELD_ADDR(this, kHeaderSize + offset); 5186 } 5187 } 5188 return constant_pool; 5189 } 5190 5191 Code::Flags Code::ComputeFlags(Kind kind, ExtraICState extra_ic_state, 5192 CacheHolderFlag holder) { 5193 // Compute the bit mask. 5194 unsigned int bits = KindField::encode(kind) | 5195 ExtraICStateField::encode(extra_ic_state) | 5196 CacheHolderField::encode(holder); 5197 return static_cast<Flags>(bits); 5198 } 5199 5200 Code::Flags Code::ComputeHandlerFlags(Kind handler_kind, 5201 CacheHolderFlag holder) { 5202 return ComputeFlags(Code::HANDLER, handler_kind, holder); 5203 } 5204 5205 5206 Code::Kind Code::ExtractKindFromFlags(Flags flags) { 5207 return KindField::decode(flags); 5208 } 5209 5210 5211 ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) { 5212 return ExtraICStateField::decode(flags); 5213 } 5214 5215 5216 CacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) { 5217 return CacheHolderField::decode(flags); 5218 } 5219 5220 Code::Flags Code::RemoveHolderFromFlags(Flags flags) { 5221 int bits = flags & ~CacheHolderField::kMask; 5222 return static_cast<Flags>(bits); 5223 } 5224 5225 5226 Code* Code::GetCodeFromTargetAddress(Address address) { 5227 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize); 5228 // GetCodeFromTargetAddress might be called when marking objects during mark 5229 // sweep. reinterpret_cast is therefore used instead of the more appropriate 5230 // Code::cast. Code::cast does not work when the object's map is 5231 // marked. 5232 Code* result = reinterpret_cast<Code*>(code); 5233 return result; 5234 } 5235 5236 5237 Object* Code::GetObjectFromEntryAddress(Address location_of_address) { 5238 return HeapObject:: 5239 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize); 5240 } 5241 5242 5243 bool Code::CanContainWeakObjects() { 5244 return is_optimized_code() && can_have_weak_objects(); 5245 } 5246 5247 5248 bool Code::IsWeakObject(Object* object) { 5249 return (CanContainWeakObjects() && IsWeakObjectInOptimizedCode(object)); 5250 } 5251 5252 5253 bool Code::IsWeakObjectInOptimizedCode(Object* object) { 5254 if (object->IsMap()) { 5255 return Map::cast(object)->CanTransition(); 5256 } 5257 if (object->IsCell()) { 5258 object = Cell::cast(object)->value(); 5259 } else if (object->IsPropertyCell()) { 5260 object = PropertyCell::cast(object)->value(); 5261 } 5262 if (object->IsJSReceiver() || object->IsContext()) { 5263 return true; 5264 } 5265 return false; 5266 } 5267 5268 5269 int AbstractCode::instruction_size() { 5270 if (IsCode()) { 5271 return GetCode()->instruction_size(); 5272 } else { 5273 return GetBytecodeArray()->length(); 5274 } 5275 } 5276 5277 ByteArray* AbstractCode::source_position_table() { 5278 if (IsCode()) { 5279 return GetCode()->source_position_table(); 5280 } else { 5281 return GetBytecodeArray()->source_position_table(); 5282 } 5283 } 5284 5285 void AbstractCode::set_source_position_table(ByteArray* source_position_table) { 5286 if (IsCode()) { 5287 GetCode()->set_source_position_table(source_position_table); 5288 } else { 5289 GetBytecodeArray()->set_source_position_table(source_position_table); 5290 } 5291 } 5292 5293 int AbstractCode::SizeIncludingMetadata() { 5294 if (IsCode()) { 5295 return GetCode()->SizeIncludingMetadata(); 5296 } else { 5297 return GetBytecodeArray()->SizeIncludingMetadata(); 5298 } 5299 } 5300 int AbstractCode::ExecutableSize() { 5301 if (IsCode()) { 5302 return GetCode()->ExecutableSize(); 5303 } else { 5304 return GetBytecodeArray()->BytecodeArraySize(); 5305 } 5306 } 5307 5308 Address AbstractCode::instruction_start() { 5309 if (IsCode()) { 5310 return GetCode()->instruction_start(); 5311 } else { 5312 return GetBytecodeArray()->GetFirstBytecodeAddress(); 5313 } 5314 } 5315 5316 Address AbstractCode::instruction_end() { 5317 if (IsCode()) { 5318 return GetCode()->instruction_end(); 5319 } else { 5320 return GetBytecodeArray()->GetFirstBytecodeAddress() + 5321 GetBytecodeArray()->length(); 5322 } 5323 } 5324 5325 bool AbstractCode::contains(byte* inner_pointer) { 5326 return (address() <= inner_pointer) && (inner_pointer <= address() + Size()); 5327 } 5328 5329 AbstractCode::Kind AbstractCode::kind() { 5330 if (IsCode()) { 5331 STATIC_ASSERT(AbstractCode::FUNCTION == 5332 static_cast<AbstractCode::Kind>(Code::FUNCTION)); 5333 return static_cast<AbstractCode::Kind>(GetCode()->kind()); 5334 } else { 5335 return INTERPRETED_FUNCTION; 5336 } 5337 } 5338 5339 Code* AbstractCode::GetCode() { return Code::cast(this); } 5340 5341 BytecodeArray* AbstractCode::GetBytecodeArray() { 5342 return BytecodeArray::cast(this); 5343 } 5344 5345 Object* Map::prototype() const { 5346 return READ_FIELD(this, kPrototypeOffset); 5347 } 5348 5349 5350 void Map::set_prototype(Object* value, WriteBarrierMode mode) { 5351 DCHECK(value->IsNull(GetIsolate()) || value->IsJSReceiver()); 5352 WRITE_FIELD(this, kPrototypeOffset, value); 5353 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode); 5354 } 5355 5356 5357 LayoutDescriptor* Map::layout_descriptor_gc_safe() { 5358 Object* layout_desc = READ_FIELD(this, kLayoutDescriptorOffset); 5359 return LayoutDescriptor::cast_gc_safe(layout_desc); 5360 } 5361 5362 5363 bool Map::HasFastPointerLayout() const { 5364 Object* layout_desc = READ_FIELD(this, kLayoutDescriptorOffset); 5365 return LayoutDescriptor::IsFastPointerLayout(layout_desc); 5366 } 5367 5368 5369 void Map::UpdateDescriptors(DescriptorArray* descriptors, 5370 LayoutDescriptor* layout_desc) { 5371 set_instance_descriptors(descriptors); 5372 if (FLAG_unbox_double_fields) { 5373 if (layout_descriptor()->IsSlowLayout()) { 5374 set_layout_descriptor(layout_desc); 5375 } 5376 #ifdef VERIFY_HEAP 5377 // TODO(ishell): remove these checks from VERIFY_HEAP mode. 5378 if (FLAG_verify_heap) { 5379 CHECK(layout_descriptor()->IsConsistentWithMap(this)); 5380 CHECK(visitor_id() == Heap::GetStaticVisitorIdForMap(this)); 5381 } 5382 #else 5383 SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this)); 5384 DCHECK(visitor_id() == Heap::GetStaticVisitorIdForMap(this)); 5385 #endif 5386 } 5387 } 5388 5389 5390 void Map::InitializeDescriptors(DescriptorArray* descriptors, 5391 LayoutDescriptor* layout_desc) { 5392 int len = descriptors->number_of_descriptors(); 5393 set_instance_descriptors(descriptors); 5394 SetNumberOfOwnDescriptors(len); 5395 5396 if (FLAG_unbox_double_fields) { 5397 set_layout_descriptor(layout_desc); 5398 #ifdef VERIFY_HEAP 5399 // TODO(ishell): remove these checks from VERIFY_HEAP mode. 5400 if (FLAG_verify_heap) { 5401 CHECK(layout_descriptor()->IsConsistentWithMap(this)); 5402 } 5403 #else 5404 SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this)); 5405 #endif 5406 set_visitor_id(Heap::GetStaticVisitorIdForMap(this)); 5407 } 5408 } 5409 5410 5411 ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset) 5412 ACCESSORS(Map, layout_descriptor, LayoutDescriptor, kLayoutDescriptorOffset) 5413 5414 void Map::set_bit_field3(uint32_t bits) { 5415 if (kInt32Size != kPointerSize) { 5416 WRITE_UINT32_FIELD(this, kBitField3Offset + kInt32Size, 0); 5417 } 5418 WRITE_UINT32_FIELD(this, kBitField3Offset, bits); 5419 } 5420 5421 5422 uint32_t Map::bit_field3() const { 5423 return READ_UINT32_FIELD(this, kBitField3Offset); 5424 } 5425 5426 5427 LayoutDescriptor* Map::GetLayoutDescriptor() { 5428 return FLAG_unbox_double_fields ? layout_descriptor() 5429 : LayoutDescriptor::FastPointerLayout(); 5430 } 5431 5432 5433 void Map::AppendDescriptor(Descriptor* desc) { 5434 DescriptorArray* descriptors = instance_descriptors(); 5435 int number_of_own_descriptors = NumberOfOwnDescriptors(); 5436 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); 5437 descriptors->Append(desc); 5438 SetNumberOfOwnDescriptors(number_of_own_descriptors + 1); 5439 5440 // This function does not support appending double field descriptors and 5441 // it should never try to (otherwise, layout descriptor must be updated too). 5442 #ifdef DEBUG 5443 PropertyDetails details = desc->GetDetails(); 5444 CHECK(details.location() != kField || !details.representation().IsDouble()); 5445 #endif 5446 } 5447 5448 5449 Object* Map::GetBackPointer() { 5450 Object* object = constructor_or_backpointer(); 5451 if (object->IsMap()) { 5452 return object; 5453 } 5454 return GetIsolate()->heap()->undefined_value(); 5455 } 5456 5457 5458 Map* Map::ElementsTransitionMap() { 5459 return TransitionArray::SearchSpecial( 5460 this, GetHeap()->elements_transition_symbol()); 5461 } 5462 5463 5464 ACCESSORS(Map, raw_transitions, Object, kTransitionsOrPrototypeInfoOffset) 5465 5466 5467 Object* Map::prototype_info() const { 5468 DCHECK(is_prototype_map()); 5469 return READ_FIELD(this, Map::kTransitionsOrPrototypeInfoOffset); 5470 } 5471 5472 5473 void Map::set_prototype_info(Object* value, WriteBarrierMode mode) { 5474 DCHECK(is_prototype_map()); 5475 WRITE_FIELD(this, Map::kTransitionsOrPrototypeInfoOffset, value); 5476 CONDITIONAL_WRITE_BARRIER( 5477 GetHeap(), this, Map::kTransitionsOrPrototypeInfoOffset, value, mode); 5478 } 5479 5480 5481 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { 5482 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); 5483 DCHECK(value->IsMap()); 5484 DCHECK(GetBackPointer()->IsUndefined(GetIsolate())); 5485 DCHECK(!value->IsMap() || 5486 Map::cast(value)->GetConstructor() == constructor_or_backpointer()); 5487 set_constructor_or_backpointer(value, mode); 5488 } 5489 5490 ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset) 5491 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) 5492 ACCESSORS(Map, weak_cell_cache, Object, kWeakCellCacheOffset) 5493 ACCESSORS(Map, constructor_or_backpointer, Object, 5494 kConstructorOrBackPointerOffset) 5495 5496 5497 Object* Map::GetConstructor() const { 5498 Object* maybe_constructor = constructor_or_backpointer(); 5499 // Follow any back pointers. 5500 while (maybe_constructor->IsMap()) { 5501 maybe_constructor = 5502 Map::cast(maybe_constructor)->constructor_or_backpointer(); 5503 } 5504 return maybe_constructor; 5505 } 5506 5507 5508 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { 5509 // Never overwrite a back pointer with a constructor. 5510 DCHECK(!constructor_or_backpointer()->IsMap()); 5511 set_constructor_or_backpointer(constructor, mode); 5512 } 5513 5514 5515 Handle<Map> Map::CopyInitialMap(Handle<Map> map) { 5516 return CopyInitialMap(map, map->instance_size(), map->GetInObjectProperties(), 5517 map->unused_property_fields()); 5518 } 5519 5520 5521 ACCESSORS(JSBoundFunction, bound_target_function, JSReceiver, 5522 kBoundTargetFunctionOffset) 5523 ACCESSORS(JSBoundFunction, bound_this, Object, kBoundThisOffset) 5524 ACCESSORS(JSBoundFunction, bound_arguments, FixedArray, kBoundArgumentsOffset) 5525 5526 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) 5527 ACCESSORS(JSFunction, feedback_vector_cell, Cell, kFeedbackVectorOffset) 5528 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) 5529 5530 ACCESSORS(JSGlobalObject, native_context, Context, kNativeContextOffset) 5531 ACCESSORS(JSGlobalObject, global_proxy, JSObject, kGlobalProxyOffset) 5532 5533 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) 5534 ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset) 5535 5536 ACCESSORS(AccessorInfo, name, Object, kNameOffset) 5537 SMI_ACCESSORS(AccessorInfo, flag, kFlagOffset) 5538 ACCESSORS(AccessorInfo, expected_receiver_type, Object, 5539 kExpectedReceiverTypeOffset) 5540 5541 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset) 5542 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset) 5543 ACCESSORS(AccessorInfo, js_getter, Object, kJsGetterOffset) 5544 ACCESSORS(AccessorInfo, data, Object, kDataOffset) 5545 5546 ACCESSORS(PromiseResolveThenableJobInfo, thenable, JSReceiver, kThenableOffset) 5547 ACCESSORS(PromiseResolveThenableJobInfo, then, JSReceiver, kThenOffset) 5548 ACCESSORS(PromiseResolveThenableJobInfo, resolve, JSFunction, kResolveOffset) 5549 ACCESSORS(PromiseResolveThenableJobInfo, reject, JSFunction, kRejectOffset) 5550 ACCESSORS(PromiseResolveThenableJobInfo, context, Context, kContextOffset); 5551 5552 ACCESSORS(PromiseReactionJobInfo, value, Object, kValueOffset); 5553 ACCESSORS(PromiseReactionJobInfo, tasks, Object, kTasksOffset); 5554 ACCESSORS(PromiseReactionJobInfo, deferred_promise, Object, 5555 kDeferredPromiseOffset); 5556 ACCESSORS(PromiseReactionJobInfo, deferred_on_resolve, Object, 5557 kDeferredOnResolveOffset); 5558 ACCESSORS(PromiseReactionJobInfo, deferred_on_reject, Object, 5559 kDeferredOnRejectOffset); 5560 ACCESSORS(PromiseReactionJobInfo, context, Context, kContextOffset); 5561 5562 Map* PrototypeInfo::ObjectCreateMap() { 5563 return Map::cast(WeakCell::cast(object_create_map())->value()); 5564 } 5565 5566 // static 5567 void PrototypeInfo::SetObjectCreateMap(Handle<PrototypeInfo> info, 5568 Handle<Map> map) { 5569 Handle<WeakCell> cell = Map::WeakCellForMap(map); 5570 info->set_object_create_map(*cell); 5571 } 5572 5573 bool PrototypeInfo::HasObjectCreateMap() { 5574 Object* cache = object_create_map(); 5575 return cache->IsWeakCell() && !WeakCell::cast(cache)->cleared(); 5576 } 5577 5578 bool FunctionTemplateInfo::instantiated() { 5579 return shared_function_info()->IsSharedFunctionInfo(); 5580 } 5581 5582 FunctionTemplateInfo* FunctionTemplateInfo::GetParent(Isolate* isolate) { 5583 Object* parent = parent_template(); 5584 return parent->IsUndefined(isolate) ? nullptr 5585 : FunctionTemplateInfo::cast(parent); 5586 } 5587 5588 ObjectTemplateInfo* ObjectTemplateInfo::GetParent(Isolate* isolate) { 5589 Object* maybe_ctor = constructor(); 5590 if (maybe_ctor->IsUndefined(isolate)) return nullptr; 5591 FunctionTemplateInfo* constructor = FunctionTemplateInfo::cast(maybe_ctor); 5592 while (true) { 5593 constructor = constructor->GetParent(isolate); 5594 if (constructor == nullptr) return nullptr; 5595 Object* maybe_obj = constructor->instance_template(); 5596 if (!maybe_obj->IsUndefined(isolate)) { 5597 return ObjectTemplateInfo::cast(maybe_obj); 5598 } 5599 } 5600 return nullptr; 5601 } 5602 5603 ACCESSORS(PrototypeInfo, weak_cell, Object, kWeakCellOffset) 5604 ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset) 5605 ACCESSORS(PrototypeInfo, object_create_map, Object, kObjectCreateMap) 5606 SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset) 5607 ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset) 5608 SMI_ACCESSORS(PrototypeInfo, bit_field, kBitFieldOffset) 5609 BOOL_ACCESSORS(PrototypeInfo, bit_field, should_be_fast_map, kShouldBeFastBit) 5610 5611 ACCESSORS(Tuple2, value1, Object, kValue1Offset) 5612 ACCESSORS(Tuple2, value2, Object, kValue2Offset) 5613 ACCESSORS(Tuple3, value3, Object, kValue3Offset) 5614 5615 ACCESSORS(ContextExtension, scope_info, ScopeInfo, kScopeInfoOffset) 5616 ACCESSORS(ContextExtension, extension, Object, kExtensionOffset) 5617 5618 SMI_ACCESSORS(ConstantElementsPair, elements_kind, kElementsKindOffset) 5619 ACCESSORS(ConstantElementsPair, constant_values, FixedArrayBase, 5620 kConstantValuesOffset) 5621 5622 ACCESSORS(JSModuleNamespace, module, Module, kModuleOffset) 5623 5624 ACCESSORS(Module, code, Object, kCodeOffset) 5625 ACCESSORS(Module, exports, ObjectHashTable, kExportsOffset) 5626 ACCESSORS(Module, regular_exports, FixedArray, kRegularExportsOffset) 5627 ACCESSORS(Module, regular_imports, FixedArray, kRegularImportsOffset) 5628 ACCESSORS(Module, module_namespace, HeapObject, kModuleNamespaceOffset) 5629 ACCESSORS(Module, requested_modules, FixedArray, kRequestedModulesOffset) 5630 SMI_ACCESSORS(Module, hash, kHashOffset) 5631 5632 bool Module::evaluated() const { return code()->IsModuleInfo(); } 5633 5634 void Module::set_evaluated() { 5635 DCHECK(instantiated()); 5636 DCHECK(!evaluated()); 5637 return set_code( 5638 JSFunction::cast(code())->shared()->scope_info()->ModuleDescriptorInfo()); 5639 } 5640 5641 bool Module::instantiated() const { return !code()->IsSharedFunctionInfo(); } 5642 5643 ModuleInfo* Module::info() const { 5644 if (evaluated()) return ModuleInfo::cast(code()); 5645 ScopeInfo* scope_info = instantiated() 5646 ? JSFunction::cast(code())->shared()->scope_info() 5647 : SharedFunctionInfo::cast(code())->scope_info(); 5648 return scope_info->ModuleDescriptorInfo(); 5649 } 5650 5651 ACCESSORS(AccessorPair, getter, Object, kGetterOffset) 5652 ACCESSORS(AccessorPair, setter, Object, kSetterOffset) 5653 5654 ACCESSORS(AccessCheckInfo, callback, Object, kCallbackOffset) 5655 ACCESSORS(AccessCheckInfo, named_interceptor, Object, kNamedInterceptorOffset) 5656 ACCESSORS(AccessCheckInfo, indexed_interceptor, Object, 5657 kIndexedInterceptorOffset) 5658 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset) 5659 5660 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset) 5661 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset) 5662 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) 5663 ACCESSORS(InterceptorInfo, descriptor, Object, kDescriptorOffset) 5664 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset) 5665 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) 5666 ACCESSORS(InterceptorInfo, definer, Object, kDefinerOffset) 5667 ACCESSORS(InterceptorInfo, data, Object, kDataOffset) 5668 SMI_ACCESSORS(InterceptorInfo, flags, kFlagsOffset) 5669 BOOL_ACCESSORS(InterceptorInfo, flags, can_intercept_symbols, 5670 kCanInterceptSymbolsBit) 5671 BOOL_ACCESSORS(InterceptorInfo, flags, all_can_read, kAllCanReadBit) 5672 BOOL_ACCESSORS(InterceptorInfo, flags, non_masking, kNonMasking) 5673 5674 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) 5675 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) 5676 ACCESSORS(CallHandlerInfo, fast_handler, Object, kFastHandlerOffset) 5677 5678 ACCESSORS(TemplateInfo, tag, Object, kTagOffset) 5679 ACCESSORS(TemplateInfo, serial_number, Object, kSerialNumberOffset) 5680 SMI_ACCESSORS(TemplateInfo, number_of_properties, kNumberOfProperties) 5681 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset) 5682 ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset) 5683 5684 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset) 5685 ACCESSORS(FunctionTemplateInfo, prototype_template, Object, 5686 kPrototypeTemplateOffset) 5687 ACCESSORS(FunctionTemplateInfo, prototype_provider_template, Object, 5688 kPrototypeProviderTemplateOffset) 5689 5690 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset) 5691 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object, 5692 kNamedPropertyHandlerOffset) 5693 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object, 5694 kIndexedPropertyHandlerOffset) 5695 ACCESSORS(FunctionTemplateInfo, instance_template, Object, 5696 kInstanceTemplateOffset) 5697 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset) 5698 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset) 5699 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object, 5700 kInstanceCallHandlerOffset) 5701 ACCESSORS(FunctionTemplateInfo, access_check_info, Object, 5702 kAccessCheckInfoOffset) 5703 ACCESSORS(FunctionTemplateInfo, shared_function_info, Object, 5704 kSharedFunctionInfoOffset) 5705 ACCESSORS(FunctionTemplateInfo, cached_property_name, Object, 5706 kCachedPropertyNameOffset) 5707 5708 SMI_ACCESSORS(FunctionTemplateInfo, flag, kFlagOffset) 5709 5710 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) 5711 ACCESSORS(ObjectTemplateInfo, data, Object, kDataOffset) 5712 5713 int ObjectTemplateInfo::internal_field_count() const { 5714 Object* value = data(); 5715 DCHECK(value->IsSmi()); 5716 return InternalFieldCount::decode(Smi::cast(value)->value()); 5717 } 5718 5719 void ObjectTemplateInfo::set_internal_field_count(int count) { 5720 return set_data(Smi::FromInt( 5721 InternalFieldCount::update(Smi::cast(data())->value(), count))); 5722 } 5723 5724 bool ObjectTemplateInfo::immutable_proto() const { 5725 Object* value = data(); 5726 DCHECK(value->IsSmi()); 5727 return IsImmutablePrototype::decode(Smi::cast(value)->value()); 5728 } 5729 5730 void ObjectTemplateInfo::set_immutable_proto(bool immutable) { 5731 return set_data(Smi::FromInt( 5732 IsImmutablePrototype::update(Smi::cast(data())->value(), immutable))); 5733 } 5734 5735 int TemplateList::length() const { 5736 return Smi::cast(FixedArray::cast(this)->get(kLengthIndex))->value(); 5737 } 5738 5739 Object* TemplateList::get(int index) const { 5740 return FixedArray::cast(this)->get(kFirstElementIndex + index); 5741 } 5742 5743 void TemplateList::set(int index, Object* value) { 5744 FixedArray::cast(this)->set(kFirstElementIndex + index, value); 5745 } 5746 5747 ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset) 5748 ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset) 5749 SMI_ACCESSORS(AllocationSite, pretenure_data, kPretenureDataOffset) 5750 SMI_ACCESSORS(AllocationSite, pretenure_create_count, 5751 kPretenureCreateCountOffset) 5752 ACCESSORS(AllocationSite, dependent_code, DependentCode, 5753 kDependentCodeOffset) 5754 ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset) 5755 ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset) 5756 5757 ACCESSORS(Script, source, Object, kSourceOffset) 5758 ACCESSORS(Script, name, Object, kNameOffset) 5759 SMI_ACCESSORS(Script, id, kIdOffset) 5760 SMI_ACCESSORS(Script, line_offset, kLineOffsetOffset) 5761 SMI_ACCESSORS(Script, column_offset, kColumnOffsetOffset) 5762 ACCESSORS(Script, context_data, Object, kContextOffset) 5763 ACCESSORS(Script, wrapper, HeapObject, kWrapperOffset) 5764 SMI_ACCESSORS(Script, type, kTypeOffset) 5765 ACCESSORS(Script, line_ends, Object, kLineEndsOffset) 5766 ACCESSORS_CHECKED(Script, eval_from_shared, Object, kEvalFromSharedOffset, 5767 this->type() != TYPE_WASM) 5768 SMI_ACCESSORS_CHECKED(Script, eval_from_position, kEvalFromPositionOffset, 5769 this->type() != TYPE_WASM) 5770 ACCESSORS(Script, shared_function_infos, FixedArray, kSharedFunctionInfosOffset) 5771 SMI_ACCESSORS(Script, flags, kFlagsOffset) 5772 ACCESSORS(Script, source_url, Object, kSourceUrlOffset) 5773 ACCESSORS(Script, source_mapping_url, Object, kSourceMappingUrlOffset) 5774 ACCESSORS_CHECKED(Script, wasm_compiled_module, Object, kEvalFromSharedOffset, 5775 this->type() == TYPE_WASM) 5776 5777 Script::CompilationType Script::compilation_type() { 5778 return BooleanBit::get(flags(), kCompilationTypeBit) ? 5779 COMPILATION_TYPE_EVAL : COMPILATION_TYPE_HOST; 5780 } 5781 void Script::set_compilation_type(CompilationType type) { 5782 set_flags(BooleanBit::set(flags(), kCompilationTypeBit, 5783 type == COMPILATION_TYPE_EVAL)); 5784 } 5785 Script::CompilationState Script::compilation_state() { 5786 return BooleanBit::get(flags(), kCompilationStateBit) ? 5787 COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL; 5788 } 5789 void Script::set_compilation_state(CompilationState state) { 5790 set_flags(BooleanBit::set(flags(), kCompilationStateBit, 5791 state == COMPILATION_STATE_COMPILED)); 5792 } 5793 ScriptOriginOptions Script::origin_options() { 5794 return ScriptOriginOptions((flags() & kOriginOptionsMask) >> 5795 kOriginOptionsShift); 5796 } 5797 void Script::set_origin_options(ScriptOriginOptions origin_options) { 5798 DCHECK(!(origin_options.Flags() & ~((1 << kOriginOptionsSize) - 1))); 5799 set_flags((flags() & ~kOriginOptionsMask) | 5800 (origin_options.Flags() << kOriginOptionsShift)); 5801 } 5802 5803 5804 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex) 5805 SMI_ACCESSORS(DebugInfo, debugger_hints, kDebuggerHintsIndex) 5806 ACCESSORS(DebugInfo, debug_bytecode_array, Object, kDebugBytecodeArrayIndex) 5807 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex) 5808 5809 bool DebugInfo::HasDebugBytecodeArray() { 5810 return debug_bytecode_array()->IsBytecodeArray(); 5811 } 5812 5813 bool DebugInfo::HasDebugCode() { 5814 Code* code = shared()->code(); 5815 bool has = code->kind() == Code::FUNCTION; 5816 DCHECK(!has || code->has_debug_break_slots()); 5817 return has; 5818 } 5819 5820 BytecodeArray* DebugInfo::OriginalBytecodeArray() { 5821 DCHECK(HasDebugBytecodeArray()); 5822 return shared()->bytecode_array(); 5823 } 5824 5825 BytecodeArray* DebugInfo::DebugBytecodeArray() { 5826 DCHECK(HasDebugBytecodeArray()); 5827 return BytecodeArray::cast(debug_bytecode_array()); 5828 } 5829 5830 Code* DebugInfo::DebugCode() { 5831 DCHECK(HasDebugCode()); 5832 return shared()->code(); 5833 } 5834 5835 SMI_ACCESSORS(BreakPointInfo, source_position, kSourcePositionIndex) 5836 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex) 5837 5838 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset) 5839 ACCESSORS(SharedFunctionInfo, optimized_code_map, FixedArray, 5840 kOptimizedCodeMapOffset) 5841 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset) 5842 ACCESSORS(SharedFunctionInfo, feedback_metadata, FeedbackMetadata, 5843 kFeedbackMetadataOffset) 5844 SMI_ACCESSORS(SharedFunctionInfo, function_literal_id, kFunctionLiteralIdOffset) 5845 #if TRACE_MAPS 5846 SMI_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset) 5847 #endif 5848 ACCESSORS(SharedFunctionInfo, instance_class_name, Object, 5849 kInstanceClassNameOffset) 5850 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset) 5851 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset) 5852 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset) 5853 ACCESSORS(SharedFunctionInfo, function_identifier, Object, 5854 kFunctionIdentifierOffset) 5855 5856 SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset) 5857 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype, 5858 kHiddenPrototypeBit) 5859 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit) 5860 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check, 5861 kNeedsAccessCheckBit) 5862 BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype, 5863 kReadOnlyPrototypeBit) 5864 BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype, 5865 kRemovePrototypeBit) 5866 BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache, 5867 kDoNotCacheBit) 5868 BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver, 5869 kAcceptAnyReceiver) 5870 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_named_expression, 5871 kIsNamedExpressionBit) 5872 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel, 5873 kIsTopLevelBit) 5874 5875 #if V8_HOST_ARCH_32_BIT 5876 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset) 5877 SMI_ACCESSORS(SharedFunctionInfo, internal_formal_parameter_count, 5878 kFormalParameterCountOffset) 5879 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties, 5880 kExpectedNofPropertiesOffset) 5881 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type, 5882 kStartPositionAndTypeOffset) 5883 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset) 5884 SMI_ACCESSORS(SharedFunctionInfo, function_token_position, 5885 kFunctionTokenPositionOffset) 5886 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints, 5887 kCompilerHintsOffset) 5888 SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason, 5889 kOptCountAndBailoutReasonOffset) 5890 SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset) 5891 SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset) 5892 SMI_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset) 5893 5894 #else 5895 5896 #if V8_TARGET_LITTLE_ENDIAN 5897 #define PSEUDO_SMI_LO_ALIGN 0 5898 #define PSEUDO_SMI_HI_ALIGN kIntSize 5899 #else 5900 #define PSEUDO_SMI_LO_ALIGN kIntSize 5901 #define PSEUDO_SMI_HI_ALIGN 0 5902 #endif 5903 5904 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \ 5905 STATIC_ASSERT(holder::offset % kPointerSize == PSEUDO_SMI_LO_ALIGN); \ 5906 int holder::name() const { \ 5907 int value = READ_INT_FIELD(this, offset); \ 5908 DCHECK(kHeapObjectTag == 1); \ 5909 DCHECK((value & kHeapObjectTag) == 0); \ 5910 return value >> 1; \ 5911 } \ 5912 void holder::set_##name(int value) { \ 5913 DCHECK(kHeapObjectTag == 1); \ 5914 DCHECK((value & 0xC0000000) == 0xC0000000 || (value & 0xC0000000) == 0x0); \ 5915 WRITE_INT_FIELD(this, offset, (value << 1) & ~kHeapObjectTag); \ 5916 } 5917 5918 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \ 5919 STATIC_ASSERT(holder::offset % kPointerSize == PSEUDO_SMI_HI_ALIGN); \ 5920 INT_ACCESSORS(holder, name, offset) 5921 5922 5923 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset) 5924 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, internal_formal_parameter_count, 5925 kFormalParameterCountOffset) 5926 5927 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 5928 expected_nof_properties, 5929 kExpectedNofPropertiesOffset) 5930 5931 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset) 5932 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, 5933 start_position_and_type, 5934 kStartPositionAndTypeOffset) 5935 5936 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 5937 function_token_position, 5938 kFunctionTokenPositionOffset) 5939 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, 5940 compiler_hints, 5941 kCompilerHintsOffset) 5942 5943 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 5944 opt_count_and_bailout_reason, 5945 kOptCountAndBailoutReasonOffset) 5946 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset) 5947 5948 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 5949 ast_node_count, 5950 kAstNodeCountOffset) 5951 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, 5952 profiler_ticks, 5953 kProfilerTicksOffset) 5954 5955 #endif 5956 5957 AbstractCode* SharedFunctionInfo::abstract_code() { 5958 if (HasBytecodeArray()) { 5959 return AbstractCode::cast(bytecode_array()); 5960 } else { 5961 return AbstractCode::cast(code()); 5962 } 5963 } 5964 5965 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, allows_lazy_compilation, 5966 kAllowLazyCompilation) 5967 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, uses_arguments, 5968 kUsesArguments) 5969 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, has_duplicate_parameters, 5970 kHasDuplicateParameters) 5971 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, asm_function, kIsAsmFunction) 5972 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_declaration, 5973 kIsDeclaration) 5974 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, marked_for_tier_up, 5975 kMarkedForTierUp) 5976 5977 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, needs_home_object, 5978 kNeedsHomeObject) 5979 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative) 5980 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, force_inline, kForceInline) 5981 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, must_use_ignition_turbo, 5982 kMustUseIgnitionTurbo) 5983 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush) 5984 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_asm_wasm_broken, 5985 kIsAsmWasmBroken) 5986 5987 BOOL_GETTER(SharedFunctionInfo, compiler_hints, optimization_disabled, 5988 kOptimizationDisabled) 5989 5990 void SharedFunctionInfo::set_optimization_disabled(bool disable) { 5991 set_compiler_hints(BooleanBit::set(compiler_hints(), 5992 kOptimizationDisabled, 5993 disable)); 5994 } 5995 5996 LanguageMode SharedFunctionInfo::language_mode() { 5997 STATIC_ASSERT(LANGUAGE_END == 2); 5998 return construct_language_mode( 5999 BooleanBit::get(compiler_hints(), kStrictModeFunction)); 6000 } 6001 6002 void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) { 6003 STATIC_ASSERT(LANGUAGE_END == 2); 6004 // We only allow language mode transitions that set the same language mode 6005 // again or go up in the chain: 6006 DCHECK(is_sloppy(this->language_mode()) || is_strict(language_mode)); 6007 int hints = compiler_hints(); 6008 hints = BooleanBit::set(hints, kStrictModeFunction, is_strict(language_mode)); 6009 set_compiler_hints(hints); 6010 } 6011 6012 FunctionKind SharedFunctionInfo::kind() const { 6013 return FunctionKindBits::decode(compiler_hints()); 6014 } 6015 6016 void SharedFunctionInfo::set_kind(FunctionKind kind) { 6017 DCHECK(IsValidFunctionKind(kind)); 6018 int hints = compiler_hints(); 6019 hints = FunctionKindBits::update(hints, kind); 6020 set_compiler_hints(hints); 6021 } 6022 6023 BOOL_ACCESSORS(SharedFunctionInfo, debugger_hints, 6024 name_should_print_as_anonymous, kNameShouldPrintAsAnonymous) 6025 BOOL_ACCESSORS(SharedFunctionInfo, debugger_hints, is_anonymous_expression, 6026 kIsAnonymousExpression) 6027 BOOL_ACCESSORS(SharedFunctionInfo, debugger_hints, deserialized, kDeserialized) 6028 BOOL_ACCESSORS(SharedFunctionInfo, debugger_hints, has_no_side_effect, 6029 kHasNoSideEffect) 6030 BOOL_ACCESSORS(SharedFunctionInfo, debugger_hints, computed_has_no_side_effect, 6031 kComputedHasNoSideEffect) 6032 BOOL_ACCESSORS(SharedFunctionInfo, debugger_hints, debug_is_blackboxed, 6033 kDebugIsBlackboxed) 6034 BOOL_ACCESSORS(SharedFunctionInfo, debugger_hints, computed_debug_is_blackboxed, 6035 kComputedDebugIsBlackboxed) 6036 6037 bool Script::HasValidSource() { 6038 Object* src = this->source(); 6039 if (!src->IsString()) return true; 6040 String* src_str = String::cast(src); 6041 if (!StringShape(src_str).IsExternal()) return true; 6042 if (src_str->IsOneByteRepresentation()) { 6043 return ExternalOneByteString::cast(src)->resource() != NULL; 6044 } else if (src_str->IsTwoByteRepresentation()) { 6045 return ExternalTwoByteString::cast(src)->resource() != NULL; 6046 } 6047 return true; 6048 } 6049 6050 6051 void SharedFunctionInfo::DontAdaptArguments() { 6052 DCHECK(code()->kind() == Code::BUILTIN || code()->kind() == Code::STUB); 6053 set_internal_formal_parameter_count(kDontAdaptArgumentsSentinel); 6054 } 6055 6056 6057 int SharedFunctionInfo::start_position() const { 6058 return start_position_and_type() >> kStartPositionShift; 6059 } 6060 6061 6062 void SharedFunctionInfo::set_start_position(int start_position) { 6063 set_start_position_and_type((start_position << kStartPositionShift) 6064 | (start_position_and_type() & ~kStartPositionMask)); 6065 } 6066 6067 6068 Code* SharedFunctionInfo::code() const { 6069 return Code::cast(READ_FIELD(this, kCodeOffset)); 6070 } 6071 6072 6073 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) { 6074 DCHECK(value->kind() != Code::OPTIMIZED_FUNCTION); 6075 // If the SharedFunctionInfo has bytecode we should never mark it for lazy 6076 // compile, since the bytecode is never flushed. 6077 DCHECK(value != GetIsolate()->builtins()->builtin(Builtins::kCompileLazy) || 6078 !HasBytecodeArray()); 6079 WRITE_FIELD(this, kCodeOffset, value); 6080 CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode); 6081 } 6082 6083 6084 void SharedFunctionInfo::ReplaceCode(Code* value) { 6085 // If the GC metadata field is already used then the function was 6086 // enqueued as a code flushing candidate and we remove it now. 6087 if (code()->gc_metadata() != NULL) { 6088 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher(); 6089 flusher->EvictCandidate(this); 6090 } 6091 6092 DCHECK(code()->gc_metadata() == NULL && value->gc_metadata() == NULL); 6093 #ifdef DEBUG 6094 Code::VerifyRecompiledCode(code(), value); 6095 #endif // DEBUG 6096 6097 set_code(value); 6098 } 6099 6100 bool SharedFunctionInfo::IsInterpreted() const { 6101 return code()->is_interpreter_trampoline_builtin(); 6102 } 6103 6104 bool SharedFunctionInfo::HasBaselineCode() const { 6105 return code()->kind() == Code::FUNCTION; 6106 } 6107 6108 ScopeInfo* SharedFunctionInfo::scope_info() const { 6109 return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset)); 6110 } 6111 6112 6113 void SharedFunctionInfo::set_scope_info(ScopeInfo* value, 6114 WriteBarrierMode mode) { 6115 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value)); 6116 CONDITIONAL_WRITE_BARRIER(GetHeap(), 6117 this, 6118 kScopeInfoOffset, 6119 reinterpret_cast<Object*>(value), 6120 mode); 6121 } 6122 6123 ACCESSORS(SharedFunctionInfo, outer_scope_info, HeapObject, 6124 kOuterScopeInfoOffset) 6125 6126 bool SharedFunctionInfo::is_compiled() const { 6127 Builtins* builtins = GetIsolate()->builtins(); 6128 DCHECK(code() != builtins->builtin(Builtins::kCompileOptimizedConcurrent)); 6129 DCHECK(code() != builtins->builtin(Builtins::kCompileOptimized)); 6130 DCHECK(code() != builtins->builtin(Builtins::kCompileBaseline)); 6131 return code() != builtins->builtin(Builtins::kCompileLazy); 6132 } 6133 6134 6135 bool SharedFunctionInfo::has_simple_parameters() { 6136 return scope_info()->HasSimpleParameters(); 6137 } 6138 6139 bool SharedFunctionInfo::HasDebugInfo() const { 6140 bool has_debug_info = !debug_info()->IsSmi(); 6141 DCHECK_EQ(debug_info()->IsStruct(), has_debug_info); 6142 DCHECK(!has_debug_info || HasDebugCode()); 6143 return has_debug_info; 6144 } 6145 6146 DebugInfo* SharedFunctionInfo::GetDebugInfo() const { 6147 DCHECK(HasDebugInfo()); 6148 return DebugInfo::cast(debug_info()); 6149 } 6150 6151 bool SharedFunctionInfo::HasDebugCode() const { 6152 if (HasBaselineCode()) return code()->has_debug_break_slots(); 6153 return HasBytecodeArray(); 6154 } 6155 6156 int SharedFunctionInfo::debugger_hints() const { 6157 if (HasDebugInfo()) return GetDebugInfo()->debugger_hints(); 6158 return Smi::cast(debug_info())->value(); 6159 } 6160 6161 void SharedFunctionInfo::set_debugger_hints(int value) { 6162 if (HasDebugInfo()) { 6163 GetDebugInfo()->set_debugger_hints(value); 6164 } else { 6165 set_debug_info(Smi::FromInt(value)); 6166 } 6167 } 6168 6169 bool SharedFunctionInfo::IsApiFunction() { 6170 return function_data()->IsFunctionTemplateInfo(); 6171 } 6172 6173 6174 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() { 6175 DCHECK(IsApiFunction()); 6176 return FunctionTemplateInfo::cast(function_data()); 6177 } 6178 6179 void SharedFunctionInfo::set_api_func_data(FunctionTemplateInfo* data) { 6180 DCHECK(function_data()->IsUndefined(GetIsolate())); 6181 set_function_data(data); 6182 } 6183 6184 bool SharedFunctionInfo::HasBytecodeArray() const { 6185 return function_data()->IsBytecodeArray(); 6186 } 6187 6188 BytecodeArray* SharedFunctionInfo::bytecode_array() const { 6189 DCHECK(HasBytecodeArray()); 6190 return BytecodeArray::cast(function_data()); 6191 } 6192 6193 void SharedFunctionInfo::set_bytecode_array(BytecodeArray* bytecode) { 6194 DCHECK(function_data()->IsUndefined(GetIsolate())); 6195 set_function_data(bytecode); 6196 } 6197 6198 void SharedFunctionInfo::ClearBytecodeArray() { 6199 DCHECK(function_data()->IsUndefined(GetIsolate()) || HasBytecodeArray()); 6200 set_function_data(GetHeap()->undefined_value()); 6201 } 6202 6203 bool SharedFunctionInfo::HasAsmWasmData() const { 6204 return function_data()->IsFixedArray(); 6205 } 6206 6207 FixedArray* SharedFunctionInfo::asm_wasm_data() const { 6208 DCHECK(HasAsmWasmData()); 6209 return FixedArray::cast(function_data()); 6210 } 6211 6212 void SharedFunctionInfo::set_asm_wasm_data(FixedArray* data) { 6213 DCHECK(function_data()->IsUndefined(GetIsolate()) || HasAsmWasmData()); 6214 set_function_data(data); 6215 } 6216 6217 void SharedFunctionInfo::ClearAsmWasmData() { 6218 DCHECK(function_data()->IsUndefined(GetIsolate()) || HasAsmWasmData()); 6219 set_function_data(GetHeap()->undefined_value()); 6220 } 6221 6222 bool SharedFunctionInfo::HasBuiltinFunctionId() { 6223 return function_identifier()->IsSmi(); 6224 } 6225 6226 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() { 6227 DCHECK(HasBuiltinFunctionId()); 6228 return static_cast<BuiltinFunctionId>( 6229 Smi::cast(function_identifier())->value()); 6230 } 6231 6232 void SharedFunctionInfo::set_builtin_function_id(BuiltinFunctionId id) { 6233 set_function_identifier(Smi::FromInt(id)); 6234 } 6235 6236 bool SharedFunctionInfo::HasInferredName() { 6237 return function_identifier()->IsString(); 6238 } 6239 6240 String* SharedFunctionInfo::inferred_name() { 6241 if (HasInferredName()) { 6242 return String::cast(function_identifier()); 6243 } 6244 Isolate* isolate = GetIsolate(); 6245 DCHECK(function_identifier()->IsUndefined(isolate) || HasBuiltinFunctionId()); 6246 return isolate->heap()->empty_string(); 6247 } 6248 6249 void SharedFunctionInfo::set_inferred_name(String* inferred_name) { 6250 DCHECK(function_identifier()->IsUndefined(GetIsolate()) || HasInferredName()); 6251 set_function_identifier(inferred_name); 6252 } 6253 6254 int SharedFunctionInfo::ic_age() { 6255 return ICAgeBits::decode(counters()); 6256 } 6257 6258 6259 void SharedFunctionInfo::set_ic_age(int ic_age) { 6260 set_counters(ICAgeBits::update(counters(), ic_age)); 6261 } 6262 6263 6264 int SharedFunctionInfo::deopt_count() { 6265 return DeoptCountBits::decode(counters()); 6266 } 6267 6268 6269 void SharedFunctionInfo::set_deopt_count(int deopt_count) { 6270 set_counters(DeoptCountBits::update(counters(), deopt_count)); 6271 } 6272 6273 6274 void SharedFunctionInfo::increment_deopt_count() { 6275 int value = counters(); 6276 int deopt_count = DeoptCountBits::decode(value); 6277 deopt_count = (deopt_count + 1) & DeoptCountBits::kMax; 6278 set_counters(DeoptCountBits::update(value, deopt_count)); 6279 } 6280 6281 6282 int SharedFunctionInfo::opt_reenable_tries() { 6283 return OptReenableTriesBits::decode(counters()); 6284 } 6285 6286 6287 void SharedFunctionInfo::set_opt_reenable_tries(int tries) { 6288 set_counters(OptReenableTriesBits::update(counters(), tries)); 6289 } 6290 6291 6292 int SharedFunctionInfo::opt_count() { 6293 return OptCountBits::decode(opt_count_and_bailout_reason()); 6294 } 6295 6296 6297 void SharedFunctionInfo::set_opt_count(int opt_count) { 6298 set_opt_count_and_bailout_reason( 6299 OptCountBits::update(opt_count_and_bailout_reason(), opt_count)); 6300 } 6301 6302 6303 BailoutReason SharedFunctionInfo::disable_optimization_reason() { 6304 return static_cast<BailoutReason>( 6305 DisabledOptimizationReasonBits::decode(opt_count_and_bailout_reason())); 6306 } 6307 6308 6309 bool SharedFunctionInfo::has_deoptimization_support() { 6310 Code* code = this->code(); 6311 return code->kind() == Code::FUNCTION && code->has_deoptimization_support(); 6312 } 6313 6314 6315 void SharedFunctionInfo::TryReenableOptimization() { 6316 int tries = opt_reenable_tries(); 6317 set_opt_reenable_tries((tries + 1) & OptReenableTriesBits::kMax); 6318 // We reenable optimization whenever the number of tries is a large 6319 // enough power of 2. 6320 if (tries >= 16 && (((tries - 1) & tries) == 0)) { 6321 set_optimization_disabled(false); 6322 set_opt_count(0); 6323 set_deopt_count(0); 6324 } 6325 } 6326 6327 6328 void SharedFunctionInfo::set_disable_optimization_reason(BailoutReason reason) { 6329 set_opt_count_and_bailout_reason(DisabledOptimizationReasonBits::update( 6330 opt_count_and_bailout_reason(), reason)); 6331 } 6332 6333 bool SharedFunctionInfo::IsUserJavaScript() { 6334 Object* script_obj = script(); 6335 if (script_obj->IsUndefined(GetIsolate())) return false; 6336 Script* script = Script::cast(script_obj); 6337 return static_cast<Script::Type>(script->type()) == Script::TYPE_NORMAL; 6338 } 6339 6340 bool SharedFunctionInfo::IsSubjectToDebugging() { 6341 return IsUserJavaScript() && !HasAsmWasmData(); 6342 } 6343 6344 bool SharedFunctionInfo::OptimizedCodeMapIsCleared() const { 6345 return optimized_code_map() == GetHeap()->empty_fixed_array(); 6346 } 6347 6348 FeedbackVector* JSFunction::feedback_vector() const { 6349 DCHECK(feedback_vector_cell()->value()->IsFeedbackVector()); 6350 return FeedbackVector::cast(feedback_vector_cell()->value()); 6351 } 6352 6353 bool JSFunction::IsOptimized() { 6354 return code()->kind() == Code::OPTIMIZED_FUNCTION; 6355 } 6356 6357 bool JSFunction::IsInterpreted() { 6358 return code()->is_interpreter_trampoline_builtin(); 6359 } 6360 6361 bool JSFunction::IsMarkedForBaseline() { 6362 return code() == 6363 GetIsolate()->builtins()->builtin(Builtins::kCompileBaseline); 6364 } 6365 6366 bool JSFunction::IsMarkedForOptimization() { 6367 return code() == GetIsolate()->builtins()->builtin( 6368 Builtins::kCompileOptimized); 6369 } 6370 6371 6372 bool JSFunction::IsMarkedForConcurrentOptimization() { 6373 return code() == GetIsolate()->builtins()->builtin( 6374 Builtins::kCompileOptimizedConcurrent); 6375 } 6376 6377 6378 bool JSFunction::IsInOptimizationQueue() { 6379 return code() == GetIsolate()->builtins()->builtin( 6380 Builtins::kInOptimizationQueue); 6381 } 6382 6383 6384 void JSFunction::CompleteInobjectSlackTrackingIfActive() { 6385 if (has_initial_map() && initial_map()->IsInobjectSlackTrackingInProgress()) { 6386 initial_map()->CompleteInobjectSlackTracking(); 6387 } 6388 } 6389 6390 6391 bool Map::IsInobjectSlackTrackingInProgress() { 6392 return construction_counter() != Map::kNoSlackTracking; 6393 } 6394 6395 6396 void Map::InobjectSlackTrackingStep() { 6397 if (!IsInobjectSlackTrackingInProgress()) return; 6398 int counter = construction_counter(); 6399 set_construction_counter(counter - 1); 6400 if (counter == kSlackTrackingCounterEnd) { 6401 CompleteInobjectSlackTracking(); 6402 } 6403 } 6404 6405 AbstractCode* JSFunction::abstract_code() { 6406 if (IsInterpreted()) { 6407 return AbstractCode::cast(shared()->bytecode_array()); 6408 } else { 6409 return AbstractCode::cast(code()); 6410 } 6411 } 6412 6413 Code* JSFunction::code() { 6414 return Code::cast( 6415 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset))); 6416 } 6417 6418 6419 void JSFunction::set_code(Code* value) { 6420 DCHECK(!GetHeap()->InNewSpace(value)); 6421 Address entry = value->entry(); 6422 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry)); 6423 GetHeap()->incremental_marking()->RecordWriteOfCodeEntry( 6424 this, 6425 HeapObject::RawField(this, kCodeEntryOffset), 6426 value); 6427 } 6428 6429 6430 void JSFunction::set_code_no_write_barrier(Code* value) { 6431 DCHECK(!GetHeap()->InNewSpace(value)); 6432 Address entry = value->entry(); 6433 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry)); 6434 } 6435 6436 6437 void JSFunction::ReplaceCode(Code* code) { 6438 bool was_optimized = IsOptimized(); 6439 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION; 6440 6441 if (was_optimized && is_optimized) { 6442 shared()->EvictFromOptimizedCodeMap(this->code(), 6443 "Replacing with another optimized code"); 6444 } 6445 6446 set_code(code); 6447 6448 // Add/remove the function from the list of optimized functions for this 6449 // context based on the state change. 6450 if (!was_optimized && is_optimized) { 6451 context()->native_context()->AddOptimizedFunction(this); 6452 } 6453 if (was_optimized && !is_optimized) { 6454 // TODO(titzer): linear in the number of optimized functions; fix! 6455 context()->native_context()->RemoveOptimizedFunction(this); 6456 } 6457 } 6458 6459 bool JSFunction::has_feedback_vector() const { 6460 return !feedback_vector_cell()->value()->IsUndefined(GetIsolate()); 6461 } 6462 6463 JSFunction::FeedbackVectorState JSFunction::GetFeedbackVectorState( 6464 Isolate* isolate) const { 6465 Cell* cell = feedback_vector_cell(); 6466 if (cell == isolate->heap()->undefined_cell()) { 6467 return TOP_LEVEL_SCRIPT_NEEDS_VECTOR; 6468 } else if (cell->value() == isolate->heap()->undefined_value() || 6469 !has_feedback_vector()) { 6470 return NEEDS_VECTOR; 6471 } 6472 return HAS_VECTOR; 6473 } 6474 6475 Context* JSFunction::context() { 6476 return Context::cast(READ_FIELD(this, kContextOffset)); 6477 } 6478 6479 bool JSFunction::has_context() const { 6480 return READ_FIELD(this, kContextOffset)->IsContext(); 6481 } 6482 6483 JSObject* JSFunction::global_proxy() { 6484 return context()->global_proxy(); 6485 } 6486 6487 6488 Context* JSFunction::native_context() { return context()->native_context(); } 6489 6490 6491 void JSFunction::set_context(Object* value) { 6492 DCHECK(value->IsUndefined(GetIsolate()) || value->IsContext()); 6493 WRITE_FIELD(this, kContextOffset, value); 6494 WRITE_BARRIER(GetHeap(), this, kContextOffset, value); 6495 } 6496 6497 ACCESSORS(JSFunction, prototype_or_initial_map, Object, 6498 kPrototypeOrInitialMapOffset) 6499 6500 6501 Map* JSFunction::initial_map() { 6502 return Map::cast(prototype_or_initial_map()); 6503 } 6504 6505 6506 bool JSFunction::has_initial_map() { 6507 return prototype_or_initial_map()->IsMap(); 6508 } 6509 6510 6511 bool JSFunction::has_instance_prototype() { 6512 return has_initial_map() || 6513 !prototype_or_initial_map()->IsTheHole(GetIsolate()); 6514 } 6515 6516 6517 bool JSFunction::has_prototype() { 6518 return map()->has_non_instance_prototype() || has_instance_prototype(); 6519 } 6520 6521 6522 Object* JSFunction::instance_prototype() { 6523 DCHECK(has_instance_prototype()); 6524 if (has_initial_map()) return initial_map()->prototype(); 6525 // When there is no initial map and the prototype is a JSObject, the 6526 // initial map field is used for the prototype field. 6527 return prototype_or_initial_map(); 6528 } 6529 6530 6531 Object* JSFunction::prototype() { 6532 DCHECK(has_prototype()); 6533 // If the function's prototype property has been set to a non-JSObject 6534 // value, that value is stored in the constructor field of the map. 6535 if (map()->has_non_instance_prototype()) { 6536 Object* prototype = map()->GetConstructor(); 6537 // The map must have a prototype in that field, not a back pointer. 6538 DCHECK(!prototype->IsMap()); 6539 return prototype; 6540 } 6541 return instance_prototype(); 6542 } 6543 6544 6545 bool JSFunction::is_compiled() { 6546 Builtins* builtins = GetIsolate()->builtins(); 6547 return code() != builtins->builtin(Builtins::kCompileLazy) && 6548 code() != builtins->builtin(Builtins::kCompileBaseline) && 6549 code() != builtins->builtin(Builtins::kCompileOptimized) && 6550 code() != builtins->builtin(Builtins::kCompileOptimizedConcurrent); 6551 } 6552 6553 ACCESSORS(JSProxy, target, JSReceiver, kTargetOffset) 6554 ACCESSORS(JSProxy, handler, Object, kHandlerOffset) 6555 ACCESSORS(JSProxy, hash, Object, kHashOffset) 6556 6557 bool JSProxy::IsRevoked() const { return !handler()->IsJSReceiver(); } 6558 6559 ACCESSORS(JSCollection, table, Object, kTableOffset) 6560 6561 6562 #define ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(name, type, offset) \ 6563 template<class Derived, class TableType> \ 6564 type* OrderedHashTableIterator<Derived, TableType>::name() const { \ 6565 return type::cast(READ_FIELD(this, offset)); \ 6566 } \ 6567 template<class Derived, class TableType> \ 6568 void OrderedHashTableIterator<Derived, TableType>::set_##name( \ 6569 type* value, WriteBarrierMode mode) { \ 6570 WRITE_FIELD(this, offset, value); \ 6571 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \ 6572 } 6573 6574 ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(table, Object, kTableOffset) 6575 ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(index, Object, kIndexOffset) 6576 ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(kind, Object, kKindOffset) 6577 6578 #undef ORDERED_HASH_TABLE_ITERATOR_ACCESSORS 6579 6580 6581 ACCESSORS(JSWeakCollection, table, Object, kTableOffset) 6582 ACCESSORS(JSWeakCollection, next, Object, kNextOffset) 6583 6584 6585 Address Foreign::foreign_address() { 6586 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset)); 6587 } 6588 6589 6590 void Foreign::set_foreign_address(Address value) { 6591 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value)); 6592 } 6593 6594 6595 ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset) 6596 ACCESSORS(JSGeneratorObject, context, Context, kContextOffset) 6597 ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset) 6598 ACCESSORS(JSGeneratorObject, input_or_debug_pos, Object, kInputOrDebugPosOffset) 6599 SMI_ACCESSORS(JSGeneratorObject, resume_mode, kResumeModeOffset) 6600 SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset) 6601 ACCESSORS(JSGeneratorObject, register_file, FixedArray, kRegisterFileOffset) 6602 6603 bool JSGeneratorObject::is_suspended() const { 6604 DCHECK_LT(kGeneratorExecuting, 0); 6605 DCHECK_LT(kGeneratorClosed, 0); 6606 return continuation() >= 0; 6607 } 6608 6609 bool JSGeneratorObject::is_closed() const { 6610 return continuation() == kGeneratorClosed; 6611 } 6612 6613 bool JSGeneratorObject::is_executing() const { 6614 return continuation() == kGeneratorExecuting; 6615 } 6616 6617 ACCESSORS(JSValue, value, Object, kValueOffset) 6618 6619 6620 HeapNumber* HeapNumber::cast(Object* object) { 6621 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber()); 6622 return reinterpret_cast<HeapNumber*>(object); 6623 } 6624 6625 6626 const HeapNumber* HeapNumber::cast(const Object* object) { 6627 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber()); 6628 return reinterpret_cast<const HeapNumber*>(object); 6629 } 6630 6631 6632 ACCESSORS(JSDate, value, Object, kValueOffset) 6633 ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset) 6634 ACCESSORS(JSDate, year, Object, kYearOffset) 6635 ACCESSORS(JSDate, month, Object, kMonthOffset) 6636 ACCESSORS(JSDate, day, Object, kDayOffset) 6637 ACCESSORS(JSDate, weekday, Object, kWeekdayOffset) 6638 ACCESSORS(JSDate, hour, Object, kHourOffset) 6639 ACCESSORS(JSDate, min, Object, kMinOffset) 6640 ACCESSORS(JSDate, sec, Object, kSecOffset) 6641 6642 6643 SMI_ACCESSORS(JSMessageObject, type, kTypeOffset) 6644 ACCESSORS(JSMessageObject, argument, Object, kArgumentsOffset) 6645 ACCESSORS(JSMessageObject, script, Object, kScriptOffset) 6646 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset) 6647 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset) 6648 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset) 6649 SMI_ACCESSORS(JSMessageObject, error_level, kErrorLevelOffset) 6650 6651 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset) 6652 INT_ACCESSORS(Code, prologue_offset, kPrologueOffset) 6653 INT_ACCESSORS(Code, constant_pool_offset, kConstantPoolOffset) 6654 #define CODE_ACCESSORS(name, type, offset) \ 6655 ACCESSORS_CHECKED2(Code, name, type, offset, true, \ 6656 !GetHeap()->InNewSpace(value)) 6657 CODE_ACCESSORS(relocation_info, ByteArray, kRelocationInfoOffset) 6658 CODE_ACCESSORS(handler_table, FixedArray, kHandlerTableOffset) 6659 CODE_ACCESSORS(deoptimization_data, FixedArray, kDeoptimizationDataOffset) 6660 CODE_ACCESSORS(source_position_table, ByteArray, kSourcePositionTableOffset) 6661 CODE_ACCESSORS(raw_type_feedback_info, Object, kTypeFeedbackInfoOffset) 6662 CODE_ACCESSORS(next_code_link, Object, kNextCodeLinkOffset) 6663 #undef CODE_ACCESSORS 6664 6665 void Code::WipeOutHeader() { 6666 WRITE_FIELD(this, kRelocationInfoOffset, NULL); 6667 WRITE_FIELD(this, kHandlerTableOffset, NULL); 6668 WRITE_FIELD(this, kDeoptimizationDataOffset, NULL); 6669 WRITE_FIELD(this, kSourcePositionTableOffset, NULL); 6670 // Do not wipe out major/minor keys on a code stub or IC 6671 if (!READ_FIELD(this, kTypeFeedbackInfoOffset)->IsSmi()) { 6672 WRITE_FIELD(this, kTypeFeedbackInfoOffset, NULL); 6673 } 6674 WRITE_FIELD(this, kNextCodeLinkOffset, NULL); 6675 WRITE_FIELD(this, kGCMetadataOffset, NULL); 6676 } 6677 6678 6679 Object* Code::type_feedback_info() { 6680 DCHECK(kind() == FUNCTION); 6681 return raw_type_feedback_info(); 6682 } 6683 6684 6685 void Code::set_type_feedback_info(Object* value, WriteBarrierMode mode) { 6686 DCHECK(kind() == FUNCTION); 6687 set_raw_type_feedback_info(value, mode); 6688 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset, 6689 value, mode); 6690 } 6691 6692 6693 uint32_t Code::stub_key() { 6694 DCHECK(IsCodeStubOrIC()); 6695 Smi* smi_key = Smi::cast(raw_type_feedback_info()); 6696 return static_cast<uint32_t>(smi_key->value()); 6697 } 6698 6699 6700 void Code::set_stub_key(uint32_t key) { 6701 DCHECK(IsCodeStubOrIC()); 6702 set_raw_type_feedback_info(Smi::FromInt(key)); 6703 } 6704 6705 6706 ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset) 6707 INT_ACCESSORS(Code, ic_age, kICAgeOffset) 6708 6709 6710 byte* Code::instruction_start() { 6711 return FIELD_ADDR(this, kHeaderSize); 6712 } 6713 6714 6715 byte* Code::instruction_end() { 6716 return instruction_start() + instruction_size(); 6717 } 6718 6719 int Code::GetUnwindingInfoSizeOffset() const { 6720 DCHECK(has_unwinding_info()); 6721 return RoundUp(kHeaderSize + instruction_size(), kInt64Size); 6722 } 6723 6724 int Code::unwinding_info_size() const { 6725 DCHECK(has_unwinding_info()); 6726 return static_cast<int>( 6727 READ_UINT64_FIELD(this, GetUnwindingInfoSizeOffset())); 6728 } 6729 6730 void Code::set_unwinding_info_size(int value) { 6731 DCHECK(has_unwinding_info()); 6732 WRITE_UINT64_FIELD(this, GetUnwindingInfoSizeOffset(), value); 6733 } 6734 6735 byte* Code::unwinding_info_start() { 6736 DCHECK(has_unwinding_info()); 6737 return FIELD_ADDR(this, GetUnwindingInfoSizeOffset()) + kInt64Size; 6738 } 6739 6740 byte* Code::unwinding_info_end() { 6741 DCHECK(has_unwinding_info()); 6742 return unwinding_info_start() + unwinding_info_size(); 6743 } 6744 6745 int Code::body_size() { 6746 int unpadded_body_size = 6747 has_unwinding_info() 6748 ? static_cast<int>(unwinding_info_end() - instruction_start()) 6749 : instruction_size(); 6750 return RoundUp(unpadded_body_size, kObjectAlignment); 6751 } 6752 6753 int Code::SizeIncludingMetadata() { 6754 int size = CodeSize(); 6755 size += relocation_info()->Size(); 6756 size += deoptimization_data()->Size(); 6757 size += handler_table()->Size(); 6758 if (kind() == FUNCTION) size += source_position_table()->Size(); 6759 return size; 6760 } 6761 6762 ByteArray* Code::unchecked_relocation_info() { 6763 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset)); 6764 } 6765 6766 6767 byte* Code::relocation_start() { 6768 return unchecked_relocation_info()->GetDataStartAddress(); 6769 } 6770 6771 6772 int Code::relocation_size() { 6773 return unchecked_relocation_info()->length(); 6774 } 6775 6776 6777 byte* Code::entry() { 6778 return instruction_start(); 6779 } 6780 6781 6782 bool Code::contains(byte* inner_pointer) { 6783 return (address() <= inner_pointer) && (inner_pointer <= address() + Size()); 6784 } 6785 6786 6787 int Code::ExecutableSize() { 6788 // Check that the assumptions about the layout of the code object holds. 6789 DCHECK_EQ(static_cast<int>(instruction_start() - address()), 6790 Code::kHeaderSize); 6791 return instruction_size() + Code::kHeaderSize; 6792 } 6793 6794 6795 int Code::CodeSize() { return SizeFor(body_size()); } 6796 6797 6798 ACCESSORS(JSArray, length, Object, kLengthOffset) 6799 6800 6801 void* JSArrayBuffer::backing_store() const { 6802 intptr_t ptr = READ_INTPTR_FIELD(this, kBackingStoreOffset); 6803 return reinterpret_cast<void*>(ptr); 6804 } 6805 6806 6807 void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) { 6808 intptr_t ptr = reinterpret_cast<intptr_t>(value); 6809 WRITE_INTPTR_FIELD(this, kBackingStoreOffset, ptr); 6810 } 6811 6812 6813 ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset) 6814 6815 6816 void JSArrayBuffer::set_bit_field(uint32_t bits) { 6817 if (kInt32Size != kPointerSize) { 6818 #if V8_TARGET_LITTLE_ENDIAN 6819 WRITE_UINT32_FIELD(this, kBitFieldSlot + kInt32Size, 0); 6820 #else 6821 WRITE_UINT32_FIELD(this, kBitFieldSlot, 0); 6822 #endif 6823 } 6824 WRITE_UINT32_FIELD(this, kBitFieldOffset, bits); 6825 } 6826 6827 6828 uint32_t JSArrayBuffer::bit_field() const { 6829 return READ_UINT32_FIELD(this, kBitFieldOffset); 6830 } 6831 6832 6833 bool JSArrayBuffer::is_external() { return IsExternal::decode(bit_field()); } 6834 6835 6836 void JSArrayBuffer::set_is_external(bool value) { 6837 DCHECK(!value || !has_guard_region()); 6838 set_bit_field(IsExternal::update(bit_field(), value)); 6839 } 6840 6841 6842 bool JSArrayBuffer::is_neuterable() { 6843 return IsNeuterable::decode(bit_field()); 6844 } 6845 6846 6847 void JSArrayBuffer::set_is_neuterable(bool value) { 6848 set_bit_field(IsNeuterable::update(bit_field(), value)); 6849 } 6850 6851 6852 bool JSArrayBuffer::was_neutered() { return WasNeutered::decode(bit_field()); } 6853 6854 6855 void JSArrayBuffer::set_was_neutered(bool value) { 6856 set_bit_field(WasNeutered::update(bit_field(), value)); 6857 } 6858 6859 6860 bool JSArrayBuffer::is_shared() { return IsShared::decode(bit_field()); } 6861 6862 6863 void JSArrayBuffer::set_is_shared(bool value) { 6864 set_bit_field(IsShared::update(bit_field(), value)); 6865 } 6866 6867 bool JSArrayBuffer::has_guard_region() { 6868 return HasGuardRegion::decode(bit_field()); 6869 } 6870 6871 void JSArrayBuffer::set_has_guard_region(bool value) { 6872 set_bit_field(HasGuardRegion::update(bit_field(), value)); 6873 } 6874 6875 Object* JSArrayBufferView::byte_offset() const { 6876 if (WasNeutered()) return Smi::kZero; 6877 return Object::cast(READ_FIELD(this, kByteOffsetOffset)); 6878 } 6879 6880 6881 void JSArrayBufferView::set_byte_offset(Object* value, WriteBarrierMode mode) { 6882 WRITE_FIELD(this, kByteOffsetOffset, value); 6883 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kByteOffsetOffset, value, mode); 6884 } 6885 6886 6887 Object* JSArrayBufferView::byte_length() const { 6888 if (WasNeutered()) return Smi::kZero; 6889 return Object::cast(READ_FIELD(this, kByteLengthOffset)); 6890 } 6891 6892 6893 void JSArrayBufferView::set_byte_length(Object* value, WriteBarrierMode mode) { 6894 WRITE_FIELD(this, kByteLengthOffset, value); 6895 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kByteLengthOffset, value, mode); 6896 } 6897 6898 6899 ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset) 6900 #ifdef VERIFY_HEAP 6901 ACCESSORS(JSArrayBufferView, raw_byte_offset, Object, kByteOffsetOffset) 6902 ACCESSORS(JSArrayBufferView, raw_byte_length, Object, kByteLengthOffset) 6903 #endif 6904 6905 6906 bool JSArrayBufferView::WasNeutered() const { 6907 return JSArrayBuffer::cast(buffer())->was_neutered(); 6908 } 6909 6910 6911 Object* JSTypedArray::length() const { 6912 if (WasNeutered()) return Smi::kZero; 6913 return Object::cast(READ_FIELD(this, kLengthOffset)); 6914 } 6915 6916 6917 uint32_t JSTypedArray::length_value() const { 6918 if (WasNeutered()) return 0; 6919 uint32_t index = 0; 6920 CHECK(Object::cast(READ_FIELD(this, kLengthOffset))->ToArrayLength(&index)); 6921 return index; 6922 } 6923 6924 6925 void JSTypedArray::set_length(Object* value, WriteBarrierMode mode) { 6926 WRITE_FIELD(this, kLengthOffset, value); 6927 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kLengthOffset, value, mode); 6928 } 6929 6930 // static 6931 MaybeHandle<JSTypedArray> JSTypedArray::Validate(Isolate* isolate, 6932 Handle<Object> receiver, 6933 const char* method_name) { 6934 if (V8_UNLIKELY(!receiver->IsJSTypedArray())) { 6935 const MessageTemplate::Template message = MessageTemplate::kNotTypedArray; 6936 THROW_NEW_ERROR(isolate, NewTypeError(message), JSTypedArray); 6937 } 6938 6939 // TODO(caitp): throw if array.[[ViewedArrayBuffer]] is neutered (per v8:4648) 6940 return Handle<JSTypedArray>::cast(receiver); 6941 } 6942 6943 #ifdef VERIFY_HEAP 6944 ACCESSORS(JSTypedArray, raw_length, Object, kLengthOffset) 6945 #endif 6946 6947 ACCESSORS(JSPromiseCapability, promise, Object, kPromiseOffset) 6948 ACCESSORS(JSPromiseCapability, resolve, Object, kResolveOffset) 6949 ACCESSORS(JSPromiseCapability, reject, Object, kRejectOffset) 6950 6951 SMI_ACCESSORS(JSPromise, status, kStatusOffset) 6952 ACCESSORS(JSPromise, result, Object, kResultOffset) 6953 ACCESSORS(JSPromise, deferred_promise, Object, kDeferredPromiseOffset) 6954 ACCESSORS(JSPromise, deferred_on_resolve, Object, kDeferredOnResolveOffset) 6955 ACCESSORS(JSPromise, deferred_on_reject, Object, kDeferredOnRejectOffset) 6956 ACCESSORS(JSPromise, fulfill_reactions, Object, kFulfillReactionsOffset) 6957 ACCESSORS(JSPromise, reject_reactions, Object, kRejectReactionsOffset) 6958 SMI_ACCESSORS(JSPromise, flags, kFlagsOffset) 6959 BOOL_ACCESSORS(JSPromise, flags, has_handler, kHasHandlerBit) 6960 BOOL_ACCESSORS(JSPromise, flags, handled_hint, kHandledHintBit) 6961 6962 ACCESSORS(JSRegExp, data, Object, kDataOffset) 6963 ACCESSORS(JSRegExp, flags, Object, kFlagsOffset) 6964 ACCESSORS(JSRegExp, source, Object, kSourceOffset) 6965 6966 6967 JSRegExp::Type JSRegExp::TypeTag() { 6968 Object* data = this->data(); 6969 if (data->IsUndefined(GetIsolate())) return JSRegExp::NOT_COMPILED; 6970 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex)); 6971 return static_cast<JSRegExp::Type>(smi->value()); 6972 } 6973 6974 6975 int JSRegExp::CaptureCount() { 6976 switch (TypeTag()) { 6977 case ATOM: 6978 return 0; 6979 case IRREGEXP: 6980 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value(); 6981 default: 6982 UNREACHABLE(); 6983 return -1; 6984 } 6985 } 6986 6987 6988 JSRegExp::Flags JSRegExp::GetFlags() { 6989 DCHECK(this->data()->IsFixedArray()); 6990 Object* data = this->data(); 6991 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex)); 6992 return Flags(smi->value()); 6993 } 6994 6995 6996 String* JSRegExp::Pattern() { 6997 DCHECK(this->data()->IsFixedArray()); 6998 Object* data = this->data(); 6999 String* pattern = String::cast(FixedArray::cast(data)->get(kSourceIndex)); 7000 return pattern; 7001 } 7002 7003 7004 Object* JSRegExp::DataAt(int index) { 7005 DCHECK(TypeTag() != NOT_COMPILED); 7006 return FixedArray::cast(data())->get(index); 7007 } 7008 7009 7010 void JSRegExp::SetDataAt(int index, Object* value) { 7011 DCHECK(TypeTag() != NOT_COMPILED); 7012 DCHECK(index >= kDataIndex); // Only implementation data can be set this way. 7013 FixedArray::cast(data())->set(index, value); 7014 } 7015 7016 void JSRegExp::SetLastIndex(int index) { 7017 static const int offset = 7018 kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; 7019 Smi* value = Smi::FromInt(index); 7020 WRITE_FIELD(this, offset, value); 7021 } 7022 7023 Object* JSRegExp::LastIndex() { 7024 static const int offset = 7025 kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; 7026 return READ_FIELD(this, offset); 7027 } 7028 7029 ElementsKind JSObject::GetElementsKind() { 7030 ElementsKind kind = map()->elements_kind(); 7031 #if VERIFY_HEAP && DEBUG 7032 FixedArrayBase* fixed_array = 7033 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset)); 7034 7035 // If a GC was caused while constructing this object, the elements 7036 // pointer may point to a one pointer filler map. 7037 if (ElementsAreSafeToExamine()) { 7038 Map* map = fixed_array->map(); 7039 if (IsFastSmiOrObjectElementsKind(kind)) { 7040 DCHECK(map == GetHeap()->fixed_array_map() || 7041 map == GetHeap()->fixed_cow_array_map()); 7042 } else if (IsFastDoubleElementsKind(kind)) { 7043 DCHECK(fixed_array->IsFixedDoubleArray() || 7044 fixed_array == GetHeap()->empty_fixed_array()); 7045 } else if (kind == DICTIONARY_ELEMENTS) { 7046 DCHECK(fixed_array->IsFixedArray()); 7047 DCHECK(fixed_array->IsDictionary()); 7048 } else { 7049 DCHECK(kind > DICTIONARY_ELEMENTS); 7050 } 7051 DCHECK(!IsSloppyArgumentsElements(kind) || 7052 (elements()->IsFixedArray() && elements()->length() >= 2)); 7053 } 7054 #endif 7055 return kind; 7056 } 7057 7058 7059 bool JSObject::HasFastObjectElements() { 7060 return IsFastObjectElementsKind(GetElementsKind()); 7061 } 7062 7063 7064 bool JSObject::HasFastSmiElements() { 7065 return IsFastSmiElementsKind(GetElementsKind()); 7066 } 7067 7068 7069 bool JSObject::HasFastSmiOrObjectElements() { 7070 return IsFastSmiOrObjectElementsKind(GetElementsKind()); 7071 } 7072 7073 7074 bool JSObject::HasFastDoubleElements() { 7075 return IsFastDoubleElementsKind(GetElementsKind()); 7076 } 7077 7078 7079 bool JSObject::HasFastHoleyElements() { 7080 return IsFastHoleyElementsKind(GetElementsKind()); 7081 } 7082 7083 7084 bool JSObject::HasFastElements() { 7085 return IsFastElementsKind(GetElementsKind()); 7086 } 7087 7088 7089 bool JSObject::HasDictionaryElements() { 7090 return GetElementsKind() == DICTIONARY_ELEMENTS; 7091 } 7092 7093 7094 bool JSObject::HasFastArgumentsElements() { 7095 return GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS; 7096 } 7097 7098 7099 bool JSObject::HasSlowArgumentsElements() { 7100 return GetElementsKind() == SLOW_SLOPPY_ARGUMENTS_ELEMENTS; 7101 } 7102 7103 7104 bool JSObject::HasSloppyArgumentsElements() { 7105 return IsSloppyArgumentsElements(GetElementsKind()); 7106 } 7107 7108 bool JSObject::HasStringWrapperElements() { 7109 return IsStringWrapperElementsKind(GetElementsKind()); 7110 } 7111 7112 bool JSObject::HasFastStringWrapperElements() { 7113 return GetElementsKind() == FAST_STRING_WRAPPER_ELEMENTS; 7114 } 7115 7116 bool JSObject::HasSlowStringWrapperElements() { 7117 return GetElementsKind() == SLOW_STRING_WRAPPER_ELEMENTS; 7118 } 7119 7120 bool JSObject::HasFixedTypedArrayElements() { 7121 DCHECK_NOT_NULL(elements()); 7122 return map()->has_fixed_typed_array_elements(); 7123 } 7124 7125 #define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype, size) \ 7126 bool JSObject::HasFixed##Type##Elements() { \ 7127 HeapObject* array = elements(); \ 7128 DCHECK(array != NULL); \ 7129 if (!array->IsHeapObject()) return false; \ 7130 return array->map()->instance_type() == FIXED_##TYPE##_ARRAY_TYPE; \ 7131 } 7132 7133 TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK) 7134 7135 #undef FIXED_TYPED_ELEMENTS_CHECK 7136 7137 7138 bool JSObject::HasNamedInterceptor() { 7139 return map()->has_named_interceptor(); 7140 } 7141 7142 7143 bool JSObject::HasIndexedInterceptor() { 7144 return map()->has_indexed_interceptor(); 7145 } 7146 7147 7148 GlobalDictionary* JSObject::global_dictionary() { 7149 DCHECK(!HasFastProperties()); 7150 DCHECK(IsJSGlobalObject()); 7151 return GlobalDictionary::cast(properties()); 7152 } 7153 7154 7155 SeededNumberDictionary* JSObject::element_dictionary() { 7156 DCHECK(HasDictionaryElements() || HasSlowStringWrapperElements()); 7157 return SeededNumberDictionary::cast(elements()); 7158 } 7159 7160 7161 bool Name::IsHashFieldComputed(uint32_t field) { 7162 return (field & kHashNotComputedMask) == 0; 7163 } 7164 7165 7166 bool Name::HasHashCode() { 7167 return IsHashFieldComputed(hash_field()); 7168 } 7169 7170 7171 uint32_t Name::Hash() { 7172 // Fast case: has hash code already been computed? 7173 uint32_t field = hash_field(); 7174 if (IsHashFieldComputed(field)) return field >> kHashShift; 7175 // Slow case: compute hash code and set it. Has to be a string. 7176 return String::cast(this)->ComputeAndSetHash(); 7177 } 7178 7179 7180 bool Name::IsPrivate() { 7181 return this->IsSymbol() && Symbol::cast(this)->is_private(); 7182 } 7183 7184 7185 StringHasher::StringHasher(int length, uint32_t seed) 7186 : length_(length), 7187 raw_running_hash_(seed), 7188 array_index_(0), 7189 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize), 7190 is_first_char_(true) { 7191 DCHECK(FLAG_randomize_hashes || raw_running_hash_ == 0); 7192 } 7193 7194 7195 bool StringHasher::has_trivial_hash() { 7196 return length_ > String::kMaxHashCalcLength; 7197 } 7198 7199 7200 uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) { 7201 running_hash += c; 7202 running_hash += (running_hash << 10); 7203 running_hash ^= (running_hash >> 6); 7204 return running_hash; 7205 } 7206 7207 7208 uint32_t StringHasher::GetHashCore(uint32_t running_hash) { 7209 running_hash += (running_hash << 3); 7210 running_hash ^= (running_hash >> 11); 7211 running_hash += (running_hash << 15); 7212 if ((running_hash & String::kHashBitMask) == 0) { 7213 return kZeroHash; 7214 } 7215 return running_hash; 7216 } 7217 7218 7219 uint32_t StringHasher::ComputeRunningHash(uint32_t running_hash, 7220 const uc16* chars, int length) { 7221 DCHECK_NOT_NULL(chars); 7222 DCHECK(length >= 0); 7223 for (int i = 0; i < length; ++i) { 7224 running_hash = AddCharacterCore(running_hash, *chars++); 7225 } 7226 return running_hash; 7227 } 7228 7229 7230 uint32_t StringHasher::ComputeRunningHashOneByte(uint32_t running_hash, 7231 const char* chars, 7232 int length) { 7233 DCHECK_NOT_NULL(chars); 7234 DCHECK(length >= 0); 7235 for (int i = 0; i < length; ++i) { 7236 uint16_t c = static_cast<uint16_t>(*chars++); 7237 running_hash = AddCharacterCore(running_hash, c); 7238 } 7239 return running_hash; 7240 } 7241 7242 7243 void StringHasher::AddCharacter(uint16_t c) { 7244 // Use the Jenkins one-at-a-time hash function to update the hash 7245 // for the given character. 7246 raw_running_hash_ = AddCharacterCore(raw_running_hash_, c); 7247 } 7248 7249 7250 bool StringHasher::UpdateIndex(uint16_t c) { 7251 DCHECK(is_array_index_); 7252 if (c < '0' || c > '9') { 7253 is_array_index_ = false; 7254 return false; 7255 } 7256 int d = c - '0'; 7257 if (is_first_char_) { 7258 is_first_char_ = false; 7259 if (c == '0' && length_ > 1) { 7260 is_array_index_ = false; 7261 return false; 7262 } 7263 } 7264 if (array_index_ > 429496729U - ((d + 3) >> 3)) { 7265 is_array_index_ = false; 7266 return false; 7267 } 7268 array_index_ = array_index_ * 10 + d; 7269 return true; 7270 } 7271 7272 7273 template<typename Char> 7274 inline void StringHasher::AddCharacters(const Char* chars, int length) { 7275 DCHECK(sizeof(Char) == 1 || sizeof(Char) == 2); 7276 int i = 0; 7277 if (is_array_index_) { 7278 for (; i < length; i++) { 7279 AddCharacter(chars[i]); 7280 if (!UpdateIndex(chars[i])) { 7281 i++; 7282 break; 7283 } 7284 } 7285 } 7286 for (; i < length; i++) { 7287 DCHECK(!is_array_index_); 7288 AddCharacter(chars[i]); 7289 } 7290 } 7291 7292 7293 template <typename schar> 7294 uint32_t StringHasher::HashSequentialString(const schar* chars, 7295 int length, 7296 uint32_t seed) { 7297 StringHasher hasher(length, seed); 7298 if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length); 7299 return hasher.GetHashField(); 7300 } 7301 7302 7303 IteratingStringHasher::IteratingStringHasher(int len, uint32_t seed) 7304 : StringHasher(len, seed) {} 7305 7306 7307 uint32_t IteratingStringHasher::Hash(String* string, uint32_t seed) { 7308 IteratingStringHasher hasher(string->length(), seed); 7309 // Nothing to do. 7310 if (hasher.has_trivial_hash()) return hasher.GetHashField(); 7311 ConsString* cons_string = String::VisitFlat(&hasher, string); 7312 if (cons_string == nullptr) return hasher.GetHashField(); 7313 hasher.VisitConsString(cons_string); 7314 return hasher.GetHashField(); 7315 } 7316 7317 7318 void IteratingStringHasher::VisitOneByteString(const uint8_t* chars, 7319 int length) { 7320 AddCharacters(chars, length); 7321 } 7322 7323 7324 void IteratingStringHasher::VisitTwoByteString(const uint16_t* chars, 7325 int length) { 7326 AddCharacters(chars, length); 7327 } 7328 7329 7330 bool Name::AsArrayIndex(uint32_t* index) { 7331 return IsString() && String::cast(this)->AsArrayIndex(index); 7332 } 7333 7334 7335 bool String::AsArrayIndex(uint32_t* index) { 7336 uint32_t field = hash_field(); 7337 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) { 7338 return false; 7339 } 7340 return SlowAsArrayIndex(index); 7341 } 7342 7343 7344 void String::SetForwardedInternalizedString(String* canonical) { 7345 DCHECK(IsInternalizedString()); 7346 DCHECK(HasHashCode()); 7347 if (canonical == this) return; // No need to forward. 7348 DCHECK(SlowEquals(canonical)); 7349 DCHECK(canonical->IsInternalizedString()); 7350 DCHECK(canonical->HasHashCode()); 7351 WRITE_FIELD(this, kHashFieldSlot, canonical); 7352 // Setting the hash field to a tagged value sets the LSB, causing the hash 7353 // code to be interpreted as uninitialized. We use this fact to recognize 7354 // that we have a forwarded string. 7355 DCHECK(!HasHashCode()); 7356 } 7357 7358 7359 String* String::GetForwardedInternalizedString() { 7360 DCHECK(IsInternalizedString()); 7361 if (HasHashCode()) return this; 7362 String* canonical = String::cast(READ_FIELD(this, kHashFieldSlot)); 7363 DCHECK(canonical->IsInternalizedString()); 7364 DCHECK(SlowEquals(canonical)); 7365 DCHECK(canonical->HasHashCode()); 7366 return canonical; 7367 } 7368 7369 7370 // static 7371 Maybe<bool> Object::GreaterThan(Handle<Object> x, Handle<Object> y) { 7372 Maybe<ComparisonResult> result = Compare(x, y); 7373 if (result.IsJust()) { 7374 switch (result.FromJust()) { 7375 case ComparisonResult::kGreaterThan: 7376 return Just(true); 7377 case ComparisonResult::kLessThan: 7378 case ComparisonResult::kEqual: 7379 case ComparisonResult::kUndefined: 7380 return Just(false); 7381 } 7382 } 7383 return Nothing<bool>(); 7384 } 7385 7386 7387 // static 7388 Maybe<bool> Object::GreaterThanOrEqual(Handle<Object> x, Handle<Object> y) { 7389 Maybe<ComparisonResult> result = Compare(x, y); 7390 if (result.IsJust()) { 7391 switch (result.FromJust()) { 7392 case ComparisonResult::kEqual: 7393 case ComparisonResult::kGreaterThan: 7394 return Just(true); 7395 case ComparisonResult::kLessThan: 7396 case ComparisonResult::kUndefined: 7397 return Just(false); 7398 } 7399 } 7400 return Nothing<bool>(); 7401 } 7402 7403 7404 // static 7405 Maybe<bool> Object::LessThan(Handle<Object> x, Handle<Object> y) { 7406 Maybe<ComparisonResult> result = Compare(x, y); 7407 if (result.IsJust()) { 7408 switch (result.FromJust()) { 7409 case ComparisonResult::kLessThan: 7410 return Just(true); 7411 case ComparisonResult::kEqual: 7412 case ComparisonResult::kGreaterThan: 7413 case ComparisonResult::kUndefined: 7414 return Just(false); 7415 } 7416 } 7417 return Nothing<bool>(); 7418 } 7419 7420 7421 // static 7422 Maybe<bool> Object::LessThanOrEqual(Handle<Object> x, Handle<Object> y) { 7423 Maybe<ComparisonResult> result = Compare(x, y); 7424 if (result.IsJust()) { 7425 switch (result.FromJust()) { 7426 case ComparisonResult::kEqual: 7427 case ComparisonResult::kLessThan: 7428 return Just(true); 7429 case ComparisonResult::kGreaterThan: 7430 case ComparisonResult::kUndefined: 7431 return Just(false); 7432 } 7433 } 7434 return Nothing<bool>(); 7435 } 7436 7437 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object, 7438 Handle<Name> name) { 7439 LookupIterator it = 7440 LookupIterator::PropertyOrElement(name->GetIsolate(), object, name); 7441 return GetProperty(&it); 7442 } 7443 7444 MaybeHandle<Object> Object::SetPropertyOrElement(Handle<Object> object, 7445 Handle<Name> name, 7446 Handle<Object> value, 7447 LanguageMode language_mode, 7448 StoreFromKeyed store_mode) { 7449 LookupIterator it = 7450 LookupIterator::PropertyOrElement(name->GetIsolate(), object, name); 7451 MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode)); 7452 return value; 7453 } 7454 7455 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver, 7456 Handle<Name> name, 7457 Handle<JSReceiver> holder) { 7458 LookupIterator it = LookupIterator::PropertyOrElement( 7459 name->GetIsolate(), receiver, name, holder); 7460 return GetProperty(&it); 7461 } 7462 7463 7464 void JSReceiver::initialize_properties() { 7465 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); 7466 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_properties_dictionary())); 7467 if (map()->is_dictionary_map()) { 7468 WRITE_FIELD(this, kPropertiesOffset, 7469 GetHeap()->empty_properties_dictionary()); 7470 } else { 7471 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); 7472 } 7473 } 7474 7475 7476 bool JSReceiver::HasFastProperties() { 7477 DCHECK_EQ(properties()->IsDictionary(), map()->is_dictionary_map()); 7478 return !properties()->IsDictionary(); 7479 } 7480 7481 7482 NameDictionary* JSReceiver::property_dictionary() { 7483 DCHECK(!HasFastProperties()); 7484 DCHECK(!IsJSGlobalObject()); 7485 return NameDictionary::cast(properties()); 7486 } 7487 7488 Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object, 7489 Handle<Name> name) { 7490 LookupIterator it = LookupIterator::PropertyOrElement(object->GetIsolate(), 7491 object, name, object); 7492 return HasProperty(&it); 7493 } 7494 7495 7496 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object, 7497 Handle<Name> name) { 7498 if (object->IsJSObject()) { // Shortcut 7499 LookupIterator it = LookupIterator::PropertyOrElement( 7500 object->GetIsolate(), object, name, object, LookupIterator::OWN); 7501 return HasProperty(&it); 7502 } 7503 7504 Maybe<PropertyAttributes> attributes = 7505 JSReceiver::GetOwnPropertyAttributes(object, name); 7506 MAYBE_RETURN(attributes, Nothing<bool>()); 7507 return Just(attributes.FromJust() != ABSENT); 7508 } 7509 7510 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object, 7511 uint32_t index) { 7512 if (object->IsJSObject()) { // Shortcut 7513 LookupIterator it(object->GetIsolate(), object, index, object, 7514 LookupIterator::OWN); 7515 return HasProperty(&it); 7516 } 7517 7518 Maybe<PropertyAttributes> attributes = 7519 JSReceiver::GetOwnPropertyAttributes(object, index); 7520 MAYBE_RETURN(attributes, Nothing<bool>()); 7521 return Just(attributes.FromJust() != ABSENT); 7522 } 7523 7524 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes( 7525 Handle<JSReceiver> object, Handle<Name> name) { 7526 LookupIterator it = LookupIterator::PropertyOrElement(name->GetIsolate(), 7527 object, name, object); 7528 return GetPropertyAttributes(&it); 7529 } 7530 7531 7532 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes( 7533 Handle<JSReceiver> object, Handle<Name> name) { 7534 LookupIterator it = LookupIterator::PropertyOrElement( 7535 name->GetIsolate(), object, name, object, LookupIterator::OWN); 7536 return GetPropertyAttributes(&it); 7537 } 7538 7539 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes( 7540 Handle<JSReceiver> object, uint32_t index) { 7541 LookupIterator it(object->GetIsolate(), object, index, object, 7542 LookupIterator::OWN); 7543 return GetPropertyAttributes(&it); 7544 } 7545 7546 Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) { 7547 LookupIterator it(object->GetIsolate(), object, index, object); 7548 return HasProperty(&it); 7549 } 7550 7551 7552 Maybe<PropertyAttributes> JSReceiver::GetElementAttributes( 7553 Handle<JSReceiver> object, uint32_t index) { 7554 Isolate* isolate = object->GetIsolate(); 7555 LookupIterator it(isolate, object, index, object); 7556 return GetPropertyAttributes(&it); 7557 } 7558 7559 7560 Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttributes( 7561 Handle<JSReceiver> object, uint32_t index) { 7562 Isolate* isolate = object->GetIsolate(); 7563 LookupIterator it(isolate, object, index, object, LookupIterator::OWN); 7564 return GetPropertyAttributes(&it); 7565 } 7566 7567 7568 bool JSGlobalObject::IsDetached() { 7569 return JSGlobalProxy::cast(global_proxy())->IsDetachedFrom(this); 7570 } 7571 7572 7573 bool JSGlobalProxy::IsDetachedFrom(JSGlobalObject* global) const { 7574 const PrototypeIterator iter(this->GetIsolate(), 7575 const_cast<JSGlobalProxy*>(this)); 7576 return iter.GetCurrent() != global; 7577 } 7578 7579 inline int JSGlobalProxy::SizeWithInternalFields(int internal_field_count) { 7580 DCHECK_GE(internal_field_count, 0); 7581 return kSize + internal_field_count * kPointerSize; 7582 } 7583 7584 Smi* JSReceiver::GetOrCreateIdentityHash(Isolate* isolate, 7585 Handle<JSReceiver> object) { 7586 return object->IsJSProxy() ? JSProxy::GetOrCreateIdentityHash( 7587 isolate, Handle<JSProxy>::cast(object)) 7588 : JSObject::GetOrCreateIdentityHash( 7589 isolate, Handle<JSObject>::cast(object)); 7590 } 7591 7592 Object* JSReceiver::GetIdentityHash(Isolate* isolate, 7593 Handle<JSReceiver> receiver) { 7594 return receiver->IsJSProxy() 7595 ? JSProxy::GetIdentityHash(Handle<JSProxy>::cast(receiver)) 7596 : JSObject::GetIdentityHash(isolate, 7597 Handle<JSObject>::cast(receiver)); 7598 } 7599 7600 7601 bool AccessorInfo::all_can_read() { 7602 return BooleanBit::get(flag(), kAllCanReadBit); 7603 } 7604 7605 7606 void AccessorInfo::set_all_can_read(bool value) { 7607 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value)); 7608 } 7609 7610 7611 bool AccessorInfo::all_can_write() { 7612 return BooleanBit::get(flag(), kAllCanWriteBit); 7613 } 7614 7615 7616 void AccessorInfo::set_all_can_write(bool value) { 7617 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value)); 7618 } 7619 7620 7621 bool AccessorInfo::is_special_data_property() { 7622 return BooleanBit::get(flag(), kSpecialDataProperty); 7623 } 7624 7625 7626 void AccessorInfo::set_is_special_data_property(bool value) { 7627 set_flag(BooleanBit::set(flag(), kSpecialDataProperty, value)); 7628 } 7629 7630 bool AccessorInfo::replace_on_access() { 7631 return BooleanBit::get(flag(), kReplaceOnAccess); 7632 } 7633 7634 void AccessorInfo::set_replace_on_access(bool value) { 7635 set_flag(BooleanBit::set(flag(), kReplaceOnAccess, value)); 7636 } 7637 7638 bool AccessorInfo::is_sloppy() { return BooleanBit::get(flag(), kIsSloppy); } 7639 7640 void AccessorInfo::set_is_sloppy(bool value) { 7641 set_flag(BooleanBit::set(flag(), kIsSloppy, value)); 7642 } 7643 7644 PropertyAttributes AccessorInfo::property_attributes() { 7645 return AttributesField::decode(static_cast<uint32_t>(flag())); 7646 } 7647 7648 7649 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) { 7650 set_flag(AttributesField::update(flag(), attributes)); 7651 } 7652 7653 bool FunctionTemplateInfo::IsTemplateFor(JSObject* object) { 7654 return IsTemplateFor(object->map()); 7655 } 7656 7657 bool AccessorInfo::IsCompatibleReceiver(Object* receiver) { 7658 if (!HasExpectedReceiverType()) return true; 7659 if (!receiver->IsJSObject()) return false; 7660 return FunctionTemplateInfo::cast(expected_receiver_type()) 7661 ->IsTemplateFor(JSObject::cast(receiver)->map()); 7662 } 7663 7664 7665 bool AccessorInfo::HasExpectedReceiverType() { 7666 return expected_receiver_type()->IsFunctionTemplateInfo(); 7667 } 7668 7669 7670 Object* AccessorPair::get(AccessorComponent component) { 7671 return component == ACCESSOR_GETTER ? getter() : setter(); 7672 } 7673 7674 7675 void AccessorPair::set(AccessorComponent component, Object* value) { 7676 if (component == ACCESSOR_GETTER) { 7677 set_getter(value); 7678 } else { 7679 set_setter(value); 7680 } 7681 } 7682 7683 7684 void AccessorPair::SetComponents(Object* getter, Object* setter) { 7685 Isolate* isolate = GetIsolate(); 7686 if (!getter->IsNull(isolate)) set_getter(getter); 7687 if (!setter->IsNull(isolate)) set_setter(setter); 7688 } 7689 7690 7691 bool AccessorPair::Equals(AccessorPair* pair) { 7692 return (this == pair) || pair->Equals(getter(), setter()); 7693 } 7694 7695 7696 bool AccessorPair::Equals(Object* getter_value, Object* setter_value) { 7697 return (getter() == getter_value) && (setter() == setter_value); 7698 } 7699 7700 7701 bool AccessorPair::ContainsAccessor() { 7702 return IsJSAccessor(getter()) || IsJSAccessor(setter()); 7703 } 7704 7705 7706 bool AccessorPair::IsJSAccessor(Object* obj) { 7707 return obj->IsCallable() || obj->IsUndefined(GetIsolate()); 7708 } 7709 7710 7711 template<typename Derived, typename Shape, typename Key> 7712 void Dictionary<Derived, Shape, Key>::SetEntry(int entry, 7713 Handle<Object> key, 7714 Handle<Object> value) { 7715 this->SetEntry(entry, key, value, PropertyDetails(Smi::kZero)); 7716 } 7717 7718 7719 template<typename Derived, typename Shape, typename Key> 7720 void Dictionary<Derived, Shape, Key>::SetEntry(int entry, 7721 Handle<Object> key, 7722 Handle<Object> value, 7723 PropertyDetails details) { 7724 Shape::SetEntry(static_cast<Derived*>(this), entry, key, value, details); 7725 } 7726 7727 7728 template <typename Key> 7729 template <typename Dictionary> 7730 void BaseDictionaryShape<Key>::SetEntry(Dictionary* dict, int entry, 7731 Handle<Object> key, 7732 Handle<Object> value, 7733 PropertyDetails details) { 7734 STATIC_ASSERT(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3); 7735 DCHECK(!key->IsName() || details.dictionary_index() > 0); 7736 int index = dict->EntryToIndex(entry); 7737 DisallowHeapAllocation no_gc; 7738 WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc); 7739 dict->set(index + Dictionary::kEntryKeyIndex, *key, mode); 7740 dict->set(index + Dictionary::kEntryValueIndex, *value, mode); 7741 if (Dictionary::kEntrySize == 3) { 7742 dict->set(index + Dictionary::kEntryDetailsIndex, details.AsSmi()); 7743 } 7744 } 7745 7746 7747 template <typename Dictionary> 7748 void GlobalDictionaryShape::SetEntry(Dictionary* dict, int entry, 7749 Handle<Object> key, Handle<Object> value, 7750 PropertyDetails details) { 7751 STATIC_ASSERT(Dictionary::kEntrySize == 2); 7752 DCHECK(!key->IsName() || details.dictionary_index() > 0); 7753 DCHECK(value->IsPropertyCell()); 7754 int index = dict->EntryToIndex(entry); 7755 DisallowHeapAllocation no_gc; 7756 WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc); 7757 dict->set(index + Dictionary::kEntryKeyIndex, *key, mode); 7758 dict->set(index + Dictionary::kEntryValueIndex, *value, mode); 7759 PropertyCell::cast(*value)->set_property_details(details); 7760 } 7761 7762 7763 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { 7764 DCHECK(other->IsNumber()); 7765 return key == static_cast<uint32_t>(other->Number()); 7766 } 7767 7768 7769 uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) { 7770 return ComputeIntegerHash(key, 0); 7771 } 7772 7773 7774 uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key, 7775 Object* other) { 7776 DCHECK(other->IsNumber()); 7777 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0); 7778 } 7779 7780 Map* UnseededNumberDictionaryShape::GetMap(Isolate* isolate) { 7781 return isolate->heap()->unseeded_number_dictionary_map(); 7782 } 7783 7784 uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) { 7785 return ComputeIntegerHash(key, seed); 7786 } 7787 7788 7789 uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key, 7790 uint32_t seed, 7791 Object* other) { 7792 DCHECK(other->IsNumber()); 7793 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed); 7794 } 7795 7796 7797 Handle<Object> NumberDictionaryShape::AsHandle(Isolate* isolate, uint32_t key) { 7798 return isolate->factory()->NewNumberFromUint(key); 7799 } 7800 7801 7802 bool NameDictionaryShape::IsMatch(Handle<Name> key, Object* other) { 7803 // We know that all entries in a hash table had their hash keys created. 7804 // Use that knowledge to have fast failure. 7805 if (key->Hash() != Name::cast(other)->Hash()) return false; 7806 return key->Equals(Name::cast(other)); 7807 } 7808 7809 7810 uint32_t NameDictionaryShape::Hash(Handle<Name> key) { 7811 return key->Hash(); 7812 } 7813 7814 7815 uint32_t NameDictionaryShape::HashForObject(Handle<Name> key, Object* other) { 7816 return Name::cast(other)->Hash(); 7817 } 7818 7819 7820 Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate, 7821 Handle<Name> key) { 7822 DCHECK(key->IsUniqueName()); 7823 return key; 7824 } 7825 7826 7827 Handle<FixedArray> NameDictionary::DoGenerateNewEnumerationIndices( 7828 Handle<NameDictionary> dictionary) { 7829 return DerivedDictionary::GenerateNewEnumerationIndices(dictionary); 7830 } 7831 7832 7833 template <typename Dictionary> 7834 PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary* dict, int entry) { 7835 DCHECK(entry >= 0); // Not found is -1, which is not caught by get(). 7836 Object* raw_value = dict->ValueAt(entry); 7837 DCHECK(raw_value->IsPropertyCell()); 7838 PropertyCell* cell = PropertyCell::cast(raw_value); 7839 return cell->property_details(); 7840 } 7841 7842 7843 template <typename Dictionary> 7844 void GlobalDictionaryShape::DetailsAtPut(Dictionary* dict, int entry, 7845 PropertyDetails value) { 7846 DCHECK(entry >= 0); // Not found is -1, which is not caught by get(). 7847 Object* raw_value = dict->ValueAt(entry); 7848 DCHECK(raw_value->IsPropertyCell()); 7849 PropertyCell* cell = PropertyCell::cast(raw_value); 7850 cell->set_property_details(value); 7851 } 7852 7853 7854 template <typename Dictionary> 7855 bool GlobalDictionaryShape::IsDeleted(Dictionary* dict, int entry) { 7856 DCHECK(dict->ValueAt(entry)->IsPropertyCell()); 7857 Isolate* isolate = dict->GetIsolate(); 7858 return PropertyCell::cast(dict->ValueAt(entry))->value()->IsTheHole(isolate); 7859 } 7860 7861 7862 bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object* other) { 7863 return key->SameValue(other); 7864 } 7865 7866 7867 uint32_t ObjectHashTableShape::Hash(Handle<Object> key) { 7868 return Smi::cast(key->GetHash())->value(); 7869 } 7870 7871 7872 uint32_t ObjectHashTableShape::HashForObject(Handle<Object> key, 7873 Object* other) { 7874 return Smi::cast(other->GetHash())->value(); 7875 } 7876 7877 7878 Handle<Object> ObjectHashTableShape::AsHandle(Isolate* isolate, 7879 Handle<Object> key) { 7880 return key; 7881 } 7882 7883 7884 Handle<ObjectHashTable> ObjectHashTable::Shrink( 7885 Handle<ObjectHashTable> table, Handle<Object> key) { 7886 return DerivedHashTable::Shrink(table, key); 7887 } 7888 7889 7890 Object* OrderedHashMap::ValueAt(int entry) { 7891 return get(EntryToIndex(entry) + kValueOffset); 7892 } 7893 7894 7895 template <int entrysize> 7896 bool WeakHashTableShape<entrysize>::IsMatch(Handle<Object> key, Object* other) { 7897 if (other->IsWeakCell()) other = WeakCell::cast(other)->value(); 7898 return key->IsWeakCell() ? WeakCell::cast(*key)->value() == other 7899 : *key == other; 7900 } 7901 7902 7903 template <int entrysize> 7904 uint32_t WeakHashTableShape<entrysize>::Hash(Handle<Object> key) { 7905 intptr_t hash = 7906 key->IsWeakCell() 7907 ? reinterpret_cast<intptr_t>(WeakCell::cast(*key)->value()) 7908 : reinterpret_cast<intptr_t>(*key); 7909 return (uint32_t)(hash & 0xFFFFFFFF); 7910 } 7911 7912 7913 template <int entrysize> 7914 uint32_t WeakHashTableShape<entrysize>::HashForObject(Handle<Object> key, 7915 Object* other) { 7916 if (other->IsWeakCell()) other = WeakCell::cast(other)->value(); 7917 intptr_t hash = reinterpret_cast<intptr_t>(other); 7918 return (uint32_t)(hash & 0xFFFFFFFF); 7919 } 7920 7921 7922 template <int entrysize> 7923 Handle<Object> WeakHashTableShape<entrysize>::AsHandle(Isolate* isolate, 7924 Handle<Object> key) { 7925 return key; 7926 } 7927 7928 7929 ACCESSORS(ModuleInfoEntry, export_name, Object, kExportNameOffset) 7930 ACCESSORS(ModuleInfoEntry, local_name, Object, kLocalNameOffset) 7931 ACCESSORS(ModuleInfoEntry, import_name, Object, kImportNameOffset) 7932 SMI_ACCESSORS(ModuleInfoEntry, module_request, kModuleRequestOffset) 7933 SMI_ACCESSORS(ModuleInfoEntry, cell_index, kCellIndexOffset) 7934 SMI_ACCESSORS(ModuleInfoEntry, beg_pos, kBegPosOffset) 7935 SMI_ACCESSORS(ModuleInfoEntry, end_pos, kEndPosOffset) 7936 7937 void Map::ClearCodeCache(Heap* heap) { 7938 // No write barrier is needed since empty_fixed_array is not in new space. 7939 // Please note this function is used during marking: 7940 // - MarkCompactCollector::MarkUnmarkedObject 7941 // - IncrementalMarking::Step 7942 WRITE_FIELD(this, kCodeCacheOffset, heap->empty_fixed_array()); 7943 } 7944 7945 7946 int Map::SlackForArraySize(int old_size, int size_limit) { 7947 const int max_slack = size_limit - old_size; 7948 CHECK_LE(0, max_slack); 7949 if (old_size < 4) { 7950 DCHECK_LE(1, max_slack); 7951 return 1; 7952 } 7953 return Min(max_slack, old_size / 4); 7954 } 7955 7956 7957 void JSArray::set_length(Smi* length) { 7958 // Don't need a write barrier for a Smi. 7959 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER); 7960 } 7961 7962 7963 bool JSArray::SetLengthWouldNormalize(Heap* heap, uint32_t new_length) { 7964 // This constant is somewhat arbitrary. Any large enough value would work. 7965 const uint32_t kMaxFastArrayLength = 32 * 1024 * 1024; 7966 // If the new array won't fit in a some non-trivial fraction of the max old 7967 // space size, then force it to go dictionary mode. 7968 uint32_t heap_based_upper_bound = 7969 static_cast<uint32_t>((heap->MaxOldGenerationSize() / kDoubleSize) / 4); 7970 return new_length >= Min(kMaxFastArrayLength, heap_based_upper_bound); 7971 } 7972 7973 7974 bool JSArray::AllowsSetLength() { 7975 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray(); 7976 DCHECK(result == !HasFixedTypedArrayElements()); 7977 return result; 7978 } 7979 7980 7981 void JSArray::SetContent(Handle<JSArray> array, 7982 Handle<FixedArrayBase> storage) { 7983 EnsureCanContainElements(array, storage, storage->length(), 7984 ALLOW_COPIED_DOUBLE_ELEMENTS); 7985 7986 DCHECK((storage->map() == array->GetHeap()->fixed_double_array_map() && 7987 IsFastDoubleElementsKind(array->GetElementsKind())) || 7988 ((storage->map() != array->GetHeap()->fixed_double_array_map()) && 7989 (IsFastObjectElementsKind(array->GetElementsKind()) || 7990 (IsFastSmiElementsKind(array->GetElementsKind()) && 7991 Handle<FixedArray>::cast(storage)->ContainsOnlySmisOrHoles())))); 7992 array->set_elements(*storage); 7993 array->set_length(Smi::FromInt(storage->length())); 7994 } 7995 7996 7997 bool JSArray::HasArrayPrototype(Isolate* isolate) { 7998 return map()->prototype() == *isolate->initial_array_prototype(); 7999 } 8000 8001 8002 int TypeFeedbackInfo::ic_total_count() { 8003 int current = Smi::cast(READ_FIELD(this, kStorage1Offset))->value(); 8004 return ICTotalCountField::decode(current); 8005 } 8006 8007 8008 void TypeFeedbackInfo::set_ic_total_count(int count) { 8009 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value(); 8010 value = ICTotalCountField::update(value, 8011 ICTotalCountField::decode(count)); 8012 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value)); 8013 } 8014 8015 8016 int TypeFeedbackInfo::ic_with_type_info_count() { 8017 int current = Smi::cast(READ_FIELD(this, kStorage2Offset))->value(); 8018 return ICsWithTypeInfoCountField::decode(current); 8019 } 8020 8021 8022 void TypeFeedbackInfo::change_ic_with_type_info_count(int delta) { 8023 if (delta == 0) return; 8024 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value(); 8025 int new_count = ICsWithTypeInfoCountField::decode(value) + delta; 8026 // We can get negative count here when the type-feedback info is 8027 // shared between two code objects. The can only happen when 8028 // the debugger made a shallow copy of code object (see Heap::CopyCode). 8029 // Since we do not optimize when the debugger is active, we can skip 8030 // this counter update. 8031 if (new_count >= 0) { 8032 new_count &= ICsWithTypeInfoCountField::kMask; 8033 value = ICsWithTypeInfoCountField::update(value, new_count); 8034 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value)); 8035 } 8036 } 8037 8038 8039 int TypeFeedbackInfo::ic_generic_count() { 8040 return Smi::cast(READ_FIELD(this, kStorage3Offset))->value(); 8041 } 8042 8043 8044 void TypeFeedbackInfo::change_ic_generic_count(int delta) { 8045 if (delta == 0) return; 8046 int new_count = ic_generic_count() + delta; 8047 if (new_count >= 0) { 8048 new_count &= ~Smi::kMinValue; 8049 WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(new_count)); 8050 } 8051 } 8052 8053 8054 void TypeFeedbackInfo::initialize_storage() { 8055 WRITE_FIELD(this, kStorage1Offset, Smi::kZero); 8056 WRITE_FIELD(this, kStorage2Offset, Smi::kZero); 8057 WRITE_FIELD(this, kStorage3Offset, Smi::kZero); 8058 } 8059 8060 8061 void TypeFeedbackInfo::change_own_type_change_checksum() { 8062 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value(); 8063 int checksum = OwnTypeChangeChecksum::decode(value); 8064 checksum = (checksum + 1) % (1 << kTypeChangeChecksumBits); 8065 value = OwnTypeChangeChecksum::update(value, checksum); 8066 // Ensure packed bit field is in Smi range. 8067 if (value > Smi::kMaxValue) value |= Smi::kMinValue; 8068 if (value < Smi::kMinValue) value &= ~Smi::kMinValue; 8069 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value)); 8070 } 8071 8072 8073 void TypeFeedbackInfo::set_inlined_type_change_checksum(int checksum) { 8074 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value(); 8075 int mask = (1 << kTypeChangeChecksumBits) - 1; 8076 value = InlinedTypeChangeChecksum::update(value, checksum & mask); 8077 // Ensure packed bit field is in Smi range. 8078 if (value > Smi::kMaxValue) value |= Smi::kMinValue; 8079 if (value < Smi::kMinValue) value &= ~Smi::kMinValue; 8080 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value)); 8081 } 8082 8083 8084 int TypeFeedbackInfo::own_type_change_checksum() { 8085 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value(); 8086 return OwnTypeChangeChecksum::decode(value); 8087 } 8088 8089 8090 bool TypeFeedbackInfo::matches_inlined_type_change_checksum(int checksum) { 8091 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value(); 8092 int mask = (1 << kTypeChangeChecksumBits) - 1; 8093 return InlinedTypeChangeChecksum::decode(value) == (checksum & mask); 8094 } 8095 8096 8097 SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot) 8098 8099 8100 Relocatable::Relocatable(Isolate* isolate) { 8101 isolate_ = isolate; 8102 prev_ = isolate->relocatable_top(); 8103 isolate->set_relocatable_top(this); 8104 } 8105 8106 8107 Relocatable::~Relocatable() { 8108 DCHECK_EQ(isolate_->relocatable_top(), this); 8109 isolate_->set_relocatable_top(prev_); 8110 } 8111 8112 8113 template<class Derived, class TableType> 8114 Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() { 8115 TableType* table(TableType::cast(this->table())); 8116 int index = Smi::cast(this->index())->value(); 8117 Object* key = table->KeyAt(index); 8118 DCHECK(!key->IsTheHole(table->GetIsolate())); 8119 return key; 8120 } 8121 8122 8123 void JSSetIterator::PopulateValueArray(FixedArray* array) { 8124 array->set(0, CurrentKey()); 8125 } 8126 8127 8128 void JSMapIterator::PopulateValueArray(FixedArray* array) { 8129 array->set(0, CurrentKey()); 8130 array->set(1, CurrentValue()); 8131 } 8132 8133 8134 Object* JSMapIterator::CurrentValue() { 8135 OrderedHashMap* table(OrderedHashMap::cast(this->table())); 8136 int index = Smi::cast(this->index())->value(); 8137 Object* value = table->ValueAt(index); 8138 DCHECK(!value->IsTheHole(table->GetIsolate())); 8139 return value; 8140 } 8141 8142 8143 String::SubStringRange::SubStringRange(String* string, int first, int length) 8144 : string_(string), 8145 first_(first), 8146 length_(length == -1 ? string->length() : length) {} 8147 8148 8149 class String::SubStringRange::iterator final { 8150 public: 8151 typedef std::forward_iterator_tag iterator_category; 8152 typedef int difference_type; 8153 typedef uc16 value_type; 8154 typedef uc16* pointer; 8155 typedef uc16& reference; 8156 8157 iterator(const iterator& other) 8158 : content_(other.content_), offset_(other.offset_) {} 8159 8160 uc16 operator*() { return content_.Get(offset_); } 8161 bool operator==(const iterator& other) const { 8162 return content_.UsesSameString(other.content_) && offset_ == other.offset_; 8163 } 8164 bool operator!=(const iterator& other) const { 8165 return !content_.UsesSameString(other.content_) || offset_ != other.offset_; 8166 } 8167 iterator& operator++() { 8168 ++offset_; 8169 return *this; 8170 } 8171 iterator operator++(int); 8172 8173 private: 8174 friend class String; 8175 iterator(String* from, int offset) 8176 : content_(from->GetFlatContent()), offset_(offset) {} 8177 String::FlatContent content_; 8178 int offset_; 8179 }; 8180 8181 8182 String::SubStringRange::iterator String::SubStringRange::begin() { 8183 return String::SubStringRange::iterator(string_, first_); 8184 } 8185 8186 8187 String::SubStringRange::iterator String::SubStringRange::end() { 8188 return String::SubStringRange::iterator(string_, first_ + length_); 8189 } 8190 8191 8192 // Predictably converts HeapObject* or Address to uint32 by calculating 8193 // offset of the address in respective MemoryChunk. 8194 static inline uint32_t ObjectAddressForHashing(void* object) { 8195 uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object)); 8196 return value & MemoryChunk::kAlignmentMask; 8197 } 8198 8199 static inline Handle<Object> MakeEntryPair(Isolate* isolate, uint32_t index, 8200 Handle<Object> value) { 8201 Handle<Object> key = isolate->factory()->Uint32ToString(index); 8202 Handle<FixedArray> entry_storage = 8203 isolate->factory()->NewUninitializedFixedArray(2); 8204 { 8205 entry_storage->set(0, *key, SKIP_WRITE_BARRIER); 8206 entry_storage->set(1, *value, SKIP_WRITE_BARRIER); 8207 } 8208 return isolate->factory()->NewJSArrayWithElements(entry_storage, 8209 FAST_ELEMENTS, 2); 8210 } 8211 8212 static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Name> key, 8213 Handle<Object> value) { 8214 Handle<FixedArray> entry_storage = 8215 isolate->factory()->NewUninitializedFixedArray(2); 8216 { 8217 entry_storage->set(0, *key, SKIP_WRITE_BARRIER); 8218 entry_storage->set(1, *value, SKIP_WRITE_BARRIER); 8219 } 8220 return isolate->factory()->NewJSArrayWithElements(entry_storage, 8221 FAST_ELEMENTS, 2); 8222 } 8223 8224 ACCESSORS(JSIteratorResult, value, Object, kValueOffset) 8225 ACCESSORS(JSIteratorResult, done, Object, kDoneOffset) 8226 8227 ACCESSORS(JSArrayIterator, object, Object, kIteratedObjectOffset) 8228 ACCESSORS(JSArrayIterator, index, Object, kNextIndexOffset) 8229 ACCESSORS(JSArrayIterator, object_map, Object, kIteratedObjectMapOffset) 8230 8231 ACCESSORS(JSAsyncFromSyncIterator, sync_iterator, JSReceiver, 8232 kSyncIteratorOffset) 8233 8234 ACCESSORS(JSStringIterator, string, String, kStringOffset) 8235 SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset) 8236 8237 #undef INT_ACCESSORS 8238 #undef ACCESSORS 8239 #undef ACCESSORS_CHECKED 8240 #undef ACCESSORS_CHECKED2 8241 #undef SMI_ACCESSORS 8242 #undef SYNCHRONIZED_SMI_ACCESSORS 8243 #undef NOBARRIER_SMI_ACCESSORS 8244 #undef BOOL_GETTER 8245 #undef BOOL_ACCESSORS 8246 #undef FIELD_ADDR 8247 #undef FIELD_ADDR_CONST 8248 #undef READ_FIELD 8249 #undef NOBARRIER_READ_FIELD 8250 #undef WRITE_FIELD 8251 #undef NOBARRIER_WRITE_FIELD 8252 #undef WRITE_BARRIER 8253 #undef CONDITIONAL_WRITE_BARRIER 8254 #undef READ_DOUBLE_FIELD 8255 #undef WRITE_DOUBLE_FIELD 8256 #undef READ_INT_FIELD 8257 #undef WRITE_INT_FIELD 8258 #undef READ_INTPTR_FIELD 8259 #undef WRITE_INTPTR_FIELD 8260 #undef READ_UINT8_FIELD 8261 #undef WRITE_UINT8_FIELD 8262 #undef READ_INT8_FIELD 8263 #undef WRITE_INT8_FIELD 8264 #undef READ_UINT16_FIELD 8265 #undef WRITE_UINT16_FIELD 8266 #undef READ_INT16_FIELD 8267 #undef WRITE_INT16_FIELD 8268 #undef READ_UINT32_FIELD 8269 #undef WRITE_UINT32_FIELD 8270 #undef READ_INT32_FIELD 8271 #undef WRITE_INT32_FIELD 8272 #undef READ_FLOAT_FIELD 8273 #undef WRITE_FLOAT_FIELD 8274 #undef READ_UINT64_FIELD 8275 #undef WRITE_UINT64_FIELD 8276 #undef READ_INT64_FIELD 8277 #undef WRITE_INT64_FIELD 8278 #undef READ_BYTE_FIELD 8279 #undef WRITE_BYTE_FIELD 8280 #undef NOBARRIER_READ_BYTE_FIELD 8281 #undef NOBARRIER_WRITE_BYTE_FIELD 8282 8283 } // namespace internal 8284 } // namespace v8 8285 8286 #endif // V8_OBJECTS_INL_H_ 8287