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 |