| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Review notes: | 5 // Review notes: |
| 6 // | 6 // |
| 7 // - The use of macros in these inline functions may seem superfluous | 7 // - The use of macros in these inline functions may seem superfluous |
| 8 // but it is absolutely needed to make sure gcc generates optimal | 8 // but it is absolutely needed to make sure gcc generates optimal |
| 9 // code. gcc is not happy when attempting to inline too deep. | 9 // code. gcc is not happy when attempting to inline too deep. |
| 10 // | 10 // |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 } | 52 } |
| 53 | 53 |
| 54 | 54 |
| 55 int PropertyDetails::field_width_in_words() const { | 55 int PropertyDetails::field_width_in_words() const { |
| 56 DCHECK(location() == kField); | 56 DCHECK(location() == kField); |
| 57 if (!FLAG_unbox_double_fields) return 1; | 57 if (!FLAG_unbox_double_fields) return 1; |
| 58 if (kDoubleSize == kPointerSize) return 1; | 58 if (kDoubleSize == kPointerSize) return 1; |
| 59 return representation().IsDouble() ? kDoubleSize / kPointerSize : 1; | 59 return representation().IsDouble() ? kDoubleSize / kPointerSize : 1; |
| 60 } | 60 } |
| 61 | 61 |
| 62 #define TYPE_CHECKER(type, instancetype) \ | |
| 63 bool HeapObject::Is##type() const { \ | |
| 64 return map()->instance_type() == instancetype; \ | |
| 65 } | |
| 66 | |
| 67 #define CAST_ACCESSOR(type) \ | |
| 68 type* type::cast(Object* object) { \ | |
| 69 SLOW_DCHECK(object->Is##type()); \ | |
| 70 return reinterpret_cast<type*>(object); \ | |
| 71 } \ | |
| 72 const type* type::cast(const Object* object) { \ | |
| 73 SLOW_DCHECK(object->Is##type()); \ | |
| 74 return reinterpret_cast<const type*>(object); \ | |
| 75 } | |
| 76 | |
| 77 | |
| 78 #define INT_ACCESSORS(holder, name, offset) \ | 62 #define INT_ACCESSORS(holder, name, offset) \ |
| 79 int holder::name() const { return READ_INT_FIELD(this, offset); } \ | 63 int holder::name() const { return READ_INT_FIELD(this, offset); } \ |
| 80 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); } | 64 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); } |
| 81 | 65 |
| 82 #define ACCESSORS_CHECKED(holder, name, type, offset, condition) \ | 66 #define ACCESSORS_CHECKED(holder, name, type, offset, condition) \ |
| 83 type* holder::name() const { \ | 67 type* holder::name() const { \ |
| 84 DCHECK(condition); \ | 68 DCHECK(condition); \ |
| 85 return type::cast(READ_FIELD(this, offset)); \ | 69 return type::cast(READ_FIELD(this, offset)); \ |
| 86 } \ | 70 } \ |
| 87 void holder::set_##name(type* value, WriteBarrierMode mode) { \ | 71 void holder::set_##name(type* value, WriteBarrierMode mode) { \ |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 | 117 |
| 134 | 118 |
| 135 #define BOOL_ACCESSORS(holder, field, name, offset) \ | 119 #define BOOL_ACCESSORS(holder, field, name, offset) \ |
| 136 bool holder::name() const { \ | 120 bool holder::name() const { \ |
| 137 return BooleanBit::get(field(), offset); \ | 121 return BooleanBit::get(field(), offset); \ |
| 138 } \ | 122 } \ |
| 139 void holder::set_##name(bool value) { \ | 123 void holder::set_##name(bool value) { \ |
| 140 set_##field(BooleanBit::set(field(), offset, value)); \ | 124 set_##field(BooleanBit::set(field(), offset, value)); \ |
| 141 } | 125 } |
| 142 | 126 |
| 127 #define TYPE_CHECKER(type, instancetype) \ |
| 128 bool HeapObject::Is##type() const { \ |
| 129 return map()->instance_type() == instancetype; \ |
| 130 } |
| 131 |
| 132 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE) |
| 133 TYPE_CHECKER(BytecodeArray, BYTECODE_ARRAY_TYPE) |
| 134 TYPE_CHECKER(Cell, CELL_TYPE) |
| 135 TYPE_CHECKER(Code, CODE_TYPE) |
| 136 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE) |
| 137 TYPE_CHECKER(Foreign, FOREIGN_TYPE) |
| 138 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE) |
| 139 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE) |
| 140 TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE) |
| 141 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE) |
| 142 TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE) |
| 143 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE) |
| 144 TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE) |
| 145 TYPE_CHECKER(JSDate, JS_DATE_TYPE) |
| 146 TYPE_CHECKER(JSError, JS_ERROR_TYPE) |
| 147 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE) |
| 148 TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE) |
| 149 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE) |
| 150 TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE) |
| 151 TYPE_CHECKER(JSMap, JS_MAP_TYPE) |
| 152 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE) |
| 153 TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE) |
| 154 TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE) |
| 155 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE) |
| 156 TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE) |
| 157 TYPE_CHECKER(JSSet, JS_SET_TYPE) |
| 158 TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE) |
| 159 TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE) |
| 160 TYPE_CHECKER(JSValue, JS_VALUE_TYPE) |
| 161 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE) |
| 162 TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE) |
| 163 TYPE_CHECKER(Map, MAP_TYPE) |
| 164 TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE) |
| 165 TYPE_CHECKER(Oddball, ODDBALL_TYPE) |
| 166 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE) |
| 167 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE) |
| 168 TYPE_CHECKER(Simd128Value, SIMD128_VALUE_TYPE) |
| 169 TYPE_CHECKER(Symbol, SYMBOL_TYPE) |
| 170 TYPE_CHECKER(TransitionArray, TRANSITION_ARRAY_TYPE) |
| 171 TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE) |
| 172 TYPE_CHECKER(WeakFixedArray, FIXED_ARRAY_TYPE) |
| 173 |
| 174 #define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \ |
| 175 TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE) |
| 176 TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER) |
| 177 #undef TYPED_ARRAY_TYPE_CHECKER |
| 178 |
| 179 #undef TYPE_CHECKER |
| 180 |
| 143 bool HeapObject::IsFixedArrayBase() const { | 181 bool HeapObject::IsFixedArrayBase() const { |
| 144 return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); | 182 return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); |
| 145 } | 183 } |
| 146 | 184 |
| 147 bool HeapObject::IsFixedArray() const { | 185 bool HeapObject::IsFixedArray() const { |
| 148 InstanceType instance_type = map()->instance_type(); | 186 InstanceType instance_type = map()->instance_type(); |
| 149 return instance_type == FIXED_ARRAY_TYPE || | 187 return instance_type == FIXED_ARRAY_TYPE || |
| 150 instance_type == TRANSITION_ARRAY_TYPE; | 188 instance_type == TRANSITION_ARRAY_TYPE; |
| 151 } | 189 } |
| 152 | 190 |
| 153 | |
| 154 // External objects are not extensible, so the map check is enough. | 191 // External objects are not extensible, so the map check is enough. |
| 155 bool HeapObject::IsExternal() const { | 192 bool HeapObject::IsExternal() const { |
| 156 return map() == GetHeap()->external_map(); | 193 return map() == GetHeap()->external_map(); |
| 157 } | 194 } |
| 158 | 195 |
| 159 | |
| 160 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE) | |
| 161 TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE) | |
| 162 TYPE_CHECKER(Symbol, SYMBOL_TYPE) | |
| 163 TYPE_CHECKER(Simd128Value, SIMD128_VALUE_TYPE) | |
| 164 | |
| 165 #define SIMD128_TYPE_CHECKER(TYPE, Type, type, lane_count, lane_type) \ | 196 #define SIMD128_TYPE_CHECKER(TYPE, Type, type, lane_count, lane_type) \ |
| 166 bool HeapObject::Is##Type() const { return map() == GetHeap()->type##_map(); } | 197 bool HeapObject::Is##Type() const { return map() == GetHeap()->type##_map(); } |
| 167 SIMD128_TYPES(SIMD128_TYPE_CHECKER) | 198 SIMD128_TYPES(SIMD128_TYPE_CHECKER) |
| 168 #undef SIMD128_TYPE_CHECKER | 199 #undef SIMD128_TYPE_CHECKER |
| 169 | 200 |
| 170 #define IS_TYPE_FUNCTION_DEF(type_) \ | 201 #define IS_TYPE_FUNCTION_DEF(type_) \ |
| 171 bool Object::Is##type_() const { \ | 202 bool Object::Is##type_() const { \ |
| 172 return IsHeapObject() && HeapObject::cast(this)->Is##type_(); \ | 203 return IsHeapObject() && HeapObject::cast(this)->Is##type_(); \ |
| 173 } | 204 } |
| 174 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF) | 205 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF) |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 return StringShape(String::cast(this)).IsExternal() && | 290 return StringShape(String::cast(this)).IsExternal() && |
| 260 String::cast(this)->IsOneByteRepresentation(); | 291 String::cast(this)->IsOneByteRepresentation(); |
| 261 } | 292 } |
| 262 | 293 |
| 263 bool HeapObject::IsExternalTwoByteString() const { | 294 bool HeapObject::IsExternalTwoByteString() const { |
| 264 if (!IsString()) return false; | 295 if (!IsString()) return false; |
| 265 return StringShape(String::cast(this)).IsExternal() && | 296 return StringShape(String::cast(this)).IsExternal() && |
| 266 String::cast(this)->IsTwoByteRepresentation(); | 297 String::cast(this)->IsTwoByteRepresentation(); |
| 267 } | 298 } |
| 268 | 299 |
| 300 bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); } |
| 301 |
| 302 bool HeapObject::IsFiller() const { |
| 303 InstanceType instance_type = map()->instance_type(); |
| 304 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE; |
| 305 } |
| 306 |
| 307 bool HeapObject::IsFixedTypedArrayBase() const { |
| 308 InstanceType instance_type = map()->instance_type(); |
| 309 return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE && |
| 310 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE); |
| 311 } |
| 312 |
| 313 bool HeapObject::IsJSReceiver() const { |
| 314 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 315 return map()->instance_type() >= FIRST_JS_RECEIVER_TYPE; |
| 316 } |
| 317 |
| 318 bool HeapObject::IsJSObject() const { |
| 319 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); |
| 320 return map()->IsJSObjectMap(); |
| 321 } |
| 322 |
| 323 bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); } |
| 324 |
| 325 bool HeapObject::IsJSArrayIterator() const { |
| 326 InstanceType instance_type = map()->instance_type(); |
| 327 return (instance_type >= FIRST_ARRAY_ITERATOR_TYPE && |
| 328 instance_type <= LAST_ARRAY_ITERATOR_TYPE); |
| 329 } |
| 330 |
| 331 bool HeapObject::IsJSWeakCollection() const { |
| 332 return IsJSWeakMap() || IsJSWeakSet(); |
| 333 } |
| 334 |
| 335 bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); } |
| 336 |
| 337 bool HeapObject::IsDescriptorArray() const { return IsFixedArray(); } |
| 338 |
| 339 bool HeapObject::IsFrameArray() const { return IsFixedArray(); } |
| 340 |
| 341 bool HeapObject::IsArrayList() const { return IsFixedArray(); } |
| 342 |
| 343 bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArray(); } |
| 344 |
| 345 bool Object::IsLayoutDescriptor() const { |
| 346 return IsSmi() || IsFixedTypedArrayBase(); |
| 347 } |
| 348 |
| 349 bool HeapObject::IsTypeFeedbackVector() const { return IsFixedArray(); } |
| 350 |
| 351 bool HeapObject::IsTypeFeedbackMetadata() const { return IsFixedArray(); } |
| 352 |
| 353 bool HeapObject::IsLiteralsArray() const { return IsFixedArray(); } |
| 354 |
| 355 bool HeapObject::IsDeoptimizationInputData() const { |
| 356 // Must be a fixed array. |
| 357 if (!IsFixedArray()) return false; |
| 358 |
| 359 // There's no sure way to detect the difference between a fixed array and |
| 360 // a deoptimization data array. Since this is used for asserts we can |
| 361 // check that the length is zero or else the fixed size plus a multiple of |
| 362 // the entry size. |
| 363 int length = FixedArray::cast(this)->length(); |
| 364 if (length == 0) return true; |
| 365 |
| 366 length -= DeoptimizationInputData::kFirstDeoptEntryIndex; |
| 367 return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0; |
| 368 } |
| 369 |
| 370 bool HeapObject::IsDeoptimizationOutputData() const { |
| 371 if (!IsFixedArray()) return false; |
| 372 // There's actually no way to see the difference between a fixed array and |
| 373 // a deoptimization data array. Since this is used for asserts we can check |
| 374 // that the length is plausible though. |
| 375 if (FixedArray::cast(this)->length() % 2 != 0) return false; |
| 376 return true; |
| 377 } |
| 378 |
| 379 bool HeapObject::IsHandlerTable() const { |
| 380 if (!IsFixedArray()) return false; |
| 381 // There's actually no way to see the difference between a fixed array and |
| 382 // a handler table array. |
| 383 return true; |
| 384 } |
| 385 |
| 386 bool HeapObject::IsTemplateList() const { |
| 387 if (!IsFixedArray()) return false; |
| 388 // There's actually no way to see the difference between a fixed array and |
| 389 // a template list. |
| 390 if (FixedArray::cast(this)->length() < 1) return false; |
| 391 return true; |
| 392 } |
| 393 |
| 394 bool HeapObject::IsDependentCode() const { |
| 395 if (!IsFixedArray()) return false; |
| 396 // There's actually no way to see the difference between a fixed array and |
| 397 // a dependent codes array. |
| 398 return true; |
| 399 } |
| 400 |
| 401 bool HeapObject::IsContext() const { |
| 402 Map* map = this->map(); |
| 403 Heap* heap = GetHeap(); |
| 404 return ( |
| 405 map == heap->function_context_map() || map == heap->catch_context_map() || |
| 406 map == heap->with_context_map() || map == heap->native_context_map() || |
| 407 map == heap->block_context_map() || map == heap->module_context_map() || |
| 408 map == heap->script_context_map() || |
| 409 map == heap->debug_evaluate_context_map()); |
| 410 } |
| 411 |
| 412 bool HeapObject::IsNativeContext() const { |
| 413 return map() == GetHeap()->native_context_map(); |
| 414 } |
| 415 |
| 416 bool HeapObject::IsScriptContextTable() const { |
| 417 return map() == GetHeap()->script_context_table_map(); |
| 418 } |
| 419 |
| 420 bool HeapObject::IsScopeInfo() const { |
| 421 return map() == GetHeap()->scope_info_map(); |
| 422 } |
| 423 |
| 424 bool HeapObject::IsModuleInfo() const { |
| 425 return map() == GetHeap()->module_info_map(); |
| 426 } |
| 427 |
| 428 template <> |
| 429 inline bool Is<JSFunction>(Object* obj) { |
| 430 return obj->IsJSFunction(); |
| 431 } |
| 432 |
| 433 bool HeapObject::IsAbstractCode() const { |
| 434 return IsBytecodeArray() || IsCode(); |
| 435 } |
| 436 |
| 437 bool HeapObject::IsStringWrapper() const { |
| 438 return IsJSValue() && JSValue::cast(this)->value()->IsString(); |
| 439 } |
| 440 |
| 441 bool HeapObject::IsBoolean() const { |
| 442 return IsOddball() && |
| 443 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0); |
| 444 } |
| 445 |
| 446 bool HeapObject::IsJSArrayBufferView() const { |
| 447 return IsJSDataView() || IsJSTypedArray(); |
| 448 } |
| 449 |
| 450 template <> |
| 451 inline bool Is<JSArray>(Object* obj) { |
| 452 return obj->IsJSArray(); |
| 453 } |
| 454 |
| 455 bool HeapObject::IsHashTable() const { |
| 456 return map() == GetHeap()->hash_table_map(); |
| 457 } |
| 458 |
| 459 bool HeapObject::IsWeakHashTable() const { return IsHashTable(); } |
| 460 |
| 461 bool HeapObject::IsDictionary() const { |
| 462 return IsHashTable() && this != GetHeap()->string_table(); |
| 463 } |
| 464 |
| 465 bool Object::IsNameDictionary() const { return IsDictionary(); } |
| 466 |
| 467 bool Object::IsGlobalDictionary() const { return IsDictionary(); } |
| 468 |
| 469 bool Object::IsSeededNumberDictionary() const { return IsDictionary(); } |
| 470 |
| 471 bool HeapObject::IsUnseededNumberDictionary() const { |
| 472 return map() == GetHeap()->unseeded_number_dictionary_map(); |
| 473 } |
| 474 |
| 475 bool HeapObject::IsStringTable() const { return IsHashTable(); } |
| 476 |
| 477 bool HeapObject::IsStringSet() const { return IsHashTable(); } |
| 478 |
| 479 bool HeapObject::IsObjectHashSet() const { return IsHashTable(); } |
| 480 |
| 481 bool HeapObject::IsNormalizedMapCache() const { |
| 482 return NormalizedMapCache::IsNormalizedMapCache(this); |
| 483 } |
| 484 |
| 485 int NormalizedMapCache::GetIndex(Handle<Map> map) { |
| 486 return map->Hash() % NormalizedMapCache::kEntries; |
| 487 } |
| 488 |
| 489 bool NormalizedMapCache::IsNormalizedMapCache(const HeapObject* obj) { |
| 490 if (!obj->IsFixedArray()) return false; |
| 491 if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) { |
| 492 return false; |
| 493 } |
| 494 #ifdef VERIFY_HEAP |
| 495 if (FLAG_verify_heap) { |
| 496 reinterpret_cast<NormalizedMapCache*>(const_cast<HeapObject*>(obj)) |
| 497 ->NormalizedMapCacheVerify(); |
| 498 } |
| 499 #endif |
| 500 return true; |
| 501 } |
| 502 |
| 503 bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); } |
| 504 |
| 505 bool HeapObject::IsCodeCacheHashTable() const { return IsHashTable(); } |
| 506 |
| 507 bool HeapObject::IsMapCache() const { return IsHashTable(); } |
| 508 |
| 509 bool HeapObject::IsObjectHashTable() const { return IsHashTable(); } |
| 510 |
| 511 bool HeapObject::IsOrderedHashTable() const { |
| 512 return map() == GetHeap()->ordered_hash_table_map(); |
| 513 } |
| 514 |
| 515 bool Object::IsOrderedHashSet() const { return IsOrderedHashTable(); } |
| 516 |
| 517 bool Object::IsOrderedHashMap() const { return IsOrderedHashTable(); } |
| 518 |
| 519 bool Object::IsPrimitive() const { |
| 520 return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap(); |
| 521 } |
| 522 |
| 523 bool HeapObject::IsJSGlobalProxy() const { |
| 524 bool result = map()->instance_type() == JS_GLOBAL_PROXY_TYPE; |
| 525 DCHECK(!result || map()->is_access_check_needed()); |
| 526 return result; |
| 527 } |
| 528 |
| 529 bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); } |
| 530 |
| 531 bool HeapObject::IsAccessCheckNeeded() const { |
| 532 if (IsJSGlobalProxy()) { |
| 533 const JSGlobalProxy* proxy = JSGlobalProxy::cast(this); |
| 534 JSGlobalObject* global = proxy->GetIsolate()->context()->global_object(); |
| 535 return proxy->IsDetachedFrom(global); |
| 536 } |
| 537 return map()->is_access_check_needed(); |
| 538 } |
| 539 |
| 540 bool HeapObject::IsStruct() const { |
| 541 switch (map()->instance_type()) { |
| 542 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
| 543 case NAME##_TYPE: \ |
| 544 return true; |
| 545 STRUCT_LIST(MAKE_STRUCT_CASE) |
| 546 #undef MAKE_STRUCT_CASE |
| 547 default: |
| 548 return false; |
| 549 } |
| 550 } |
| 551 |
| 552 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \ |
| 553 bool Object::Is##Name() const { \ |
| 554 return IsHeapObject() && HeapObject::cast(this)->Is##Name(); \ |
| 555 } \ |
| 556 bool HeapObject::Is##Name() const { \ |
| 557 return map()->instance_type() == NAME##_TYPE; \ |
| 558 } |
| 559 STRUCT_LIST(MAKE_STRUCT_PREDICATE) |
| 560 #undef MAKE_STRUCT_PREDICATE |
| 561 |
| 562 double Object::Number() const { |
| 563 DCHECK(IsNumber()); |
| 564 return IsSmi() |
| 565 ? static_cast<double>(reinterpret_cast<const Smi*>(this)->value()) |
| 566 : reinterpret_cast<const HeapNumber*>(this)->value(); |
| 567 } |
| 568 |
| 569 bool Object::IsNaN() const { |
| 570 return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value()); |
| 571 } |
| 572 |
| 573 bool Object::IsMinusZero() const { |
| 574 return this->IsHeapNumber() && |
| 575 i::IsMinusZero(HeapNumber::cast(this)->value()); |
| 576 } |
| 577 |
| 578 // ------------------------------------ |
| 579 // Cast operations |
| 580 |
| 581 #define CAST_ACCESSOR(type) \ |
| 582 type* type::cast(Object* object) { \ |
| 583 SLOW_DCHECK(object->Is##type()); \ |
| 584 return reinterpret_cast<type*>(object); \ |
| 585 } \ |
| 586 const type* type::cast(const Object* object) { \ |
| 587 SLOW_DCHECK(object->Is##type()); \ |
| 588 return reinterpret_cast<const type*>(object); \ |
| 589 } |
| 590 |
| 591 CAST_ACCESSOR(AbstractCode) |
| 592 CAST_ACCESSOR(ArrayList) |
| 593 CAST_ACCESSOR(Bool16x8) |
| 594 CAST_ACCESSOR(Bool32x4) |
| 595 CAST_ACCESSOR(Bool8x16) |
| 596 CAST_ACCESSOR(ByteArray) |
| 597 CAST_ACCESSOR(BytecodeArray) |
| 598 CAST_ACCESSOR(Cell) |
| 599 CAST_ACCESSOR(Code) |
| 600 CAST_ACCESSOR(CodeCacheHashTable) |
| 601 CAST_ACCESSOR(CompilationCacheTable) |
| 602 CAST_ACCESSOR(ConsString) |
| 603 CAST_ACCESSOR(DeoptimizationInputData) |
| 604 CAST_ACCESSOR(DeoptimizationOutputData) |
| 605 CAST_ACCESSOR(DependentCode) |
| 606 CAST_ACCESSOR(DescriptorArray) |
| 607 CAST_ACCESSOR(ExternalOneByteString) |
| 608 CAST_ACCESSOR(ExternalString) |
| 609 CAST_ACCESSOR(ExternalTwoByteString) |
| 610 CAST_ACCESSOR(FixedArray) |
| 611 CAST_ACCESSOR(FixedArrayBase) |
| 612 CAST_ACCESSOR(FixedDoubleArray) |
| 613 CAST_ACCESSOR(FixedTypedArrayBase) |
| 614 CAST_ACCESSOR(Float32x4) |
| 615 CAST_ACCESSOR(Foreign) |
| 616 CAST_ACCESSOR(FrameArray) |
| 617 CAST_ACCESSOR(GlobalDictionary) |
| 618 CAST_ACCESSOR(HandlerTable) |
| 619 CAST_ACCESSOR(HeapObject) |
| 620 CAST_ACCESSOR(Int16x8) |
| 621 CAST_ACCESSOR(Int32x4) |
| 622 CAST_ACCESSOR(Int8x16) |
| 623 CAST_ACCESSOR(JSArray) |
| 624 CAST_ACCESSOR(JSArrayBuffer) |
| 625 CAST_ACCESSOR(JSArrayBufferView) |
| 626 CAST_ACCESSOR(JSBoundFunction) |
| 627 CAST_ACCESSOR(JSDataView) |
| 628 CAST_ACCESSOR(JSDate) |
| 629 CAST_ACCESSOR(JSFunction) |
| 630 CAST_ACCESSOR(JSGeneratorObject) |
| 631 CAST_ACCESSOR(JSGlobalObject) |
| 632 CAST_ACCESSOR(JSGlobalProxy) |
| 633 CAST_ACCESSOR(JSMap) |
| 634 CAST_ACCESSOR(JSMapIterator) |
| 635 CAST_ACCESSOR(JSMessageObject) |
| 636 CAST_ACCESSOR(JSModuleNamespace) |
| 637 CAST_ACCESSOR(JSObject) |
| 638 CAST_ACCESSOR(JSProxy) |
| 639 CAST_ACCESSOR(JSReceiver) |
| 640 CAST_ACCESSOR(JSRegExp) |
| 641 CAST_ACCESSOR(JSPromise) |
| 642 CAST_ACCESSOR(JSSet) |
| 643 CAST_ACCESSOR(JSSetIterator) |
| 644 CAST_ACCESSOR(JSStringIterator) |
| 645 CAST_ACCESSOR(JSArrayIterator) |
| 646 CAST_ACCESSOR(JSTypedArray) |
| 647 CAST_ACCESSOR(JSValue) |
| 648 CAST_ACCESSOR(JSWeakCollection) |
| 649 CAST_ACCESSOR(JSWeakMap) |
| 650 CAST_ACCESSOR(JSWeakSet) |
| 651 CAST_ACCESSOR(LayoutDescriptor) |
| 652 CAST_ACCESSOR(Map) |
| 653 CAST_ACCESSOR(ModuleInfo) |
| 654 CAST_ACCESSOR(Name) |
| 655 CAST_ACCESSOR(NameDictionary) |
| 656 CAST_ACCESSOR(NormalizedMapCache) |
| 657 CAST_ACCESSOR(Object) |
| 658 CAST_ACCESSOR(ObjectHashTable) |
| 659 CAST_ACCESSOR(ObjectHashSet) |
| 660 CAST_ACCESSOR(Oddball) |
| 661 CAST_ACCESSOR(OrderedHashMap) |
| 662 CAST_ACCESSOR(OrderedHashSet) |
| 663 CAST_ACCESSOR(PropertyCell) |
| 664 CAST_ACCESSOR(TemplateList) |
| 665 CAST_ACCESSOR(RegExpMatchInfo) |
| 666 CAST_ACCESSOR(ScopeInfo) |
| 667 CAST_ACCESSOR(SeededNumberDictionary) |
| 668 CAST_ACCESSOR(SeqOneByteString) |
| 669 CAST_ACCESSOR(SeqString) |
| 670 CAST_ACCESSOR(SeqTwoByteString) |
| 671 CAST_ACCESSOR(SharedFunctionInfo) |
| 672 CAST_ACCESSOR(Simd128Value) |
| 673 CAST_ACCESSOR(SlicedString) |
| 674 CAST_ACCESSOR(Smi) |
| 675 CAST_ACCESSOR(String) |
| 676 CAST_ACCESSOR(StringSet) |
| 677 CAST_ACCESSOR(StringTable) |
| 678 CAST_ACCESSOR(Struct) |
| 679 CAST_ACCESSOR(Symbol) |
| 680 CAST_ACCESSOR(TemplateInfo) |
| 681 CAST_ACCESSOR(Uint16x8) |
| 682 CAST_ACCESSOR(Uint32x4) |
| 683 CAST_ACCESSOR(Uint8x16) |
| 684 CAST_ACCESSOR(UnseededNumberDictionary) |
| 685 CAST_ACCESSOR(WeakCell) |
| 686 CAST_ACCESSOR(WeakFixedArray) |
| 687 CAST_ACCESSOR(WeakHashTable) |
| 688 |
| 689 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name) |
| 690 STRUCT_LIST(MAKE_STRUCT_CAST) |
| 691 #undef MAKE_STRUCT_CAST |
| 692 |
| 693 #undef CAST_ACCESSOR |
| 694 |
| 269 bool Object::HasValidElements() { | 695 bool Object::HasValidElements() { |
| 270 // Dictionary is covered under FixedArray. | 696 // Dictionary is covered under FixedArray. |
| 271 return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); | 697 return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); |
| 272 } | 698 } |
| 273 | 699 |
| 274 | |
| 275 bool Object::KeyEquals(Object* second) { | 700 bool Object::KeyEquals(Object* second) { |
| 276 Object* first = this; | 701 Object* first = this; |
| 277 if (second->IsNumber()) { | 702 if (second->IsNumber()) { |
| 278 if (first->IsNumber()) return first->Number() == second->Number(); | 703 if (first->IsNumber()) return first->Number() == second->Number(); |
| 279 Object* temp = first; | 704 Object* temp = first; |
| 280 first = second; | 705 first = second; |
| 281 second = temp; | 706 second = temp; |
| 282 } | 707 } |
| 283 if (first->IsNumber()) { | 708 if (first->IsNumber()) { |
| 284 DCHECK_LE(0, first->Number()); | 709 DCHECK_LE(0, first->Number()); |
| 285 uint32_t expected = static_cast<uint32_t>(first->Number()); | 710 uint32_t expected = static_cast<uint32_t>(first->Number()); |
| 286 uint32_t index; | 711 uint32_t index; |
| 287 return Name::cast(second)->AsArrayIndex(&index) && index == expected; | 712 return Name::cast(second)->AsArrayIndex(&index) && index == expected; |
| 288 } | 713 } |
| 289 return Name::cast(first)->Equals(Name::cast(second)); | 714 return Name::cast(first)->Equals(Name::cast(second)); |
| 290 } | 715 } |
| 291 | 716 |
| 292 | |
| 293 bool Object::FilterKey(PropertyFilter filter) { | 717 bool Object::FilterKey(PropertyFilter filter) { |
| 294 if (IsSymbol()) { | 718 if (IsSymbol()) { |
| 295 if (filter & SKIP_SYMBOLS) return true; | 719 if (filter & SKIP_SYMBOLS) return true; |
| 296 if (Symbol::cast(this)->is_private()) return true; | 720 if (Symbol::cast(this)->is_private()) return true; |
| 297 } else { | 721 } else { |
| 298 if (filter & SKIP_STRINGS) return true; | 722 if (filter & SKIP_STRINGS) return true; |
| 299 } | 723 } |
| 300 return false; | 724 return false; |
| 301 } | 725 } |
| 302 | 726 |
| 303 | 727 Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object, |
| 304 Handle<Object> Object::NewStorageFor(Isolate* isolate, | |
| 305 Handle<Object> object, | |
| 306 Representation representation) { | 728 Representation representation) { |
| 307 if (representation.IsSmi() && object->IsUninitialized(isolate)) { | 729 if (representation.IsSmi() && object->IsUninitialized(isolate)) { |
| 308 return handle(Smi::kZero, isolate); | 730 return handle(Smi::kZero, isolate); |
| 309 } | 731 } |
| 310 if (!representation.IsDouble()) return object; | 732 if (!representation.IsDouble()) return object; |
| 311 double value; | 733 double value; |
| 312 if (object->IsUninitialized(isolate)) { | 734 if (object->IsUninitialized(isolate)) { |
| 313 value = 0; | 735 value = 0; |
| 314 } else if (object->IsMutableHeapNumber()) { | 736 } else if (object->IsMutableHeapNumber()) { |
| 315 value = HeapNumber::cast(*object)->value(); | 737 value = HeapNumber::cast(*object)->value(); |
| 316 } else { | 738 } else { |
| 317 value = object->Number(); | 739 value = object->Number(); |
| 318 } | 740 } |
| 319 return isolate->factory()->NewHeapNumber(value, MUTABLE); | 741 return isolate->factory()->NewHeapNumber(value, MUTABLE); |
| 320 } | 742 } |
| 321 | 743 |
| 322 | 744 Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object, |
| 323 Handle<Object> Object::WrapForRead(Isolate* isolate, | |
| 324 Handle<Object> object, | |
| 325 Representation representation) { | 745 Representation representation) { |
| 326 DCHECK(!object->IsUninitialized(isolate)); | 746 DCHECK(!object->IsUninitialized(isolate)); |
| 327 if (!representation.IsDouble()) { | 747 if (!representation.IsDouble()) { |
| 328 DCHECK(object->FitsRepresentation(representation)); | 748 DCHECK(object->FitsRepresentation(representation)); |
| 329 return object; | 749 return object; |
| 330 } | 750 } |
| 331 return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value()); | 751 return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value()); |
| 332 } | 752 } |
| 333 | 753 |
| 334 | |
| 335 StringShape::StringShape(const String* str) | 754 StringShape::StringShape(const String* str) |
| 336 : type_(str->map()->instance_type()) { | 755 : type_(str->map()->instance_type()) { |
| 337 set_valid(); | 756 set_valid(); |
| 338 DCHECK((type_ & kIsNotStringMask) == kStringTag); | 757 DCHECK((type_ & kIsNotStringMask) == kStringTag); |
| 339 } | 758 } |
| 340 | 759 |
| 341 | 760 StringShape::StringShape(Map* map) : type_(map->instance_type()) { |
| 342 StringShape::StringShape(Map* map) | |
| 343 : type_(map->instance_type()) { | |
| 344 set_valid(); | 761 set_valid(); |
| 345 DCHECK((type_ & kIsNotStringMask) == kStringTag); | 762 DCHECK((type_ & kIsNotStringMask) == kStringTag); |
| 346 } | 763 } |
| 347 | 764 |
| 348 | 765 StringShape::StringShape(InstanceType t) : type_(static_cast<uint32_t>(t)) { |
| 349 StringShape::StringShape(InstanceType t) | |
| 350 : type_(static_cast<uint32_t>(t)) { | |
| 351 set_valid(); | 766 set_valid(); |
| 352 DCHECK((type_ & kIsNotStringMask) == kStringTag); | 767 DCHECK((type_ & kIsNotStringMask) == kStringTag); |
| 353 } | 768 } |
| 354 | 769 |
| 355 | |
| 356 bool StringShape::IsInternalized() { | 770 bool StringShape::IsInternalized() { |
| 357 DCHECK(valid()); | 771 DCHECK(valid()); |
| 358 STATIC_ASSERT(kNotInternalizedTag != 0); | 772 STATIC_ASSERT(kNotInternalizedTag != 0); |
| 359 return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) == | 773 return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) == |
| 360 (kStringTag | kInternalizedTag); | 774 (kStringTag | kInternalizedTag); |
| 361 } | 775 } |
| 362 | |
| 363 | 776 |
| 364 bool String::IsOneByteRepresentation() const { | 777 bool String::IsOneByteRepresentation() const { |
| 365 uint32_t type = map()->instance_type(); | 778 uint32_t type = map()->instance_type(); |
| 366 return (type & kStringEncodingMask) == kOneByteStringTag; | 779 return (type & kStringEncodingMask) == kOneByteStringTag; |
| 367 } | 780 } |
| 368 | 781 |
| 369 | |
| 370 bool String::IsTwoByteRepresentation() const { | 782 bool String::IsTwoByteRepresentation() const { |
| 371 uint32_t type = map()->instance_type(); | 783 uint32_t type = map()->instance_type(); |
| 372 return (type & kStringEncodingMask) == kTwoByteStringTag; | 784 return (type & kStringEncodingMask) == kTwoByteStringTag; |
| 373 } | 785 } |
| 374 | 786 |
| 375 | |
| 376 bool String::IsOneByteRepresentationUnderneath() { | 787 bool String::IsOneByteRepresentationUnderneath() { |
| 377 uint32_t type = map()->instance_type(); | 788 uint32_t type = map()->instance_type(); |
| 378 STATIC_ASSERT(kIsIndirectStringTag != 0); | 789 STATIC_ASSERT(kIsIndirectStringTag != 0); |
| 379 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0); | 790 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0); |
| 380 DCHECK(IsFlat()); | 791 DCHECK(IsFlat()); |
| 381 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { | 792 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { |
| 382 case kOneByteStringTag: | 793 case kOneByteStringTag: |
| 383 return true; | 794 return true; |
| 384 case kTwoByteStringTag: | 795 case kTwoByteStringTag: |
| 385 return false; | 796 return false; |
| 386 default: // Cons or sliced string. Need to go deeper. | 797 default: // Cons or sliced string. Need to go deeper. |
| 387 return GetUnderlying()->IsOneByteRepresentation(); | 798 return GetUnderlying()->IsOneByteRepresentation(); |
| 388 } | 799 } |
| 389 } | 800 } |
| 390 | 801 |
| 391 | |
| 392 bool String::IsTwoByteRepresentationUnderneath() { | 802 bool String::IsTwoByteRepresentationUnderneath() { |
| 393 uint32_t type = map()->instance_type(); | 803 uint32_t type = map()->instance_type(); |
| 394 STATIC_ASSERT(kIsIndirectStringTag != 0); | 804 STATIC_ASSERT(kIsIndirectStringTag != 0); |
| 395 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0); | 805 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0); |
| 396 DCHECK(IsFlat()); | 806 DCHECK(IsFlat()); |
| 397 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { | 807 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { |
| 398 case kOneByteStringTag: | 808 case kOneByteStringTag: |
| 399 return false; | 809 return false; |
| 400 case kTwoByteStringTag: | 810 case kTwoByteStringTag: |
| 401 return true; | 811 return true; |
| 402 default: // Cons or sliced string. Need to go deeper. | 812 default: // Cons or sliced string. Need to go deeper. |
| 403 return GetUnderlying()->IsTwoByteRepresentation(); | 813 return GetUnderlying()->IsTwoByteRepresentation(); |
| 404 } | 814 } |
| 405 } | 815 } |
| 406 | 816 |
| 407 | |
| 408 bool String::HasOnlyOneByteChars() { | 817 bool String::HasOnlyOneByteChars() { |
| 409 uint32_t type = map()->instance_type(); | 818 uint32_t type = map()->instance_type(); |
| 410 return (type & kOneByteDataHintMask) == kOneByteDataHintTag || | 819 return (type & kOneByteDataHintMask) == kOneByteDataHintTag || |
| 411 IsOneByteRepresentation(); | 820 IsOneByteRepresentation(); |
| 412 } | 821 } |
| 413 | 822 |
| 414 | |
| 415 bool StringShape::IsCons() { | 823 bool StringShape::IsCons() { |
| 416 return (type_ & kStringRepresentationMask) == kConsStringTag; | 824 return (type_ & kStringRepresentationMask) == kConsStringTag; |
| 417 } | 825 } |
| 418 | 826 |
| 419 | |
| 420 bool StringShape::IsSliced() { | 827 bool StringShape::IsSliced() { |
| 421 return (type_ & kStringRepresentationMask) == kSlicedStringTag; | 828 return (type_ & kStringRepresentationMask) == kSlicedStringTag; |
| 422 } | 829 } |
| 423 | 830 |
| 424 | |
| 425 bool StringShape::IsIndirect() { | 831 bool StringShape::IsIndirect() { |
| 426 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag; | 832 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag; |
| 427 } | 833 } |
| 428 | 834 |
| 429 | |
| 430 bool StringShape::IsExternal() { | 835 bool StringShape::IsExternal() { |
| 431 return (type_ & kStringRepresentationMask) == kExternalStringTag; | 836 return (type_ & kStringRepresentationMask) == kExternalStringTag; |
| 432 } | 837 } |
| 433 | 838 |
| 434 | |
| 435 bool StringShape::IsSequential() { | 839 bool StringShape::IsSequential() { |
| 436 return (type_ & kStringRepresentationMask) == kSeqStringTag; | 840 return (type_ & kStringRepresentationMask) == kSeqStringTag; |
| 437 } | 841 } |
| 438 | 842 |
| 439 | |
| 440 StringRepresentationTag StringShape::representation_tag() { | 843 StringRepresentationTag StringShape::representation_tag() { |
| 441 uint32_t tag = (type_ & kStringRepresentationMask); | 844 uint32_t tag = (type_ & kStringRepresentationMask); |
| 442 return static_cast<StringRepresentationTag>(tag); | 845 return static_cast<StringRepresentationTag>(tag); |
| 443 } | 846 } |
| 444 | 847 |
| 445 | 848 uint32_t StringShape::encoding_tag() { return type_ & kStringEncodingMask; } |
| 446 uint32_t StringShape::encoding_tag() { | |
| 447 return type_ & kStringEncodingMask; | |
| 448 } | |
| 449 | |
| 450 | 849 |
| 451 uint32_t StringShape::full_representation_tag() { | 850 uint32_t StringShape::full_representation_tag() { |
| 452 return (type_ & (kStringRepresentationMask | kStringEncodingMask)); | 851 return (type_ & (kStringRepresentationMask | kStringEncodingMask)); |
| 453 } | 852 } |
| 454 | 853 |
| 455 | |
| 456 STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) == | 854 STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) == |
| 457 Internals::kFullStringRepresentationMask); | 855 Internals::kFullStringRepresentationMask); |
| 458 | 856 |
| 459 STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) == | 857 STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) == |
| 460 Internals::kStringEncodingMask); | 858 Internals::kStringEncodingMask); |
| 461 | |
| 462 | 859 |
| 463 bool StringShape::IsSequentialOneByte() { | 860 bool StringShape::IsSequentialOneByte() { |
| 464 return full_representation_tag() == (kSeqStringTag | kOneByteStringTag); | 861 return full_representation_tag() == (kSeqStringTag | kOneByteStringTag); |
| 465 } | 862 } |
| 466 | 863 |
| 467 | |
| 468 bool StringShape::IsSequentialTwoByte() { | 864 bool StringShape::IsSequentialTwoByte() { |
| 469 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag); | 865 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag); |
| 470 } | 866 } |
| 471 | 867 |
| 472 | |
| 473 bool StringShape::IsExternalOneByte() { | 868 bool StringShape::IsExternalOneByte() { |
| 474 return full_representation_tag() == (kExternalStringTag | kOneByteStringTag); | 869 return full_representation_tag() == (kExternalStringTag | kOneByteStringTag); |
| 475 } | 870 } |
| 476 | 871 |
| 477 | |
| 478 STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) == | 872 STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) == |
| 479 Internals::kExternalOneByteRepresentationTag); | 873 Internals::kExternalOneByteRepresentationTag); |
| 480 | 874 |
| 481 STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag); | 875 STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag); |
| 482 | 876 |
| 483 | |
| 484 bool StringShape::IsExternalTwoByte() { | 877 bool StringShape::IsExternalTwoByte() { |
| 485 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag); | 878 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag); |
| 486 } | 879 } |
| 487 | 880 |
| 488 | |
| 489 STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) == | 881 STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) == |
| 490 Internals::kExternalTwoByteRepresentationTag); | 882 Internals::kExternalTwoByteRepresentationTag); |
| 491 | 883 |
| 492 STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag); | 884 STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag); |
| 493 | 885 |
| 494 | |
| 495 uc32 FlatStringReader::Get(int index) { | 886 uc32 FlatStringReader::Get(int index) { |
| 496 if (is_one_byte_) { | 887 if (is_one_byte_) { |
| 497 return Get<uint8_t>(index); | 888 return Get<uint8_t>(index); |
| 498 } else { | 889 } else { |
| 499 return Get<uc16>(index); | 890 return Get<uc16>(index); |
| 500 } | 891 } |
| 501 } | 892 } |
| 502 | 893 |
| 503 | |
| 504 template <typename Char> | 894 template <typename Char> |
| 505 Char FlatStringReader::Get(int index) { | 895 Char FlatStringReader::Get(int index) { |
| 506 DCHECK_EQ(is_one_byte_, sizeof(Char) == 1); | 896 DCHECK_EQ(is_one_byte_, sizeof(Char) == 1); |
| 507 DCHECK(0 <= index && index <= length_); | 897 DCHECK(0 <= index && index <= length_); |
| 508 if (sizeof(Char) == 1) { | 898 if (sizeof(Char) == 1) { |
| 509 return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]); | 899 return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]); |
| 510 } else { | 900 } else { |
| 511 return static_cast<Char>(static_cast<const uc16*>(start_)[index]); | 901 return static_cast<Char>(static_cast<const uc16*>(start_)[index]); |
| 512 } | 902 } |
| 513 } | 903 } |
| 514 | 904 |
| 515 | |
| 516 Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) { | 905 Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) { |
| 517 return key->AsHandle(isolate); | 906 return key->AsHandle(isolate); |
| 518 } | 907 } |
| 519 | 908 |
| 520 | |
| 521 Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate, | 909 Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate, |
| 522 HashTableKey* key) { | 910 HashTableKey* key) { |
| 523 return key->AsHandle(isolate); | 911 return key->AsHandle(isolate); |
| 524 } | 912 } |
| 525 | 913 |
| 526 | |
| 527 Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate, | 914 Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate, |
| 528 HashTableKey* key) { | 915 HashTableKey* key) { |
| 529 return key->AsHandle(isolate); | 916 return key->AsHandle(isolate); |
| 530 } | 917 } |
| 531 | 918 |
| 532 template <typename Char> | 919 template <typename Char> |
| 533 class SequentialStringKey : public HashTableKey { | 920 class SequentialStringKey : public HashTableKey { |
| 534 public: | 921 public: |
| 535 explicit SequentialStringKey(Vector<const Char> string, uint32_t seed) | 922 explicit SequentialStringKey(Vector<const Char> string, uint32_t seed) |
| 536 : string_(string), hash_field_(0), seed_(seed) { } | 923 : string_(string), hash_field_(0), seed_(seed) {} |
| 537 | 924 |
| 538 uint32_t Hash() override { | 925 uint32_t Hash() override { |
| 539 hash_field_ = StringHasher::HashSequentialString<Char>(string_.start(), | 926 hash_field_ = StringHasher::HashSequentialString<Char>( |
| 540 string_.length(), | 927 string_.start(), string_.length(), seed_); |
| 541 seed_); | |
| 542 | 928 |
| 543 uint32_t result = hash_field_ >> String::kHashShift; | 929 uint32_t result = hash_field_ >> String::kHashShift; |
| 544 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. | 930 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. |
| 545 return result; | 931 return result; |
| 546 } | 932 } |
| 547 | 933 |
| 548 | |
| 549 uint32_t HashForObject(Object* other) override { | 934 uint32_t HashForObject(Object* other) override { |
| 550 return String::cast(other)->Hash(); | 935 return String::cast(other)->Hash(); |
| 551 } | 936 } |
| 552 | 937 |
| 553 Vector<const Char> string_; | 938 Vector<const Char> string_; |
| 554 uint32_t hash_field_; | 939 uint32_t hash_field_; |
| 555 uint32_t seed_; | 940 uint32_t seed_; |
| 556 }; | 941 }; |
| 557 | 942 |
| 558 | |
| 559 class OneByteStringKey : public SequentialStringKey<uint8_t> { | 943 class OneByteStringKey : public SequentialStringKey<uint8_t> { |
| 560 public: | 944 public: |
| 561 OneByteStringKey(Vector<const uint8_t> str, uint32_t seed) | 945 OneByteStringKey(Vector<const uint8_t> str, uint32_t seed) |
| 562 : SequentialStringKey<uint8_t>(str, seed) { } | 946 : SequentialStringKey<uint8_t>(str, seed) {} |
| 563 | 947 |
| 564 bool IsMatch(Object* string) override { | 948 bool IsMatch(Object* string) override { |
| 565 return String::cast(string)->IsOneByteEqualTo(string_); | 949 return String::cast(string)->IsOneByteEqualTo(string_); |
| 566 } | 950 } |
| 567 | 951 |
| 568 Handle<Object> AsHandle(Isolate* isolate) override; | 952 Handle<Object> AsHandle(Isolate* isolate) override; |
| 569 }; | 953 }; |
| 570 | 954 |
| 571 | |
| 572 class SeqOneByteSubStringKey : public HashTableKey { | 955 class SeqOneByteSubStringKey : public HashTableKey { |
| 573 public: | 956 public: |
| 574 SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length) | 957 SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length) |
| 575 : string_(string), from_(from), length_(length) { | 958 : string_(string), from_(from), length_(length) { |
| 576 DCHECK(string_->IsSeqOneByteString()); | 959 DCHECK(string_->IsSeqOneByteString()); |
| 577 } | 960 } |
| 578 | 961 |
| 579 uint32_t Hash() override { | 962 uint32_t Hash() override { |
| 580 DCHECK(length_ >= 0); | 963 DCHECK(length_ >= 0); |
| 581 DCHECK(from_ + length_ <= string_->length()); | 964 DCHECK(from_ + length_ <= string_->length()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 594 bool IsMatch(Object* string) override; | 977 bool IsMatch(Object* string) override; |
| 595 Handle<Object> AsHandle(Isolate* isolate) override; | 978 Handle<Object> AsHandle(Isolate* isolate) override; |
| 596 | 979 |
| 597 private: | 980 private: |
| 598 Handle<SeqOneByteString> string_; | 981 Handle<SeqOneByteString> string_; |
| 599 int from_; | 982 int from_; |
| 600 int length_; | 983 int length_; |
| 601 uint32_t hash_field_; | 984 uint32_t hash_field_; |
| 602 }; | 985 }; |
| 603 | 986 |
| 604 | |
| 605 class TwoByteStringKey : public SequentialStringKey<uc16> { | 987 class TwoByteStringKey : public SequentialStringKey<uc16> { |
| 606 public: | 988 public: |
| 607 explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed) | 989 explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed) |
| 608 : SequentialStringKey<uc16>(str, seed) { } | 990 : SequentialStringKey<uc16>(str, seed) {} |
| 609 | 991 |
| 610 bool IsMatch(Object* string) override { | 992 bool IsMatch(Object* string) override { |
| 611 return String::cast(string)->IsTwoByteEqualTo(string_); | 993 return String::cast(string)->IsTwoByteEqualTo(string_); |
| 612 } | 994 } |
| 613 | 995 |
| 614 Handle<Object> AsHandle(Isolate* isolate) override; | 996 Handle<Object> AsHandle(Isolate* isolate) override; |
| 615 }; | 997 }; |
| 616 | 998 |
| 617 | |
| 618 // Utf8StringKey carries a vector of chars as key. | 999 // Utf8StringKey carries a vector of chars as key. |
| 619 class Utf8StringKey : public HashTableKey { | 1000 class Utf8StringKey : public HashTableKey { |
| 620 public: | 1001 public: |
| 621 explicit Utf8StringKey(Vector<const char> string, uint32_t seed) | 1002 explicit Utf8StringKey(Vector<const char> string, uint32_t seed) |
| 622 : string_(string), hash_field_(0), seed_(seed) { } | 1003 : string_(string), hash_field_(0), seed_(seed) {} |
| 623 | 1004 |
| 624 bool IsMatch(Object* string) override { | 1005 bool IsMatch(Object* string) override { |
| 625 return String::cast(string)->IsUtf8EqualTo(string_); | 1006 return String::cast(string)->IsUtf8EqualTo(string_); |
| 626 } | 1007 } |
| 627 | 1008 |
| 628 uint32_t Hash() override { | 1009 uint32_t Hash() override { |
| 629 if (hash_field_ != 0) return hash_field_ >> String::kHashShift; | 1010 if (hash_field_ != 0) return hash_field_ >> String::kHashShift; |
| 630 hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_); | 1011 hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_); |
| 631 uint32_t result = hash_field_ >> String::kHashShift; | 1012 uint32_t result = hash_field_ >> String::kHashShift; |
| 632 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. | 1013 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. |
| 633 return result; | 1014 return result; |
| 634 } | 1015 } |
| 635 | 1016 |
| 636 uint32_t HashForObject(Object* other) override { | 1017 uint32_t HashForObject(Object* other) override { |
| 637 return String::cast(other)->Hash(); | 1018 return String::cast(other)->Hash(); |
| 638 } | 1019 } |
| 639 | 1020 |
| 640 Handle<Object> AsHandle(Isolate* isolate) override { | 1021 Handle<Object> AsHandle(Isolate* isolate) override { |
| 641 if (hash_field_ == 0) Hash(); | 1022 if (hash_field_ == 0) Hash(); |
| 642 return isolate->factory()->NewInternalizedStringFromUtf8( | 1023 return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_, |
| 643 string_, chars_, hash_field_); | 1024 hash_field_); |
| 644 } | 1025 } |
| 645 | 1026 |
| 646 Vector<const char> string_; | 1027 Vector<const char> string_; |
| 647 uint32_t hash_field_; | 1028 uint32_t hash_field_; |
| 648 int chars_; // Caches the number of characters when computing the hash code. | 1029 int chars_; // Caches the number of characters when computing the hash code. |
| 649 uint32_t seed_; | 1030 uint32_t seed_; |
| 650 }; | 1031 }; |
| 651 | 1032 |
| 652 | |
| 653 bool Object::IsNumber() const { | |
| 654 return IsSmi() || HeapObject::cast(this)->IsHeapNumber(); | |
| 655 } | |
| 656 | |
| 657 | |
| 658 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE) | |
| 659 TYPE_CHECKER(BytecodeArray, BYTECODE_ARRAY_TYPE) | |
| 660 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE) | |
| 661 | |
| 662 bool HeapObject::IsFiller() const { | |
| 663 InstanceType instance_type = map()->instance_type(); | |
| 664 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE; | |
| 665 } | |
| 666 | |
| 667 | |
| 668 | |
| 669 #define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \ | |
| 670 TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE) | |
| 671 | |
| 672 TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER) | |
| 673 #undef TYPED_ARRAY_TYPE_CHECKER | |
| 674 | |
| 675 bool HeapObject::IsFixedTypedArrayBase() const { | |
| 676 InstanceType instance_type = map()->instance_type(); | |
| 677 return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE && | |
| 678 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE); | |
| 679 } | |
| 680 | |
| 681 bool HeapObject::IsJSReceiver() const { | |
| 682 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
| 683 return map()->instance_type() >= FIRST_JS_RECEIVER_TYPE; | |
| 684 } | |
| 685 | |
| 686 bool HeapObject::IsJSObject() const { | |
| 687 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); | |
| 688 return map()->IsJSObjectMap(); | |
| 689 } | |
| 690 | |
| 691 bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); } | |
| 692 | |
| 693 bool HeapObject::IsJSArrayIterator() const { | |
| 694 InstanceType instance_type = map()->instance_type(); | |
| 695 return (instance_type >= FIRST_ARRAY_ITERATOR_TYPE && | |
| 696 instance_type <= LAST_ARRAY_ITERATOR_TYPE); | |
| 697 } | |
| 698 | |
| 699 TYPE_CHECKER(JSSet, JS_SET_TYPE) | |
| 700 TYPE_CHECKER(JSMap, JS_MAP_TYPE) | |
| 701 TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE) | |
| 702 TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE) | |
| 703 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE) | |
| 704 TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE) | |
| 705 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE) | |
| 706 TYPE_CHECKER(Map, MAP_TYPE) | |
| 707 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE) | |
| 708 TYPE_CHECKER(WeakFixedArray, FIXED_ARRAY_TYPE) | |
| 709 TYPE_CHECKER(TransitionArray, TRANSITION_ARRAY_TYPE) | |
| 710 TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE) | |
| 711 | |
| 712 bool HeapObject::IsJSWeakCollection() const { | |
| 713 return IsJSWeakMap() || IsJSWeakSet(); | |
| 714 } | |
| 715 | |
| 716 bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); } | |
| 717 | |
| 718 bool HeapObject::IsDescriptorArray() const { return IsFixedArray(); } | |
| 719 | |
| 720 bool HeapObject::IsFrameArray() const { return IsFixedArray(); } | |
| 721 | |
| 722 bool HeapObject::IsArrayList() const { return IsFixedArray(); } | |
| 723 | |
| 724 bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArray(); } | |
| 725 | |
| 726 bool Object::IsLayoutDescriptor() const { | |
| 727 return IsSmi() || IsFixedTypedArrayBase(); | |
| 728 } | |
| 729 | |
| 730 bool HeapObject::IsTypeFeedbackVector() const { return IsFixedArray(); } | |
| 731 | |
| 732 bool HeapObject::IsTypeFeedbackMetadata() const { return IsFixedArray(); } | |
| 733 | |
| 734 bool HeapObject::IsLiteralsArray() const { return IsFixedArray(); } | |
| 735 | |
| 736 bool HeapObject::IsDeoptimizationInputData() const { | |
| 737 // Must be a fixed array. | |
| 738 if (!IsFixedArray()) return false; | |
| 739 | |
| 740 // There's no sure way to detect the difference between a fixed array and | |
| 741 // a deoptimization data array. Since this is used for asserts we can | |
| 742 // check that the length is zero or else the fixed size plus a multiple of | |
| 743 // the entry size. | |
| 744 int length = FixedArray::cast(this)->length(); | |
| 745 if (length == 0) return true; | |
| 746 | |
| 747 length -= DeoptimizationInputData::kFirstDeoptEntryIndex; | |
| 748 return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0; | |
| 749 } | |
| 750 | |
| 751 bool HeapObject::IsDeoptimizationOutputData() const { | |
| 752 if (!IsFixedArray()) return false; | |
| 753 // There's actually no way to see the difference between a fixed array and | |
| 754 // a deoptimization data array. Since this is used for asserts we can check | |
| 755 // that the length is plausible though. | |
| 756 if (FixedArray::cast(this)->length() % 2 != 0) return false; | |
| 757 return true; | |
| 758 } | |
| 759 | |
| 760 bool HeapObject::IsHandlerTable() const { | |
| 761 if (!IsFixedArray()) return false; | |
| 762 // There's actually no way to see the difference between a fixed array and | |
| 763 // a handler table array. | |
| 764 return true; | |
| 765 } | |
| 766 | |
| 767 bool HeapObject::IsTemplateList() const { | |
| 768 if (!IsFixedArray()) return false; | |
| 769 // There's actually no way to see the difference between a fixed array and | |
| 770 // a template list. | |
| 771 if (FixedArray::cast(this)->length() < 1) return false; | |
| 772 return true; | |
| 773 } | |
| 774 | |
| 775 bool HeapObject::IsDependentCode() const { | |
| 776 if (!IsFixedArray()) return false; | |
| 777 // There's actually no way to see the difference between a fixed array and | |
| 778 // a dependent codes array. | |
| 779 return true; | |
| 780 } | |
| 781 | |
| 782 bool HeapObject::IsContext() const { | |
| 783 Map* map = this->map(); | |
| 784 Heap* heap = GetHeap(); | |
| 785 return ( | |
| 786 map == heap->function_context_map() || map == heap->catch_context_map() || | |
| 787 map == heap->with_context_map() || map == heap->native_context_map() || | |
| 788 map == heap->block_context_map() || map == heap->module_context_map() || | |
| 789 map == heap->script_context_map() || | |
| 790 map == heap->debug_evaluate_context_map()); | |
| 791 } | |
| 792 | |
| 793 bool HeapObject::IsNativeContext() const { | |
| 794 return map() == GetHeap()->native_context_map(); | |
| 795 } | |
| 796 | |
| 797 bool HeapObject::IsScriptContextTable() const { | |
| 798 return map() == GetHeap()->script_context_table_map(); | |
| 799 } | |
| 800 | |
| 801 bool HeapObject::IsScopeInfo() const { | |
| 802 return map() == GetHeap()->scope_info_map(); | |
| 803 } | |
| 804 | |
| 805 bool HeapObject::IsModuleInfo() const { | |
| 806 return map() == GetHeap()->module_info_map(); | |
| 807 } | |
| 808 | |
| 809 TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE) | |
| 810 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE) | |
| 811 | |
| 812 | |
| 813 template <> inline bool Is<JSFunction>(Object* obj) { | |
| 814 return obj->IsJSFunction(); | |
| 815 } | |
| 816 | |
| 817 | |
| 818 TYPE_CHECKER(Code, CODE_TYPE) | |
| 819 TYPE_CHECKER(Oddball, ODDBALL_TYPE) | |
| 820 TYPE_CHECKER(Cell, CELL_TYPE) | |
| 821 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE) | |
| 822 TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE) | |
| 823 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE) | |
| 824 TYPE_CHECKER(JSDate, JS_DATE_TYPE) | |
| 825 TYPE_CHECKER(JSError, JS_ERROR_TYPE) | |
| 826 TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE) | |
| 827 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE) | |
| 828 TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE) | |
| 829 TYPE_CHECKER(JSValue, JS_VALUE_TYPE) | |
| 830 | |
| 831 bool HeapObject::IsAbstractCode() const { | |
| 832 return IsBytecodeArray() || IsCode(); | |
| 833 } | |
| 834 | |
| 835 bool HeapObject::IsStringWrapper() const { | |
| 836 return IsJSValue() && JSValue::cast(this)->value()->IsString(); | |
| 837 } | |
| 838 | |
| 839 | |
| 840 TYPE_CHECKER(Foreign, FOREIGN_TYPE) | |
| 841 | |
| 842 bool HeapObject::IsBoolean() const { | |
| 843 return IsOddball() && | |
| 844 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0); | |
| 845 } | |
| 846 | |
| 847 | |
| 848 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE) | |
| 849 TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE) | |
| 850 TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE) | |
| 851 TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE) | |
| 852 | |
| 853 bool HeapObject::IsJSArrayBufferView() const { | |
| 854 return IsJSDataView() || IsJSTypedArray(); | |
| 855 } | |
| 856 | |
| 857 | |
| 858 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE) | |
| 859 | |
| 860 template <> inline bool Is<JSArray>(Object* obj) { | |
| 861 return obj->IsJSArray(); | |
| 862 } | |
| 863 | |
| 864 bool HeapObject::IsHashTable() const { | |
| 865 return map() == GetHeap()->hash_table_map(); | |
| 866 } | |
| 867 | |
| 868 bool HeapObject::IsWeakHashTable() const { return IsHashTable(); } | |
| 869 | |
| 870 bool HeapObject::IsDictionary() const { | |
| 871 return IsHashTable() && this != GetHeap()->string_table(); | |
| 872 } | |
| 873 | |
| 874 | |
| 875 bool Object::IsNameDictionary() const { | |
| 876 return IsDictionary(); | |
| 877 } | |
| 878 | |
| 879 | |
| 880 bool Object::IsGlobalDictionary() const { return IsDictionary(); } | |
| 881 | |
| 882 | |
| 883 bool Object::IsSeededNumberDictionary() const { | |
| 884 return IsDictionary(); | |
| 885 } | |
| 886 | |
| 887 bool HeapObject::IsUnseededNumberDictionary() const { | |
| 888 return map() == GetHeap()->unseeded_number_dictionary_map(); | |
| 889 } | |
| 890 | |
| 891 bool HeapObject::IsStringTable() const { return IsHashTable(); } | |
| 892 | |
| 893 bool HeapObject::IsStringSet() const { return IsHashTable(); } | |
| 894 | |
| 895 bool HeapObject::IsObjectHashSet() const { return IsHashTable(); } | |
| 896 | |
| 897 bool HeapObject::IsNormalizedMapCache() const { | |
| 898 return NormalizedMapCache::IsNormalizedMapCache(this); | |
| 899 } | |
| 900 | |
| 901 | |
| 902 int NormalizedMapCache::GetIndex(Handle<Map> map) { | |
| 903 return map->Hash() % NormalizedMapCache::kEntries; | |
| 904 } | |
| 905 | |
| 906 bool NormalizedMapCache::IsNormalizedMapCache(const HeapObject* obj) { | |
| 907 if (!obj->IsFixedArray()) return false; | |
| 908 if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) { | |
| 909 return false; | |
| 910 } | |
| 911 #ifdef VERIFY_HEAP | |
| 912 if (FLAG_verify_heap) { | |
| 913 reinterpret_cast<NormalizedMapCache*>(const_cast<HeapObject*>(obj)) | |
| 914 ->NormalizedMapCacheVerify(); | |
| 915 } | |
| 916 #endif | |
| 917 return true; | |
| 918 } | |
| 919 | |
| 920 bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); } | |
| 921 | |
| 922 bool HeapObject::IsCodeCacheHashTable() const { return IsHashTable(); } | |
| 923 | |
| 924 bool HeapObject::IsMapCache() const { return IsHashTable(); } | |
| 925 | |
| 926 bool HeapObject::IsObjectHashTable() const { return IsHashTable(); } | |
| 927 | |
| 928 bool HeapObject::IsOrderedHashTable() const { | |
| 929 return map() == GetHeap()->ordered_hash_table_map(); | |
| 930 } | |
| 931 | |
| 932 | |
| 933 bool Object::IsOrderedHashSet() const { | |
| 934 return IsOrderedHashTable(); | |
| 935 } | |
| 936 | |
| 937 | |
| 938 bool Object::IsOrderedHashMap() const { | |
| 939 return IsOrderedHashTable(); | |
| 940 } | |
| 941 | |
| 942 | |
| 943 bool Object::IsPrimitive() const { | |
| 944 return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap(); | |
| 945 } | |
| 946 | |
| 947 bool HeapObject::IsJSGlobalProxy() const { | |
| 948 bool result = map()->instance_type() == JS_GLOBAL_PROXY_TYPE; | |
| 949 DCHECK(!result || map()->is_access_check_needed()); | |
| 950 return result; | |
| 951 } | |
| 952 | |
| 953 | |
| 954 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE) | |
| 955 | |
| 956 bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); } | |
| 957 | |
| 958 bool HeapObject::IsAccessCheckNeeded() const { | |
| 959 if (IsJSGlobalProxy()) { | |
| 960 const JSGlobalProxy* proxy = JSGlobalProxy::cast(this); | |
| 961 JSGlobalObject* global = proxy->GetIsolate()->context()->global_object(); | |
| 962 return proxy->IsDetachedFrom(global); | |
| 963 } | |
| 964 return map()->is_access_check_needed(); | |
| 965 } | |
| 966 | |
| 967 bool HeapObject::IsStruct() const { | |
| 968 switch (map()->instance_type()) { | |
| 969 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true; | |
| 970 STRUCT_LIST(MAKE_STRUCT_CASE) | |
| 971 #undef MAKE_STRUCT_CASE | |
| 972 default: return false; | |
| 973 } | |
| 974 } | |
| 975 | |
| 976 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \ | |
| 977 bool Object::Is##Name() const { \ | |
| 978 return IsHeapObject() && HeapObject::cast(this)->Is##Name(); \ | |
| 979 } \ | |
| 980 bool HeapObject::Is##Name() const { \ | |
| 981 return map()->instance_type() == NAME##_TYPE; \ | |
| 982 } | |
| 983 STRUCT_LIST(MAKE_STRUCT_PREDICATE) | |
| 984 #undef MAKE_STRUCT_PREDICATE | |
| 985 | |
| 986 double Object::Number() const { | |
| 987 DCHECK(IsNumber()); | |
| 988 return IsSmi() | |
| 989 ? static_cast<double>(reinterpret_cast<const Smi*>(this)->value()) | |
| 990 : reinterpret_cast<const HeapNumber*>(this)->value(); | |
| 991 } | |
| 992 | |
| 993 | |
| 994 bool Object::IsNaN() const { | |
| 995 return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value()); | |
| 996 } | |
| 997 | |
| 998 | |
| 999 bool Object::IsMinusZero() const { | |
| 1000 return this->IsHeapNumber() && | |
| 1001 i::IsMinusZero(HeapNumber::cast(this)->value()); | |
| 1002 } | |
| 1003 | |
| 1004 | |
| 1005 Representation Object::OptimalRepresentation() { | 1033 Representation Object::OptimalRepresentation() { |
| 1006 if (!FLAG_track_fields) return Representation::Tagged(); | 1034 if (!FLAG_track_fields) return Representation::Tagged(); |
| 1007 if (IsSmi()) { | 1035 if (IsSmi()) { |
| 1008 return Representation::Smi(); | 1036 return Representation::Smi(); |
| 1009 } else if (FLAG_track_double_fields && IsHeapNumber()) { | 1037 } else if (FLAG_track_double_fields && IsHeapNumber()) { |
| 1010 return Representation::Double(); | 1038 return Representation::Double(); |
| 1011 } else if (FLAG_track_computed_fields && | 1039 } else if (FLAG_track_computed_fields && |
| 1012 IsUninitialized(HeapObject::cast(this)->GetIsolate())) { | 1040 IsUninitialized(HeapObject::cast(this)->GetIsolate())) { |
| 1013 return Representation::None(); | 1041 return Representation::None(); |
| 1014 } else if (FLAG_track_heap_object_fields) { | 1042 } else if (FLAG_track_heap_object_fields) { |
| (...skipping 2274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3289 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value()); | 3317 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value()); |
| 3290 return value >> kRequiresSlowElementsTagSize; | 3318 return value >> kRequiresSlowElementsTagSize; |
| 3291 } | 3319 } |
| 3292 | 3320 |
| 3293 | 3321 |
| 3294 void SeededNumberDictionary::set_requires_slow_elements() { | 3322 void SeededNumberDictionary::set_requires_slow_elements() { |
| 3295 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask)); | 3323 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask)); |
| 3296 } | 3324 } |
| 3297 | 3325 |
| 3298 | 3326 |
| 3299 // ------------------------------------ | |
| 3300 // Cast operations | |
| 3301 | |
| 3302 CAST_ACCESSOR(AbstractCode) | |
| 3303 CAST_ACCESSOR(ArrayList) | |
| 3304 CAST_ACCESSOR(Bool16x8) | |
| 3305 CAST_ACCESSOR(Bool32x4) | |
| 3306 CAST_ACCESSOR(Bool8x16) | |
| 3307 CAST_ACCESSOR(ByteArray) | |
| 3308 CAST_ACCESSOR(BytecodeArray) | |
| 3309 CAST_ACCESSOR(Cell) | |
| 3310 CAST_ACCESSOR(Code) | |
| 3311 CAST_ACCESSOR(CodeCacheHashTable) | |
| 3312 CAST_ACCESSOR(CompilationCacheTable) | |
| 3313 CAST_ACCESSOR(ConsString) | |
| 3314 CAST_ACCESSOR(DeoptimizationInputData) | |
| 3315 CAST_ACCESSOR(DeoptimizationOutputData) | |
| 3316 CAST_ACCESSOR(DependentCode) | |
| 3317 CAST_ACCESSOR(DescriptorArray) | |
| 3318 CAST_ACCESSOR(ExternalOneByteString) | |
| 3319 CAST_ACCESSOR(ExternalString) | |
| 3320 CAST_ACCESSOR(ExternalTwoByteString) | |
| 3321 CAST_ACCESSOR(FixedArray) | |
| 3322 CAST_ACCESSOR(FixedArrayBase) | |
| 3323 CAST_ACCESSOR(FixedDoubleArray) | |
| 3324 CAST_ACCESSOR(FixedTypedArrayBase) | |
| 3325 CAST_ACCESSOR(Float32x4) | |
| 3326 CAST_ACCESSOR(Foreign) | |
| 3327 CAST_ACCESSOR(FrameArray) | |
| 3328 CAST_ACCESSOR(GlobalDictionary) | |
| 3329 CAST_ACCESSOR(HandlerTable) | |
| 3330 CAST_ACCESSOR(HeapObject) | |
| 3331 CAST_ACCESSOR(Int16x8) | |
| 3332 CAST_ACCESSOR(Int32x4) | |
| 3333 CAST_ACCESSOR(Int8x16) | |
| 3334 CAST_ACCESSOR(JSArray) | |
| 3335 CAST_ACCESSOR(JSArrayBuffer) | |
| 3336 CAST_ACCESSOR(JSArrayBufferView) | |
| 3337 CAST_ACCESSOR(JSBoundFunction) | |
| 3338 CAST_ACCESSOR(JSDataView) | |
| 3339 CAST_ACCESSOR(JSDate) | |
| 3340 CAST_ACCESSOR(JSFunction) | |
| 3341 CAST_ACCESSOR(JSGeneratorObject) | |
| 3342 CAST_ACCESSOR(JSGlobalObject) | |
| 3343 CAST_ACCESSOR(JSGlobalProxy) | |
| 3344 CAST_ACCESSOR(JSMap) | |
| 3345 CAST_ACCESSOR(JSMapIterator) | |
| 3346 CAST_ACCESSOR(JSMessageObject) | |
| 3347 CAST_ACCESSOR(JSModuleNamespace) | |
| 3348 CAST_ACCESSOR(JSObject) | |
| 3349 CAST_ACCESSOR(JSProxy) | |
| 3350 CAST_ACCESSOR(JSReceiver) | |
| 3351 CAST_ACCESSOR(JSRegExp) | |
| 3352 CAST_ACCESSOR(JSPromise) | |
| 3353 CAST_ACCESSOR(JSSet) | |
| 3354 CAST_ACCESSOR(JSSetIterator) | |
| 3355 CAST_ACCESSOR(JSStringIterator) | |
| 3356 CAST_ACCESSOR(JSArrayIterator) | |
| 3357 CAST_ACCESSOR(JSTypedArray) | |
| 3358 CAST_ACCESSOR(JSValue) | |
| 3359 CAST_ACCESSOR(JSWeakCollection) | |
| 3360 CAST_ACCESSOR(JSWeakMap) | |
| 3361 CAST_ACCESSOR(JSWeakSet) | |
| 3362 CAST_ACCESSOR(LayoutDescriptor) | |
| 3363 CAST_ACCESSOR(Map) | |
| 3364 CAST_ACCESSOR(ModuleInfo) | |
| 3365 CAST_ACCESSOR(Name) | |
| 3366 CAST_ACCESSOR(NameDictionary) | |
| 3367 CAST_ACCESSOR(NormalizedMapCache) | |
| 3368 CAST_ACCESSOR(Object) | |
| 3369 CAST_ACCESSOR(ObjectHashTable) | |
| 3370 CAST_ACCESSOR(ObjectHashSet) | |
| 3371 CAST_ACCESSOR(Oddball) | |
| 3372 CAST_ACCESSOR(OrderedHashMap) | |
| 3373 CAST_ACCESSOR(OrderedHashSet) | |
| 3374 CAST_ACCESSOR(PropertyCell) | |
| 3375 CAST_ACCESSOR(TemplateList) | |
| 3376 CAST_ACCESSOR(RegExpMatchInfo) | |
| 3377 CAST_ACCESSOR(ScopeInfo) | |
| 3378 CAST_ACCESSOR(SeededNumberDictionary) | |
| 3379 CAST_ACCESSOR(SeqOneByteString) | |
| 3380 CAST_ACCESSOR(SeqString) | |
| 3381 CAST_ACCESSOR(SeqTwoByteString) | |
| 3382 CAST_ACCESSOR(SharedFunctionInfo) | |
| 3383 CAST_ACCESSOR(Simd128Value) | |
| 3384 CAST_ACCESSOR(SlicedString) | |
| 3385 CAST_ACCESSOR(Smi) | |
| 3386 CAST_ACCESSOR(String) | |
| 3387 CAST_ACCESSOR(StringSet) | |
| 3388 CAST_ACCESSOR(StringTable) | |
| 3389 CAST_ACCESSOR(Struct) | |
| 3390 CAST_ACCESSOR(Symbol) | |
| 3391 CAST_ACCESSOR(TemplateInfo) | |
| 3392 CAST_ACCESSOR(Uint16x8) | |
| 3393 CAST_ACCESSOR(Uint32x4) | |
| 3394 CAST_ACCESSOR(Uint8x16) | |
| 3395 CAST_ACCESSOR(UnseededNumberDictionary) | |
| 3396 CAST_ACCESSOR(WeakCell) | |
| 3397 CAST_ACCESSOR(WeakFixedArray) | |
| 3398 CAST_ACCESSOR(WeakHashTable) | |
| 3399 | |
| 3400 template <class T> | 3327 template <class T> |
| 3401 PodArray<T>* PodArray<T>::cast(Object* object) { | 3328 PodArray<T>* PodArray<T>::cast(Object* object) { |
| 3402 SLOW_DCHECK(object->IsByteArray()); | 3329 SLOW_DCHECK(object->IsByteArray()); |
| 3403 return reinterpret_cast<PodArray<T>*>(object); | 3330 return reinterpret_cast<PodArray<T>*>(object); |
| 3404 } | 3331 } |
| 3405 template <class T> | 3332 template <class T> |
| 3406 const PodArray<T>* PodArray<T>::cast(const Object* object) { | 3333 const PodArray<T>* PodArray<T>::cast(const Object* object) { |
| 3407 SLOW_DCHECK(object->IsByteArray()); | 3334 SLOW_DCHECK(object->IsByteArray()); |
| 3408 return reinterpret_cast<const PodArray<T>*>(object); | 3335 return reinterpret_cast<const PodArray<T>*>(object); |
| 3409 } | 3336 } |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3620 | 3547 |
| 3621 void HandlerTable::SetReturnHandler(int index, int offset) { | 3548 void HandlerTable::SetReturnHandler(int index, int offset) { |
| 3622 int value = HandlerOffsetField::encode(offset); | 3549 int value = HandlerOffsetField::encode(offset); |
| 3623 set(index * kReturnEntrySize + kReturnHandlerIndex, Smi::FromInt(value)); | 3550 set(index * kReturnEntrySize + kReturnHandlerIndex, Smi::FromInt(value)); |
| 3624 } | 3551 } |
| 3625 | 3552 |
| 3626 int HandlerTable::NumberOfRangeEntries() const { | 3553 int HandlerTable::NumberOfRangeEntries() const { |
| 3627 return length() / kRangeEntrySize; | 3554 return length() / kRangeEntrySize; |
| 3628 } | 3555 } |
| 3629 | 3556 |
| 3630 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name) | |
| 3631 STRUCT_LIST(MAKE_STRUCT_CAST) | |
| 3632 #undef MAKE_STRUCT_CAST | |
| 3633 | |
| 3634 | |
| 3635 template <typename Derived, typename Shape, typename Key> | 3557 template <typename Derived, typename Shape, typename Key> |
| 3636 HashTable<Derived, Shape, Key>* | 3558 HashTable<Derived, Shape, Key>* |
| 3637 HashTable<Derived, Shape, Key>::cast(Object* obj) { | 3559 HashTable<Derived, Shape, Key>::cast(Object* obj) { |
| 3638 SLOW_DCHECK(obj->IsHashTable()); | 3560 SLOW_DCHECK(obj->IsHashTable()); |
| 3639 return reinterpret_cast<HashTable*>(obj); | 3561 return reinterpret_cast<HashTable*>(obj); |
| 3640 } | 3562 } |
| 3641 | 3563 |
| 3642 | 3564 |
| 3643 template <typename Derived, typename Shape, typename Key> | 3565 template <typename Derived, typename Shape, typename Key> |
| 3644 const HashTable<Derived, Shape, Key>* | 3566 const HashTable<Derived, Shape, Key>* |
| (...skipping 3163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6808 } | 6730 } |
| 6809 | 6731 |
| 6810 bool JSGeneratorObject::is_closed() const { | 6732 bool JSGeneratorObject::is_closed() const { |
| 6811 return continuation() == kGeneratorClosed; | 6733 return continuation() == kGeneratorClosed; |
| 6812 } | 6734 } |
| 6813 | 6735 |
| 6814 bool JSGeneratorObject::is_executing() const { | 6736 bool JSGeneratorObject::is_executing() const { |
| 6815 return continuation() == kGeneratorExecuting; | 6737 return continuation() == kGeneratorExecuting; |
| 6816 } | 6738 } |
| 6817 | 6739 |
| 6818 TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE) | |
| 6819 | |
| 6820 ACCESSORS(JSValue, value, Object, kValueOffset) | 6740 ACCESSORS(JSValue, value, Object, kValueOffset) |
| 6821 | 6741 |
| 6822 | 6742 |
| 6823 HeapNumber* HeapNumber::cast(Object* object) { | 6743 HeapNumber* HeapNumber::cast(Object* object) { |
| 6824 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber()); | 6744 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber()); |
| 6825 return reinterpret_cast<HeapNumber*>(object); | 6745 return reinterpret_cast<HeapNumber*>(object); |
| 6826 } | 6746 } |
| 6827 | 6747 |
| 6828 | 6748 |
| 6829 const HeapNumber* HeapNumber::cast(const Object* object) { | 6749 const HeapNumber* HeapNumber::cast(const Object* object) { |
| (...skipping 1627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8457 ACCESSORS(JSIteratorResult, value, Object, kValueOffset) | 8377 ACCESSORS(JSIteratorResult, value, Object, kValueOffset) |
| 8458 ACCESSORS(JSIteratorResult, done, Object, kDoneOffset) | 8378 ACCESSORS(JSIteratorResult, done, Object, kDoneOffset) |
| 8459 | 8379 |
| 8460 ACCESSORS(JSArrayIterator, object, Object, kIteratedObjectOffset) | 8380 ACCESSORS(JSArrayIterator, object, Object, kIteratedObjectOffset) |
| 8461 ACCESSORS(JSArrayIterator, index, Object, kNextIndexOffset) | 8381 ACCESSORS(JSArrayIterator, index, Object, kNextIndexOffset) |
| 8462 ACCESSORS(JSArrayIterator, object_map, Object, kIteratedObjectMapOffset) | 8382 ACCESSORS(JSArrayIterator, object_map, Object, kIteratedObjectMapOffset) |
| 8463 | 8383 |
| 8464 ACCESSORS(JSStringIterator, string, String, kStringOffset) | 8384 ACCESSORS(JSStringIterator, string, String, kStringOffset) |
| 8465 SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset) | 8385 SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset) |
| 8466 | 8386 |
| 8467 #undef TYPE_CHECKER | |
| 8468 #undef CAST_ACCESSOR | |
| 8469 #undef INT_ACCESSORS | 8387 #undef INT_ACCESSORS |
| 8470 #undef ACCESSORS | 8388 #undef ACCESSORS |
| 8471 #undef SMI_ACCESSORS | 8389 #undef SMI_ACCESSORS |
| 8472 #undef SYNCHRONIZED_SMI_ACCESSORS | 8390 #undef SYNCHRONIZED_SMI_ACCESSORS |
| 8473 #undef NOBARRIER_SMI_ACCESSORS | 8391 #undef NOBARRIER_SMI_ACCESSORS |
| 8474 #undef BOOL_GETTER | 8392 #undef BOOL_GETTER |
| 8475 #undef BOOL_ACCESSORS | 8393 #undef BOOL_ACCESSORS |
| 8476 #undef FIELD_ADDR | 8394 #undef FIELD_ADDR |
| 8477 #undef FIELD_ADDR_CONST | 8395 #undef FIELD_ADDR_CONST |
| 8478 #undef READ_FIELD | 8396 #undef READ_FIELD |
| (...skipping 28 matching lines...) Expand all Loading... |
| 8507 #undef WRITE_INT64_FIELD | 8425 #undef WRITE_INT64_FIELD |
| 8508 #undef READ_BYTE_FIELD | 8426 #undef READ_BYTE_FIELD |
| 8509 #undef WRITE_BYTE_FIELD | 8427 #undef WRITE_BYTE_FIELD |
| 8510 #undef NOBARRIER_READ_BYTE_FIELD | 8428 #undef NOBARRIER_READ_BYTE_FIELD |
| 8511 #undef NOBARRIER_WRITE_BYTE_FIELD | 8429 #undef NOBARRIER_WRITE_BYTE_FIELD |
| 8512 | 8430 |
| 8513 } // namespace internal | 8431 } // namespace internal |
| 8514 } // namespace v8 | 8432 } // namespace v8 |
| 8515 | 8433 |
| 8516 #endif // V8_OBJECTS_INL_H_ | 8434 #endif // V8_OBJECTS_INL_H_ |
| OLD | NEW |