1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // Review notes:
29 //
30 // - The use of macros in these inline functions may seem superfluous
31 // but it is absolutely needed to make sure gcc generates optimal
32 // code. gcc is not happy when attempting to inline too deep.
33 //
34
35 #ifndef V8_OBJECTS_INL_H_
36 #define V8_OBJECTS_INL_H_
37
38 #include "elements.h"
39 #include "objects.h"
40 #include "contexts.h"
41 #include "conversions-inl.h"
42 #include "heap.h"
43 #include "isolate.h"
44 #include "property.h"
45 #include "spaces.h"
46 #include "store-buffer.h"
47 #include "v8memory.h"
48 #include "factory.h"
49 #include "incremental-marking.h"
50
51 namespace v8 {
52 namespace internal {
53
PropertyDetails(Smi * smi)54 PropertyDetails::PropertyDetails(Smi* smi) {
55 value_ = smi->value();
56 }
57
58
AsSmi()59 Smi* PropertyDetails::AsSmi() {
60 return Smi::FromInt(value_);
61 }
62
63
AsDeleted()64 PropertyDetails PropertyDetails::AsDeleted() {
65 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
66 return PropertyDetails(smi);
67 }
68
69
70 #define TYPE_CHECKER(type, instancetype) \
71 bool Object::Is##type() { \
72 return Object::IsHeapObject() && \
73 HeapObject::cast(this)->map()->instance_type() == instancetype; \
74 }
75
76
77 #define CAST_ACCESSOR(type) \
78 type* type::cast(Object* object) { \
79 ASSERT(object->Is##type()); \
80 return reinterpret_cast<type*>(object); \
81 }
82
83
84 #define INT_ACCESSORS(holder, name, offset) \
85 int holder::name() { return READ_INT_FIELD(this, offset); } \
86 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
87
88
89 #define ACCESSORS(holder, name, type, offset) \
90 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
91 void holder::set_##name(type* value, WriteBarrierMode mode) { \
92 WRITE_FIELD(this, offset, value); \
93 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \
94 }
95
96
97 // Getter that returns a tagged Smi and setter that writes a tagged Smi.
98 #define ACCESSORS_TO_SMI(holder, name, offset) \
99 Smi* holder::name() { return Smi::cast(READ_FIELD(this, offset)); } \
100 void holder::set_##name(Smi* value, WriteBarrierMode mode) { \
101 WRITE_FIELD(this, offset, value); \
102 }
103
104
105 // Getter that returns a Smi as an int and writes an int as a Smi.
106 #define SMI_ACCESSORS(holder, name, offset) \
107 int holder::name() { \
108 Object* value = READ_FIELD(this, offset); \
109 return Smi::cast(value)->value(); \
110 } \
111 void holder::set_##name(int value) { \
112 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
113 }
114
115
116 #define BOOL_GETTER(holder, field, name, offset) \
117 bool holder::name() { \
118 return BooleanBit::get(field(), offset); \
119 } \
120
121
122 #define BOOL_ACCESSORS(holder, field, name, offset) \
123 bool holder::name() { \
124 return BooleanBit::get(field(), offset); \
125 } \
126 void holder::set_##name(bool value) { \
127 set_##field(BooleanBit::set(field(), offset, value)); \
128 }
129
130
IsMoreGeneralElementsKindTransition(ElementsKind from_kind,ElementsKind to_kind)131 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
132 ElementsKind to_kind) {
133 if (to_kind == FAST_ELEMENTS) {
134 return from_kind == FAST_SMI_ONLY_ELEMENTS ||
135 from_kind == FAST_DOUBLE_ELEMENTS;
136 } else {
137 return to_kind == FAST_DOUBLE_ELEMENTS &&
138 from_kind == FAST_SMI_ONLY_ELEMENTS;
139 }
140 }
141
142
IsFixedArrayBase()143 bool Object::IsFixedArrayBase() {
144 return IsFixedArray() || IsFixedDoubleArray();
145 }
146
147
IsInstanceOf(FunctionTemplateInfo * expected)148 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
149 // There is a constraint on the object; check.
150 if (!this->IsJSObject()) return false;
151 // Fetch the constructor function of the object.
152 Object* cons_obj = JSObject::cast(this)->map()->constructor();
153 if (!cons_obj->IsJSFunction()) return false;
154 JSFunction* fun = JSFunction::cast(cons_obj);
155 // Iterate through the chain of inheriting function templates to
156 // see if the required one occurs.
157 for (Object* type = fun->shared()->function_data();
158 type->IsFunctionTemplateInfo();
159 type = FunctionTemplateInfo::cast(type)->parent_template()) {
160 if (type == expected) return true;
161 }
162 // Didn't find the required type in the inheritance chain.
163 return false;
164 }
165
166
IsSmi()167 bool Object::IsSmi() {
168 return HAS_SMI_TAG(this);
169 }
170
171
IsHeapObject()172 bool Object::IsHeapObject() {
173 return Internals::HasHeapObjectTag(this);
174 }
175
176
NonFailureIsHeapObject()177 bool Object::NonFailureIsHeapObject() {
178 ASSERT(!this->IsFailure());
179 return (reinterpret_cast<intptr_t>(this) & kSmiTagMask) != 0;
180 }
181
182
TYPE_CHECKER(HeapNumber,HEAP_NUMBER_TYPE)183 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
184
185
186 bool Object::IsString() {
187 return Object::IsHeapObject()
188 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
189 }
190
191
IsSpecObject()192 bool Object::IsSpecObject() {
193 return Object::IsHeapObject()
194 && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
195 }
196
197
IsSpecFunction()198 bool Object::IsSpecFunction() {
199 if (!Object::IsHeapObject()) return false;
200 InstanceType type = HeapObject::cast(this)->map()->instance_type();
201 return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
202 }
203
204
IsSymbol()205 bool Object::IsSymbol() {
206 if (!this->IsHeapObject()) return false;
207 uint32_t type = HeapObject::cast(this)->map()->instance_type();
208 // Because the symbol tag is non-zero and no non-string types have the
209 // symbol bit set we can test for symbols with a very simple test
210 // operation.
211 STATIC_ASSERT(kSymbolTag != 0);
212 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
213 return (type & kIsSymbolMask) != 0;
214 }
215
216
IsConsString()217 bool Object::IsConsString() {
218 if (!IsString()) return false;
219 return StringShape(String::cast(this)).IsCons();
220 }
221
222
IsSlicedString()223 bool Object::IsSlicedString() {
224 if (!IsString()) return false;
225 return StringShape(String::cast(this)).IsSliced();
226 }
227
228
IsSeqString()229 bool Object::IsSeqString() {
230 if (!IsString()) return false;
231 return StringShape(String::cast(this)).IsSequential();
232 }
233
234
IsSeqAsciiString()235 bool Object::IsSeqAsciiString() {
236 if (!IsString()) return false;
237 return StringShape(String::cast(this)).IsSequential() &&
238 String::cast(this)->IsAsciiRepresentation();
239 }
240
241
IsSeqTwoByteString()242 bool Object::IsSeqTwoByteString() {
243 if (!IsString()) return false;
244 return StringShape(String::cast(this)).IsSequential() &&
245 String::cast(this)->IsTwoByteRepresentation();
246 }
247
248
IsExternalString()249 bool Object::IsExternalString() {
250 if (!IsString()) return false;
251 return StringShape(String::cast(this)).IsExternal();
252 }
253
254
IsExternalAsciiString()255 bool Object::IsExternalAsciiString() {
256 if (!IsString()) return false;
257 return StringShape(String::cast(this)).IsExternal() &&
258 String::cast(this)->IsAsciiRepresentation();
259 }
260
261
IsExternalTwoByteString()262 bool Object::IsExternalTwoByteString() {
263 if (!IsString()) return false;
264 return StringShape(String::cast(this)).IsExternal() &&
265 String::cast(this)->IsTwoByteRepresentation();
266 }
267
HasValidElements()268 bool Object::HasValidElements() {
269 // Dictionary is covered under FixedArray.
270 return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
271 }
272
StringShape(String * str)273 StringShape::StringShape(String* str)
274 : type_(str->map()->instance_type()) {
275 set_valid();
276 ASSERT((type_ & kIsNotStringMask) == kStringTag);
277 }
278
279
StringShape(Map * map)280 StringShape::StringShape(Map* map)
281 : type_(map->instance_type()) {
282 set_valid();
283 ASSERT((type_ & kIsNotStringMask) == kStringTag);
284 }
285
286
StringShape(InstanceType t)287 StringShape::StringShape(InstanceType t)
288 : type_(static_cast<uint32_t>(t)) {
289 set_valid();
290 ASSERT((type_ & kIsNotStringMask) == kStringTag);
291 }
292
293
IsSymbol()294 bool StringShape::IsSymbol() {
295 ASSERT(valid());
296 STATIC_ASSERT(kSymbolTag != 0);
297 return (type_ & kIsSymbolMask) != 0;
298 }
299
300
IsAsciiRepresentation()301 bool String::IsAsciiRepresentation() {
302 uint32_t type = map()->instance_type();
303 return (type & kStringEncodingMask) == kAsciiStringTag;
304 }
305
306
IsTwoByteRepresentation()307 bool String::IsTwoByteRepresentation() {
308 uint32_t type = map()->instance_type();
309 return (type & kStringEncodingMask) == kTwoByteStringTag;
310 }
311
312
IsAsciiRepresentationUnderneath()313 bool String::IsAsciiRepresentationUnderneath() {
314 uint32_t type = map()->instance_type();
315 STATIC_ASSERT(kIsIndirectStringTag != 0);
316 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
317 ASSERT(IsFlat());
318 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
319 case kAsciiStringTag:
320 return true;
321 case kTwoByteStringTag:
322 return false;
323 default: // Cons or sliced string. Need to go deeper.
324 return GetUnderlying()->IsAsciiRepresentation();
325 }
326 }
327
328
IsTwoByteRepresentationUnderneath()329 bool String::IsTwoByteRepresentationUnderneath() {
330 uint32_t type = map()->instance_type();
331 STATIC_ASSERT(kIsIndirectStringTag != 0);
332 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
333 ASSERT(IsFlat());
334 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
335 case kAsciiStringTag:
336 return false;
337 case kTwoByteStringTag:
338 return true;
339 default: // Cons or sliced string. Need to go deeper.
340 return GetUnderlying()->IsTwoByteRepresentation();
341 }
342 }
343
344
HasOnlyAsciiChars()345 bool String::HasOnlyAsciiChars() {
346 uint32_t type = map()->instance_type();
347 return (type & kStringEncodingMask) == kAsciiStringTag ||
348 (type & kAsciiDataHintMask) == kAsciiDataHintTag;
349 }
350
351
IsCons()352 bool StringShape::IsCons() {
353 return (type_ & kStringRepresentationMask) == kConsStringTag;
354 }
355
356
IsSliced()357 bool StringShape::IsSliced() {
358 return (type_ & kStringRepresentationMask) == kSlicedStringTag;
359 }
360
361
IsIndirect()362 bool StringShape::IsIndirect() {
363 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
364 }
365
366
IsExternal()367 bool StringShape::IsExternal() {
368 return (type_ & kStringRepresentationMask) == kExternalStringTag;
369 }
370
371
IsSequential()372 bool StringShape::IsSequential() {
373 return (type_ & kStringRepresentationMask) == kSeqStringTag;
374 }
375
376
representation_tag()377 StringRepresentationTag StringShape::representation_tag() {
378 uint32_t tag = (type_ & kStringRepresentationMask);
379 return static_cast<StringRepresentationTag>(tag);
380 }
381
382
encoding_tag()383 uint32_t StringShape::encoding_tag() {
384 return type_ & kStringEncodingMask;
385 }
386
387
full_representation_tag()388 uint32_t StringShape::full_representation_tag() {
389 return (type_ & (kStringRepresentationMask | kStringEncodingMask));
390 }
391
392
393 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
394 Internals::kFullStringRepresentationMask);
395
396
IsSequentialAscii()397 bool StringShape::IsSequentialAscii() {
398 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
399 }
400
401
IsSequentialTwoByte()402 bool StringShape::IsSequentialTwoByte() {
403 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
404 }
405
406
IsExternalAscii()407 bool StringShape::IsExternalAscii() {
408 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
409 }
410
411
IsExternalTwoByte()412 bool StringShape::IsExternalTwoByte() {
413 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
414 }
415
416
417 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
418 Internals::kExternalTwoByteRepresentationTag);
419
420
Get(int index)421 uc32 FlatStringReader::Get(int index) {
422 ASSERT(0 <= index && index <= length_);
423 if (is_ascii_) {
424 return static_cast<const byte*>(start_)[index];
425 } else {
426 return static_cast<const uc16*>(start_)[index];
427 }
428 }
429
430
IsNumber()431 bool Object::IsNumber() {
432 return IsSmi() || IsHeapNumber();
433 }
434
435
TYPE_CHECKER(ByteArray,BYTE_ARRAY_TYPE)436 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
437 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
438
439
440 bool Object::IsFiller() {
441 if (!Object::IsHeapObject()) return false;
442 InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
443 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
444 }
445
446
TYPE_CHECKER(ExternalPixelArray,EXTERNAL_PIXEL_ARRAY_TYPE)447 TYPE_CHECKER(ExternalPixelArray, EXTERNAL_PIXEL_ARRAY_TYPE)
448
449
450 bool Object::IsExternalArray() {
451 if (!Object::IsHeapObject())
452 return false;
453 InstanceType instance_type =
454 HeapObject::cast(this)->map()->instance_type();
455 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
456 instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
457 }
458
459
TYPE_CHECKER(ExternalByteArray,EXTERNAL_BYTE_ARRAY_TYPE)460 TYPE_CHECKER(ExternalByteArray, EXTERNAL_BYTE_ARRAY_TYPE)
461 TYPE_CHECKER(ExternalUnsignedByteArray, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
462 TYPE_CHECKER(ExternalShortArray, EXTERNAL_SHORT_ARRAY_TYPE)
463 TYPE_CHECKER(ExternalUnsignedShortArray, EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
464 TYPE_CHECKER(ExternalIntArray, EXTERNAL_INT_ARRAY_TYPE)
465 TYPE_CHECKER(ExternalUnsignedIntArray, EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
466 TYPE_CHECKER(ExternalFloatArray, EXTERNAL_FLOAT_ARRAY_TYPE)
467 TYPE_CHECKER(ExternalDoubleArray, EXTERNAL_DOUBLE_ARRAY_TYPE)
468
469
470 bool MaybeObject::IsFailure() {
471 return HAS_FAILURE_TAG(this);
472 }
473
474
IsRetryAfterGC()475 bool MaybeObject::IsRetryAfterGC() {
476 return HAS_FAILURE_TAG(this)
477 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
478 }
479
480
IsOutOfMemory()481 bool MaybeObject::IsOutOfMemory() {
482 return HAS_FAILURE_TAG(this)
483 && Failure::cast(this)->IsOutOfMemoryException();
484 }
485
486
IsException()487 bool MaybeObject::IsException() {
488 return this == Failure::Exception();
489 }
490
491
IsTheHole()492 bool MaybeObject::IsTheHole() {
493 return !IsFailure() && ToObjectUnchecked()->IsTheHole();
494 }
495
496
cast(MaybeObject * obj)497 Failure* Failure::cast(MaybeObject* obj) {
498 ASSERT(HAS_FAILURE_TAG(obj));
499 return reinterpret_cast<Failure*>(obj);
500 }
501
502
IsJSReceiver()503 bool Object::IsJSReceiver() {
504 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
505 return IsHeapObject() &&
506 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
507 }
508
509
IsJSObject()510 bool Object::IsJSObject() {
511 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
512 return IsHeapObject() &&
513 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
514 }
515
516
IsJSProxy()517 bool Object::IsJSProxy() {
518 if (!Object::IsHeapObject()) return false;
519 InstanceType type = HeapObject::cast(this)->map()->instance_type();
520 return FIRST_JS_PROXY_TYPE <= type && type <= LAST_JS_PROXY_TYPE;
521 }
522
523
TYPE_CHECKER(JSFunctionProxy,JS_FUNCTION_PROXY_TYPE)524 TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
525 TYPE_CHECKER(JSSet, JS_SET_TYPE)
526 TYPE_CHECKER(JSMap, JS_MAP_TYPE)
527 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
528 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
529 TYPE_CHECKER(Map, MAP_TYPE)
530 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
531 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
532
533
534 bool Object::IsDescriptorArray() {
535 return IsFixedArray();
536 }
537
538
IsDeoptimizationInputData()539 bool Object::IsDeoptimizationInputData() {
540 // Must be a fixed array.
541 if (!IsFixedArray()) return false;
542
543 // There's no sure way to detect the difference between a fixed array and
544 // a deoptimization data array. Since this is used for asserts we can
545 // check that the length is zero or else the fixed size plus a multiple of
546 // the entry size.
547 int length = FixedArray::cast(this)->length();
548 if (length == 0) return true;
549
550 length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
551 return length >= 0 &&
552 length % DeoptimizationInputData::kDeoptEntrySize == 0;
553 }
554
555
IsDeoptimizationOutputData()556 bool Object::IsDeoptimizationOutputData() {
557 if (!IsFixedArray()) return false;
558 // There's actually no way to see the difference between a fixed array and
559 // a deoptimization data array. Since this is used for asserts we can check
560 // that the length is plausible though.
561 if (FixedArray::cast(this)->length() % 2 != 0) return false;
562 return true;
563 }
564
565
IsTypeFeedbackCells()566 bool Object::IsTypeFeedbackCells() {
567 if (!IsFixedArray()) return false;
568 // There's actually no way to see the difference between a fixed array and
569 // a cache cells array. Since this is used for asserts we can check that
570 // the length is plausible though.
571 if (FixedArray::cast(this)->length() % 2 != 0) return false;
572 return true;
573 }
574
575
IsContext()576 bool Object::IsContext() {
577 if (Object::IsHeapObject()) {
578 Map* map = HeapObject::cast(this)->map();
579 Heap* heap = map->GetHeap();
580 return (map == heap->function_context_map() ||
581 map == heap->catch_context_map() ||
582 map == heap->with_context_map() ||
583 map == heap->global_context_map() ||
584 map == heap->block_context_map());
585 }
586 return false;
587 }
588
589
IsGlobalContext()590 bool Object::IsGlobalContext() {
591 return Object::IsHeapObject() &&
592 HeapObject::cast(this)->map() ==
593 HeapObject::cast(this)->GetHeap()->global_context_map();
594 }
595
596
IsScopeInfo()597 bool Object::IsScopeInfo() {
598 return Object::IsHeapObject() &&
599 HeapObject::cast(this)->map() ==
600 HeapObject::cast(this)->GetHeap()->scope_info_map();
601 }
602
603
TYPE_CHECKER(JSFunction,JS_FUNCTION_TYPE)604 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
605
606
607 template <> inline bool Is<JSFunction>(Object* obj) {
608 return obj->IsJSFunction();
609 }
610
611
TYPE_CHECKER(Code,CODE_TYPE)612 TYPE_CHECKER(Code, CODE_TYPE)
613 TYPE_CHECKER(Oddball, ODDBALL_TYPE)
614 TYPE_CHECKER(JSGlobalPropertyCell, JS_GLOBAL_PROPERTY_CELL_TYPE)
615 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
616 TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
617 TYPE_CHECKER(JSDate, JS_DATE_TYPE)
618 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
619
620
621 bool Object::IsStringWrapper() {
622 return IsJSValue() && JSValue::cast(this)->value()->IsString();
623 }
624
625
TYPE_CHECKER(Foreign,FOREIGN_TYPE)626 TYPE_CHECKER(Foreign, FOREIGN_TYPE)
627
628
629 bool Object::IsBoolean() {
630 return IsOddball() &&
631 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
632 }
633
634
TYPE_CHECKER(JSArray,JS_ARRAY_TYPE)635 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
636 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
637
638
639 template <> inline bool Is<JSArray>(Object* obj) {
640 return obj->IsJSArray();
641 }
642
643
IsHashTable()644 bool Object::IsHashTable() {
645 return Object::IsHeapObject() &&
646 HeapObject::cast(this)->map() ==
647 HeapObject::cast(this)->GetHeap()->hash_table_map();
648 }
649
650
IsDictionary()651 bool Object::IsDictionary() {
652 return IsHashTable() &&
653 this != HeapObject::cast(this)->GetHeap()->symbol_table();
654 }
655
656
IsSymbolTable()657 bool Object::IsSymbolTable() {
658 return IsHashTable() && this ==
659 HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
660 }
661
662
IsJSFunctionResultCache()663 bool Object::IsJSFunctionResultCache() {
664 if (!IsFixedArray()) return false;
665 FixedArray* self = FixedArray::cast(this);
666 int length = self->length();
667 if (length < JSFunctionResultCache::kEntriesIndex) return false;
668 if ((length - JSFunctionResultCache::kEntriesIndex)
669 % JSFunctionResultCache::kEntrySize != 0) {
670 return false;
671 }
672 #ifdef DEBUG
673 if (FLAG_verify_heap) {
674 reinterpret_cast<JSFunctionResultCache*>(this)->
675 JSFunctionResultCacheVerify();
676 }
677 #endif
678 return true;
679 }
680
681
IsNormalizedMapCache()682 bool Object::IsNormalizedMapCache() {
683 if (!IsFixedArray()) return false;
684 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
685 return false;
686 }
687 #ifdef DEBUG
688 if (FLAG_verify_heap) {
689 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
690 }
691 #endif
692 return true;
693 }
694
695
IsCompilationCacheTable()696 bool Object::IsCompilationCacheTable() {
697 return IsHashTable();
698 }
699
700
IsCodeCacheHashTable()701 bool Object::IsCodeCacheHashTable() {
702 return IsHashTable();
703 }
704
705
IsPolymorphicCodeCacheHashTable()706 bool Object::IsPolymorphicCodeCacheHashTable() {
707 return IsHashTable();
708 }
709
710
IsMapCache()711 bool Object::IsMapCache() {
712 return IsHashTable();
713 }
714
715
IsPrimitive()716 bool Object::IsPrimitive() {
717 return IsOddball() || IsNumber() || IsString();
718 }
719
720
IsJSGlobalProxy()721 bool Object::IsJSGlobalProxy() {
722 bool result = IsHeapObject() &&
723 (HeapObject::cast(this)->map()->instance_type() ==
724 JS_GLOBAL_PROXY_TYPE);
725 ASSERT(!result || IsAccessCheckNeeded());
726 return result;
727 }
728
729
IsGlobalObject()730 bool Object::IsGlobalObject() {
731 if (!IsHeapObject()) return false;
732
733 InstanceType type = HeapObject::cast(this)->map()->instance_type();
734 return type == JS_GLOBAL_OBJECT_TYPE ||
735 type == JS_BUILTINS_OBJECT_TYPE;
736 }
737
738
TYPE_CHECKER(JSGlobalObject,JS_GLOBAL_OBJECT_TYPE)739 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
740 TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
741
742
743 bool Object::IsUndetectableObject() {
744 return IsHeapObject()
745 && HeapObject::cast(this)->map()->is_undetectable();
746 }
747
748
IsAccessCheckNeeded()749 bool Object::IsAccessCheckNeeded() {
750 return IsHeapObject()
751 && HeapObject::cast(this)->map()->is_access_check_needed();
752 }
753
754
IsStruct()755 bool Object::IsStruct() {
756 if (!IsHeapObject()) return false;
757 switch (HeapObject::cast(this)->map()->instance_type()) {
758 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
759 STRUCT_LIST(MAKE_STRUCT_CASE)
760 #undef MAKE_STRUCT_CASE
761 default: return false;
762 }
763 }
764
765
766 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
767 bool Object::Is##Name() { \
768 return Object::IsHeapObject() \
769 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
770 }
STRUCT_LIST(MAKE_STRUCT_PREDICATE)771 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
772 #undef MAKE_STRUCT_PREDICATE
773
774
775 bool Object::IsUndefined() {
776 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
777 }
778
779
IsNull()780 bool Object::IsNull() {
781 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
782 }
783
784
IsTheHole()785 bool Object::IsTheHole() {
786 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
787 }
788
789
IsTrue()790 bool Object::IsTrue() {
791 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
792 }
793
794
IsFalse()795 bool Object::IsFalse() {
796 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
797 }
798
799
IsArgumentsMarker()800 bool Object::IsArgumentsMarker() {
801 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
802 }
803
804
Number()805 double Object::Number() {
806 ASSERT(IsNumber());
807 return IsSmi()
808 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
809 : reinterpret_cast<HeapNumber*>(this)->value();
810 }
811
812
IsNaN()813 bool Object::IsNaN() {
814 return this->IsHeapNumber() && isnan(HeapNumber::cast(this)->value());
815 }
816
817
ToSmi()818 MaybeObject* Object::ToSmi() {
819 if (IsSmi()) return this;
820 if (IsHeapNumber()) {
821 double value = HeapNumber::cast(this)->value();
822 int int_value = FastD2I(value);
823 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
824 return Smi::FromInt(int_value);
825 }
826 }
827 return Failure::Exception();
828 }
829
830
HasSpecificClassOf(String * name)831 bool Object::HasSpecificClassOf(String* name) {
832 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
833 }
834
835
GetElement(uint32_t index)836 MaybeObject* Object::GetElement(uint32_t index) {
837 // GetElement can trigger a getter which can cause allocation.
838 // This was not always the case. This ASSERT is here to catch
839 // leftover incorrect uses.
840 ASSERT(HEAP->IsAllocationAllowed());
841 return GetElementWithReceiver(this, index);
842 }
843
844
GetElementNoExceptionThrown(uint32_t index)845 Object* Object::GetElementNoExceptionThrown(uint32_t index) {
846 MaybeObject* maybe = GetElementWithReceiver(this, index);
847 ASSERT(!maybe->IsFailure());
848 Object* result = NULL; // Initialization to please compiler.
849 maybe->ToObject(&result);
850 return result;
851 }
852
853
GetProperty(String * key)854 MaybeObject* Object::GetProperty(String* key) {
855 PropertyAttributes attributes;
856 return GetPropertyWithReceiver(this, key, &attributes);
857 }
858
859
GetProperty(String * key,PropertyAttributes * attributes)860 MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
861 return GetPropertyWithReceiver(this, key, attributes);
862 }
863
864
865 #define FIELD_ADDR(p, offset) \
866 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
867
868 #define READ_FIELD(p, offset) \
869 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
870
871 #define WRITE_FIELD(p, offset, value) \
872 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
873
874 #define WRITE_BARRIER(heap, object, offset, value) \
875 heap->incremental_marking()->RecordWrite( \
876 object, HeapObject::RawField(object, offset), value); \
877 if (heap->InNewSpace(value)) { \
878 heap->RecordWrite(object->address(), offset); \
879 }
880
881 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
882 if (mode == UPDATE_WRITE_BARRIER) { \
883 heap->incremental_marking()->RecordWrite( \
884 object, HeapObject::RawField(object, offset), value); \
885 if (heap->InNewSpace(value)) { \
886 heap->RecordWrite(object->address(), offset); \
887 } \
888 }
889
890 #ifndef V8_TARGET_ARCH_MIPS
891 #define READ_DOUBLE_FIELD(p, offset) \
892 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
893 #else // V8_TARGET_ARCH_MIPS
894 // Prevent gcc from using load-double (mips ldc1) on (possibly)
895 // non-64-bit aligned HeapNumber::value.
read_double_field(void * p,int offset)896 static inline double read_double_field(void* p, int offset) {
897 union conversion {
898 double d;
899 uint32_t u[2];
900 } c;
901 c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
902 c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
903 return c.d;
904 }
905 #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
906 #endif // V8_TARGET_ARCH_MIPS
907
908 #ifndef V8_TARGET_ARCH_MIPS
909 #define WRITE_DOUBLE_FIELD(p, offset, value) \
910 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
911 #else // V8_TARGET_ARCH_MIPS
912 // Prevent gcc from using store-double (mips sdc1) on (possibly)
913 // non-64-bit aligned HeapNumber::value.
write_double_field(void * p,int offset,double value)914 static inline void write_double_field(void* p, int offset,
915 double value) {
916 union conversion {
917 double d;
918 uint32_t u[2];
919 } c;
920 c.d = value;
921 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
922 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
923 }
924 #define WRITE_DOUBLE_FIELD(p, offset, value) \
925 write_double_field(p, offset, value)
926 #endif // V8_TARGET_ARCH_MIPS
927
928
929 #define READ_INT_FIELD(p, offset) \
930 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
931
932 #define WRITE_INT_FIELD(p, offset, value) \
933 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
934
935 #define READ_INTPTR_FIELD(p, offset) \
936 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
937
938 #define WRITE_INTPTR_FIELD(p, offset, value) \
939 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
940
941 #define READ_UINT32_FIELD(p, offset) \
942 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
943
944 #define WRITE_UINT32_FIELD(p, offset, value) \
945 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
946
947 #define READ_INT64_FIELD(p, offset) \
948 (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)))
949
950 #define WRITE_INT64_FIELD(p, offset, value) \
951 (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value)
952
953 #define READ_SHORT_FIELD(p, offset) \
954 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
955
956 #define WRITE_SHORT_FIELD(p, offset, value) \
957 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
958
959 #define READ_BYTE_FIELD(p, offset) \
960 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
961
962 #define WRITE_BYTE_FIELD(p, offset, value) \
963 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
964
965
RawField(HeapObject * obj,int byte_offset)966 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
967 return &READ_FIELD(obj, byte_offset);
968 }
969
970
value()971 int Smi::value() {
972 return Internals::SmiValue(this);
973 }
974
975
FromInt(int value)976 Smi* Smi::FromInt(int value) {
977 ASSERT(Smi::IsValid(value));
978 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
979 intptr_t tagged_value =
980 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
981 return reinterpret_cast<Smi*>(tagged_value);
982 }
983
984
FromIntptr(intptr_t value)985 Smi* Smi::FromIntptr(intptr_t value) {
986 ASSERT(Smi::IsValid(value));
987 int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
988 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
989 }
990
991
type()992 Failure::Type Failure::type() const {
993 return static_cast<Type>(value() & kFailureTypeTagMask);
994 }
995
996
IsInternalError()997 bool Failure::IsInternalError() const {
998 return type() == INTERNAL_ERROR;
999 }
1000
1001
IsOutOfMemoryException()1002 bool Failure::IsOutOfMemoryException() const {
1003 return type() == OUT_OF_MEMORY_EXCEPTION;
1004 }
1005
1006
allocation_space()1007 AllocationSpace Failure::allocation_space() const {
1008 ASSERT_EQ(RETRY_AFTER_GC, type());
1009 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
1010 & kSpaceTagMask);
1011 }
1012
1013
InternalError()1014 Failure* Failure::InternalError() {
1015 return Construct(INTERNAL_ERROR);
1016 }
1017
1018
Exception()1019 Failure* Failure::Exception() {
1020 return Construct(EXCEPTION);
1021 }
1022
1023
OutOfMemoryException()1024 Failure* Failure::OutOfMemoryException() {
1025 return Construct(OUT_OF_MEMORY_EXCEPTION);
1026 }
1027
1028
value()1029 intptr_t Failure::value() const {
1030 return static_cast<intptr_t>(
1031 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
1032 }
1033
1034
RetryAfterGC()1035 Failure* Failure::RetryAfterGC() {
1036 return RetryAfterGC(NEW_SPACE);
1037 }
1038
1039
RetryAfterGC(AllocationSpace space)1040 Failure* Failure::RetryAfterGC(AllocationSpace space) {
1041 ASSERT((space & ~kSpaceTagMask) == 0);
1042 return Construct(RETRY_AFTER_GC, space);
1043 }
1044
1045
Construct(Type type,intptr_t value)1046 Failure* Failure::Construct(Type type, intptr_t value) {
1047 uintptr_t info =
1048 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
1049 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
1050 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
1051 }
1052
1053
IsValid(intptr_t value)1054 bool Smi::IsValid(intptr_t value) {
1055 #ifdef DEBUG
1056 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
1057 #endif
1058
1059 #ifdef V8_TARGET_ARCH_X64
1060 // To be representable as a long smi, the value must be a 32-bit integer.
1061 bool result = (value == static_cast<int32_t>(value));
1062 #else
1063 // To be representable as an tagged small integer, the two
1064 // most-significant bits of 'value' must be either 00 or 11 due to
1065 // sign-extension. To check this we add 01 to the two
1066 // most-significant bits, and check if the most-significant bit is 0
1067 //
1068 // CAUTION: The original code below:
1069 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
1070 // may lead to incorrect results according to the C language spec, and
1071 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
1072 // compiler may produce undefined results in case of signed integer
1073 // overflow. The computation must be done w/ unsigned ints.
1074 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
1075 #endif
1076 ASSERT(result == in_range);
1077 return result;
1078 }
1079
1080
FromMap(Map * map)1081 MapWord MapWord::FromMap(Map* map) {
1082 return MapWord(reinterpret_cast<uintptr_t>(map));
1083 }
1084
1085
ToMap()1086 Map* MapWord::ToMap() {
1087 return reinterpret_cast<Map*>(value_);
1088 }
1089
1090
IsForwardingAddress()1091 bool MapWord::IsForwardingAddress() {
1092 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1093 }
1094
1095
FromForwardingAddress(HeapObject * object)1096 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1097 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1098 return MapWord(reinterpret_cast<uintptr_t>(raw));
1099 }
1100
1101
ToForwardingAddress()1102 HeapObject* MapWord::ToForwardingAddress() {
1103 ASSERT(IsForwardingAddress());
1104 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1105 }
1106
1107
1108 #ifdef DEBUG
VerifyObjectField(int offset)1109 void HeapObject::VerifyObjectField(int offset) {
1110 VerifyPointer(READ_FIELD(this, offset));
1111 }
1112
VerifySmiField(int offset)1113 void HeapObject::VerifySmiField(int offset) {
1114 ASSERT(READ_FIELD(this, offset)->IsSmi());
1115 }
1116 #endif
1117
1118
GetHeap()1119 Heap* HeapObject::GetHeap() {
1120 Heap* heap =
1121 MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();
1122 ASSERT(heap != NULL);
1123 ASSERT(heap->isolate() == Isolate::Current());
1124 return heap;
1125 }
1126
1127
GetIsolate()1128 Isolate* HeapObject::GetIsolate() {
1129 return GetHeap()->isolate();
1130 }
1131
1132
map()1133 Map* HeapObject::map() {
1134 return map_word().ToMap();
1135 }
1136
1137
set_map(Map * value)1138 void HeapObject::set_map(Map* value) {
1139 set_map_word(MapWord::FromMap(value));
1140 if (value != NULL) {
1141 // TODO(1600) We are passing NULL as a slot because maps can never be on
1142 // evacuation candidate.
1143 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1144 }
1145 }
1146
1147
1148 // Unsafe accessor omitting write barrier.
set_map_no_write_barrier(Map * value)1149 void HeapObject::set_map_no_write_barrier(Map* value) {
1150 set_map_word(MapWord::FromMap(value));
1151 }
1152
1153
map_word()1154 MapWord HeapObject::map_word() {
1155 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1156 }
1157
1158
set_map_word(MapWord map_word)1159 void HeapObject::set_map_word(MapWord map_word) {
1160 // WRITE_FIELD does not invoke write barrier, but there is no need
1161 // here.
1162 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1163 }
1164
1165
FromAddress(Address address)1166 HeapObject* HeapObject::FromAddress(Address address) {
1167 ASSERT_TAG_ALIGNED(address);
1168 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1169 }
1170
1171
address()1172 Address HeapObject::address() {
1173 return reinterpret_cast<Address>(this) - kHeapObjectTag;
1174 }
1175
1176
Size()1177 int HeapObject::Size() {
1178 return SizeFromMap(map());
1179 }
1180
1181
IteratePointers(ObjectVisitor * v,int start,int end)1182 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1183 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1184 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1185 }
1186
1187
IteratePointer(ObjectVisitor * v,int offset)1188 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1189 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1190 }
1191
1192
value()1193 double HeapNumber::value() {
1194 return READ_DOUBLE_FIELD(this, kValueOffset);
1195 }
1196
1197
set_value(double value)1198 void HeapNumber::set_value(double value) {
1199 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1200 }
1201
1202
get_exponent()1203 int HeapNumber::get_exponent() {
1204 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1205 kExponentShift) - kExponentBias;
1206 }
1207
1208
get_sign()1209 int HeapNumber::get_sign() {
1210 return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1211 }
1212
1213
ACCESSORS(JSObject,properties,FixedArray,kPropertiesOffset)1214 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1215
1216
1217 Object** FixedArray::GetFirstElementAddress() {
1218 return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
1219 }
1220
1221
ContainsOnlySmisOrHoles()1222 bool FixedArray::ContainsOnlySmisOrHoles() {
1223 Object* the_hole = GetHeap()->the_hole_value();
1224 Object** current = GetFirstElementAddress();
1225 for (int i = 0; i < length(); ++i) {
1226 Object* candidate = *current++;
1227 if (!candidate->IsSmi() && candidate != the_hole) return false;
1228 }
1229 return true;
1230 }
1231
1232
elements()1233 FixedArrayBase* JSObject::elements() {
1234 Object* array = READ_FIELD(this, kElementsOffset);
1235 return static_cast<FixedArrayBase*>(array);
1236 }
1237
ValidateSmiOnlyElements()1238 void JSObject::ValidateSmiOnlyElements() {
1239 #if DEBUG
1240 if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
1241 Heap* heap = GetHeap();
1242 // Don't use elements, since integrity checks will fail if there
1243 // are filler pointers in the array.
1244 FixedArray* fixed_array =
1245 reinterpret_cast<FixedArray*>(READ_FIELD(this, kElementsOffset));
1246 Map* map = fixed_array->map();
1247 // Arrays that have been shifted in place can't be verified.
1248 if (map != heap->raw_unchecked_one_pointer_filler_map() &&
1249 map != heap->raw_unchecked_two_pointer_filler_map() &&
1250 map != heap->free_space_map()) {
1251 for (int i = 0; i < fixed_array->length(); i++) {
1252 Object* current = fixed_array->get(i);
1253 ASSERT(current->IsSmi() || current->IsTheHole());
1254 }
1255 }
1256 }
1257 #endif
1258 }
1259
1260
EnsureCanContainHeapObjectElements()1261 MaybeObject* JSObject::EnsureCanContainHeapObjectElements() {
1262 #if DEBUG
1263 ValidateSmiOnlyElements();
1264 #endif
1265 if ((map()->elements_kind() != FAST_ELEMENTS)) {
1266 return TransitionElementsKind(FAST_ELEMENTS);
1267 }
1268 return this;
1269 }
1270
1271
EnsureCanContainElements(Object ** objects,uint32_t count,EnsureElementsMode mode)1272 MaybeObject* JSObject::EnsureCanContainElements(Object** objects,
1273 uint32_t count,
1274 EnsureElementsMode mode) {
1275 ElementsKind current_kind = map()->elements_kind();
1276 ElementsKind target_kind = current_kind;
1277 ASSERT(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1278 if (current_kind == FAST_ELEMENTS) return this;
1279
1280 Heap* heap = GetHeap();
1281 Object* the_hole = heap->the_hole_value();
1282 Object* heap_number_map = heap->heap_number_map();
1283 for (uint32_t i = 0; i < count; ++i) {
1284 Object* current = *objects++;
1285 if (!current->IsSmi() && current != the_hole) {
1286 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS &&
1287 HeapObject::cast(current)->map() == heap_number_map) {
1288 target_kind = FAST_DOUBLE_ELEMENTS;
1289 } else {
1290 target_kind = FAST_ELEMENTS;
1291 break;
1292 }
1293 }
1294 }
1295
1296 if (target_kind != current_kind) {
1297 return TransitionElementsKind(target_kind);
1298 }
1299 return this;
1300 }
1301
1302
EnsureCanContainElements(FixedArrayBase * elements,EnsureElementsMode mode)1303 MaybeObject* JSObject::EnsureCanContainElements(FixedArrayBase* elements,
1304 EnsureElementsMode mode) {
1305 if (elements->map() != GetHeap()->fixed_double_array_map()) {
1306 ASSERT(elements->map() == GetHeap()->fixed_array_map() ||
1307 elements->map() == GetHeap()->fixed_cow_array_map());
1308 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
1309 mode = DONT_ALLOW_DOUBLE_ELEMENTS;
1310 }
1311 Object** objects = FixedArray::cast(elements)->GetFirstElementAddress();
1312 return EnsureCanContainElements(objects, elements->length(), mode);
1313 }
1314
1315 ASSERT(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1316 if (GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) {
1317 return TransitionElementsKind(FAST_DOUBLE_ELEMENTS);
1318 }
1319
1320 return this;
1321 }
1322
1323
GetElementsTransitionMap(Isolate * isolate,ElementsKind to_kind)1324 MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate,
1325 ElementsKind to_kind) {
1326 Map* current_map = map();
1327 ElementsKind from_kind = current_map->elements_kind();
1328
1329 if (from_kind == to_kind) return current_map;
1330
1331 Context* global_context = isolate->context()->global_context();
1332 if (current_map == global_context->smi_js_array_map()) {
1333 if (to_kind == FAST_ELEMENTS) {
1334 return global_context->object_js_array_map();
1335 } else {
1336 if (to_kind == FAST_DOUBLE_ELEMENTS) {
1337 return global_context->double_js_array_map();
1338 } else {
1339 ASSERT(to_kind == DICTIONARY_ELEMENTS);
1340 }
1341 }
1342 }
1343 return GetElementsTransitionMapSlow(to_kind);
1344 }
1345
1346
set_map_and_elements(Map * new_map,FixedArrayBase * value,WriteBarrierMode mode)1347 void JSObject::set_map_and_elements(Map* new_map,
1348 FixedArrayBase* value,
1349 WriteBarrierMode mode) {
1350 ASSERT(value->HasValidElements());
1351 #ifdef DEBUG
1352 ValidateSmiOnlyElements();
1353 #endif
1354 if (new_map != NULL) {
1355 if (mode == UPDATE_WRITE_BARRIER) {
1356 set_map(new_map);
1357 } else {
1358 ASSERT(mode == SKIP_WRITE_BARRIER);
1359 set_map_no_write_barrier(new_map);
1360 }
1361 }
1362 ASSERT((map()->has_fast_elements() ||
1363 map()->has_fast_smi_only_elements() ||
1364 (value == GetHeap()->empty_fixed_array())) ==
1365 (value->map() == GetHeap()->fixed_array_map() ||
1366 value->map() == GetHeap()->fixed_cow_array_map()));
1367 ASSERT((value == GetHeap()->empty_fixed_array()) ||
1368 (map()->has_fast_double_elements() == value->IsFixedDoubleArray()));
1369 WRITE_FIELD(this, kElementsOffset, value);
1370 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1371 }
1372
1373
set_elements(FixedArrayBase * value,WriteBarrierMode mode)1374 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
1375 set_map_and_elements(NULL, value, mode);
1376 }
1377
1378
initialize_properties()1379 void JSObject::initialize_properties() {
1380 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1381 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
1382 }
1383
1384
initialize_elements()1385 void JSObject::initialize_elements() {
1386 ASSERT(map()->has_fast_elements() ||
1387 map()->has_fast_smi_only_elements() ||
1388 map()->has_fast_double_elements());
1389 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1390 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
1391 }
1392
1393
ResetElements()1394 MaybeObject* JSObject::ResetElements() {
1395 Object* obj;
1396 ElementsKind elements_kind = FLAG_smi_only_arrays
1397 ? FAST_SMI_ONLY_ELEMENTS
1398 : FAST_ELEMENTS;
1399 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
1400 elements_kind);
1401 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1402 set_map(Map::cast(obj));
1403 initialize_elements();
1404 return this;
1405 }
1406
1407
ACCESSORS(Oddball,to_string,String,kToStringOffset)1408 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1409 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1410
1411
1412 byte Oddball::kind() {
1413 return Smi::cast(READ_FIELD(this, kKindOffset))->value();
1414 }
1415
1416
set_kind(byte value)1417 void Oddball::set_kind(byte value) {
1418 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
1419 }
1420
1421
value()1422 Object* JSGlobalPropertyCell::value() {
1423 return READ_FIELD(this, kValueOffset);
1424 }
1425
1426
set_value(Object * val,WriteBarrierMode ignored)1427 void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1428 // The write barrier is not used for global property cells.
1429 ASSERT(!val->IsJSGlobalPropertyCell());
1430 WRITE_FIELD(this, kValueOffset, val);
1431 }
1432
1433
GetHeaderSize()1434 int JSObject::GetHeaderSize() {
1435 InstanceType type = map()->instance_type();
1436 // Check for the most common kind of JavaScript object before
1437 // falling into the generic switch. This speeds up the internal
1438 // field operations considerably on average.
1439 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1440 switch (type) {
1441 case JS_GLOBAL_PROXY_TYPE:
1442 return JSGlobalProxy::kSize;
1443 case JS_GLOBAL_OBJECT_TYPE:
1444 return JSGlobalObject::kSize;
1445 case JS_BUILTINS_OBJECT_TYPE:
1446 return JSBuiltinsObject::kSize;
1447 case JS_FUNCTION_TYPE:
1448 return JSFunction::kSize;
1449 case JS_VALUE_TYPE:
1450 return JSValue::kSize;
1451 case JS_DATE_TYPE:
1452 return JSDate::kSize;
1453 case JS_ARRAY_TYPE:
1454 return JSArray::kSize;
1455 case JS_WEAK_MAP_TYPE:
1456 return JSWeakMap::kSize;
1457 case JS_REGEXP_TYPE:
1458 return JSRegExp::kSize;
1459 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1460 return JSObject::kHeaderSize;
1461 case JS_MESSAGE_OBJECT_TYPE:
1462 return JSMessageObject::kSize;
1463 default:
1464 UNREACHABLE();
1465 return 0;
1466 }
1467 }
1468
1469
GetInternalFieldCount()1470 int JSObject::GetInternalFieldCount() {
1471 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1472 // Make sure to adjust for the number of in-object properties. These
1473 // properties do contribute to the size, but are not internal fields.
1474 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1475 map()->inobject_properties();
1476 }
1477
1478
GetInternalFieldOffset(int index)1479 int JSObject::GetInternalFieldOffset(int index) {
1480 ASSERT(index < GetInternalFieldCount() && index >= 0);
1481 return GetHeaderSize() + (kPointerSize * index);
1482 }
1483
1484
GetInternalField(int index)1485 Object* JSObject::GetInternalField(int index) {
1486 ASSERT(index < GetInternalFieldCount() && index >= 0);
1487 // Internal objects do follow immediately after the header, whereas in-object
1488 // properties are at the end of the object. Therefore there is no need
1489 // to adjust the index here.
1490 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1491 }
1492
1493
SetInternalField(int index,Object * value)1494 void JSObject::SetInternalField(int index, Object* value) {
1495 ASSERT(index < GetInternalFieldCount() && index >= 0);
1496 // Internal objects do follow immediately after the header, whereas in-object
1497 // properties are at the end of the object. Therefore there is no need
1498 // to adjust the index here.
1499 int offset = GetHeaderSize() + (kPointerSize * index);
1500 WRITE_FIELD(this, offset, value);
1501 WRITE_BARRIER(GetHeap(), this, offset, value);
1502 }
1503
1504
SetInternalField(int index,Smi * value)1505 void JSObject::SetInternalField(int index, Smi* value) {
1506 ASSERT(index < GetInternalFieldCount() && index >= 0);
1507 // Internal objects do follow immediately after the header, whereas in-object
1508 // properties are at the end of the object. Therefore there is no need
1509 // to adjust the index here.
1510 int offset = GetHeaderSize() + (kPointerSize * index);
1511 WRITE_FIELD(this, offset, value);
1512 }
1513
1514
1515 // Access fast-case object properties at index. The use of these routines
1516 // is needed to correctly distinguish between properties stored in-object and
1517 // properties stored in the properties array.
FastPropertyAt(int index)1518 Object* JSObject::FastPropertyAt(int index) {
1519 // Adjust for the number of properties stored in the object.
1520 index -= map()->inobject_properties();
1521 if (index < 0) {
1522 int offset = map()->instance_size() + (index * kPointerSize);
1523 return READ_FIELD(this, offset);
1524 } else {
1525 ASSERT(index < properties()->length());
1526 return properties()->get(index);
1527 }
1528 }
1529
1530
FastPropertyAtPut(int index,Object * value)1531 Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1532 // Adjust for the number of properties stored in the object.
1533 index -= map()->inobject_properties();
1534 if (index < 0) {
1535 int offset = map()->instance_size() + (index * kPointerSize);
1536 WRITE_FIELD(this, offset, value);
1537 WRITE_BARRIER(GetHeap(), this, offset, value);
1538 } else {
1539 ASSERT(index < properties()->length());
1540 properties()->set(index, value);
1541 }
1542 return value;
1543 }
1544
1545
GetInObjectPropertyOffset(int index)1546 int JSObject::GetInObjectPropertyOffset(int index) {
1547 // Adjust for the number of properties stored in the object.
1548 index -= map()->inobject_properties();
1549 ASSERT(index < 0);
1550 return map()->instance_size() + (index * kPointerSize);
1551 }
1552
1553
InObjectPropertyAt(int index)1554 Object* JSObject::InObjectPropertyAt(int index) {
1555 // Adjust for the number of properties stored in the object.
1556 index -= map()->inobject_properties();
1557 ASSERT(index < 0);
1558 int offset = map()->instance_size() + (index * kPointerSize);
1559 return READ_FIELD(this, offset);
1560 }
1561
1562
InObjectPropertyAtPut(int index,Object * value,WriteBarrierMode mode)1563 Object* JSObject::InObjectPropertyAtPut(int index,
1564 Object* value,
1565 WriteBarrierMode mode) {
1566 // Adjust for the number of properties stored in the object.
1567 index -= map()->inobject_properties();
1568 ASSERT(index < 0);
1569 int offset = map()->instance_size() + (index * kPointerSize);
1570 WRITE_FIELD(this, offset, value);
1571 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1572 return value;
1573 }
1574
1575
1576
InitializeBody(Map * map,Object * pre_allocated_value,Object * filler_value)1577 void JSObject::InitializeBody(Map* map,
1578 Object* pre_allocated_value,
1579 Object* filler_value) {
1580 ASSERT(!filler_value->IsHeapObject() ||
1581 !GetHeap()->InNewSpace(filler_value));
1582 ASSERT(!pre_allocated_value->IsHeapObject() ||
1583 !GetHeap()->InNewSpace(pre_allocated_value));
1584 int size = map->instance_size();
1585 int offset = kHeaderSize;
1586 if (filler_value != pre_allocated_value) {
1587 int pre_allocated = map->pre_allocated_property_fields();
1588 ASSERT(pre_allocated * kPointerSize + kHeaderSize <= size);
1589 for (int i = 0; i < pre_allocated; i++) {
1590 WRITE_FIELD(this, offset, pre_allocated_value);
1591 offset += kPointerSize;
1592 }
1593 }
1594 while (offset < size) {
1595 WRITE_FIELD(this, offset, filler_value);
1596 offset += kPointerSize;
1597 }
1598 }
1599
1600
HasFastProperties()1601 bool JSObject::HasFastProperties() {
1602 return !properties()->IsDictionary();
1603 }
1604
1605
MaxFastProperties()1606 int JSObject::MaxFastProperties() {
1607 // Allow extra fast properties if the object has more than
1608 // kMaxFastProperties in-object properties. When this is the case,
1609 // it is very unlikely that the object is being used as a dictionary
1610 // and there is a good chance that allowing more map transitions
1611 // will be worth it.
1612 return Max(map()->inobject_properties(), kMaxFastProperties);
1613 }
1614
1615
InitializeBody(int object_size)1616 void Struct::InitializeBody(int object_size) {
1617 Object* value = GetHeap()->undefined_value();
1618 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1619 WRITE_FIELD(this, offset, value);
1620 }
1621 }
1622
1623
ToArrayIndex(uint32_t * index)1624 bool Object::ToArrayIndex(uint32_t* index) {
1625 if (IsSmi()) {
1626 int value = Smi::cast(this)->value();
1627 if (value < 0) return false;
1628 *index = value;
1629 return true;
1630 }
1631 if (IsHeapNumber()) {
1632 double value = HeapNumber::cast(this)->value();
1633 uint32_t uint_value = static_cast<uint32_t>(value);
1634 if (value == static_cast<double>(uint_value)) {
1635 *index = uint_value;
1636 return true;
1637 }
1638 }
1639 return false;
1640 }
1641
1642
IsStringObjectWithCharacterAt(uint32_t index)1643 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1644 if (!this->IsJSValue()) return false;
1645
1646 JSValue* js_value = JSValue::cast(this);
1647 if (!js_value->value()->IsString()) return false;
1648
1649 String* str = String::cast(js_value->value());
1650 if (index >= (uint32_t)str->length()) return false;
1651
1652 return true;
1653 }
1654
1655
cast(Object * object)1656 FixedArrayBase* FixedArrayBase::cast(Object* object) {
1657 ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray());
1658 return reinterpret_cast<FixedArrayBase*>(object);
1659 }
1660
1661
get(int index)1662 Object* FixedArray::get(int index) {
1663 ASSERT(index >= 0 && index < this->length());
1664 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1665 }
1666
1667
set(int index,Smi * value)1668 void FixedArray::set(int index, Smi* value) {
1669 ASSERT(map() != HEAP->fixed_cow_array_map());
1670 ASSERT(index >= 0 && index < this->length());
1671 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1672 int offset = kHeaderSize + index * kPointerSize;
1673 WRITE_FIELD(this, offset, value);
1674 }
1675
1676
set(int index,Object * value)1677 void FixedArray::set(int index, Object* value) {
1678 ASSERT(map() != HEAP->fixed_cow_array_map());
1679 ASSERT(index >= 0 && index < this->length());
1680 int offset = kHeaderSize + index * kPointerSize;
1681 WRITE_FIELD(this, offset, value);
1682 WRITE_BARRIER(GetHeap(), this, offset, value);
1683 }
1684
1685
is_the_hole_nan(double value)1686 inline bool FixedDoubleArray::is_the_hole_nan(double value) {
1687 return BitCast<uint64_t, double>(value) == kHoleNanInt64;
1688 }
1689
1690
hole_nan_as_double()1691 inline double FixedDoubleArray::hole_nan_as_double() {
1692 return BitCast<double, uint64_t>(kHoleNanInt64);
1693 }
1694
1695
canonical_not_the_hole_nan_as_double()1696 inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
1697 ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
1698 ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
1699 return OS::nan_value();
1700 }
1701
1702
get_scalar(int index)1703 double FixedDoubleArray::get_scalar(int index) {
1704 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1705 map() != HEAP->fixed_array_map());
1706 ASSERT(index >= 0 && index < this->length());
1707 double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
1708 ASSERT(!is_the_hole_nan(result));
1709 return result;
1710 }
1711
get_representation(int index)1712 int64_t FixedDoubleArray::get_representation(int index) {
1713 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1714 map() != HEAP->fixed_array_map());
1715 ASSERT(index >= 0 && index < this->length());
1716 return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
1717 }
1718
get(int index)1719 MaybeObject* FixedDoubleArray::get(int index) {
1720 if (is_the_hole(index)) {
1721 return GetHeap()->the_hole_value();
1722 } else {
1723 return GetHeap()->NumberFromDouble(get_scalar(index));
1724 }
1725 }
1726
1727
set(int index,double value)1728 void FixedDoubleArray::set(int index, double value) {
1729 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1730 map() != HEAP->fixed_array_map());
1731 int offset = kHeaderSize + index * kDoubleSize;
1732 if (isnan(value)) value = canonical_not_the_hole_nan_as_double();
1733 WRITE_DOUBLE_FIELD(this, offset, value);
1734 }
1735
1736
set_the_hole(int index)1737 void FixedDoubleArray::set_the_hole(int index) {
1738 ASSERT(map() != HEAP->fixed_cow_array_map() &&
1739 map() != HEAP->fixed_array_map());
1740 int offset = kHeaderSize + index * kDoubleSize;
1741 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1742 }
1743
1744
is_the_hole(int index)1745 bool FixedDoubleArray::is_the_hole(int index) {
1746 int offset = kHeaderSize + index * kDoubleSize;
1747 return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
1748 }
1749
1750
GetWriteBarrierMode(const AssertNoAllocation &)1751 WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
1752 Heap* heap = GetHeap();
1753 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
1754 if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
1755 return UPDATE_WRITE_BARRIER;
1756 }
1757
1758
set(int index,Object * value,WriteBarrierMode mode)1759 void FixedArray::set(int index,
1760 Object* value,
1761 WriteBarrierMode mode) {
1762 ASSERT(map() != HEAP->fixed_cow_array_map());
1763 ASSERT(index >= 0 && index < this->length());
1764 int offset = kHeaderSize + index * kPointerSize;
1765 WRITE_FIELD(this, offset, value);
1766 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1767 }
1768
1769
NoIncrementalWriteBarrierSet(FixedArray * array,int index,Object * value)1770 void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
1771 int index,
1772 Object* value) {
1773 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
1774 ASSERT(index >= 0 && index < array->length());
1775 int offset = kHeaderSize + index * kPointerSize;
1776 WRITE_FIELD(array, offset, value);
1777 Heap* heap = array->GetHeap();
1778 if (heap->InNewSpace(value)) {
1779 heap->RecordWrite(array->address(), offset);
1780 }
1781 }
1782
1783
NoWriteBarrierSet(FixedArray * array,int index,Object * value)1784 void FixedArray::NoWriteBarrierSet(FixedArray* array,
1785 int index,
1786 Object* value) {
1787 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
1788 ASSERT(index >= 0 && index < array->length());
1789 ASSERT(!HEAP->InNewSpace(value));
1790 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1791 }
1792
1793
set_undefined(int index)1794 void FixedArray::set_undefined(int index) {
1795 ASSERT(map() != HEAP->fixed_cow_array_map());
1796 set_undefined(GetHeap(), index);
1797 }
1798
1799
set_undefined(Heap * heap,int index)1800 void FixedArray::set_undefined(Heap* heap, int index) {
1801 ASSERT(index >= 0 && index < this->length());
1802 ASSERT(!heap->InNewSpace(heap->undefined_value()));
1803 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1804 heap->undefined_value());
1805 }
1806
1807
set_null(int index)1808 void FixedArray::set_null(int index) {
1809 set_null(GetHeap(), index);
1810 }
1811
1812
set_null(Heap * heap,int index)1813 void FixedArray::set_null(Heap* heap, int index) {
1814 ASSERT(index >= 0 && index < this->length());
1815 ASSERT(!heap->InNewSpace(heap->null_value()));
1816 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
1817 }
1818
1819
set_the_hole(int index)1820 void FixedArray::set_the_hole(int index) {
1821 ASSERT(map() != HEAP->fixed_cow_array_map());
1822 ASSERT(index >= 0 && index < this->length());
1823 ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
1824 WRITE_FIELD(this,
1825 kHeaderSize + index * kPointerSize,
1826 GetHeap()->the_hole_value());
1827 }
1828
1829
set_unchecked(int index,Smi * value)1830 void FixedArray::set_unchecked(int index, Smi* value) {
1831 ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1832 int offset = kHeaderSize + index * kPointerSize;
1833 WRITE_FIELD(this, offset, value);
1834 }
1835
1836
set_unchecked(Heap * heap,int index,Object * value,WriteBarrierMode mode)1837 void FixedArray::set_unchecked(Heap* heap,
1838 int index,
1839 Object* value,
1840 WriteBarrierMode mode) {
1841 int offset = kHeaderSize + index * kPointerSize;
1842 WRITE_FIELD(this, offset, value);
1843 CONDITIONAL_WRITE_BARRIER(heap, this, offset, value, mode);
1844 }
1845
1846
set_null_unchecked(Heap * heap,int index)1847 void FixedArray::set_null_unchecked(Heap* heap, int index) {
1848 ASSERT(index >= 0 && index < this->length());
1849 ASSERT(!HEAP->InNewSpace(heap->null_value()));
1850 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
1851 }
1852
1853
data_start()1854 Object** FixedArray::data_start() {
1855 return HeapObject::RawField(this, kHeaderSize);
1856 }
1857
1858
IsEmpty()1859 bool DescriptorArray::IsEmpty() {
1860 ASSERT(this->IsSmi() ||
1861 this->length() > kFirstIndex ||
1862 this == HEAP->empty_descriptor_array());
1863 return this->IsSmi() || length() <= kFirstIndex;
1864 }
1865
1866
bit_field3_storage()1867 int DescriptorArray::bit_field3_storage() {
1868 Object* storage = READ_FIELD(this, kBitField3StorageOffset);
1869 return Smi::cast(storage)->value();
1870 }
1871
set_bit_field3_storage(int value)1872 void DescriptorArray::set_bit_field3_storage(int value) {
1873 ASSERT(!IsEmpty());
1874 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
1875 }
1876
1877
NoIncrementalWriteBarrierSwap(FixedArray * array,int first,int second)1878 void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array,
1879 int first,
1880 int second) {
1881 Object* tmp = array->get(first);
1882 NoIncrementalWriteBarrierSet(array, first, array->get(second));
1883 NoIncrementalWriteBarrierSet(array, second, tmp);
1884 }
1885
1886
Search(String * name)1887 int DescriptorArray::Search(String* name) {
1888 SLOW_ASSERT(IsSortedNoDuplicates());
1889
1890 // Check for empty descriptor array.
1891 int nof = number_of_descriptors();
1892 if (nof == 0) return kNotFound;
1893
1894 // Fast case: do linear search for small arrays.
1895 const int kMaxElementsForLinearSearch = 8;
1896 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1897 return LinearSearch(name, nof);
1898 }
1899
1900 // Slow case: perform binary search.
1901 return BinarySearch(name, 0, nof - 1);
1902 }
1903
1904
SearchWithCache(String * name)1905 int DescriptorArray::SearchWithCache(String* name) {
1906 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
1907 if (number == DescriptorLookupCache::kAbsent) {
1908 number = Search(name);
1909 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
1910 }
1911 return number;
1912 }
1913
1914
GetKey(int descriptor_number)1915 String* DescriptorArray::GetKey(int descriptor_number) {
1916 ASSERT(descriptor_number < number_of_descriptors());
1917 return String::cast(get(ToKeyIndex(descriptor_number)));
1918 }
1919
1920
GetValue(int descriptor_number)1921 Object* DescriptorArray::GetValue(int descriptor_number) {
1922 ASSERT(descriptor_number < number_of_descriptors());
1923 return GetContentArray()->get(ToValueIndex(descriptor_number));
1924 }
1925
1926
GetDetails(int descriptor_number)1927 Smi* DescriptorArray::GetDetails(int descriptor_number) {
1928 ASSERT(descriptor_number < number_of_descriptors());
1929 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1930 }
1931
1932
GetType(int descriptor_number)1933 PropertyType DescriptorArray::GetType(int descriptor_number) {
1934 ASSERT(descriptor_number < number_of_descriptors());
1935 return PropertyDetails(GetDetails(descriptor_number)).type();
1936 }
1937
1938
GetFieldIndex(int descriptor_number)1939 int DescriptorArray::GetFieldIndex(int descriptor_number) {
1940 return Descriptor::IndexFromValue(GetValue(descriptor_number));
1941 }
1942
1943
GetConstantFunction(int descriptor_number)1944 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1945 return JSFunction::cast(GetValue(descriptor_number));
1946 }
1947
1948
GetCallbacksObject(int descriptor_number)1949 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1950 ASSERT(GetType(descriptor_number) == CALLBACKS);
1951 return GetValue(descriptor_number);
1952 }
1953
1954
GetCallbacks(int descriptor_number)1955 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1956 ASSERT(GetType(descriptor_number) == CALLBACKS);
1957 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
1958 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
1959 }
1960
1961
IsProperty(int descriptor_number)1962 bool DescriptorArray::IsProperty(int descriptor_number) {
1963 Entry entry(this, descriptor_number);
1964 return IsPropertyDescriptor(&entry);
1965 }
1966
1967
IsTransitionOnly(int descriptor_number)1968 bool DescriptorArray::IsTransitionOnly(int descriptor_number) {
1969 switch (GetType(descriptor_number)) {
1970 case MAP_TRANSITION:
1971 case CONSTANT_TRANSITION:
1972 case ELEMENTS_TRANSITION:
1973 return true;
1974 case CALLBACKS: {
1975 Object* value = GetValue(descriptor_number);
1976 if (!value->IsAccessorPair()) return false;
1977 AccessorPair* accessors = AccessorPair::cast(value);
1978 return accessors->getter()->IsMap() && accessors->setter()->IsMap();
1979 }
1980 case NORMAL:
1981 case FIELD:
1982 case CONSTANT_FUNCTION:
1983 case HANDLER:
1984 case INTERCEPTOR:
1985 case NULL_DESCRIPTOR:
1986 return false;
1987 }
1988 UNREACHABLE(); // Keep the compiler happy.
1989 return false;
1990 }
1991
1992
IsNullDescriptor(int descriptor_number)1993 bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1994 return GetType(descriptor_number) == NULL_DESCRIPTOR;
1995 }
1996
1997
IsDontEnum(int descriptor_number)1998 bool DescriptorArray::IsDontEnum(int descriptor_number) {
1999 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
2000 }
2001
2002
Get(int descriptor_number,Descriptor * desc)2003 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
2004 desc->Init(GetKey(descriptor_number),
2005 GetValue(descriptor_number),
2006 PropertyDetails(GetDetails(descriptor_number)));
2007 }
2008
2009
Set(int descriptor_number,Descriptor * desc,const WhitenessWitness &)2010 void DescriptorArray::Set(int descriptor_number,
2011 Descriptor* desc,
2012 const WhitenessWitness&) {
2013 // Range check.
2014 ASSERT(descriptor_number < number_of_descriptors());
2015
2016 NoIncrementalWriteBarrierSet(this,
2017 ToKeyIndex(descriptor_number),
2018 desc->GetKey());
2019 FixedArray* content_array = GetContentArray();
2020 NoIncrementalWriteBarrierSet(content_array,
2021 ToValueIndex(descriptor_number),
2022 desc->GetValue());
2023 NoIncrementalWriteBarrierSet(content_array,
2024 ToDetailsIndex(descriptor_number),
2025 desc->GetDetails().AsSmi());
2026 }
2027
2028
NoIncrementalWriteBarrierSwapDescriptors(int first,int second)2029 void DescriptorArray::NoIncrementalWriteBarrierSwapDescriptors(
2030 int first, int second) {
2031 NoIncrementalWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
2032 FixedArray* content_array = GetContentArray();
2033 NoIncrementalWriteBarrierSwap(content_array,
2034 ToValueIndex(first),
2035 ToValueIndex(second));
2036 NoIncrementalWriteBarrierSwap(content_array,
2037 ToDetailsIndex(first),
2038 ToDetailsIndex(second));
2039 }
2040
2041
WhitenessWitness(DescriptorArray * array)2042 DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
2043 : marking_(array->GetHeap()->incremental_marking()) {
2044 marking_->EnterNoMarkingScope();
2045 if (array->number_of_descriptors() > 0) {
2046 ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
2047 ASSERT(Marking::Color(array->GetContentArray()) == Marking::WHITE_OBJECT);
2048 }
2049 }
2050
2051
~WhitenessWitness()2052 DescriptorArray::WhitenessWitness::~WhitenessWitness() {
2053 marking_->LeaveNoMarkingScope();
2054 }
2055
2056
2057 template<typename Shape, typename Key>
ComputeCapacity(int at_least_space_for)2058 int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
2059 const int kMinCapacity = 32;
2060 int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
2061 if (capacity < kMinCapacity) {
2062 capacity = kMinCapacity; // Guarantee min capacity.
2063 }
2064 return capacity;
2065 }
2066
2067
2068 template<typename Shape, typename Key>
FindEntry(Key key)2069 int HashTable<Shape, Key>::FindEntry(Key key) {
2070 return FindEntry(GetIsolate(), key);
2071 }
2072
2073
2074 // Find entry for key otherwise return kNotFound.
2075 template<typename Shape, typename Key>
FindEntry(Isolate * isolate,Key key)2076 int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
2077 uint32_t capacity = Capacity();
2078 uint32_t entry = FirstProbe(HashTable<Shape, Key>::Hash(key), capacity);
2079 uint32_t count = 1;
2080 // EnsureCapacity will guarantee the hash table is never full.
2081 while (true) {
2082 Object* element = KeyAt(entry);
2083 // Empty entry.
2084 if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
2085 if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
2086 Shape::IsMatch(key, element)) return entry;
2087 entry = NextProbe(entry, count++, capacity);
2088 }
2089 return kNotFound;
2090 }
2091
2092
requires_slow_elements()2093 bool SeededNumberDictionary::requires_slow_elements() {
2094 Object* max_index_object = get(kMaxNumberKeyIndex);
2095 if (!max_index_object->IsSmi()) return false;
2096 return 0 !=
2097 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
2098 }
2099
max_number_key()2100 uint32_t SeededNumberDictionary::max_number_key() {
2101 ASSERT(!requires_slow_elements());
2102 Object* max_index_object = get(kMaxNumberKeyIndex);
2103 if (!max_index_object->IsSmi()) return 0;
2104 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
2105 return value >> kRequiresSlowElementsTagSize;
2106 }
2107
set_requires_slow_elements()2108 void SeededNumberDictionary::set_requires_slow_elements() {
2109 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
2110 }
2111
2112
2113 // ------------------------------------
2114 // Cast operations
2115
2116
2117 CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedDoubleArray)2118 CAST_ACCESSOR(FixedDoubleArray)
2119 CAST_ACCESSOR(DescriptorArray)
2120 CAST_ACCESSOR(DeoptimizationInputData)
2121 CAST_ACCESSOR(DeoptimizationOutputData)
2122 CAST_ACCESSOR(TypeFeedbackCells)
2123 CAST_ACCESSOR(SymbolTable)
2124 CAST_ACCESSOR(JSFunctionResultCache)
2125 CAST_ACCESSOR(NormalizedMapCache)
2126 CAST_ACCESSOR(ScopeInfo)
2127 CAST_ACCESSOR(CompilationCacheTable)
2128 CAST_ACCESSOR(CodeCacheHashTable)
2129 CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
2130 CAST_ACCESSOR(MapCache)
2131 CAST_ACCESSOR(String)
2132 CAST_ACCESSOR(SeqString)
2133 CAST_ACCESSOR(SeqAsciiString)
2134 CAST_ACCESSOR(SeqTwoByteString)
2135 CAST_ACCESSOR(SlicedString)
2136 CAST_ACCESSOR(ConsString)
2137 CAST_ACCESSOR(ExternalString)
2138 CAST_ACCESSOR(ExternalAsciiString)
2139 CAST_ACCESSOR(ExternalTwoByteString)
2140 CAST_ACCESSOR(JSReceiver)
2141 CAST_ACCESSOR(JSObject)
2142 CAST_ACCESSOR(Smi)
2143 CAST_ACCESSOR(HeapObject)
2144 CAST_ACCESSOR(HeapNumber)
2145 CAST_ACCESSOR(Oddball)
2146 CAST_ACCESSOR(JSGlobalPropertyCell)
2147 CAST_ACCESSOR(SharedFunctionInfo)
2148 CAST_ACCESSOR(Map)
2149 CAST_ACCESSOR(JSFunction)
2150 CAST_ACCESSOR(GlobalObject)
2151 CAST_ACCESSOR(JSGlobalProxy)
2152 CAST_ACCESSOR(JSGlobalObject)
2153 CAST_ACCESSOR(JSBuiltinsObject)
2154 CAST_ACCESSOR(Code)
2155 CAST_ACCESSOR(JSArray)
2156 CAST_ACCESSOR(JSRegExp)
2157 CAST_ACCESSOR(JSProxy)
2158 CAST_ACCESSOR(JSFunctionProxy)
2159 CAST_ACCESSOR(JSSet)
2160 CAST_ACCESSOR(JSMap)
2161 CAST_ACCESSOR(JSWeakMap)
2162 CAST_ACCESSOR(Foreign)
2163 CAST_ACCESSOR(ByteArray)
2164 CAST_ACCESSOR(FreeSpace)
2165 CAST_ACCESSOR(ExternalArray)
2166 CAST_ACCESSOR(ExternalByteArray)
2167 CAST_ACCESSOR(ExternalUnsignedByteArray)
2168 CAST_ACCESSOR(ExternalShortArray)
2169 CAST_ACCESSOR(ExternalUnsignedShortArray)
2170 CAST_ACCESSOR(ExternalIntArray)
2171 CAST_ACCESSOR(ExternalUnsignedIntArray)
2172 CAST_ACCESSOR(ExternalFloatArray)
2173 CAST_ACCESSOR(ExternalDoubleArray)
2174 CAST_ACCESSOR(ExternalPixelArray)
2175 CAST_ACCESSOR(Struct)
2176
2177
2178 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2179 STRUCT_LIST(MAKE_STRUCT_CAST)
2180 #undef MAKE_STRUCT_CAST
2181
2182
2183 template <typename Shape, typename Key>
2184 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
2185 ASSERT(obj->IsHashTable());
2186 return reinterpret_cast<HashTable*>(obj);
2187 }
2188
2189
SMI_ACCESSORS(FixedArrayBase,length,kLengthOffset)2190 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
2191 SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2192
2193 SMI_ACCESSORS(String, length, kLengthOffset)
2194
2195
2196 uint32_t String::hash_field() {
2197 return READ_UINT32_FIELD(this, kHashFieldOffset);
2198 }
2199
2200
set_hash_field(uint32_t value)2201 void String::set_hash_field(uint32_t value) {
2202 WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
2203 #if V8_HOST_ARCH_64_BIT
2204 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2205 #endif
2206 }
2207
2208
Equals(String * other)2209 bool String::Equals(String* other) {
2210 if (other == this) return true;
2211 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
2212 return false;
2213 }
2214 return SlowEquals(other);
2215 }
2216
2217
TryFlatten(PretenureFlag pretenure)2218 MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
2219 if (!StringShape(this).IsCons()) return this;
2220 ConsString* cons = ConsString::cast(this);
2221 if (cons->IsFlat()) return cons->first();
2222 return SlowTryFlatten(pretenure);
2223 }
2224
2225
TryFlattenGetString(PretenureFlag pretenure)2226 String* String::TryFlattenGetString(PretenureFlag pretenure) {
2227 MaybeObject* flat = TryFlatten(pretenure);
2228 Object* successfully_flattened;
2229 if (!flat->ToObject(&successfully_flattened)) return this;
2230 return String::cast(successfully_flattened);
2231 }
2232
2233
Get(int index)2234 uint16_t String::Get(int index) {
2235 ASSERT(index >= 0 && index < length());
2236 switch (StringShape(this).full_representation_tag()) {
2237 case kSeqStringTag | kAsciiStringTag:
2238 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
2239 case kSeqStringTag | kTwoByteStringTag:
2240 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2241 case kConsStringTag | kAsciiStringTag:
2242 case kConsStringTag | kTwoByteStringTag:
2243 return ConsString::cast(this)->ConsStringGet(index);
2244 case kExternalStringTag | kAsciiStringTag:
2245 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2246 case kExternalStringTag | kTwoByteStringTag:
2247 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
2248 case kSlicedStringTag | kAsciiStringTag:
2249 case kSlicedStringTag | kTwoByteStringTag:
2250 return SlicedString::cast(this)->SlicedStringGet(index);
2251 default:
2252 break;
2253 }
2254
2255 UNREACHABLE();
2256 return 0;
2257 }
2258
2259
Set(int index,uint16_t value)2260 void String::Set(int index, uint16_t value) {
2261 ASSERT(index >= 0 && index < length());
2262 ASSERT(StringShape(this).IsSequential());
2263
2264 return this->IsAsciiRepresentation()
2265 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
2266 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
2267 }
2268
2269
IsFlat()2270 bool String::IsFlat() {
2271 if (!StringShape(this).IsCons()) return true;
2272 return ConsString::cast(this)->second()->length() == 0;
2273 }
2274
2275
GetUnderlying()2276 String* String::GetUnderlying() {
2277 // Giving direct access to underlying string only makes sense if the
2278 // wrapping string is already flattened.
2279 ASSERT(this->IsFlat());
2280 ASSERT(StringShape(this).IsIndirect());
2281 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
2282 const int kUnderlyingOffset = SlicedString::kParentOffset;
2283 return String::cast(READ_FIELD(this, kUnderlyingOffset));
2284 }
2285
2286
SeqAsciiStringGet(int index)2287 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
2288 ASSERT(index >= 0 && index < length());
2289 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2290 }
2291
2292
SeqAsciiStringSet(int index,uint16_t value)2293 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
2294 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
2295 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
2296 static_cast<byte>(value));
2297 }
2298
2299
GetCharsAddress()2300 Address SeqAsciiString::GetCharsAddress() {
2301 return FIELD_ADDR(this, kHeaderSize);
2302 }
2303
2304
GetChars()2305 char* SeqAsciiString::GetChars() {
2306 return reinterpret_cast<char*>(GetCharsAddress());
2307 }
2308
2309
GetCharsAddress()2310 Address SeqTwoByteString::GetCharsAddress() {
2311 return FIELD_ADDR(this, kHeaderSize);
2312 }
2313
2314
GetChars()2315 uc16* SeqTwoByteString::GetChars() {
2316 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2317 }
2318
2319
SeqTwoByteStringGet(int index)2320 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
2321 ASSERT(index >= 0 && index < length());
2322 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2323 }
2324
2325
SeqTwoByteStringSet(int index,uint16_t value)2326 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
2327 ASSERT(index >= 0 && index < length());
2328 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2329 }
2330
2331
SeqTwoByteStringSize(InstanceType instance_type)2332 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
2333 return SizeFor(length());
2334 }
2335
2336
SeqAsciiStringSize(InstanceType instance_type)2337 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
2338 return SizeFor(length());
2339 }
2340
2341
parent()2342 String* SlicedString::parent() {
2343 return String::cast(READ_FIELD(this, kParentOffset));
2344 }
2345
2346
set_parent(String * parent)2347 void SlicedString::set_parent(String* parent) {
2348 ASSERT(parent->IsSeqString() || parent->IsExternalString());
2349 WRITE_FIELD(this, kParentOffset, parent);
2350 }
2351
2352
SMI_ACCESSORS(SlicedString,offset,kOffsetOffset)2353 SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
2354
2355
2356 String* ConsString::first() {
2357 return String::cast(READ_FIELD(this, kFirstOffset));
2358 }
2359
2360
unchecked_first()2361 Object* ConsString::unchecked_first() {
2362 return READ_FIELD(this, kFirstOffset);
2363 }
2364
2365
set_first(String * value,WriteBarrierMode mode)2366 void ConsString::set_first(String* value, WriteBarrierMode mode) {
2367 WRITE_FIELD(this, kFirstOffset, value);
2368 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
2369 }
2370
2371
second()2372 String* ConsString::second() {
2373 return String::cast(READ_FIELD(this, kSecondOffset));
2374 }
2375
2376
unchecked_second()2377 Object* ConsString::unchecked_second() {
2378 return READ_FIELD(this, kSecondOffset);
2379 }
2380
2381
set_second(String * value,WriteBarrierMode mode)2382 void ConsString::set_second(String* value, WriteBarrierMode mode) {
2383 WRITE_FIELD(this, kSecondOffset, value);
2384 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
2385 }
2386
2387
is_short()2388 bool ExternalString::is_short() {
2389 InstanceType type = map()->instance_type();
2390 return (type & kShortExternalStringMask) == kShortExternalStringTag;
2391 }
2392
2393
resource()2394 const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
2395 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2396 }
2397
2398
update_data_cache()2399 void ExternalAsciiString::update_data_cache() {
2400 if (is_short()) return;
2401 const char** data_field =
2402 reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
2403 *data_field = resource()->data();
2404 }
2405
2406
set_resource(const ExternalAsciiString::Resource * resource)2407 void ExternalAsciiString::set_resource(
2408 const ExternalAsciiString::Resource* resource) {
2409 *reinterpret_cast<const Resource**>(
2410 FIELD_ADDR(this, kResourceOffset)) = resource;
2411 if (resource != NULL) update_data_cache();
2412 }
2413
2414
GetChars()2415 const char* ExternalAsciiString::GetChars() {
2416 return resource()->data();
2417 }
2418
2419
ExternalAsciiStringGet(int index)2420 uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
2421 ASSERT(index >= 0 && index < length());
2422 return GetChars()[index];
2423 }
2424
2425
resource()2426 const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
2427 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2428 }
2429
2430
update_data_cache()2431 void ExternalTwoByteString::update_data_cache() {
2432 if (is_short()) return;
2433 const uint16_t** data_field =
2434 reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
2435 *data_field = resource()->data();
2436 }
2437
2438
set_resource(const ExternalTwoByteString::Resource * resource)2439 void ExternalTwoByteString::set_resource(
2440 const ExternalTwoByteString::Resource* resource) {
2441 *reinterpret_cast<const Resource**>(
2442 FIELD_ADDR(this, kResourceOffset)) = resource;
2443 if (resource != NULL) update_data_cache();
2444 }
2445
2446
GetChars()2447 const uint16_t* ExternalTwoByteString::GetChars() {
2448 return resource()->data();
2449 }
2450
2451
ExternalTwoByteStringGet(int index)2452 uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
2453 ASSERT(index >= 0 && index < length());
2454 return GetChars()[index];
2455 }
2456
2457
ExternalTwoByteStringGetData(unsigned start)2458 const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
2459 unsigned start) {
2460 return GetChars() + start;
2461 }
2462
2463
MakeZeroSize()2464 void JSFunctionResultCache::MakeZeroSize() {
2465 set_finger_index(kEntriesIndex);
2466 set_size(kEntriesIndex);
2467 }
2468
2469
Clear()2470 void JSFunctionResultCache::Clear() {
2471 int cache_size = size();
2472 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
2473 MemsetPointer(entries_start,
2474 GetHeap()->the_hole_value(),
2475 cache_size - kEntriesIndex);
2476 MakeZeroSize();
2477 }
2478
2479
size()2480 int JSFunctionResultCache::size() {
2481 return Smi::cast(get(kCacheSizeIndex))->value();
2482 }
2483
2484
set_size(int size)2485 void JSFunctionResultCache::set_size(int size) {
2486 set(kCacheSizeIndex, Smi::FromInt(size));
2487 }
2488
2489
finger_index()2490 int JSFunctionResultCache::finger_index() {
2491 return Smi::cast(get(kFingerIndex))->value();
2492 }
2493
2494
set_finger_index(int finger_index)2495 void JSFunctionResultCache::set_finger_index(int finger_index) {
2496 set(kFingerIndex, Smi::FromInt(finger_index));
2497 }
2498
2499
get(int index)2500 byte ByteArray::get(int index) {
2501 ASSERT(index >= 0 && index < this->length());
2502 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2503 }
2504
2505
set(int index,byte value)2506 void ByteArray::set(int index, byte value) {
2507 ASSERT(index >= 0 && index < this->length());
2508 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2509 }
2510
2511
get_int(int index)2512 int ByteArray::get_int(int index) {
2513 ASSERT(index >= 0 && (index * kIntSize) < this->length());
2514 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2515 }
2516
2517
FromDataStartAddress(Address address)2518 ByteArray* ByteArray::FromDataStartAddress(Address address) {
2519 ASSERT_TAG_ALIGNED(address);
2520 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2521 }
2522
2523
GetDataStartAddress()2524 Address ByteArray::GetDataStartAddress() {
2525 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2526 }
2527
2528
external_pixel_pointer()2529 uint8_t* ExternalPixelArray::external_pixel_pointer() {
2530 return reinterpret_cast<uint8_t*>(external_pointer());
2531 }
2532
2533
get_scalar(int index)2534 uint8_t ExternalPixelArray::get_scalar(int index) {
2535 ASSERT((index >= 0) && (index < this->length()));
2536 uint8_t* ptr = external_pixel_pointer();
2537 return ptr[index];
2538 }
2539
2540
get(int index)2541 MaybeObject* ExternalPixelArray::get(int index) {
2542 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2543 }
2544
2545
set(int index,uint8_t value)2546 void ExternalPixelArray::set(int index, uint8_t value) {
2547 ASSERT((index >= 0) && (index < this->length()));
2548 uint8_t* ptr = external_pixel_pointer();
2549 ptr[index] = value;
2550 }
2551
2552
external_pointer()2553 void* ExternalArray::external_pointer() {
2554 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2555 return reinterpret_cast<void*>(ptr);
2556 }
2557
2558
set_external_pointer(void * value,WriteBarrierMode mode)2559 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2560 intptr_t ptr = reinterpret_cast<intptr_t>(value);
2561 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2562 }
2563
2564
get_scalar(int index)2565 int8_t ExternalByteArray::get_scalar(int index) {
2566 ASSERT((index >= 0) && (index < this->length()));
2567 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2568 return ptr[index];
2569 }
2570
2571
get(int index)2572 MaybeObject* ExternalByteArray::get(int index) {
2573 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2574 }
2575
2576
set(int index,int8_t value)2577 void ExternalByteArray::set(int index, int8_t value) {
2578 ASSERT((index >= 0) && (index < this->length()));
2579 int8_t* ptr = static_cast<int8_t*>(external_pointer());
2580 ptr[index] = value;
2581 }
2582
2583
get_scalar(int index)2584 uint8_t ExternalUnsignedByteArray::get_scalar(int index) {
2585 ASSERT((index >= 0) && (index < this->length()));
2586 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2587 return ptr[index];
2588 }
2589
2590
get(int index)2591 MaybeObject* ExternalUnsignedByteArray::get(int index) {
2592 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2593 }
2594
2595
set(int index,uint8_t value)2596 void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2597 ASSERT((index >= 0) && (index < this->length()));
2598 uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2599 ptr[index] = value;
2600 }
2601
2602
get_scalar(int index)2603 int16_t ExternalShortArray::get_scalar(int index) {
2604 ASSERT((index >= 0) && (index < this->length()));
2605 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2606 return ptr[index];
2607 }
2608
2609
get(int index)2610 MaybeObject* ExternalShortArray::get(int index) {
2611 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2612 }
2613
2614
set(int index,int16_t value)2615 void ExternalShortArray::set(int index, int16_t value) {
2616 ASSERT((index >= 0) && (index < this->length()));
2617 int16_t* ptr = static_cast<int16_t*>(external_pointer());
2618 ptr[index] = value;
2619 }
2620
2621
get_scalar(int index)2622 uint16_t ExternalUnsignedShortArray::get_scalar(int index) {
2623 ASSERT((index >= 0) && (index < this->length()));
2624 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2625 return ptr[index];
2626 }
2627
2628
get(int index)2629 MaybeObject* ExternalUnsignedShortArray::get(int index) {
2630 return Smi::FromInt(static_cast<int>(get_scalar(index)));
2631 }
2632
2633
set(int index,uint16_t value)2634 void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2635 ASSERT((index >= 0) && (index < this->length()));
2636 uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2637 ptr[index] = value;
2638 }
2639
2640
get_scalar(int index)2641 int32_t ExternalIntArray::get_scalar(int index) {
2642 ASSERT((index >= 0) && (index < this->length()));
2643 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2644 return ptr[index];
2645 }
2646
2647
get(int index)2648 MaybeObject* ExternalIntArray::get(int index) {
2649 return GetHeap()->NumberFromInt32(get_scalar(index));
2650 }
2651
2652
set(int index,int32_t value)2653 void ExternalIntArray::set(int index, int32_t value) {
2654 ASSERT((index >= 0) && (index < this->length()));
2655 int32_t* ptr = static_cast<int32_t*>(external_pointer());
2656 ptr[index] = value;
2657 }
2658
2659
get_scalar(int index)2660 uint32_t ExternalUnsignedIntArray::get_scalar(int index) {
2661 ASSERT((index >= 0) && (index < this->length()));
2662 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2663 return ptr[index];
2664 }
2665
2666
get(int index)2667 MaybeObject* ExternalUnsignedIntArray::get(int index) {
2668 return GetHeap()->NumberFromUint32(get_scalar(index));
2669 }
2670
2671
set(int index,uint32_t value)2672 void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2673 ASSERT((index >= 0) && (index < this->length()));
2674 uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2675 ptr[index] = value;
2676 }
2677
2678
get_scalar(int index)2679 float ExternalFloatArray::get_scalar(int index) {
2680 ASSERT((index >= 0) && (index < this->length()));
2681 float* ptr = static_cast<float*>(external_pointer());
2682 return ptr[index];
2683 }
2684
2685
get(int index)2686 MaybeObject* ExternalFloatArray::get(int index) {
2687 return GetHeap()->NumberFromDouble(get_scalar(index));
2688 }
2689
2690
set(int index,float value)2691 void ExternalFloatArray::set(int index, float value) {
2692 ASSERT((index >= 0) && (index < this->length()));
2693 float* ptr = static_cast<float*>(external_pointer());
2694 ptr[index] = value;
2695 }
2696
2697
get_scalar(int index)2698 double ExternalDoubleArray::get_scalar(int index) {
2699 ASSERT((index >= 0) && (index < this->length()));
2700 double* ptr = static_cast<double*>(external_pointer());
2701 return ptr[index];
2702 }
2703
2704
get(int index)2705 MaybeObject* ExternalDoubleArray::get(int index) {
2706 return GetHeap()->NumberFromDouble(get_scalar(index));
2707 }
2708
2709
set(int index,double value)2710 void ExternalDoubleArray::set(int index, double value) {
2711 ASSERT((index >= 0) && (index < this->length()));
2712 double* ptr = static_cast<double*>(external_pointer());
2713 ptr[index] = value;
2714 }
2715
2716
visitor_id()2717 int Map::visitor_id() {
2718 return READ_BYTE_FIELD(this, kVisitorIdOffset);
2719 }
2720
2721
set_visitor_id(int id)2722 void Map::set_visitor_id(int id) {
2723 ASSERT(0 <= id && id < 256);
2724 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2725 }
2726
2727
instance_size()2728 int Map::instance_size() {
2729 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2730 }
2731
2732
inobject_properties()2733 int Map::inobject_properties() {
2734 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2735 }
2736
2737
pre_allocated_property_fields()2738 int Map::pre_allocated_property_fields() {
2739 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2740 }
2741
2742
SizeFromMap(Map * map)2743 int HeapObject::SizeFromMap(Map* map) {
2744 int instance_size = map->instance_size();
2745 if (instance_size != kVariableSizeSentinel) return instance_size;
2746 // We can ignore the "symbol" bit becase it is only set for symbols
2747 // and implies a string type.
2748 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
2749 // Only inline the most frequent cases.
2750 if (instance_type == FIXED_ARRAY_TYPE) {
2751 return FixedArray::BodyDescriptor::SizeOf(map, this);
2752 }
2753 if (instance_type == ASCII_STRING_TYPE) {
2754 return SeqAsciiString::SizeFor(
2755 reinterpret_cast<SeqAsciiString*>(this)->length());
2756 }
2757 if (instance_type == BYTE_ARRAY_TYPE) {
2758 return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2759 }
2760 if (instance_type == FREE_SPACE_TYPE) {
2761 return reinterpret_cast<FreeSpace*>(this)->size();
2762 }
2763 if (instance_type == STRING_TYPE) {
2764 return SeqTwoByteString::SizeFor(
2765 reinterpret_cast<SeqTwoByteString*>(this)->length());
2766 }
2767 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2768 return FixedDoubleArray::SizeFor(
2769 reinterpret_cast<FixedDoubleArray*>(this)->length());
2770 }
2771 ASSERT(instance_type == CODE_TYPE);
2772 return reinterpret_cast<Code*>(this)->CodeSize();
2773 }
2774
2775
set_instance_size(int value)2776 void Map::set_instance_size(int value) {
2777 ASSERT_EQ(0, value & (kPointerSize - 1));
2778 value >>= kPointerSizeLog2;
2779 ASSERT(0 <= value && value < 256);
2780 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2781 }
2782
2783
set_inobject_properties(int value)2784 void Map::set_inobject_properties(int value) {
2785 ASSERT(0 <= value && value < 256);
2786 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2787 }
2788
2789
set_pre_allocated_property_fields(int value)2790 void Map::set_pre_allocated_property_fields(int value) {
2791 ASSERT(0 <= value && value < 256);
2792 WRITE_BYTE_FIELD(this,
2793 kPreAllocatedPropertyFieldsOffset,
2794 static_cast<byte>(value));
2795 }
2796
2797
instance_type()2798 InstanceType Map::instance_type() {
2799 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2800 }
2801
2802
set_instance_type(InstanceType value)2803 void Map::set_instance_type(InstanceType value) {
2804 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2805 }
2806
2807
unused_property_fields()2808 int Map::unused_property_fields() {
2809 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2810 }
2811
2812
set_unused_property_fields(int value)2813 void Map::set_unused_property_fields(int value) {
2814 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2815 }
2816
2817
bit_field()2818 byte Map::bit_field() {
2819 return READ_BYTE_FIELD(this, kBitFieldOffset);
2820 }
2821
2822
set_bit_field(byte value)2823 void Map::set_bit_field(byte value) {
2824 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2825 }
2826
2827
bit_field2()2828 byte Map::bit_field2() {
2829 return READ_BYTE_FIELD(this, kBitField2Offset);
2830 }
2831
2832
set_bit_field2(byte value)2833 void Map::set_bit_field2(byte value) {
2834 WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2835 }
2836
2837
set_non_instance_prototype(bool value)2838 void Map::set_non_instance_prototype(bool value) {
2839 if (value) {
2840 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2841 } else {
2842 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2843 }
2844 }
2845
2846
has_non_instance_prototype()2847 bool Map::has_non_instance_prototype() {
2848 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2849 }
2850
2851
set_function_with_prototype(bool value)2852 void Map::set_function_with_prototype(bool value) {
2853 if (value) {
2854 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2855 } else {
2856 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2857 }
2858 }
2859
2860
function_with_prototype()2861 bool Map::function_with_prototype() {
2862 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2863 }
2864
2865
set_is_access_check_needed(bool access_check_needed)2866 void Map::set_is_access_check_needed(bool access_check_needed) {
2867 if (access_check_needed) {
2868 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2869 } else {
2870 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2871 }
2872 }
2873
2874
is_access_check_needed()2875 bool Map::is_access_check_needed() {
2876 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2877 }
2878
2879
set_is_extensible(bool value)2880 void Map::set_is_extensible(bool value) {
2881 if (value) {
2882 set_bit_field2(bit_field2() | (1 << kIsExtensible));
2883 } else {
2884 set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2885 }
2886 }
2887
is_extensible()2888 bool Map::is_extensible() {
2889 return ((1 << kIsExtensible) & bit_field2()) != 0;
2890 }
2891
2892
set_attached_to_shared_function_info(bool value)2893 void Map::set_attached_to_shared_function_info(bool value) {
2894 if (value) {
2895 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2896 } else {
2897 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2898 }
2899 }
2900
attached_to_shared_function_info()2901 bool Map::attached_to_shared_function_info() {
2902 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2903 }
2904
2905
set_is_shared(bool value)2906 void Map::set_is_shared(bool value) {
2907 if (value) {
2908 set_bit_field3(bit_field3() | (1 << kIsShared));
2909 } else {
2910 set_bit_field3(bit_field3() & ~(1 << kIsShared));
2911 }
2912 }
2913
is_shared()2914 bool Map::is_shared() {
2915 return ((1 << kIsShared) & bit_field3()) != 0;
2916 }
2917
2918
unchecked_constructor()2919 JSFunction* Map::unchecked_constructor() {
2920 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2921 }
2922
2923
flags()2924 Code::Flags Code::flags() {
2925 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2926 }
2927
2928
set_flags(Code::Flags flags)2929 void Code::set_flags(Code::Flags flags) {
2930 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
2931 // Make sure that all call stubs have an arguments count.
2932 ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2933 ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
2934 ExtractArgumentsCountFromFlags(flags) >= 0);
2935 WRITE_INT_FIELD(this, kFlagsOffset, flags);
2936 }
2937
2938
kind()2939 Code::Kind Code::kind() {
2940 return ExtractKindFromFlags(flags());
2941 }
2942
2943
ic_state()2944 InlineCacheState Code::ic_state() {
2945 InlineCacheState result = ExtractICStateFromFlags(flags());
2946 // Only allow uninitialized or debugger states for non-IC code
2947 // objects. This is used in the debugger to determine whether or not
2948 // a call to code object has been replaced with a debug break call.
2949 ASSERT(is_inline_cache_stub() ||
2950 result == UNINITIALIZED ||
2951 result == DEBUG_BREAK ||
2952 result == DEBUG_PREPARE_STEP_IN);
2953 return result;
2954 }
2955
2956
extra_ic_state()2957 Code::ExtraICState Code::extra_ic_state() {
2958 ASSERT(is_inline_cache_stub());
2959 return ExtractExtraICStateFromFlags(flags());
2960 }
2961
2962
type()2963 PropertyType Code::type() {
2964 return ExtractTypeFromFlags(flags());
2965 }
2966
2967
arguments_count()2968 int Code::arguments_count() {
2969 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
2970 return ExtractArgumentsCountFromFlags(flags());
2971 }
2972
2973
major_key()2974 int Code::major_key() {
2975 ASSERT(kind() == STUB ||
2976 kind() == UNARY_OP_IC ||
2977 kind() == BINARY_OP_IC ||
2978 kind() == COMPARE_IC ||
2979 kind() == TO_BOOLEAN_IC);
2980 return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
2981 }
2982
2983
set_major_key(int major)2984 void Code::set_major_key(int major) {
2985 ASSERT(kind() == STUB ||
2986 kind() == UNARY_OP_IC ||
2987 kind() == BINARY_OP_IC ||
2988 kind() == COMPARE_IC ||
2989 kind() == TO_BOOLEAN_IC);
2990 ASSERT(0 <= major && major < 256);
2991 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2992 }
2993
2994
is_pregenerated()2995 bool Code::is_pregenerated() {
2996 return kind() == STUB && IsPregeneratedField::decode(flags());
2997 }
2998
2999
set_is_pregenerated(bool value)3000 void Code::set_is_pregenerated(bool value) {
3001 ASSERT(kind() == STUB);
3002 Flags f = flags();
3003 f = static_cast<Flags>(IsPregeneratedField::update(f, value));
3004 set_flags(f);
3005 }
3006
3007
optimizable()3008 bool Code::optimizable() {
3009 ASSERT(kind() == FUNCTION);
3010 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
3011 }
3012
3013
set_optimizable(bool value)3014 void Code::set_optimizable(bool value) {
3015 ASSERT(kind() == FUNCTION);
3016 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
3017 }
3018
3019
has_deoptimization_support()3020 bool Code::has_deoptimization_support() {
3021 ASSERT(kind() == FUNCTION);
3022 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3023 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
3024 }
3025
3026
set_has_deoptimization_support(bool value)3027 void Code::set_has_deoptimization_support(bool value) {
3028 ASSERT(kind() == FUNCTION);
3029 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3030 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
3031 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3032 }
3033
3034
has_debug_break_slots()3035 bool Code::has_debug_break_slots() {
3036 ASSERT(kind() == FUNCTION);
3037 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3038 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
3039 }
3040
3041
set_has_debug_break_slots(bool value)3042 void Code::set_has_debug_break_slots(bool value) {
3043 ASSERT(kind() == FUNCTION);
3044 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3045 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
3046 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3047 }
3048
3049
is_compiled_optimizable()3050 bool Code::is_compiled_optimizable() {
3051 ASSERT(kind() == FUNCTION);
3052 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3053 return FullCodeFlagsIsCompiledOptimizable::decode(flags);
3054 }
3055
3056
set_compiled_optimizable(bool value)3057 void Code::set_compiled_optimizable(bool value) {
3058 ASSERT(kind() == FUNCTION);
3059 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3060 flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
3061 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3062 }
3063
3064
has_self_optimization_header()3065 bool Code::has_self_optimization_header() {
3066 ASSERT(kind() == FUNCTION);
3067 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3068 return FullCodeFlagsHasSelfOptimizationHeader::decode(flags);
3069 }
3070
3071
set_self_optimization_header(bool value)3072 void Code::set_self_optimization_header(bool value) {
3073 ASSERT(kind() == FUNCTION);
3074 byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
3075 flags = FullCodeFlagsHasSelfOptimizationHeader::update(flags, value);
3076 WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
3077 }
3078
3079
allow_osr_at_loop_nesting_level()3080 int Code::allow_osr_at_loop_nesting_level() {
3081 ASSERT(kind() == FUNCTION);
3082 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
3083 }
3084
3085
set_allow_osr_at_loop_nesting_level(int level)3086 void Code::set_allow_osr_at_loop_nesting_level(int level) {
3087 ASSERT(kind() == FUNCTION);
3088 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
3089 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
3090 }
3091
3092
profiler_ticks()3093 int Code::profiler_ticks() {
3094 ASSERT(kind() == FUNCTION);
3095 return READ_BYTE_FIELD(this, kProfilerTicksOffset);
3096 }
3097
3098
set_profiler_ticks(int ticks)3099 void Code::set_profiler_ticks(int ticks) {
3100 ASSERT(kind() == FUNCTION);
3101 ASSERT(ticks < 256);
3102 WRITE_BYTE_FIELD(this, kProfilerTicksOffset, ticks);
3103 }
3104
3105
stack_slots()3106 unsigned Code::stack_slots() {
3107 ASSERT(kind() == OPTIMIZED_FUNCTION);
3108 return READ_UINT32_FIELD(this, kStackSlotsOffset);
3109 }
3110
3111
set_stack_slots(unsigned slots)3112 void Code::set_stack_slots(unsigned slots) {
3113 ASSERT(kind() == OPTIMIZED_FUNCTION);
3114 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
3115 }
3116
3117
safepoint_table_offset()3118 unsigned Code::safepoint_table_offset() {
3119 ASSERT(kind() == OPTIMIZED_FUNCTION);
3120 return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
3121 }
3122
3123
set_safepoint_table_offset(unsigned offset)3124 void Code::set_safepoint_table_offset(unsigned offset) {
3125 ASSERT(kind() == OPTIMIZED_FUNCTION);
3126 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
3127 WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
3128 }
3129
3130
stack_check_table_offset()3131 unsigned Code::stack_check_table_offset() {
3132 ASSERT(kind() == FUNCTION);
3133 return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
3134 }
3135
3136
set_stack_check_table_offset(unsigned offset)3137 void Code::set_stack_check_table_offset(unsigned offset) {
3138 ASSERT(kind() == FUNCTION);
3139 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
3140 WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
3141 }
3142
3143
check_type()3144 CheckType Code::check_type() {
3145 ASSERT(is_call_stub() || is_keyed_call_stub());
3146 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
3147 return static_cast<CheckType>(type);
3148 }
3149
3150
set_check_type(CheckType value)3151 void Code::set_check_type(CheckType value) {
3152 ASSERT(is_call_stub() || is_keyed_call_stub());
3153 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
3154 }
3155
3156
unary_op_type()3157 byte Code::unary_op_type() {
3158 ASSERT(is_unary_op_stub());
3159 return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
3160 }
3161
3162
set_unary_op_type(byte value)3163 void Code::set_unary_op_type(byte value) {
3164 ASSERT(is_unary_op_stub());
3165 WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
3166 }
3167
3168
binary_op_type()3169 byte Code::binary_op_type() {
3170 ASSERT(is_binary_op_stub());
3171 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
3172 }
3173
3174
set_binary_op_type(byte value)3175 void Code::set_binary_op_type(byte value) {
3176 ASSERT(is_binary_op_stub());
3177 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
3178 }
3179
3180
binary_op_result_type()3181 byte Code::binary_op_result_type() {
3182 ASSERT(is_binary_op_stub());
3183 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
3184 }
3185
3186
set_binary_op_result_type(byte value)3187 void Code::set_binary_op_result_type(byte value) {
3188 ASSERT(is_binary_op_stub());
3189 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
3190 }
3191
3192
compare_state()3193 byte Code::compare_state() {
3194 ASSERT(is_compare_ic_stub());
3195 return READ_BYTE_FIELD(this, kCompareStateOffset);
3196 }
3197
3198
set_compare_state(byte value)3199 void Code::set_compare_state(byte value) {
3200 ASSERT(is_compare_ic_stub());
3201 WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
3202 }
3203
3204
to_boolean_state()3205 byte Code::to_boolean_state() {
3206 ASSERT(is_to_boolean_ic_stub());
3207 return READ_BYTE_FIELD(this, kToBooleanTypeOffset);
3208 }
3209
3210
set_to_boolean_state(byte value)3211 void Code::set_to_boolean_state(byte value) {
3212 ASSERT(is_to_boolean_ic_stub());
3213 WRITE_BYTE_FIELD(this, kToBooleanTypeOffset, value);
3214 }
3215
3216
has_function_cache()3217 bool Code::has_function_cache() {
3218 ASSERT(kind() == STUB);
3219 return READ_BYTE_FIELD(this, kHasFunctionCacheOffset) != 0;
3220 }
3221
3222
set_has_function_cache(bool flag)3223 void Code::set_has_function_cache(bool flag) {
3224 ASSERT(kind() == STUB);
3225 WRITE_BYTE_FIELD(this, kHasFunctionCacheOffset, flag);
3226 }
3227
3228
is_inline_cache_stub()3229 bool Code::is_inline_cache_stub() {
3230 Kind kind = this->kind();
3231 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
3232 }
3233
3234
ComputeFlags(Kind kind,InlineCacheState ic_state,ExtraICState extra_ic_state,PropertyType type,int argc,InlineCacheHolderFlag holder)3235 Code::Flags Code::ComputeFlags(Kind kind,
3236 InlineCacheState ic_state,
3237 ExtraICState extra_ic_state,
3238 PropertyType type,
3239 int argc,
3240 InlineCacheHolderFlag holder) {
3241 // Extra IC state is only allowed for call IC stubs or for store IC
3242 // stubs.
3243 ASSERT(extra_ic_state == kNoExtraICState ||
3244 kind == CALL_IC ||
3245 kind == STORE_IC ||
3246 kind == KEYED_STORE_IC);
3247 // Compute the bit mask.
3248 int bits = KindField::encode(kind)
3249 | ICStateField::encode(ic_state)
3250 | TypeField::encode(type)
3251 | ExtraICStateField::encode(extra_ic_state)
3252 | (argc << kArgumentsCountShift)
3253 | CacheHolderField::encode(holder);
3254 return static_cast<Flags>(bits);
3255 }
3256
3257
ComputeMonomorphicFlags(Kind kind,PropertyType type,ExtraICState extra_ic_state,InlineCacheHolderFlag holder,int argc)3258 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
3259 PropertyType type,
3260 ExtraICState extra_ic_state,
3261 InlineCacheHolderFlag holder,
3262 int argc) {
3263 return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
3264 }
3265
3266
ExtractKindFromFlags(Flags flags)3267 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
3268 return KindField::decode(flags);
3269 }
3270
3271
ExtractICStateFromFlags(Flags flags)3272 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
3273 return ICStateField::decode(flags);
3274 }
3275
3276
ExtractExtraICStateFromFlags(Flags flags)3277 Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
3278 return ExtraICStateField::decode(flags);
3279 }
3280
3281
ExtractTypeFromFlags(Flags flags)3282 PropertyType Code::ExtractTypeFromFlags(Flags flags) {
3283 return TypeField::decode(flags);
3284 }
3285
3286
ExtractArgumentsCountFromFlags(Flags flags)3287 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
3288 return (flags & kArgumentsCountMask) >> kArgumentsCountShift;
3289 }
3290
3291
ExtractCacheHolderFromFlags(Flags flags)3292 InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
3293 return CacheHolderField::decode(flags);
3294 }
3295
3296
RemoveTypeFromFlags(Flags flags)3297 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
3298 int bits = flags & ~TypeField::kMask;
3299 return static_cast<Flags>(bits);
3300 }
3301
3302
GetCodeFromTargetAddress(Address address)3303 Code* Code::GetCodeFromTargetAddress(Address address) {
3304 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
3305 // GetCodeFromTargetAddress might be called when marking objects during mark
3306 // sweep. reinterpret_cast is therefore used instead of the more appropriate
3307 // Code::cast. Code::cast does not work when the object's map is
3308 // marked.
3309 Code* result = reinterpret_cast<Code*>(code);
3310 return result;
3311 }
3312
3313
GetObjectFromEntryAddress(Address location_of_address)3314 Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
3315 return HeapObject::
3316 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
3317 }
3318
3319
prototype()3320 Object* Map::prototype() {
3321 return READ_FIELD(this, kPrototypeOffset);
3322 }
3323
3324
set_prototype(Object * value,WriteBarrierMode mode)3325 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
3326 ASSERT(value->IsNull() || value->IsJSReceiver());
3327 WRITE_FIELD(this, kPrototypeOffset, value);
3328 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
3329 }
3330
3331
instance_descriptors()3332 DescriptorArray* Map::instance_descriptors() {
3333 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
3334 if (object->IsSmi()) {
3335 return GetHeap()->empty_descriptor_array();
3336 } else {
3337 return DescriptorArray::cast(object);
3338 }
3339 }
3340
3341
init_instance_descriptors()3342 void Map::init_instance_descriptors() {
3343 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0));
3344 }
3345
3346
clear_instance_descriptors()3347 void Map::clear_instance_descriptors() {
3348 Object* object = READ_FIELD(this,
3349 kInstanceDescriptorsOrBitField3Offset);
3350 if (!object->IsSmi()) {
3351 WRITE_FIELD(
3352 this,
3353 kInstanceDescriptorsOrBitField3Offset,
3354 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage()));
3355 }
3356 }
3357
3358
set_instance_descriptors(DescriptorArray * value,WriteBarrierMode mode)3359 void Map::set_instance_descriptors(DescriptorArray* value,
3360 WriteBarrierMode mode) {
3361 Object* object = READ_FIELD(this,
3362 kInstanceDescriptorsOrBitField3Offset);
3363 Heap* heap = GetHeap();
3364 if (value == heap->empty_descriptor_array()) {
3365 clear_instance_descriptors();
3366 return;
3367 } else {
3368 if (object->IsSmi()) {
3369 value->set_bit_field3_storage(Smi::cast(object)->value());
3370 } else {
3371 value->set_bit_field3_storage(
3372 DescriptorArray::cast(object)->bit_field3_storage());
3373 }
3374 }
3375 ASSERT(!is_shared());
3376 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
3377 CONDITIONAL_WRITE_BARRIER(
3378 heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode);
3379 }
3380
3381
bit_field3()3382 int Map::bit_field3() {
3383 Object* object = READ_FIELD(this,
3384 kInstanceDescriptorsOrBitField3Offset);
3385 if (object->IsSmi()) {
3386 return Smi::cast(object)->value();
3387 } else {
3388 return DescriptorArray::cast(object)->bit_field3_storage();
3389 }
3390 }
3391
3392
set_bit_field3(int value)3393 void Map::set_bit_field3(int value) {
3394 ASSERT(Smi::IsValid(value));
3395 Object* object = READ_FIELD(this,
3396 kInstanceDescriptorsOrBitField3Offset);
3397 if (object->IsSmi()) {
3398 WRITE_FIELD(this,
3399 kInstanceDescriptorsOrBitField3Offset,
3400 Smi::FromInt(value));
3401 } else {
3402 DescriptorArray::cast(object)->set_bit_field3_storage(value);
3403 }
3404 }
3405
3406
unchecked_prototype_transitions()3407 FixedArray* Map::unchecked_prototype_transitions() {
3408 return reinterpret_cast<FixedArray*>(
3409 READ_FIELD(this, kPrototypeTransitionsOffset));
3410 }
3411
3412
ACCESSORS(Map,code_cache,Object,kCodeCacheOffset)3413 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
3414 ACCESSORS(Map, prototype_transitions, FixedArray, kPrototypeTransitionsOffset)
3415 ACCESSORS(Map, constructor, Object, kConstructorOffset)
3416
3417 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
3418 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
3419 ACCESSORS(JSFunction,
3420 next_function_link,
3421 Object,
3422 kNextFunctionLinkOffset)
3423
3424 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
3425 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
3426 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
3427
3428 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
3429
3430 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
3431 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
3432 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
3433 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
3434 ACCESSORS_TO_SMI(AccessorInfo, flag, kFlagOffset)
3435
3436 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
3437 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
3438
3439 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
3440 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
3441 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
3442
3443 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
3444 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
3445 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
3446 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
3447 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
3448 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
3449
3450 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
3451 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
3452
3453 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
3454 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
3455
3456 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
3457 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
3458 ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
3459 kPropertyAccessorsOffset)
3460 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
3461 kPrototypeTemplateOffset)
3462 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
3463 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
3464 kNamedPropertyHandlerOffset)
3465 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
3466 kIndexedPropertyHandlerOffset)
3467 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
3468 kInstanceTemplateOffset)
3469 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
3470 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
3471 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
3472 kInstanceCallHandlerOffset)
3473 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
3474 kAccessCheckInfoOffset)
3475 ACCESSORS_TO_SMI(FunctionTemplateInfo, flag, kFlagOffset)
3476
3477 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
3478 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
3479 kInternalFieldCountOffset)
3480
3481 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
3482 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
3483
3484 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
3485
3486 ACCESSORS(Script, source, Object, kSourceOffset)
3487 ACCESSORS(Script, name, Object, kNameOffset)
3488 ACCESSORS(Script, id, Object, kIdOffset)
3489 ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
3490 ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
3491 ACCESSORS(Script, data, Object, kDataOffset)
3492 ACCESSORS(Script, context_data, Object, kContextOffset)
3493 ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
3494 ACCESSORS_TO_SMI(Script, type, kTypeOffset)
3495 ACCESSORS_TO_SMI(Script, compilation_type, kCompilationTypeOffset)
3496 ACCESSORS_TO_SMI(Script, compilation_state, kCompilationStateOffset)
3497 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
3498 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
3499 ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
3500 kEvalFrominstructionsOffsetOffset)
3501
3502 #ifdef ENABLE_DEBUGGER_SUPPORT
3503 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
3504 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
3505 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
3506 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
3507
3508 ACCESSORS_TO_SMI(BreakPointInfo, code_position, kCodePositionIndex)
3509 ACCESSORS_TO_SMI(BreakPointInfo, source_position, kSourcePositionIndex)
3510 ACCESSORS_TO_SMI(BreakPointInfo, statement_position, kStatementPositionIndex)
3511 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
3512 #endif
3513
3514 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
3515 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
3516 ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
3517 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
3518 kInstanceClassNameOffset)
3519 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
3520 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
3521 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
3522 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
3523 ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
3524 kThisPropertyAssignmentsOffset)
3525 SMI_ACCESSORS(SharedFunctionInfo, ic_age, kICAgeOffset)
3526
3527
3528 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
3529 kHiddenPrototypeBit)
3530 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
3531 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
3532 kNeedsAccessCheckBit)
3533 BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
3534 kReadOnlyPrototypeBit)
3535 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
3536 kIsExpressionBit)
3537 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
3538 kIsTopLevelBit)
3539 BOOL_GETTER(SharedFunctionInfo,
3540 compiler_hints,
3541 has_only_simple_this_property_assignments,
3542 kHasOnlySimpleThisPropertyAssignments)
3543 BOOL_ACCESSORS(SharedFunctionInfo,
3544 compiler_hints,
3545 allows_lazy_compilation,
3546 kAllowLazyCompilation)
3547 BOOL_ACCESSORS(SharedFunctionInfo,
3548 compiler_hints,
3549 uses_arguments,
3550 kUsesArguments)
3551 BOOL_ACCESSORS(SharedFunctionInfo,
3552 compiler_hints,
3553 has_duplicate_parameters,
3554 kHasDuplicateParameters)
3555
3556
3557 #if V8_HOST_ARCH_32_BIT
3558 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3559 SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
3560 kFormalParameterCountOffset)
3561 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
3562 kExpectedNofPropertiesOffset)
3563 SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3564 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
3565 kStartPositionAndTypeOffset)
3566 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3567 SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
3568 kFunctionTokenPositionOffset)
3569 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
3570 kCompilerHintsOffset)
3571 SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
3572 kThisPropertyAssignmentsCountOffset)
3573 SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
3574 SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
3575 SMI_ACCESSORS(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
3576 #else
3577
3578 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
3579 STATIC_ASSERT(holder::offset % kPointerSize == 0); \
3580 int holder::name() { \
3581 int value = READ_INT_FIELD(this, offset); \
3582 ASSERT(kHeapObjectTag == 1); \
3583 ASSERT((value & kHeapObjectTag) == 0); \
3584 return value >> 1; \
3585 } \
3586 void holder::set_##name(int value) { \
3587 ASSERT(kHeapObjectTag == 1); \
3588 ASSERT((value & 0xC0000000) == 0xC0000000 || \
3589 (value & 0xC0000000) == 0x000000000); \
3590 WRITE_INT_FIELD(this, \
3591 offset, \
3592 (value << 1) & ~kHeapObjectTag); \
3593 }
3594
3595 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
3596 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \
3597 INT_ACCESSORS(holder, name, offset)
3598
3599
3600 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
3601 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3602 formal_parameter_count,
3603 kFormalParameterCountOffset)
3604
3605 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3606 expected_nof_properties,
3607 kExpectedNofPropertiesOffset)
3608 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3609
3610 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3611 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3612 start_position_and_type,
3613 kStartPositionAndTypeOffset)
3614
3615 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3616 function_token_position,
3617 kFunctionTokenPositionOffset)
3618 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3619 compiler_hints,
3620 kCompilerHintsOffset)
3621
3622 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3623 this_property_assignments_count,
3624 kThisPropertyAssignmentsCountOffset)
3625 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
3626
3627 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
3628 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
3629 #endif
3630
3631
3632 int SharedFunctionInfo::construction_count() {
3633 return READ_BYTE_FIELD(this, kConstructionCountOffset);
3634 }
3635
3636
set_construction_count(int value)3637 void SharedFunctionInfo::set_construction_count(int value) {
3638 ASSERT(0 <= value && value < 256);
3639 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3640 }
3641
3642
BOOL_ACCESSORS(SharedFunctionInfo,compiler_hints,live_objects_may_exist,kLiveObjectsMayExist)3643 BOOL_ACCESSORS(SharedFunctionInfo,
3644 compiler_hints,
3645 live_objects_may_exist,
3646 kLiveObjectsMayExist)
3647
3648
3649 bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
3650 return initial_map() != GetHeap()->undefined_value();
3651 }
3652
3653
BOOL_GETTER(SharedFunctionInfo,compiler_hints,optimization_disabled,kOptimizationDisabled)3654 BOOL_GETTER(SharedFunctionInfo,
3655 compiler_hints,
3656 optimization_disabled,
3657 kOptimizationDisabled)
3658
3659
3660 void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3661 set_compiler_hints(BooleanBit::set(compiler_hints(),
3662 kOptimizationDisabled,
3663 disable));
3664 // If disabling optimizations we reflect that in the code object so
3665 // it will not be counted as optimizable code.
3666 if ((code()->kind() == Code::FUNCTION) && disable) {
3667 code()->set_optimizable(false);
3668 }
3669 }
3670
3671
language_mode()3672 LanguageMode SharedFunctionInfo::language_mode() {
3673 int hints = compiler_hints();
3674 if (BooleanBit::get(hints, kExtendedModeFunction)) {
3675 ASSERT(BooleanBit::get(hints, kStrictModeFunction));
3676 return EXTENDED_MODE;
3677 }
3678 return BooleanBit::get(hints, kStrictModeFunction)
3679 ? STRICT_MODE : CLASSIC_MODE;
3680 }
3681
3682
set_language_mode(LanguageMode language_mode)3683 void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
3684 // We only allow language mode transitions that go set the same language mode
3685 // again or go up in the chain:
3686 // CLASSIC_MODE -> STRICT_MODE -> EXTENDED_MODE.
3687 ASSERT(this->language_mode() == CLASSIC_MODE ||
3688 this->language_mode() == language_mode ||
3689 language_mode == EXTENDED_MODE);
3690 int hints = compiler_hints();
3691 hints = BooleanBit::set(
3692 hints, kStrictModeFunction, language_mode != CLASSIC_MODE);
3693 hints = BooleanBit::set(
3694 hints, kExtendedModeFunction, language_mode == EXTENDED_MODE);
3695 set_compiler_hints(hints);
3696 }
3697
3698
is_classic_mode()3699 bool SharedFunctionInfo::is_classic_mode() {
3700 return !BooleanBit::get(compiler_hints(), kStrictModeFunction);
3701 }
3702
BOOL_GETTER(SharedFunctionInfo,compiler_hints,is_extended_mode,kExtendedModeFunction)3703 BOOL_GETTER(SharedFunctionInfo, compiler_hints, is_extended_mode,
3704 kExtendedModeFunction)
3705 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
3706 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
3707 name_should_print_as_anonymous,
3708 kNameShouldPrintAsAnonymous)
3709 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
3710 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
3711 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
3712 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_optimize,
3713 kDontOptimize)
3714 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
3715
3716 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3717 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3718
3719 ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
3720
3721 bool Script::HasValidSource() {
3722 Object* src = this->source();
3723 if (!src->IsString()) return true;
3724 String* src_str = String::cast(src);
3725 if (!StringShape(src_str).IsExternal()) return true;
3726 if (src_str->IsAsciiRepresentation()) {
3727 return ExternalAsciiString::cast(src)->resource() != NULL;
3728 } else if (src_str->IsTwoByteRepresentation()) {
3729 return ExternalTwoByteString::cast(src)->resource() != NULL;
3730 }
3731 return true;
3732 }
3733
3734
DontAdaptArguments()3735 void SharedFunctionInfo::DontAdaptArguments() {
3736 ASSERT(code()->kind() == Code::BUILTIN);
3737 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3738 }
3739
3740
start_position()3741 int SharedFunctionInfo::start_position() {
3742 return start_position_and_type() >> kStartPositionShift;
3743 }
3744
3745
set_start_position(int start_position)3746 void SharedFunctionInfo::set_start_position(int start_position) {
3747 set_start_position_and_type((start_position << kStartPositionShift)
3748 | (start_position_and_type() & ~kStartPositionMask));
3749 }
3750
3751
code()3752 Code* SharedFunctionInfo::code() {
3753 return Code::cast(READ_FIELD(this, kCodeOffset));
3754 }
3755
3756
unchecked_code()3757 Code* SharedFunctionInfo::unchecked_code() {
3758 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3759 }
3760
3761
set_code(Code * value,WriteBarrierMode mode)3762 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
3763 WRITE_FIELD(this, kCodeOffset, value);
3764 CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
3765 }
3766
3767
scope_info()3768 ScopeInfo* SharedFunctionInfo::scope_info() {
3769 return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
3770 }
3771
3772
set_scope_info(ScopeInfo * value,WriteBarrierMode mode)3773 void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
3774 WriteBarrierMode mode) {
3775 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
3776 CONDITIONAL_WRITE_BARRIER(GetHeap(),
3777 this,
3778 kScopeInfoOffset,
3779 reinterpret_cast<Object*>(value),
3780 mode);
3781 }
3782
3783
is_compiled()3784 bool SharedFunctionInfo::is_compiled() {
3785 return code() !=
3786 Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
3787 }
3788
3789
IsApiFunction()3790 bool SharedFunctionInfo::IsApiFunction() {
3791 return function_data()->IsFunctionTemplateInfo();
3792 }
3793
3794
get_api_func_data()3795 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3796 ASSERT(IsApiFunction());
3797 return FunctionTemplateInfo::cast(function_data());
3798 }
3799
3800
HasBuiltinFunctionId()3801 bool SharedFunctionInfo::HasBuiltinFunctionId() {
3802 return function_data()->IsSmi();
3803 }
3804
3805
builtin_function_id()3806 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3807 ASSERT(HasBuiltinFunctionId());
3808 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
3809 }
3810
3811
code_age()3812 int SharedFunctionInfo::code_age() {
3813 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3814 }
3815
3816
set_code_age(int code_age)3817 void SharedFunctionInfo::set_code_age(int code_age) {
3818 int hints = compiler_hints() & ~(kCodeAgeMask << kCodeAgeShift);
3819 set_compiler_hints(hints | ((code_age & kCodeAgeMask) << kCodeAgeShift));
3820 }
3821
3822
has_deoptimization_support()3823 bool SharedFunctionInfo::has_deoptimization_support() {
3824 Code* code = this->code();
3825 return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3826 }
3827
3828
IsBuiltin()3829 bool JSFunction::IsBuiltin() {
3830 return context()->global()->IsJSBuiltinsObject();
3831 }
3832
3833
NeedsArgumentsAdaption()3834 bool JSFunction::NeedsArgumentsAdaption() {
3835 return shared()->formal_parameter_count() !=
3836 SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3837 }
3838
3839
IsOptimized()3840 bool JSFunction::IsOptimized() {
3841 return code()->kind() == Code::OPTIMIZED_FUNCTION;
3842 }
3843
3844
IsOptimizable()3845 bool JSFunction::IsOptimizable() {
3846 return code()->kind() == Code::FUNCTION && code()->optimizable();
3847 }
3848
3849
IsMarkedForLazyRecompilation()3850 bool JSFunction::IsMarkedForLazyRecompilation() {
3851 return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
3852 }
3853
3854
code()3855 Code* JSFunction::code() {
3856 return Code::cast(unchecked_code());
3857 }
3858
3859
unchecked_code()3860 Code* JSFunction::unchecked_code() {
3861 return reinterpret_cast<Code*>(
3862 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
3863 }
3864
3865
set_code(Code * value)3866 void JSFunction::set_code(Code* value) {
3867 ASSERT(!HEAP->InNewSpace(value));
3868 Address entry = value->entry();
3869 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
3870 GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
3871 this,
3872 HeapObject::RawField(this, kCodeEntryOffset),
3873 value);
3874 }
3875
3876
ReplaceCode(Code * code)3877 void JSFunction::ReplaceCode(Code* code) {
3878 bool was_optimized = IsOptimized();
3879 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3880
3881 set_code(code);
3882
3883 // Add/remove the function from the list of optimized functions for this
3884 // context based on the state change.
3885 if (!was_optimized && is_optimized) {
3886 context()->global_context()->AddOptimizedFunction(this);
3887 }
3888 if (was_optimized && !is_optimized) {
3889 context()->global_context()->RemoveOptimizedFunction(this);
3890 }
3891 }
3892
3893
context()3894 Context* JSFunction::context() {
3895 return Context::cast(READ_FIELD(this, kContextOffset));
3896 }
3897
3898
unchecked_context()3899 Object* JSFunction::unchecked_context() {
3900 return READ_FIELD(this, kContextOffset);
3901 }
3902
3903
unchecked_shared()3904 SharedFunctionInfo* JSFunction::unchecked_shared() {
3905 return reinterpret_cast<SharedFunctionInfo*>(
3906 READ_FIELD(this, kSharedFunctionInfoOffset));
3907 }
3908
3909
set_context(Object * value)3910 void JSFunction::set_context(Object* value) {
3911 ASSERT(value->IsUndefined() || value->IsContext());
3912 WRITE_FIELD(this, kContextOffset, value);
3913 WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
3914 }
3915
ACCESSORS(JSFunction,prototype_or_initial_map,Object,kPrototypeOrInitialMapOffset)3916 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3917 kPrototypeOrInitialMapOffset)
3918
3919
3920 Map* JSFunction::initial_map() {
3921 return Map::cast(prototype_or_initial_map());
3922 }
3923
3924
set_initial_map(Map * value)3925 void JSFunction::set_initial_map(Map* value) {
3926 set_prototype_or_initial_map(value);
3927 }
3928
3929
set_initial_map_and_cache_transitions(Map * initial_map)3930 MaybeObject* JSFunction::set_initial_map_and_cache_transitions(
3931 Map* initial_map) {
3932 Context* global_context = context()->global_context();
3933 Object* array_function =
3934 global_context->get(Context::ARRAY_FUNCTION_INDEX);
3935 if (array_function->IsJSFunction() &&
3936 this == JSFunction::cast(array_function)) {
3937 ASSERT(initial_map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
3938
3939 MaybeObject* maybe_map = initial_map->CopyDropTransitions();
3940 Map* new_double_map = NULL;
3941 if (!maybe_map->To<Map>(&new_double_map)) return maybe_map;
3942 new_double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
3943 maybe_map = initial_map->AddElementsTransition(FAST_DOUBLE_ELEMENTS,
3944 new_double_map);
3945 if (maybe_map->IsFailure()) return maybe_map;
3946
3947 maybe_map = new_double_map->CopyDropTransitions();
3948 Map* new_object_map = NULL;
3949 if (!maybe_map->To<Map>(&new_object_map)) return maybe_map;
3950 new_object_map->set_elements_kind(FAST_ELEMENTS);
3951 maybe_map = new_double_map->AddElementsTransition(FAST_ELEMENTS,
3952 new_object_map);
3953 if (maybe_map->IsFailure()) return maybe_map;
3954
3955 global_context->set_smi_js_array_map(initial_map);
3956 global_context->set_double_js_array_map(new_double_map);
3957 global_context->set_object_js_array_map(new_object_map);
3958 }
3959 set_initial_map(initial_map);
3960 return this;
3961 }
3962
3963
has_initial_map()3964 bool JSFunction::has_initial_map() {
3965 return prototype_or_initial_map()->IsMap();
3966 }
3967
3968
has_instance_prototype()3969 bool JSFunction::has_instance_prototype() {
3970 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3971 }
3972
3973
has_prototype()3974 bool JSFunction::has_prototype() {
3975 return map()->has_non_instance_prototype() || has_instance_prototype();
3976 }
3977
3978
instance_prototype()3979 Object* JSFunction::instance_prototype() {
3980 ASSERT(has_instance_prototype());
3981 if (has_initial_map()) return initial_map()->prototype();
3982 // When there is no initial map and the prototype is a JSObject, the
3983 // initial map field is used for the prototype field.
3984 return prototype_or_initial_map();
3985 }
3986
3987
prototype()3988 Object* JSFunction::prototype() {
3989 ASSERT(has_prototype());
3990 // If the function's prototype property has been set to a non-JSObject
3991 // value, that value is stored in the constructor field of the map.
3992 if (map()->has_non_instance_prototype()) return map()->constructor();
3993 return instance_prototype();
3994 }
3995
should_have_prototype()3996 bool JSFunction::should_have_prototype() {
3997 return map()->function_with_prototype();
3998 }
3999
4000
is_compiled()4001 bool JSFunction::is_compiled() {
4002 return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
4003 }
4004
4005
literals()4006 FixedArray* JSFunction::literals() {
4007 ASSERT(!shared()->bound());
4008 return literals_or_bindings();
4009 }
4010
4011
set_literals(FixedArray * literals)4012 void JSFunction::set_literals(FixedArray* literals) {
4013 ASSERT(!shared()->bound());
4014 set_literals_or_bindings(literals);
4015 }
4016
4017
function_bindings()4018 FixedArray* JSFunction::function_bindings() {
4019 ASSERT(shared()->bound());
4020 return literals_or_bindings();
4021 }
4022
4023
set_function_bindings(FixedArray * bindings)4024 void JSFunction::set_function_bindings(FixedArray* bindings) {
4025 ASSERT(shared()->bound());
4026 // Bound function literal may be initialized to the empty fixed array
4027 // before the bindings are set.
4028 ASSERT(bindings == GetHeap()->empty_fixed_array() ||
4029 bindings->map() == GetHeap()->fixed_cow_array_map());
4030 set_literals_or_bindings(bindings);
4031 }
4032
4033
NumberOfLiterals()4034 int JSFunction::NumberOfLiterals() {
4035 ASSERT(!shared()->bound());
4036 return literals()->length();
4037 }
4038
4039
javascript_builtin(Builtins::JavaScript id)4040 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
4041 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
4042 return READ_FIELD(this, OffsetOfFunctionWithId(id));
4043 }
4044
4045
set_javascript_builtin(Builtins::JavaScript id,Object * value)4046 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
4047 Object* value) {
4048 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
4049 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
4050 WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
4051 }
4052
4053
javascript_builtin_code(Builtins::JavaScript id)4054 Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
4055 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
4056 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
4057 }
4058
4059
set_javascript_builtin_code(Builtins::JavaScript id,Code * value)4060 void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
4061 Code* value) {
4062 ASSERT(id < kJSBuiltinsCount); // id is unsigned.
4063 WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
4064 ASSERT(!HEAP->InNewSpace(value));
4065 }
4066
4067
ACCESSORS(JSProxy,handler,Object,kHandlerOffset)4068 ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
4069 ACCESSORS(JSProxy, hash, Object, kHashOffset)
4070 ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
4071 ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
4072
4073
4074 void JSProxy::InitializeBody(int object_size, Object* value) {
4075 ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
4076 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
4077 WRITE_FIELD(this, offset, value);
4078 }
4079 }
4080
4081
ACCESSORS(JSSet,table,Object,kTableOffset)4082 ACCESSORS(JSSet, table, Object, kTableOffset)
4083 ACCESSORS(JSMap, table, Object, kTableOffset)
4084 ACCESSORS(JSWeakMap, table, Object, kTableOffset)
4085 ACCESSORS(JSWeakMap, next, Object, kNextOffset)
4086
4087
4088 Address Foreign::foreign_address() {
4089 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
4090 }
4091
4092
set_foreign_address(Address value)4093 void Foreign::set_foreign_address(Address value) {
4094 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
4095 }
4096
4097
ACCESSORS(JSValue,value,Object,kValueOffset)4098 ACCESSORS(JSValue, value, Object, kValueOffset)
4099
4100
4101 JSValue* JSValue::cast(Object* obj) {
4102 ASSERT(obj->IsJSValue());
4103 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
4104 return reinterpret_cast<JSValue*>(obj);
4105 }
4106
4107
ACCESSORS(JSDate,value,Object,kValueOffset)4108 ACCESSORS(JSDate, value, Object, kValueOffset)
4109 ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
4110 ACCESSORS(JSDate, year, Object, kYearOffset)
4111 ACCESSORS(JSDate, month, Object, kMonthOffset)
4112 ACCESSORS(JSDate, day, Object, kDayOffset)
4113 ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
4114 ACCESSORS(JSDate, hour, Object, kHourOffset)
4115 ACCESSORS(JSDate, min, Object, kMinOffset)
4116 ACCESSORS(JSDate, sec, Object, kSecOffset)
4117
4118
4119 JSDate* JSDate::cast(Object* obj) {
4120 ASSERT(obj->IsJSDate());
4121 ASSERT(HeapObject::cast(obj)->Size() == JSDate::kSize);
4122 return reinterpret_cast<JSDate*>(obj);
4123 }
4124
4125
ACCESSORS(JSMessageObject,type,String,kTypeOffset)4126 ACCESSORS(JSMessageObject, type, String, kTypeOffset)
4127 ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
4128 ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
4129 ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
4130 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
4131 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
4132 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
4133
4134
4135 JSMessageObject* JSMessageObject::cast(Object* obj) {
4136 ASSERT(obj->IsJSMessageObject());
4137 ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
4138 return reinterpret_cast<JSMessageObject*>(obj);
4139 }
4140
4141
INT_ACCESSORS(Code,instruction_size,kInstructionSizeOffset)4142 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
4143 ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
4144 ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
4145 ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
4146 ACCESSORS(Code, type_feedback_info, Object, kTypeFeedbackInfoOffset)
4147 ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
4148 INT_ACCESSORS(Code, ic_age, kICAgeOffset)
4149
4150 byte* Code::instruction_start() {
4151 return FIELD_ADDR(this, kHeaderSize);
4152 }
4153
4154
instruction_end()4155 byte* Code::instruction_end() {
4156 return instruction_start() + instruction_size();
4157 }
4158
4159
body_size()4160 int Code::body_size() {
4161 return RoundUp(instruction_size(), kObjectAlignment);
4162 }
4163
4164
unchecked_deoptimization_data()4165 FixedArray* Code::unchecked_deoptimization_data() {
4166 return reinterpret_cast<FixedArray*>(
4167 READ_FIELD(this, kDeoptimizationDataOffset));
4168 }
4169
4170
unchecked_relocation_info()4171 ByteArray* Code::unchecked_relocation_info() {
4172 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
4173 }
4174
4175
relocation_start()4176 byte* Code::relocation_start() {
4177 return unchecked_relocation_info()->GetDataStartAddress();
4178 }
4179
4180
relocation_size()4181 int Code::relocation_size() {
4182 return unchecked_relocation_info()->length();
4183 }
4184
4185
entry()4186 byte* Code::entry() {
4187 return instruction_start();
4188 }
4189
4190
contains(byte * inner_pointer)4191 bool Code::contains(byte* inner_pointer) {
4192 return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
4193 }
4194
4195
ACCESSORS(JSArray,length,Object,kLengthOffset)4196 ACCESSORS(JSArray, length, Object, kLengthOffset)
4197
4198
4199 ACCESSORS(JSRegExp, data, Object, kDataOffset)
4200
4201
4202 JSRegExp::Type JSRegExp::TypeTag() {
4203 Object* data = this->data();
4204 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
4205 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
4206 return static_cast<JSRegExp::Type>(smi->value());
4207 }
4208
4209
TypeTagUnchecked()4210 JSRegExp::Type JSRegExp::TypeTagUnchecked() {
4211 Smi* smi = Smi::cast(DataAtUnchecked(kTagIndex));
4212 return static_cast<JSRegExp::Type>(smi->value());
4213 }
4214
4215
CaptureCount()4216 int JSRegExp::CaptureCount() {
4217 switch (TypeTag()) {
4218 case ATOM:
4219 return 0;
4220 case IRREGEXP:
4221 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
4222 default:
4223 UNREACHABLE();
4224 return -1;
4225 }
4226 }
4227
4228
GetFlags()4229 JSRegExp::Flags JSRegExp::GetFlags() {
4230 ASSERT(this->data()->IsFixedArray());
4231 Object* data = this->data();
4232 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
4233 return Flags(smi->value());
4234 }
4235
4236
Pattern()4237 String* JSRegExp::Pattern() {
4238 ASSERT(this->data()->IsFixedArray());
4239 Object* data = this->data();
4240 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
4241 return pattern;
4242 }
4243
4244
DataAt(int index)4245 Object* JSRegExp::DataAt(int index) {
4246 ASSERT(TypeTag() != NOT_COMPILED);
4247 return FixedArray::cast(data())->get(index);
4248 }
4249
4250
DataAtUnchecked(int index)4251 Object* JSRegExp::DataAtUnchecked(int index) {
4252 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4253 int offset = FixedArray::kHeaderSize + index * kPointerSize;
4254 return READ_FIELD(fa, offset);
4255 }
4256
4257
SetDataAt(int index,Object * value)4258 void JSRegExp::SetDataAt(int index, Object* value) {
4259 ASSERT(TypeTag() != NOT_COMPILED);
4260 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4261 FixedArray::cast(data())->set(index, value);
4262 }
4263
4264
SetDataAtUnchecked(int index,Object * value,Heap * heap)4265 void JSRegExp::SetDataAtUnchecked(int index, Object* value, Heap* heap) {
4266 ASSERT(index >= kDataIndex); // Only implementation data can be set this way.
4267 FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4268 if (value->IsSmi()) {
4269 fa->set_unchecked(index, Smi::cast(value));
4270 } else {
4271 // We only do this during GC, so we don't need to notify the write barrier.
4272 fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER);
4273 }
4274 }
4275
4276
GetElementsKind()4277 ElementsKind JSObject::GetElementsKind() {
4278 ElementsKind kind = map()->elements_kind();
4279 #if DEBUG
4280 FixedArrayBase* fixed_array =
4281 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
4282 Map* map = fixed_array->map();
4283 ASSERT(((kind == FAST_ELEMENTS || kind == FAST_SMI_ONLY_ELEMENTS) &&
4284 (map == GetHeap()->fixed_array_map() ||
4285 map == GetHeap()->fixed_cow_array_map())) ||
4286 (kind == FAST_DOUBLE_ELEMENTS &&
4287 (fixed_array->IsFixedDoubleArray() ||
4288 fixed_array == GetHeap()->empty_fixed_array())) ||
4289 (kind == DICTIONARY_ELEMENTS &&
4290 fixed_array->IsFixedArray() &&
4291 fixed_array->IsDictionary()) ||
4292 (kind > DICTIONARY_ELEMENTS));
4293 ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) ||
4294 (elements()->IsFixedArray() && elements()->length() >= 2));
4295 #endif
4296 return kind;
4297 }
4298
4299
GetElementsAccessor()4300 ElementsAccessor* JSObject::GetElementsAccessor() {
4301 return ElementsAccessor::ForKind(GetElementsKind());
4302 }
4303
4304
HasFastElements()4305 bool JSObject::HasFastElements() {
4306 return GetElementsKind() == FAST_ELEMENTS;
4307 }
4308
4309
HasFastSmiOnlyElements()4310 bool JSObject::HasFastSmiOnlyElements() {
4311 return GetElementsKind() == FAST_SMI_ONLY_ELEMENTS;
4312 }
4313
4314
HasFastTypeElements()4315 bool JSObject::HasFastTypeElements() {
4316 ElementsKind elements_kind = GetElementsKind();
4317 return elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4318 elements_kind == FAST_ELEMENTS;
4319 }
4320
4321
HasFastDoubleElements()4322 bool JSObject::HasFastDoubleElements() {
4323 return GetElementsKind() == FAST_DOUBLE_ELEMENTS;
4324 }
4325
4326
HasDictionaryElements()4327 bool JSObject::HasDictionaryElements() {
4328 return GetElementsKind() == DICTIONARY_ELEMENTS;
4329 }
4330
4331
HasNonStrictArgumentsElements()4332 bool JSObject::HasNonStrictArgumentsElements() {
4333 return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS;
4334 }
4335
4336
HasExternalArrayElements()4337 bool JSObject::HasExternalArrayElements() {
4338 HeapObject* array = elements();
4339 ASSERT(array != NULL);
4340 return array->IsExternalArray();
4341 }
4342
4343
4344 #define EXTERNAL_ELEMENTS_CHECK(name, type) \
4345 bool JSObject::HasExternal##name##Elements() { \
4346 HeapObject* array = elements(); \
4347 ASSERT(array != NULL); \
4348 if (!array->IsHeapObject()) \
4349 return false; \
4350 return array->map()->instance_type() == type; \
4351 }
4352
4353
EXTERNAL_ELEMENTS_CHECK(Byte,EXTERNAL_BYTE_ARRAY_TYPE)4354 EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
4355 EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
4356 EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
4357 EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
4358 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
4359 EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
4360 EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
4361 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
4362 EXTERNAL_ELEMENTS_CHECK(Float,
4363 EXTERNAL_FLOAT_ARRAY_TYPE)
4364 EXTERNAL_ELEMENTS_CHECK(Double,
4365 EXTERNAL_DOUBLE_ARRAY_TYPE)
4366 EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
4367
4368
4369 bool JSObject::HasNamedInterceptor() {
4370 return map()->has_named_interceptor();
4371 }
4372
4373
HasIndexedInterceptor()4374 bool JSObject::HasIndexedInterceptor() {
4375 return map()->has_indexed_interceptor();
4376 }
4377
4378
EnsureWritableFastElements()4379 MaybeObject* JSObject::EnsureWritableFastElements() {
4380 ASSERT(HasFastTypeElements());
4381 FixedArray* elems = FixedArray::cast(elements());
4382 Isolate* isolate = GetIsolate();
4383 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
4384 Object* writable_elems;
4385 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
4386 elems, isolate->heap()->fixed_array_map());
4387 if (!maybe_writable_elems->ToObject(&writable_elems)) {
4388 return maybe_writable_elems;
4389 }
4390 }
4391 set_elements(FixedArray::cast(writable_elems));
4392 isolate->counters()->cow_arrays_converted()->Increment();
4393 return writable_elems;
4394 }
4395
4396
property_dictionary()4397 StringDictionary* JSObject::property_dictionary() {
4398 ASSERT(!HasFastProperties());
4399 return StringDictionary::cast(properties());
4400 }
4401
4402
element_dictionary()4403 SeededNumberDictionary* JSObject::element_dictionary() {
4404 ASSERT(HasDictionaryElements());
4405 return SeededNumberDictionary::cast(elements());
4406 }
4407
4408
IsHashFieldComputed(uint32_t field)4409 bool String::IsHashFieldComputed(uint32_t field) {
4410 return (field & kHashNotComputedMask) == 0;
4411 }
4412
4413
HasHashCode()4414 bool String::HasHashCode() {
4415 return IsHashFieldComputed(hash_field());
4416 }
4417
4418
Hash()4419 uint32_t String::Hash() {
4420 // Fast case: has hash code already been computed?
4421 uint32_t field = hash_field();
4422 if (IsHashFieldComputed(field)) return field >> kHashShift;
4423 // Slow case: compute hash code and set it.
4424 return ComputeAndSetHash();
4425 }
4426
4427
StringHasher(int length,uint32_t seed)4428 StringHasher::StringHasher(int length, uint32_t seed)
4429 : length_(length),
4430 raw_running_hash_(seed),
4431 array_index_(0),
4432 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
4433 is_first_char_(true),
4434 is_valid_(true) {
4435 ASSERT(FLAG_randomize_hashes || raw_running_hash_ == 0);
4436 }
4437
4438
has_trivial_hash()4439 bool StringHasher::has_trivial_hash() {
4440 return length_ > String::kMaxHashCalcLength;
4441 }
4442
4443
AddCharacter(uint32_t c)4444 void StringHasher::AddCharacter(uint32_t c) {
4445 if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
4446 AddSurrogatePair(c); // Not inlined.
4447 return;
4448 }
4449 // Use the Jenkins one-at-a-time hash function to update the hash
4450 // for the given character.
4451 raw_running_hash_ += c;
4452 raw_running_hash_ += (raw_running_hash_ << 10);
4453 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4454 // Incremental array index computation.
4455 if (is_array_index_) {
4456 if (c < '0' || c > '9') {
4457 is_array_index_ = false;
4458 } else {
4459 int d = c - '0';
4460 if (is_first_char_) {
4461 is_first_char_ = false;
4462 if (c == '0' && length_ > 1) {
4463 is_array_index_ = false;
4464 return;
4465 }
4466 }
4467 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
4468 is_array_index_ = false;
4469 } else {
4470 array_index_ = array_index_ * 10 + d;
4471 }
4472 }
4473 }
4474 }
4475
4476
AddCharacterNoIndex(uint32_t c)4477 void StringHasher::AddCharacterNoIndex(uint32_t c) {
4478 ASSERT(!is_array_index());
4479 if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
4480 AddSurrogatePairNoIndex(c); // Not inlined.
4481 return;
4482 }
4483 raw_running_hash_ += c;
4484 raw_running_hash_ += (raw_running_hash_ << 10);
4485 raw_running_hash_ ^= (raw_running_hash_ >> 6);
4486 }
4487
4488
GetHash()4489 uint32_t StringHasher::GetHash() {
4490 // Get the calculated raw hash value and do some more bit ops to distribute
4491 // the hash further. Ensure that we never return zero as the hash value.
4492 uint32_t result = raw_running_hash_;
4493 result += (result << 3);
4494 result ^= (result >> 11);
4495 result += (result << 15);
4496 if ((result & String::kHashBitMask) == 0) {
4497 result = 27;
4498 }
4499 return result;
4500 }
4501
4502
4503 template <typename schar>
HashSequentialString(const schar * chars,int length,uint32_t seed)4504 uint32_t HashSequentialString(const schar* chars, int length, uint32_t seed) {
4505 StringHasher hasher(length, seed);
4506 if (!hasher.has_trivial_hash()) {
4507 int i;
4508 for (i = 0; hasher.is_array_index() && (i < length); i++) {
4509 hasher.AddCharacter(chars[i]);
4510 }
4511 for (; i < length; i++) {
4512 hasher.AddCharacterNoIndex(chars[i]);
4513 }
4514 }
4515 return hasher.GetHashField();
4516 }
4517
4518
AsArrayIndex(uint32_t * index)4519 bool String::AsArrayIndex(uint32_t* index) {
4520 uint32_t field = hash_field();
4521 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
4522 return false;
4523 }
4524 return SlowAsArrayIndex(index);
4525 }
4526
4527
GetPrototype()4528 Object* JSReceiver::GetPrototype() {
4529 return HeapObject::cast(this)->map()->prototype();
4530 }
4531
4532
HasProperty(String * name)4533 bool JSReceiver::HasProperty(String* name) {
4534 if (IsJSProxy()) {
4535 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4536 }
4537 return GetPropertyAttribute(name) != ABSENT;
4538 }
4539
4540
HasLocalProperty(String * name)4541 bool JSReceiver::HasLocalProperty(String* name) {
4542 if (IsJSProxy()) {
4543 return JSProxy::cast(this)->HasPropertyWithHandler(name);
4544 }
4545 return GetLocalPropertyAttribute(name) != ABSENT;
4546 }
4547
4548
GetPropertyAttribute(String * key)4549 PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
4550 return GetPropertyAttributeWithReceiver(this, key);
4551 }
4552
4553 // TODO(504): this may be useful in other places too where JSGlobalProxy
4554 // is used.
BypassGlobalProxy()4555 Object* JSObject::BypassGlobalProxy() {
4556 if (IsJSGlobalProxy()) {
4557 Object* proto = GetPrototype();
4558 if (proto->IsNull()) return GetHeap()->undefined_value();
4559 ASSERT(proto->IsJSGlobalObject());
4560 return proto;
4561 }
4562 return this;
4563 }
4564
4565
GetIdentityHash(CreationFlag flag)4566 MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) {
4567 return IsJSProxy()
4568 ? JSProxy::cast(this)->GetIdentityHash(flag)
4569 : JSObject::cast(this)->GetIdentityHash(flag);
4570 }
4571
4572
HasElement(uint32_t index)4573 bool JSReceiver::HasElement(uint32_t index) {
4574 if (IsJSProxy()) {
4575 return JSProxy::cast(this)->HasElementWithHandler(index);
4576 }
4577 return JSObject::cast(this)->HasElementWithReceiver(this, index);
4578 }
4579
4580
all_can_read()4581 bool AccessorInfo::all_can_read() {
4582 return BooleanBit::get(flag(), kAllCanReadBit);
4583 }
4584
4585
set_all_can_read(bool value)4586 void AccessorInfo::set_all_can_read(bool value) {
4587 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
4588 }
4589
4590
all_can_write()4591 bool AccessorInfo::all_can_write() {
4592 return BooleanBit::get(flag(), kAllCanWriteBit);
4593 }
4594
4595
set_all_can_write(bool value)4596 void AccessorInfo::set_all_can_write(bool value) {
4597 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
4598 }
4599
4600
prohibits_overwriting()4601 bool AccessorInfo::prohibits_overwriting() {
4602 return BooleanBit::get(flag(), kProhibitsOverwritingBit);
4603 }
4604
4605
set_prohibits_overwriting(bool value)4606 void AccessorInfo::set_prohibits_overwriting(bool value) {
4607 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
4608 }
4609
4610
property_attributes()4611 PropertyAttributes AccessorInfo::property_attributes() {
4612 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
4613 }
4614
4615
set_property_attributes(PropertyAttributes attributes)4616 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
4617 set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
4618 }
4619
4620
4621 template<typename Shape, typename Key>
SetEntry(int entry,Object * key,Object * value)4622 void Dictionary<Shape, Key>::SetEntry(int entry,
4623 Object* key,
4624 Object* value) {
4625 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
4626 }
4627
4628
4629 template<typename Shape, typename Key>
SetEntry(int entry,Object * key,Object * value,PropertyDetails details)4630 void Dictionary<Shape, Key>::SetEntry(int entry,
4631 Object* key,
4632 Object* value,
4633 PropertyDetails details) {
4634 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
4635 int index = HashTable<Shape, Key>::EntryToIndex(entry);
4636 AssertNoAllocation no_gc;
4637 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
4638 FixedArray::set(index, key, mode);
4639 FixedArray::set(index+1, value, mode);
4640 FixedArray::set(index+2, details.AsSmi());
4641 }
4642
4643
IsMatch(uint32_t key,Object * other)4644 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
4645 ASSERT(other->IsNumber());
4646 return key == static_cast<uint32_t>(other->Number());
4647 }
4648
4649
Hash(uint32_t key)4650 uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
4651 return ComputeIntegerHash(key, 0);
4652 }
4653
4654
HashForObject(uint32_t key,Object * other)4655 uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
4656 Object* other) {
4657 ASSERT(other->IsNumber());
4658 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
4659 }
4660
SeededHash(uint32_t key,uint32_t seed)4661 uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
4662 return ComputeIntegerHash(key, seed);
4663 }
4664
SeededHashForObject(uint32_t key,uint32_t seed,Object * other)4665 uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
4666 uint32_t seed,
4667 Object* other) {
4668 ASSERT(other->IsNumber());
4669 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
4670 }
4671
AsObject(uint32_t key)4672 MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
4673 return Isolate::Current()->heap()->NumberFromUint32(key);
4674 }
4675
4676
IsMatch(String * key,Object * other)4677 bool StringDictionaryShape::IsMatch(String* key, Object* other) {
4678 // We know that all entries in a hash table had their hash keys created.
4679 // Use that knowledge to have fast failure.
4680 if (key->Hash() != String::cast(other)->Hash()) return false;
4681 return key->Equals(String::cast(other));
4682 }
4683
4684
Hash(String * key)4685 uint32_t StringDictionaryShape::Hash(String* key) {
4686 return key->Hash();
4687 }
4688
4689
HashForObject(String * key,Object * other)4690 uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
4691 return String::cast(other)->Hash();
4692 }
4693
4694
AsObject(String * key)4695 MaybeObject* StringDictionaryShape::AsObject(String* key) {
4696 return key;
4697 }
4698
4699
4700 template <int entrysize>
IsMatch(Object * key,Object * other)4701 bool ObjectHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
4702 return key->SameValue(other);
4703 }
4704
4705
4706 template <int entrysize>
Hash(Object * key)4707 uint32_t ObjectHashTableShape<entrysize>::Hash(Object* key) {
4708 MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
4709 return Smi::cast(maybe_hash->ToObjectChecked())->value();
4710 }
4711
4712
4713 template <int entrysize>
HashForObject(Object * key,Object * other)4714 uint32_t ObjectHashTableShape<entrysize>::HashForObject(Object* key,
4715 Object* other) {
4716 MaybeObject* maybe_hash = other->GetHash(OMIT_CREATION);
4717 return Smi::cast(maybe_hash->ToObjectChecked())->value();
4718 }
4719
4720
4721 template <int entrysize>
AsObject(Object * key)4722 MaybeObject* ObjectHashTableShape<entrysize>::AsObject(Object* key) {
4723 return key;
4724 }
4725
4726
ClearCodeCache(Heap * heap)4727 void Map::ClearCodeCache(Heap* heap) {
4728 // No write barrier is needed since empty_fixed_array is not in new space.
4729 // Please note this function is used during marking:
4730 // - MarkCompactCollector::MarkUnmarkedObject
4731 // - IncrementalMarking::Step
4732 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
4733 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
4734 }
4735
4736
EnsureSize(int required_size)4737 void JSArray::EnsureSize(int required_size) {
4738 ASSERT(HasFastTypeElements());
4739 FixedArray* elts = FixedArray::cast(elements());
4740 const int kArraySizeThatFitsComfortablyInNewSpace = 128;
4741 if (elts->length() < required_size) {
4742 // Doubling in size would be overkill, but leave some slack to avoid
4743 // constantly growing.
4744 Expand(required_size + (required_size >> 3));
4745 // It's a performance benefit to keep a frequently used array in new-space.
4746 } else if (!GetHeap()->new_space()->Contains(elts) &&
4747 required_size < kArraySizeThatFitsComfortablyInNewSpace) {
4748 // Expand will allocate a new backing store in new space even if the size
4749 // we asked for isn't larger than what we had before.
4750 Expand(required_size);
4751 }
4752 }
4753
4754
set_length(Smi * length)4755 void JSArray::set_length(Smi* length) {
4756 // Don't need a write barrier for a Smi.
4757 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
4758 }
4759
4760
AllowsSetElementsLength()4761 bool JSArray::AllowsSetElementsLength() {
4762 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
4763 ASSERT(result == !HasExternalArrayElements());
4764 return result;
4765 }
4766
4767
SetContent(FixedArrayBase * storage)4768 MaybeObject* JSArray::SetContent(FixedArrayBase* storage) {
4769 MaybeObject* maybe_result = EnsureCanContainElements(
4770 storage, ALLOW_COPIED_DOUBLE_ELEMENTS);
4771 if (maybe_result->IsFailure()) return maybe_result;
4772 ASSERT((storage->map() == GetHeap()->fixed_double_array_map() &&
4773 GetElementsKind() == FAST_DOUBLE_ELEMENTS) ||
4774 ((storage->map() != GetHeap()->fixed_double_array_map()) &&
4775 ((GetElementsKind() == FAST_ELEMENTS) ||
4776 (GetElementsKind() == FAST_SMI_ONLY_ELEMENTS &&
4777 FixedArray::cast(storage)->ContainsOnlySmisOrHoles()))));
4778 set_elements(storage);
4779 set_length(Smi::FromInt(storage->length()));
4780 return this;
4781 }
4782
4783
Copy()4784 MaybeObject* FixedArray::Copy() {
4785 if (length() == 0) return this;
4786 return GetHeap()->CopyFixedArray(this);
4787 }
4788
4789
Copy()4790 MaybeObject* FixedDoubleArray::Copy() {
4791 if (length() == 0) return this;
4792 return GetHeap()->CopyFixedDoubleArray(this);
4793 }
4794
4795
SetAstId(int index,Smi * id)4796 void TypeFeedbackCells::SetAstId(int index, Smi* id) {
4797 set(1 + index * 2, id);
4798 }
4799
4800
AstId(int index)4801 Smi* TypeFeedbackCells::AstId(int index) {
4802 return Smi::cast(get(1 + index * 2));
4803 }
4804
4805
SetCell(int index,JSGlobalPropertyCell * cell)4806 void TypeFeedbackCells::SetCell(int index, JSGlobalPropertyCell* cell) {
4807 set(index * 2, cell);
4808 }
4809
4810
Cell(int index)4811 JSGlobalPropertyCell* TypeFeedbackCells::Cell(int index) {
4812 return JSGlobalPropertyCell::cast(get(index * 2));
4813 }
4814
4815
UninitializedSentinel(Isolate * isolate)4816 Handle<Object> TypeFeedbackCells::UninitializedSentinel(Isolate* isolate) {
4817 return isolate->factory()->the_hole_value();
4818 }
4819
4820
MegamorphicSentinel(Isolate * isolate)4821 Handle<Object> TypeFeedbackCells::MegamorphicSentinel(Isolate* isolate) {
4822 return isolate->factory()->undefined_value();
4823 }
4824
4825
RawUninitializedSentinel(Heap * heap)4826 Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) {
4827 return heap->raw_unchecked_the_hole_value();
4828 }
4829
4830
SMI_ACCESSORS(TypeFeedbackInfo,ic_total_count,kIcTotalCountOffset)4831 SMI_ACCESSORS(TypeFeedbackInfo, ic_total_count, kIcTotalCountOffset)
4832 SMI_ACCESSORS(TypeFeedbackInfo, ic_with_type_info_count,
4833 kIcWithTypeinfoCountOffset)
4834 ACCESSORS(TypeFeedbackInfo, type_feedback_cells, TypeFeedbackCells,
4835 kTypeFeedbackCellsOffset)
4836
4837
4838 SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
4839
4840
4841 Relocatable::Relocatable(Isolate* isolate) {
4842 ASSERT(isolate == Isolate::Current());
4843 isolate_ = isolate;
4844 prev_ = isolate->relocatable_top();
4845 isolate->set_relocatable_top(this);
4846 }
4847
4848
~Relocatable()4849 Relocatable::~Relocatable() {
4850 ASSERT(isolate_ == Isolate::Current());
4851 ASSERT_EQ(isolate_->relocatable_top(), this);
4852 isolate_->set_relocatable_top(prev_);
4853 }
4854
4855
SizeOf(Map * map,HeapObject * object)4856 int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4857 return map->instance_size();
4858 }
4859
4860
ForeignIterateBody(ObjectVisitor * v)4861 void Foreign::ForeignIterateBody(ObjectVisitor* v) {
4862 v->VisitExternalReference(
4863 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
4864 }
4865
4866
4867 template<typename StaticVisitor>
ForeignIterateBody()4868 void Foreign::ForeignIterateBody() {
4869 StaticVisitor::VisitExternalReference(
4870 reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
4871 }
4872
4873
ExternalAsciiStringIterateBody(ObjectVisitor * v)4874 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4875 typedef v8::String::ExternalAsciiStringResource Resource;
4876 v->VisitExternalAsciiString(
4877 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4878 }
4879
4880
4881 template<typename StaticVisitor>
ExternalAsciiStringIterateBody()4882 void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4883 typedef v8::String::ExternalAsciiStringResource Resource;
4884 StaticVisitor::VisitExternalAsciiString(
4885 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4886 }
4887
4888
ExternalTwoByteStringIterateBody(ObjectVisitor * v)4889 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4890 typedef v8::String::ExternalStringResource Resource;
4891 v->VisitExternalTwoByteString(
4892 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4893 }
4894
4895
4896 template<typename StaticVisitor>
ExternalTwoByteStringIterateBody()4897 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4898 typedef v8::String::ExternalStringResource Resource;
4899 StaticVisitor::VisitExternalTwoByteString(
4900 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4901 }
4902
4903 #define SLOT_ADDR(obj, offset) \
4904 reinterpret_cast<Object**>((obj)->address() + offset)
4905
4906 template<int start_offset, int end_offset, int size>
IterateBody(HeapObject * obj,ObjectVisitor * v)4907 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4908 HeapObject* obj,
4909 ObjectVisitor* v) {
4910 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4911 }
4912
4913
4914 template<int start_offset>
IterateBody(HeapObject * obj,int object_size,ObjectVisitor * v)4915 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4916 int object_size,
4917 ObjectVisitor* v) {
4918 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4919 }
4920
4921 #undef SLOT_ADDR
4922
4923 #undef TYPE_CHECKER
4924 #undef CAST_ACCESSOR
4925 #undef INT_ACCESSORS
4926 #undef ACCESSORS
4927 #undef ACCESSORS_TO_SMI
4928 #undef SMI_ACCESSORS
4929 #undef BOOL_GETTER
4930 #undef BOOL_ACCESSORS
4931 #undef FIELD_ADDR
4932 #undef READ_FIELD
4933 #undef WRITE_FIELD
4934 #undef WRITE_BARRIER
4935 #undef CONDITIONAL_WRITE_BARRIER
4936 #undef READ_DOUBLE_FIELD
4937 #undef WRITE_DOUBLE_FIELD
4938 #undef READ_INT_FIELD
4939 #undef WRITE_INT_FIELD
4940 #undef READ_INTPTR_FIELD
4941 #undef WRITE_INTPTR_FIELD
4942 #undef READ_UINT32_FIELD
4943 #undef WRITE_UINT32_FIELD
4944 #undef READ_SHORT_FIELD
4945 #undef WRITE_SHORT_FIELD
4946 #undef READ_BYTE_FIELD
4947 #undef WRITE_BYTE_FIELD
4948
4949
4950 } } // namespace v8::internal
4951
4952 #endif // V8_OBJECTS_INL_H_
4953