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